From 4e00a9b1a5942c6e8e81d1a22e18f640b8ba7f12 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Tue, 29 Sep 2020 15:23:07 +0100 Subject: [PATCH 0001/1837] fix #106487 Contribute an "activating" placeholder message and button --- extensions/git/package.json | 6 ++++++ extensions/git/package.nls.json | 1 + 2 files changed, 7 insertions(+) diff --git a/extensions/git/package.json b/extensions/git/package.json index 975e81f7d27..3ce5776241f 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2104,6 +2104,12 @@ "when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount == 0", "group": "2_open@1" }, + { + "view": "explorer", + "contents": "%view.workbench.activating%", + "when": "config.git.enabled && git.state != initialized", + "group": "5_scm@1" + }, { "view": "explorer", "contents": "%view.workbench.cloneRepository%", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 7300b63acbc..f8838782e3d 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -181,5 +181,6 @@ "view.workbench.scm.folder": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.activating": "Git extension is activating...\n[Learn More](https://aka.ms/vscode-scm)", "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)" } From af4fb006877b18671967303d90bdcc98952e2e1f Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Wed, 30 Sep 2020 06:49:32 +0100 Subject: [PATCH 0002/1837] Initial 'Git extension is activating...' in SCM view --- extensions/git/package.json | 5 +++++ extensions/git/package.nls.json | 1 + 2 files changed, 6 insertions(+) diff --git a/extensions/git/package.json b/extensions/git/package.json index 3ce5776241f..2f0c11b17ce 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2075,6 +2075,11 @@ "contents": "%view.workbench.scm.disabled%", "when": "!config.git.enabled" }, + { + "view": "scm", + "contents": "%view.workbench.scm.activating%", + "when": "config.git.enabled && git.state != initialized" + }, { "view": "scm", "contents": "%view.workbench.scm.missing%", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index f8838782e3d..85f893edff6 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -177,6 +177,7 @@ "colors.submodule": "Color for submodule resources.", "view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.", "view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.activating": "Git extension is activating...\n[Learn More](https://aka.ms/vscode-scm)", "view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.folder": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", From ceeb9748562afb00c191606ffa22d9bfb1b13a38 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Wed, 30 Sep 2020 13:01:46 +0100 Subject: [PATCH 0003/1837] Wire up `preconditions` for viewsWelcome buttons, and use it --- extensions/git/package.json | 24 +++++++------------ extensions/git/package.nls.json | 4 +--- .../browser/parts/views/viewPaneContainer.ts | 3 +-- .../common/viewsWelcomeContribution.ts | 1 + .../common/viewsWelcomeExtensionPoint.ts | 6 +++++ 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 2f0c11b17ce..5b16c29b4b2 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2075,11 +2075,6 @@ "contents": "%view.workbench.scm.disabled%", "when": "!config.git.enabled" }, - { - "view": "scm", - "contents": "%view.workbench.scm.activating%", - "when": "config.git.enabled && git.state != initialized" - }, { "view": "scm", "contents": "%view.workbench.scm.missing%", @@ -2088,37 +2083,36 @@ { "view": "scm", "contents": "%view.workbench.scm.empty%", - "when": "config.git.enabled && git.state == initialized && workbenchState == empty", + "when": "config.git.enabled && workbenchState == empty", + "preconditions": ["git.state == initialized"], "group": "2_open@1" }, { "view": "scm", "contents": "%view.workbench.scm.folder%", - "when": "config.git.enabled && git.state == initialized && workbenchState == folder", + "when": "config.git.enabled && workbenchState == folder", + "preconditions": ["git.state == initialized"], "group": "5_scm@1" }, { "view": "scm", "contents": "%view.workbench.scm.workspace%", "when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0", + "preconditions": ["git.state == initialized"], "group": "5_scm@1" }, { "view": "scm", "contents": "%view.workbench.scm.emptyWorkspace%", - "when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount == 0", + "when": "config.git.enabled && workbenchState == workspace && workspaceFolderCount == 0", + "preconditions": ["git.state == initialized"], "group": "2_open@1" }, - { - "view": "explorer", - "contents": "%view.workbench.activating%", - "when": "config.git.enabled && git.state != initialized", - "group": "5_scm@1" - }, { "view": "explorer", "contents": "%view.workbench.cloneRepository%", - "when": "config.git.enabled && git.state == initialized", + "when": "config.git.enabled", + "preconditions": ["git.state == initialized"], "group": "5_scm@1" } ] diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 85f893edff6..dfae8e48cec 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -177,11 +177,9 @@ "colors.submodule": "Color for submodule resources.", "view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.", "view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.activating": "Git extension is activating...\n[Learn More](https://aka.ms/vscode-scm)", "view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.folder": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.activating": "Git extension is activating...\n[Learn More](https://aka.ms/vscode-scm)", - "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)" + "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone 'Clone a repository once the git extension has activated')" } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 3024b15fdba..e3a940e7647 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -554,9 +554,8 @@ export abstract class ViewPane extends Pane implements IView { this.bodyContainer.classList.add('welcome'); this.viewWelcomeContainer.innerText = ''; - let buttonIndex = 0; - for (const { content, preconditions } of contents) { + let buttonIndex = 0; const lines = content.split('\n'); for (let line of lines) { diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index 25049bac517..8dc246670d3 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -39,6 +39,7 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo const disposable = viewsRegistry.registerViewWelcomeContent(id, { content: welcome.contents, when: ContextKeyExpr.deserialize(welcome.when), + preconditions: welcome.preconditions?.map((value) => ContextKeyExpr.deserialize(value)), group, order }); diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts index 6724d8a95ab..9c43fd59738 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts @@ -11,6 +11,7 @@ export enum ViewsWelcomeExtensionPointFields { contents = 'contents', when = 'when', group = 'group', + preconditions = 'preconditions', } export interface ViewWelcome { @@ -18,6 +19,7 @@ export interface ViewWelcome { readonly [ViewsWelcomeExtensionPointFields.contents]: string; readonly [ViewsWelcomeExtensionPointFields.when]: string; readonly [ViewsWelcomeExtensionPointFields.group]: string; + readonly [ViewsWelcomeExtensionPointFields.preconditions]: string[]; } export type ViewsWelcomeExtensionPoint = ViewWelcome[]; @@ -64,6 +66,10 @@ const viewsWelcomeExtensionPointSchema = Object.freeze Date: Thu, 1 Oct 2020 14:31:07 -0600 Subject: [PATCH 0004/1837] Fixed issue 104346 --- .../themes/quietlight-color-theme.json | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index ffcb30cff03..c91fb20c1e6 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -421,6 +421,27 @@ "foreground": "#434343" } }, + { + "name": "diff: deleted", + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#C73D20" + } + }, + { + "name": "diff: changed", + "scope": "markup.changed.diff", + "settings": { + "foreground": "#9C5D27" + } + }, + { + "name": "diff: inserted", + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#448C27" + } + }, { "name": "JSX: Tags", "scope": [ From c9fb06699064620b07fd6cffb9f8622cb8114938 Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Fri, 9 Oct 2020 12:59:39 +0200 Subject: [PATCH 0005/1837] Ignore LineDecoration order when comparing --- .../common/viewLayout/lineDecorations.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index 74428ae28d7..a502afc1285 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -34,8 +34,22 @@ export class LineDecoration { if (aLen !== bLen) { return false; } - for (let i = 0; i < aLen; i++) { - if (!LineDecoration._equals(a[i], b[i])) { + if (aLen === 0) { + return true; + } + if (aLen === 1) { + return LineDecoration._equals(a[0], b[0]); + } + const bSeen: (undefined | true)[] = new Array(bLen); + for (let i = 0; i < aLen; ++i) { + let j = 0; + for (; j < bLen; ++j) { + if (bSeen[j] !== true && LineDecoration._equals(a[i], b[j])) { + bSeen[j] = true; + break; + } + } + if (j === bLen) { return false; } } From d119c924891172dc11807c346aeaf661747bb76b Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Fri, 18 Sep 2020 17:16:43 +0100 Subject: [PATCH 0006/1837] Add atomic tabs option This treats tabs faked using spaces as if they were real tabs meaning that you can't select the middle of them. --- src/vs/editor/browser/view/viewController.ts | 50 +++--- .../common/config/commonEditorConfig.ts | 5 + src/vs/editor/common/config/editorOptions.ts | 1 + .../controller/cursorAtomicMoveOperations.ts | 155 ++++++++++++++++++ .../editor/common/controller/cursorCommon.ts | 6 +- .../common/controller/cursorMoveOperations.ts | 50 +++++- src/vs/editor/common/model.ts | 7 + src/vs/editor/common/model/textModel.ts | 5 + src/vs/editor/common/model/textModelEvents.ts | 1 + .../common/services/modelServiceImpl.ts | 7 + .../browser/standaloneCodeEditor.ts | 5 + .../cursorAtomicMoveOperations.test.ts | 128 +++++++++++++++ src/vs/editor/test/common/editorTestUtils.ts | 2 + src/vs/monaco.d.ts | 8 + src/vs/vscode.d.ts | 6 + .../workbench/api/browser/mainThreadEditor.ts | 5 + .../workbench/api/common/extHost.protocol.ts | 2 + .../workbench/api/common/extHostTextEditor.ts | 20 ++- .../browser/api/extHostTextEditor.test.ts | 39 ++++- 19 files changed, 474 insertions(+), 28 deletions(-) create mode 100644 src/vs/editor/common/controller/cursorAtomicMoveOperations.ts create mode 100644 src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 519a26bb5f8..13c0079560d 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -14,6 +14,7 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import * as platform from 'vs/base/common/platform'; +import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; export interface IMouseDispatchData { position: Position; @@ -128,24 +129,35 @@ export class ViewController { } public dispatchMouse(data: IMouseDispatchData): void { + let position = data.position; + if (this.viewModel.getTextModelOptions().atomicSoftTabs) { + const minColumn = this.viewModel.getLineMinColumn(position.lineNumber); + const lineContent = this.viewModel.getLineContent(position.lineNumber); + const { tabSize } = this.viewModel.getTextModelOptions(); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); + if (newPosition !== -1) { + position = new Position(position.lineNumber, newPosition + minColumn); + } + } + const options = this.configuration.options; const selectionClipboardIsOn = (platform.isLinux && options.get(EditorOption.selectionClipboard)); const columnSelection = options.get(EditorOption.columnSelection); if (data.middleButton && !selectionClipboardIsOn) { - this._columnSelect(data.position, data.mouseColumn, data.inSelectionMode); + this._columnSelect(position, data.mouseColumn, data.inSelectionMode); } else if (data.startedOnLineNumbers) { // If the dragging started on the gutter, then have operations work on the entire line if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelect(data.position); + this._lastCursorLineSelect(position); } else { - this._createCursor(data.position, true); + this._createCursor(position, true); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(data.position); + this._lineSelectDrag(position); } else { - this._lineSelect(data.position); + this._lineSelect(position); } } } else if (data.mouseDownCount >= 4) { @@ -153,54 +165,54 @@ export class ViewController { } else if (data.mouseDownCount === 3) { if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelectDrag(data.position); + this._lastCursorLineSelectDrag(position); } else { - this._lastCursorLineSelect(data.position); + this._lastCursorLineSelect(position); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(data.position); + this._lineSelectDrag(position); } else { - this._lineSelect(data.position); + this._lineSelect(position); } } } else if (data.mouseDownCount === 2) { if (this._hasMulticursorModifier(data)) { - this._lastCursorWordSelect(data.position); + this._lastCursorWordSelect(position); } else { if (data.inSelectionMode) { - this._wordSelectDrag(data.position); + this._wordSelectDrag(position); } else { - this._wordSelect(data.position); + this._wordSelect(position); } } } else { if (this._hasMulticursorModifier(data)) { if (!this._hasNonMulticursorModifier(data)) { if (data.shiftKey) { - this._columnSelect(data.position, data.mouseColumn, true); + this._columnSelect(position, data.mouseColumn, true); } else { // Do multi-cursor operations only when purely alt is pressed if (data.inSelectionMode) { - this._lastCursorMoveToSelect(data.position); + this._lastCursorMoveToSelect(position); } else { - this._createCursor(data.position, false); + this._createCursor(position, false); } } } } else { if (data.inSelectionMode) { if (data.altKey) { - this._columnSelect(data.position, data.mouseColumn, true); + this._columnSelect(position, data.mouseColumn, true); } else { if (columnSelection) { - this._columnSelect(data.position, data.mouseColumn, true); + this._columnSelect(position, data.mouseColumn, true); } else { - this._moveToSelect(data.position); + this._moveToSelect(position); } } } else { - this.moveTo(data.position); + this.moveTo(position); } } } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 3bde5dfd839..7dc98b03b97 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -482,6 +482,11 @@ const editorConfiguration: IConfigurationNode = { default: EDITOR_MODEL_DEFAULTS.insertSpaces, markdownDescription: nls.localize('insertSpaces', "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.") }, + 'editor.atomicSoftTabs': { + type: 'boolean', + default: EDITOR_MODEL_DEFAULTS.atomicSoftTabs, + markdownDescription: nls.localize('atomicSoftTabs', "Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. This means selection will snap to indentation boundaries.") + }, 'editor.detectIndentation': { type: 'boolean', default: EDITOR_MODEL_DEFAULTS.detectIndentation, diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 12d0cd49e8a..3fd4a5d13b4 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3542,6 +3542,7 @@ export const EDITOR_MODEL_DEFAULTS = { tabSize: 4, indentSize: 4, insertSpaces: true, + atomicSoftTabs: false, detectIndentation: true, trimAutoWhitespace: true, largeFileOptimizations: true diff --git a/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts b/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts new file mode 100644 index 00000000000..3884bbfd628 --- /dev/null +++ b/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts @@ -0,0 +1,155 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CharCode } from 'vs/base/common/charCode'; +import { CursorColumns } from 'vs/editor/common/controller/cursorCommon'; + +export enum Direction { + Left, + Right, + Nearest, +} + +export class AtomicTabMoveOperations { + // Get the visible column at the position. If we get to a non-whitespace character first + // or past the end of string then return -1. Note `position` and the return + // value are 0-based. + public static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number) { + let visibleColumn = 0; + for (let i = 0; i < lineContent.length; ++i) { + if (i === position) { + return visibleColumn; + } + const chCode = lineContent.charCodeAt(i); + switch (chCode) { + case CharCode.Space: + visibleColumn += 1; + break; + case CharCode.Tab: + // Skip to the next multiple of tabSize. + visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); + break; + default: + return -1; + } + } + if (position === lineContent.length) { + return visibleColumn; + } + return -1; + } + + // Return the position that should result from a move left, right or to the + // nearest tab, if atomic tabs are enabled. Left and right are used for the + // arrow key movements, nearest is used for mouse selection. It returns + // -1 if atomic tabs are not relevant and you should fall back to normal + // behaviour. + // + // Note, `position` and the return value are 0-based. + public static atomicPosition(lineContent: string, position: number, tabSize: number, direction: Direction): number { + // Get the 0-based visible column corresponding to the position, or return + // -1 if it is not in the initial whitespace. + let visibleColumn = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize); + + if (visibleColumn === -1) { + return -1; + } + + // Is the output left or right of the current position. The case for nearest + // where it is the same as the current position is handled in the switch. + let left: boolean; + switch (direction) { + case Direction.Left: + left = true; + break; + case Direction.Right: + left = false; + break; + case Direction.Nearest: + // The code below assumes the output position is either left or right + // of the input position. If it is the same, return immediately. + if (visibleColumn % tabSize === 0) { + return position; + } + // Go to the nearest indentation. + left = visibleColumn % tabSize <= (tabSize / 2); + break; + } + + // The code below won't work if visibleColumn is zero and left is true because + // it takes the mod of a negative number, which behaves oddly. In that case + // we already know what to return. + if (left && visibleColumn === 0) { + return -1; + } + + const tmp = visibleColumn + (left ? -1 : tabSize); + const targetVisibleColumn = tmp - tmp % tabSize; + + // Find the target visible column. If going right we can just continue from + // where whitespaceVisibleColumn got to. If going left it's easiest to start + // from the beginning because the width of tab characters depend on the + // characters to their left. E.g. ' \t' is one tabSize, but so is '\t'. + if (left) { + visibleColumn = 0; + } + for (let i = (left ? 0 : position); i < lineContent.length; ++i) { + if (visibleColumn === targetVisibleColumn) { + // This is the position we want to get to, but we have one more case + // to handle if going left. + if (left) { + // If the direction is left, we need to keep scanning right to ensure + // that targetVisibleColumn + tabSize is before non-whitespace. + // This is so that when we press left at the end of a partial + // indentation it only goes one character. For example ' foo' with + // tabSize 4, should jump from position 6 to position 5, not 4. + for (let k = i; k < lineContent.length; ++k) { + if (visibleColumn === targetVisibleColumn + tabSize) { + // It is a full indentation. + return i; + } + + const chCode = lineContent.charCodeAt(k); + switch (chCode) { + case CharCode.Space: + visibleColumn += 1; + break; + case CharCode.Tab: + visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); + break; + default: + return -1; + } + } + if (visibleColumn === targetVisibleColumn + tabSize) { + return i; + } + // It must have been a partial indentation. + return -1; + } else { + // If going right then we must have been in a complete indentation. + return i; + } + } + + const chCode = lineContent.charCodeAt(i); + switch (chCode) { + case CharCode.Space: + visibleColumn += 1; + break; + case CharCode.Tab: + visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); + break; + default: + return -1; + } + } + // This condition handles when the target column is at the end of the line. + if (visibleColumn === targetVisibleColumn) { + return lineContent.length; + } + return -1; + } +} diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 92d36e239ad..2808c080ac2 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -62,6 +62,7 @@ export class CursorConfiguration { public readonly tabSize: number; public readonly indentSize: number; public readonly insertSpaces: boolean; + public readonly atomicSoftTabs: boolean; public readonly pageSize: number; public readonly lineHeight: number; public readonly useTabStops: boolean; @@ -114,6 +115,7 @@ export class CursorConfiguration { this.tabSize = modelOptions.tabSize; this.indentSize = modelOptions.indentSize; this.insertSpaces = modelOptions.insertSpaces; + this.atomicSoftTabs = modelOptions.atomicSoftTabs; this.lineHeight = options.get(EditorOption.lineHeight); this.pageSize = Math.max(1, Math.floor(layoutInfo.height / this.lineHeight) - 2); this.useTabStops = options.get(EditorOption.useTabStops); @@ -557,14 +559,14 @@ export class CursorColumns { } /** - * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns) + * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns) */ public static prevRenderTabStop(column: number, tabSize: number): number { return column - 1 - (column - 1) % tabSize; } /** - * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns) + * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns) */ public static prevIndentTabStop(column: number, indentSize: number): number { return column - 1 - (column - 1) % indentSize; diff --git a/src/vs/editor/common/controller/cursorMoveOperations.ts b/src/vs/editor/common/controller/cursorMoveOperations.ts index 20ca28947b2..84fe061d5a0 100644 --- a/src/vs/editor/common/controller/cursorMoveOperations.ts +++ b/src/vs/editor/common/controller/cursorMoveOperations.ts @@ -8,6 +8,8 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import * as strings from 'vs/base/common/strings'; import { Constants } from 'vs/base/common/uint'; +import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; + export class CursorPosition { _cursorPositionBrand: void; @@ -29,14 +31,34 @@ export class MoveOperations { if (column > model.getLineMinColumn(lineNumber)) { column = column - strings.prevCharLength(model.getLineContent(lineNumber), column - 1); } else if (lineNumber > 1) { - lineNumber = lineNumber - 1; + lineNumber -= 1; + column = model.getLineMaxColumn(lineNumber); + } + return new Position(lineNumber, column); + } + + public static leftPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position { + const minColumn = model.getLineMinColumn(lineNumber); + if (column > minColumn) { + const lineContent = model.getLineContent(lineNumber); + + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left); + if (newPosition !== -1) { + column = minColumn + newPosition; + } else { + column -= strings.prevCharLength(model.getLineContent(lineNumber), column - 1); + } + } else if (lineNumber > 1) { + lineNumber -= 1; column = model.getLineMaxColumn(lineNumber); } return new Position(lineNumber, column); } public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { - const pos = MoveOperations.leftPosition(model, lineNumber, column); + const pos = config.atomicSoftTabs + ? MoveOperations.leftPositionatomicSoftTabs(model, lineNumber, column, config.tabSize) + : MoveOperations.leftPosition(model, lineNumber, column); return new CursorPosition(pos.lineNumber, pos.column, 0); } @@ -61,14 +83,34 @@ export class MoveOperations { if (column < model.getLineMaxColumn(lineNumber)) { column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1); } else if (lineNumber < model.getLineCount()) { - lineNumber = lineNumber + 1; + lineNumber += 1; column = model.getLineMinColumn(lineNumber); } return new Position(lineNumber, column); } + public static rightPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position { + const minColumn = model.getLineMinColumn(lineNumber); + if (column < model.getLineMaxColumn(lineNumber)) { + const lineContent = model.getLineContent(lineNumber); + + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right); + if (newPosition !== -1) { + column = minColumn + newPosition; + } else { + column += strings.nextCharLength(model.getLineContent(lineNumber), column - 1); + } + } else if (lineNumber < model.getLineCount()) { + lineNumber += 1; + column = minColumn; + } + return new Position(lineNumber, column); + } + public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { - const pos = MoveOperations.rightPosition(model, lineNumber, column); + const pos = config.atomicSoftTabs + ? MoveOperations.rightPositionatomicSoftTabs(model, lineNumber, column, config.tabSize, config.indentSize) + : MoveOperations.rightPosition(model, lineNumber, column); return new CursorPosition(pos.lineNumber, pos.column, 0); } diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index fd5c9ccbb1c..baf57fc59b5 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -400,6 +400,7 @@ export class TextModelResolvedOptions { readonly tabSize: number; readonly indentSize: number; readonly insertSpaces: boolean; + readonly atomicSoftTabs: boolean; readonly defaultEOL: DefaultEndOfLine; readonly trimAutoWhitespace: boolean; @@ -410,12 +411,14 @@ export class TextModelResolvedOptions { tabSize: number; indentSize: number; insertSpaces: boolean; + atomicSoftTabs: boolean; defaultEOL: DefaultEndOfLine; trimAutoWhitespace: boolean; }) { this.tabSize = Math.max(1, src.tabSize | 0); this.indentSize = src.tabSize | 0; this.insertSpaces = Boolean(src.insertSpaces); + this.atomicSoftTabs = Boolean(src.atomicSoftTabs); this.defaultEOL = src.defaultEOL | 0; this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace); } @@ -428,6 +431,7 @@ export class TextModelResolvedOptions { this.tabSize === other.tabSize && this.indentSize === other.indentSize && this.insertSpaces === other.insertSpaces + && this.atomicSoftTabs === other.atomicSoftTabs && this.defaultEOL === other.defaultEOL && this.trimAutoWhitespace === other.trimAutoWhitespace ); @@ -441,6 +445,7 @@ export class TextModelResolvedOptions { tabSize: this.tabSize !== newOpts.tabSize, indentSize: this.indentSize !== newOpts.indentSize, insertSpaces: this.insertSpaces !== newOpts.insertSpaces, + atomicSoftTabs: this.atomicSoftTabs !== newOpts.atomicSoftTabs, trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace, }; } @@ -453,6 +458,7 @@ export interface ITextModelCreationOptions { tabSize: number; indentSize: number; insertSpaces: boolean; + atomicSoftTabs: boolean; detectIndentation: boolean; trimAutoWhitespace: boolean; defaultEOL: DefaultEndOfLine; @@ -464,6 +470,7 @@ export interface ITextModelUpdateOptions { tabSize?: number; indentSize?: number; insertSpaces?: boolean; + atomicSoftTabs?: boolean; trimAutoWhitespace?: boolean; } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 24f25a4e52b..ac2ca1c9401 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -197,6 +197,7 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: EDITOR_MODEL_DEFAULTS.tabSize, indentSize: EDITOR_MODEL_DEFAULTS.indentSize, insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces, + atomicSoftTabs: EDITOR_MODEL_DEFAULTS.atomicSoftTabs, detectIndentation: false, defaultEOL: model.DefaultEndOfLine.LF, trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace, @@ -210,6 +211,7 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: guessedIndentation.tabSize, indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize insertSpaces: guessedIndentation.insertSpaces, + atomicSoftTabs: options.atomicSoftTabs, trimAutoWhitespace: options.trimAutoWhitespace, defaultEOL: options.defaultEOL }); @@ -219,6 +221,7 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: options.tabSize, indentSize: options.indentSize, insertSpaces: options.insertSpaces, + atomicSoftTabs: options.atomicSoftTabs, trimAutoWhitespace: options.trimAutoWhitespace, defaultEOL: options.defaultEOL }); @@ -619,12 +622,14 @@ export class TextModel extends Disposable implements model.ITextModel { let tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize; let indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize; let insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces; + let atomicSoftTabs = (typeof _newOpts.atomicSoftTabs !== 'undefined') ? _newOpts.atomicSoftTabs : this._options.atomicSoftTabs; let trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace; let newOpts = new model.TextModelResolvedOptions({ tabSize: tabSize, indentSize: indentSize, insertSpaces: insertSpaces, + atomicSoftTabs: atomicSoftTabs, defaultEOL: this._options.defaultEOL, trimAutoWhitespace: trimAutoWhitespace }); diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index 6511d02173f..477c0b60433 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -104,6 +104,7 @@ export interface IModelOptionsChangedEvent { readonly tabSize: boolean; readonly indentSize: boolean; readonly insertSpaces: boolean; + readonly atomicSoftTabs: boolean; readonly trimAutoWhitespace: boolean; } diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 7836fa5de72..db6cf9500e4 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -100,6 +100,7 @@ interface IRawEditorConfig { tabSize?: any; indentSize?: any; insertSpaces?: any; + atomicSoftTabs?: any; detectIndentation?: any; trimAutoWhitespace?: any; creationOptions?: any; @@ -213,6 +214,11 @@ export class ModelServiceImpl extends Disposable implements IModelService { insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces)); } + let atomicSoftTabs = EDITOR_MODEL_DEFAULTS.atomicSoftTabs; + if (config.editor && typeof config.editor.atomicSoftTabs !== 'undefined') { + atomicSoftTabs = (config.editor.atomicSoftTabs === 'false' ? false : Boolean(config.editor.atomicSoftTabs)); + } + let newDefaultEOL = DEFAULT_EOL; const eol = config.eol; if (eol === '\r\n') { @@ -241,6 +247,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { tabSize: tabSize, indentSize: indentSize, insertSpaces: insertSpaces, + atomicSoftTabs: atomicSoftTabs, detectIndentation: detectIndentation, defaultEOL: newDefaultEOL, trimAutoWhitespace: trimAutoWhitespace, diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index e06bd35a8d0..859a1d664e4 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -93,6 +93,11 @@ export interface IGlobalEditorOptions { * Defaults to true. */ insertSpaces?: boolean; + /** + * Treat soft tabs like hard tabs. + * Defaults to false. + */ + atomicSoftTabs?: boolean; /** * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Defaults to true. diff --git a/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts b/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts new file mode 100644 index 00000000000..b037e530cf3 --- /dev/null +++ b/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts @@ -0,0 +1,128 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; + +suite('Cursor move command test', () => { + + test('Test whitespaceVisibleColumn', () => { + const testCases = [ + { + lineContent: ' ', + tabSize: 4, + expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, -1], + }, + { + lineContent: ' ', + tabSize: 4, + expected: [0, 1, 2, -1], + }, + { + lineContent: '\t', + tabSize: 4, + expected: [0, 4, -1], + }, + { + lineContent: '\t ', + tabSize: 4, + expected: [0, 4, 5, -1], + }, + { + lineContent: ' \t\t ', + tabSize: 4, + expected: [0, 1, 4, 8, 9, -1], + }, + { + lineContent: ' \tA', + tabSize: 4, + expected: [0, 1, 4, -1, -1], + }, + { + lineContent: 'A', + tabSize: 4, + expected: [0, -1, -1], + }, + { + lineContent: '', + tabSize: 4, + expected: [0, -1], + }, + ]; + + for (const testCase of testCases) { + const actual = testCase.expected.map((_, i) => AtomicTabMoveOperations.whitespaceVisibleColumn(testCase.lineContent, i, testCase.tabSize)); + assert.deepStrictEqual(actual, testCase.expected); + } + }); + + test('Test atomicPosition', () => { + const testCases = [ + { + lineContent: ' ', + tabSize: 4, + expectedLeft: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1], + expectedRight: [4, 4, 4, 4, 8, 8, 8, 8, -1, -1], + expectedNearest: [0, 0, 0, 4, 4, 4, 4, 8, 8, -1], + }, + { + lineContent: ' \t', + tabSize: 4, + expectedLeft: [-1, 0, 0, -1], + expectedRight: [2, 2, -1, -1], + expectedNearest: [0, 0, 2, -1], + }, + { + lineContent: '\t ', + tabSize: 4, + expectedLeft: [-1, 0, -1, -1], + expectedRight: [1, -1, -1, -1], + expectedNearest: [0, 1, -1, -1], + }, + { + lineContent: ' \t ', + tabSize: 4, + expectedLeft: [-1, 0, 0, -1, -1], + expectedRight: [2, 2, -1, -1, -1], + expectedNearest: [0, 0, 2, -1, -1], + }, + { + lineContent: ' A', + tabSize: 4, + expectedLeft: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1, -1], + expectedRight: [4, 4, 4, 4, 8, 8, 8, 8, -1, -1, -1], + expectedNearest: [0, 0, 0, 4, 4, 4, 4, 8, 8, -1, -1], + }, + { + lineContent: ' foo', + tabSize: 4, + expectedLeft: [-1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1], + expectedRight: [4, 4, 4, 4, -1, -1, -1, -1, -1, -1, -1], + expectedNearest: [0, 0, 0, 4, 4, -1, -1, -1, -1, -1, -1], + }, + ]; + + for (const testCase of testCases) { + for (const { direction, expected } of [ + { + direction: Direction.Left, + expected: testCase.expectedLeft, + }, + { + direction: Direction.Right, + expected: testCase.expectedRight, + }, + { + direction: Direction.Nearest, + expected: testCase.expectedNearest, + }, + ]) { + + const actual = expected.map((_, i) => AtomicTabMoveOperations.atomicPosition(testCase.lineContent, i, testCase.tabSize, direction)); + assert.deepStrictEqual(actual, expected); + } + } + }); +}); diff --git a/src/vs/editor/test/common/editorTestUtils.ts b/src/vs/editor/test/common/editorTestUtils.ts index 8298cf24b81..b3adbf3320f 100644 --- a/src/vs/editor/test/common/editorTestUtils.ts +++ b/src/vs/editor/test/common/editorTestUtils.ts @@ -21,6 +21,7 @@ export interface IRelaxedTextModelCreationOptions { tabSize?: number; indentSize?: number; insertSpaces?: boolean; + atomicSoftTabs?: boolean; detectIndentation?: boolean; trimAutoWhitespace?: boolean; defaultEOL?: DefaultEndOfLine; @@ -33,6 +34,7 @@ export function createTextModel(text: string, _options: IRelaxedTextModelCreatio tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize), indentSize: (typeof _options.indentSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.indentSize : _options.indentSize), insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces), + atomicSoftTabs: (typeof _options.atomicSoftTabs === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.atomicSoftTabs : _options.atomicSoftTabs), detectIndentation: (typeof _options.detectIndentation === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.detectIndentation : _options.detectIndentation), trimAutoWhitespace: (typeof _options.trimAutoWhitespace === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.trimAutoWhitespace : _options.trimAutoWhitespace), defaultEOL: (typeof _options.defaultEOL === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL : _options.defaultEOL), diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index a44cb3bb307..58adea72466 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1095,6 +1095,11 @@ declare namespace monaco.editor { * Defaults to true. */ insertSpaces?: boolean; + /** + * Treat soft tabs like hard tabs. + * Defaults to false. + */ + atomicSoftTabs?: boolean; /** * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Defaults to true. @@ -1575,6 +1580,7 @@ declare namespace monaco.editor { readonly tabSize: number; readonly indentSize: number; readonly insertSpaces: boolean; + readonly atomicSoftTabs: boolean; readonly defaultEOL: DefaultEndOfLine; readonly trimAutoWhitespace: boolean; } @@ -1583,6 +1589,7 @@ declare namespace monaco.editor { tabSize?: number; indentSize?: number; insertSpaces?: boolean; + atomicSoftTabs?: boolean; trimAutoWhitespace?: boolean; } @@ -2452,6 +2459,7 @@ declare namespace monaco.editor { readonly tabSize: boolean; readonly indentSize: boolean; readonly insertSpaces: boolean; + readonly atomicSoftTabs: boolean; readonly trimAutoWhitespace: boolean; } diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index f20e79170fe..51a9095e793 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -655,6 +655,12 @@ declare module 'vscode' { */ insertSpaces?: boolean | string; + /** + * When navigating treat soft tabs like hard tabs. This means you can't position + * the cursor in the middle of an indentation, even if it is made of space. + */ + atomicSoftTabs?: boolean; + /** * The rendering style of the cursor in this editor. * When getting a text editor's options, this property will always be present. diff --git a/src/vs/workbench/api/browser/mainThreadEditor.ts b/src/vs/workbench/api/browser/mainThreadEditor.ts index f805b7f9cbe..dfd926d2113 100644 --- a/src/vs/workbench/api/browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/browser/mainThreadEditor.ts @@ -80,6 +80,7 @@ export class MainThreadTextEditorProperties { insertSpaces: modelOptions.insertSpaces, tabSize: modelOptions.tabSize, indentSize: modelOptions.indentSize, + atomicSoftTabs: modelOptions.atomicSoftTabs, cursorStyle: cursorStyle, lineNumbers: lineNumbers }; @@ -148,6 +149,7 @@ export class MainThreadTextEditorProperties { a.tabSize === b.tabSize && a.indentSize === b.indentSize && a.insertSpaces === b.insertSpaces + && a.atomicSoftTabs === b.atomicSoftTabs && a.cursorStyle === b.cursorStyle && a.lineNumbers === b.lineNumbers ); @@ -374,6 +376,9 @@ export class MainThreadTextEditor { if (typeof newConfiguration.insertSpaces !== 'undefined') { newOpts.insertSpaces = newConfiguration.insertSpaces; } + if (typeof newConfiguration.atomicSoftTabs !== 'undefined') { + newOpts.atomicSoftTabs = newConfiguration.atomicSoftTabs; + } if (typeof newConfiguration.tabSize !== 'undefined') { newOpts.tabSize = newConfiguration.tabSize; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b7ad89e366b..b93f9a16abe 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -233,6 +233,7 @@ export interface ITextEditorConfigurationUpdate { tabSize?: number | 'auto'; indentSize?: number | 'tabSize'; insertSpaces?: boolean | 'auto'; + atomicSoftTabs?: boolean; cursorStyle?: TextEditorCursorStyle; lineNumbers?: RenderLineNumbersType; } @@ -241,6 +242,7 @@ export interface IResolvedTextEditorConfiguration { tabSize: number; indentSize: number; insertSpaces: boolean; + atomicSoftTabs: boolean; cursorStyle: TextEditorCursorStyle; lineNumbers: RenderLineNumbersType; } diff --git a/src/vs/workbench/api/common/extHostTextEditor.ts b/src/vs/workbench/api/common/extHostTextEditor.ts index 635a5c6c253..fe713225d9c 100644 --- a/src/vs/workbench/api/common/extHostTextEditor.ts +++ b/src/vs/workbench/api/common/extHostTextEditor.ts @@ -143,6 +143,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { private _tabSize!: number; private _indentSize!: number; private _insertSpaces!: boolean; + private _atomicSoftTabs!: boolean; private _cursorStyle!: TextEditorCursorStyle; private _lineNumbers!: TextEditorLineNumbersStyle; @@ -157,6 +158,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { this._tabSize = source.tabSize; this._indentSize = source.indentSize; this._insertSpaces = source.insertSpaces; + this._atomicSoftTabs = source.atomicSoftTabs; this._cursorStyle = source.cursorStyle; this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers); } @@ -269,6 +271,23 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { })); } + public get atomicSoftTabs(): boolean { + return this._atomicSoftTabs; + } + + public set atomicSoftTabs(value: boolean) { + const atomicSoftTabs = value; + if (this._atomicSoftTabs === atomicSoftTabs) { + // nothing to do + return; + } + // reflect the new atomicSoftTabs value immediately + this._atomicSoftTabs = atomicSoftTabs; + this._warnOnError(this._proxy.$trySetOptions(this._id, { + atomicSoftTabs + })); + } + public get cursorStyle(): TextEditorCursorStyle { return this._cursorStyle; } @@ -659,4 +678,3 @@ export class ExtHostTextEditor implements vscode.TextEditor { }); } } - diff --git a/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts b/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts index 931313c55e9..97a1164075d 100644 --- a/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts @@ -20,7 +20,7 @@ suite('ExtHostTextEditor', () => { ], '\n', 1, 'text', false); setup(() => { - editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); + editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); }); test('disposed editor', () => { @@ -47,7 +47,7 @@ suite('ExtHostTextEditor', () => { applyCount += 1; return Promise.resolve(true); } - }, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); + }, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); await editor.edit(edit => { }); assert.equal(applyCount, 0); @@ -91,6 +91,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }, new NullLogService()); @@ -106,6 +107,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: opts.tabSize, indentSize: opts.indentSize, insertSpaces: opts.insertSpaces, + atomicSoftTabs: opts.atomicSoftTabs, cursorStyle: opts.cursorStyle, lineNumbers: opts.lineNumbers }; @@ -118,6 +120,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -130,6 +133,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 1, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -142,6 +146,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 2, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -154,6 +159,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 2, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -166,6 +172,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -178,6 +185,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -190,6 +198,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -202,6 +211,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -214,6 +224,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -226,6 +237,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -238,6 +250,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 1, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -250,6 +263,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 2, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -262,6 +276,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 2, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -274,6 +289,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -286,6 +302,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -298,6 +315,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -310,6 +328,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -322,6 +341,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -334,6 +354,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -346,6 +367,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -358,6 +380,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -370,6 +393,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -382,6 +406,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -394,6 +419,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -406,6 +432,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -418,6 +445,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Block, lineNumbers: RenderLineNumbersType.On }); @@ -430,6 +458,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -442,6 +471,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.Off }); @@ -452,6 +482,7 @@ suite('ExtHostTextEditorOptions', () => { opts.assign({ tabSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: TextEditorLineNumbersStyle.On }); @@ -459,6 +490,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -474,6 +506,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -489,6 +522,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 3, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -504,6 +538,7 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, + atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Block, lineNumbers: RenderLineNumbersType.Relative }); From 3ca4059ea5918bf5683db748992f943441d98209 Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Sat, 26 Sep 2020 11:41:26 +0100 Subject: [PATCH 0007/1837] Move mouse handling to a lower level to handle more cases --- .../editor/browser/controller/mouseTarget.ts | 42 ++++++++++------ src/vs/editor/browser/view/viewController.ts | 50 +++++++------------ 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index f2be04e3a39..0113748775f 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -18,6 +18,7 @@ import { ViewContext } from 'vs/editor/common/view/viewContext'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { CursorColumns } from 'vs/editor/common/controller/cursorCommon'; import * as dom from 'vs/base/browser/dom'; +import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; export interface IViewZoneData { viewZoneId: string; @@ -998,6 +999,19 @@ export class MouseTargetFactory { }; } + private static _snapToSoftTabBoundary(position: Position, viewModel: IViewModel): Position { + if (viewModel.getTextModelOptions().atomicSoftTabs) { + const minColumn = viewModel.getLineMinColumn(position.lineNumber); + const lineContent = viewModel.getLineContent(position.lineNumber); + const { tabSize } = viewModel.getTextModelOptions(); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); + if (newPosition !== -1) { + return new Position(position.lineNumber, newPosition + minColumn); + } + } + return position; + } + private static _doHitTest(ctx: HitTestContext, request: BareHitTestRequest): IHitTestResult { // State of the art (18.10.2012): // The spec says browsers should support document.caretPositionFromPoint, but nobody implemented it (http://dev.w3.org/csswg/cssom-view/) @@ -1016,24 +1030,24 @@ export class MouseTargetFactory { // Thank you browsers for making this so 'easy' :) + let result: IHitTestResult; if (typeof document.caretRangeFromPoint === 'function') { - - return this._doHitTestWithCaretRangeFromPoint(ctx, request); - + result = this._doHitTestWithCaretRangeFromPoint(ctx, request); } else if ((document).caretPositionFromPoint) { - - return this._doHitTestWithCaretPositionFromPoint(ctx, request.pos.toClientCoordinates()); - + result = this._doHitTestWithCaretPositionFromPoint(ctx, request.pos.toClientCoordinates()); } else if ((document.body).createTextRange) { - - return this._doHitTestWithMoveToPoint(ctx, request.pos.toClientCoordinates()); - + result = this._doHitTestWithMoveToPoint(ctx, request.pos.toClientCoordinates()); + } else { + return { + position: null, + hitTarget: null + }; } - - return { - position: null, - hitTarget: null - }; + // Snap to the nearest soft tab boundary if atomic soft tabs are enabled. + if (result.position !== null && ctx.model.getTextModelOptions().atomicSoftTabs) { + result.position = this._snapToSoftTabBoundary(result.position, ctx.model); + } + return result; } } diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 13c0079560d..519a26bb5f8 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -14,7 +14,6 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import * as platform from 'vs/base/common/platform'; -import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; export interface IMouseDispatchData { position: Position; @@ -129,35 +128,24 @@ export class ViewController { } public dispatchMouse(data: IMouseDispatchData): void { - let position = data.position; - if (this.viewModel.getTextModelOptions().atomicSoftTabs) { - const minColumn = this.viewModel.getLineMinColumn(position.lineNumber); - const lineContent = this.viewModel.getLineContent(position.lineNumber); - const { tabSize } = this.viewModel.getTextModelOptions(); - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); - if (newPosition !== -1) { - position = new Position(position.lineNumber, newPosition + minColumn); - } - } - const options = this.configuration.options; const selectionClipboardIsOn = (platform.isLinux && options.get(EditorOption.selectionClipboard)); const columnSelection = options.get(EditorOption.columnSelection); if (data.middleButton && !selectionClipboardIsOn) { - this._columnSelect(position, data.mouseColumn, data.inSelectionMode); + this._columnSelect(data.position, data.mouseColumn, data.inSelectionMode); } else if (data.startedOnLineNumbers) { // If the dragging started on the gutter, then have operations work on the entire line if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelect(position); + this._lastCursorLineSelect(data.position); } else { - this._createCursor(position, true); + this._createCursor(data.position, true); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(position); + this._lineSelectDrag(data.position); } else { - this._lineSelect(position); + this._lineSelect(data.position); } } } else if (data.mouseDownCount >= 4) { @@ -165,54 +153,54 @@ export class ViewController { } else if (data.mouseDownCount === 3) { if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelectDrag(position); + this._lastCursorLineSelectDrag(data.position); } else { - this._lastCursorLineSelect(position); + this._lastCursorLineSelect(data.position); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(position); + this._lineSelectDrag(data.position); } else { - this._lineSelect(position); + this._lineSelect(data.position); } } } else if (data.mouseDownCount === 2) { if (this._hasMulticursorModifier(data)) { - this._lastCursorWordSelect(position); + this._lastCursorWordSelect(data.position); } else { if (data.inSelectionMode) { - this._wordSelectDrag(position); + this._wordSelectDrag(data.position); } else { - this._wordSelect(position); + this._wordSelect(data.position); } } } else { if (this._hasMulticursorModifier(data)) { if (!this._hasNonMulticursorModifier(data)) { if (data.shiftKey) { - this._columnSelect(position, data.mouseColumn, true); + this._columnSelect(data.position, data.mouseColumn, true); } else { // Do multi-cursor operations only when purely alt is pressed if (data.inSelectionMode) { - this._lastCursorMoveToSelect(position); + this._lastCursorMoveToSelect(data.position); } else { - this._createCursor(position, false); + this._createCursor(data.position, false); } } } } else { if (data.inSelectionMode) { if (data.altKey) { - this._columnSelect(position, data.mouseColumn, true); + this._columnSelect(data.position, data.mouseColumn, true); } else { if (columnSelection) { - this._columnSelect(position, data.mouseColumn, true); + this._columnSelect(data.position, data.mouseColumn, true); } else { - this._moveToSelect(position); + this._moveToSelect(data.position); } } } else { - this.moveTo(position); + this.moveTo(data.position); } } } From d000256957175e64c993d630a0c72665a66ef141 Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Sat, 26 Sep 2020 12:32:33 +0100 Subject: [PATCH 0008/1837] Add atomicSoftTabs in one place that I missed --- src/vs/editor/common/services/modelServiceImpl.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index db6cf9500e4..a4c297d58cc 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -310,6 +310,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { if (currentOptions && (currentOptions.detectIndentation === newOptions.detectIndentation) && (currentOptions.insertSpaces === newOptions.insertSpaces) + && (currentOptions.atomicSoftTabs === newOptions.atomicSoftTabs) && (currentOptions.tabSize === newOptions.tabSize) && (currentOptions.indentSize === newOptions.indentSize) && (currentOptions.trimAutoWhitespace === newOptions.trimAutoWhitespace) @@ -321,11 +322,13 @@ export class ModelServiceImpl extends Disposable implements IModelService { if (newOptions.detectIndentation) { model.detectIndentation(newOptions.insertSpaces, newOptions.tabSize); model.updateOptions({ + atomicSoftTabs: newOptions.atomicSoftTabs, trimAutoWhitespace: newOptions.trimAutoWhitespace }); } else { model.updateOptions({ insertSpaces: newOptions.insertSpaces, + atomicSoftTabs: newOptions.atomicSoftTabs, tabSize: newOptions.tabSize, indentSize: newOptions.indentSize, trimAutoWhitespace: newOptions.trimAutoWhitespace From d3a3f39dbf1640c4033be34ebd7b186d3f0cf5bf Mon Sep 17 00:00:00 2001 From: xndcn Date: Sat, 10 Oct 2020 20:16:08 +0800 Subject: [PATCH 0009/1837] Fix overlay area for minimap slider Since minimap always render from a complete line, we have to recalculate sliderTop with align offset. --- src/vs/editor/browser/viewParts/minimap/minimap.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 1be53aad7a3..6001fb4f7c2 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -226,8 +226,7 @@ class MinimapLayout { * Compute a desired `scrollPosition` such that the slider moves by `delta`. */ public getDesiredScrollTopFromDelta(delta: number): number { - const desiredSliderPosition = this.sliderTop + delta; - return Math.round(desiredSliderPosition / this._computedSliderRatio); + return Math.round(this.scrollTop + delta / this._computedSliderRatio); } public getDesiredScrollTopFromTouchLocation(pageY: number): number { @@ -332,8 +331,9 @@ class MinimapLayout { } const endLineNumber = Math.min(lineCount, startLineNumber + minimapLinesFitting - 1); + const sliderTopAligned = (scrollTop / lineHeight - startLineNumber + 1) * minimapLineHeight / pixelRatio; - return new MinimapLayout(scrollTop, scrollHeight, true, computedSliderRatio, sliderTop, sliderHeight, startLineNumber, endLineNumber); + return new MinimapLayout(scrollTop, scrollHeight, true, computedSliderRatio, sliderTopAligned, sliderHeight, startLineNumber, endLineNumber); } } } From c9b479c4a14d65cb7be8bfd8a5df80d6624a0d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 16 Oct 2020 10:38:06 +0200 Subject: [PATCH 0010/1837] use terrapin --- build/azure-pipelines/darwin/product-build-darwin.yml | 4 ++++ build/azure-pipelines/linux/product-build-linux-multiarch.yml | 4 ++++ build/azure-pipelines/linux/product-build-linux.yml | 4 ++++ build/azure-pipelines/product-compile.yml | 4 ++++ build/azure-pipelines/web/product-build-web.yml | 4 ++++ build/azure-pipelines/win32/product-build-win32-arm64.yml | 4 ++++ build/azure-pipelines/win32/product-build-win32.yml | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 0500f84accc..7366b36b536 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -53,6 +53,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' diff --git a/build/azure-pipelines/linux/product-build-linux-multiarch.yml b/build/azure-pipelines/linux/product-build-linux-multiarch.yml index 258f87ea3d2..1a016458693 100644 --- a/build/azure-pipelines/linux/product-build-linux-multiarch.yml +++ b/build/azure-pipelines/linux/product-build-linux-multiarch.yml @@ -62,6 +62,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 270beb898a0..8d2c4c66c3d 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -52,6 +52,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - script: | echo -n $VSCODE_ARCH > .build/arch displayName: Prepare arch cache flag diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 2eff40b53d1..90712f222cd 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -52,6 +52,10 @@ steps: displayName: Merge distro condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - script: | echo -n $VSCODE_ARCH > .build/arch displayName: Prepare arch cache flag diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index aded67174f4..4203d760f51 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -52,6 +52,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + # - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 # inputs: # keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index 2e53167e613..ffce9961040 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -58,6 +58,10 @@ steps: exec { git merge $(node -p "require('./package.json').distro") } displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 43bd2479a4e..581c55de5b2 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -58,6 +58,10 @@ steps: exec { git merge $(node -p "require('./package.json').distro") } displayName: Merge distro +- script: | + npx https://aka.ms/enablesecurefeed + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' From a0012e5f6343e6292188490e4f377cfc97ccb1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 2 Nov 2020 16:50:33 +0100 Subject: [PATCH 0011/1837] fix terrapin step --- build/azure-pipelines/product-compile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 90712f222cd..ac1c3ffee2a 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -55,6 +55,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed displayName: Switch to Terrapin packages + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | echo -n $VSCODE_ARCH > .build/arch From 3b796c6212962d70b3989488af7c7f2495349011 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 10 Nov 2020 14:18:45 -0800 Subject: [PATCH 0012/1837] allow init dimension for the diff editor and left/right side editors. --- src/vs/editor/browser/editorBrowser.ts | 5 ++++ .../editor/browser/widget/diffEditorWidget.ts | 22 ++++++++++++++---- src/vs/monaco.d.ts | 4 ++++ .../notebook/browser/diff/cellComponents.ts | 23 +++++++++++++++---- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 13552a60ec0..324ac64ab01 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -361,6 +361,11 @@ export interface IEditorConstructionOptions extends IEditorOptions { } export interface IDiffEditorConstructionOptions extends IDiffEditorOptions { + /** + * The initial editor dimension (to avoid measuring the container). + */ + dimension?: editorCommon.IDimension; + /** * Place overflow widgets inside an external DOM node. * Defaults to an internal DOM node. diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index e77d846a845..466355e7df1 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -20,7 +20,7 @@ import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffReview } from 'vs/editor/browser/widget/diffReview'; -import { IDiffEditorOptions, IEditorOptions, EditorLayoutInfo, EditorOption, EditorOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; +import { IDiffEditorOptions, EditorLayoutInfo, EditorOption, EditorOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; @@ -348,7 +348,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._isVisible = true; this._isHandlingScrollEvent = false; - this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, undefined, () => this._onDidContainerSizeChanged())); + this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, options.dimension, () => this._onDidContainerSizeChanged())); if (options.automaticLayout) { this._elementSizeObserver.startObserving(); } @@ -610,7 +610,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE return editor; } - protected _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: IEditorOptions): CodeEditorWidget { + protected _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: editorBrowser.IEditorConstructionOptions): CodeEditorWidget { return instantiationService.createInstance(CodeEditorWidget, container, options, {}); } @@ -1146,7 +1146,13 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE } result.readOnly = !isEditable; result.extraEditorClassName = 'original-in-monaco-diff-editor'; - return result; + return { + ...result, + dimension: { + height: 0, + width: 0 + } + }; } private _adjustOptionsForRightHandSide(options: editorBrowser.IDiffEditorConstructionOptions, isCodeLensEnabled: boolean): editorBrowser.IEditorConstructionOptions { @@ -1157,7 +1163,13 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE result.revealHorizontalRightPadding = EditorOptions.revealHorizontalRightPadding.defaultValue + DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH; result.scrollbar!.verticalHasArrows = false; result.extraEditorClassName = 'modified-in-monaco-diff-editor'; - return result; + return { + ...result, + dimension: { + height: 0, + width: 0 + } + }; } public doLayout(): void { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index a5a2fa1c36e..c9ef33d85ec 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -4463,6 +4463,10 @@ declare namespace monaco.editor { } export interface IDiffEditorConstructionOptions extends IDiffEditorOptions { + /** + * The initial editor dimension (to avoid measuring the container). + */ + dimension?: IDimension; /** * Place overflow widgets inside an external DOM node. * Defaults to an internal DOM node. diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 3af3a0c7832..c4719f5e63f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -63,7 +63,7 @@ const fixedDiffEditorOptions: IDiffEditorOptions = { enableSplitViewResizing: false, renderIndicators: false, readOnly: false, - isInEmbeddedEditor: true + isInEmbeddedEditor: true, }; @@ -527,7 +527,12 @@ abstract class AbstractCellRenderer extends Disposable { overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), readOnly: false, originalEditable: false, - ignoreTrimWhitespace: false + ignoreTrimWhitespace: false, + automaticLayout: false, + dimension: { + height: 0, + width: 0 + } }); this._metadataEditorContainer?.classList.add('diff'); @@ -631,7 +636,12 @@ abstract class AbstractCellRenderer extends Disposable { ...fixedDiffEditorOptions, overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), readOnly: true, - ignoreTrimWhitespace: false + ignoreTrimWhitespace: false, + automaticLayout: false, + dimension: { + height: 0, + width: 0 + } }); this._outputEditorContainer?.classList.add('diff'); @@ -945,7 +955,12 @@ export class ModifiedCell extends AbstractCellRenderer { ...fixedDiffEditorOptions, overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), originalEditable: false, - ignoreTrimWhitespace: false + ignoreTrimWhitespace: false, + automaticLayout: false, + dimension: { + height: 0, + width: 0 + } }); this._editorContainer.classList.add('diff'); From 8836c8bfeee46034baa7782a90fdb0178e2ee16b Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 10 Nov 2020 16:53:39 -0800 Subject: [PATCH 0013/1837] reuse source code editor --- .../notebooks/grooming-delta.github-issues | 11 +- .../notebook/browser/diff/cellComponents.ts | 440 +++++++++++------- .../contrib/notebook/browser/diff/common.ts | 29 +- .../browser/diff/notebookTextDiffEditor.ts | 11 +- .../browser/diff/notebookTextDiffList.ts | 219 ++++++++- 5 files changed, 519 insertions(+), 191 deletions(-) diff --git a/.vscode/notebooks/grooming-delta.github-issues b/.vscode/notebooks/grooming-delta.github-issues index 8bc9d38b48c..790ba1a28c7 100644 --- a/.vscode/notebooks/grooming-delta.github-issues +++ b/.vscode/notebooks/grooming-delta.github-issues @@ -20,7 +20,7 @@ { "kind": 2, "language": "github-issues", - "value": "//repo:microsoft/vscode is:issue closed:>$since", + "value": "repo:microsoft/vscode is:issue closed:>$since", "editable": true }, { @@ -176,17 +176,20 @@ { "kind": 1, "language": "markdown", - "value": "# vscode-pull-request-github" + "value": "# vscode-pull-request-github", + "editable": true }, { "kind": 2, "language": "github-issues", - "value": "repo:microsoft/vscode-pull-request-github is:issue closed:>$since" + "value": "repo:microsoft/vscode-pull-request-github is:issue closed:>$since", + "editable": true }, { "kind": 2, "language": "github-issues", - "value": "repo:microsoft/vscode-test is:issue created:>$since" + "value": "repo:microsoft/vscode-test is:issue created:>$since", + "editable": true }, { "kind": 1, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index c4719f5e63f..2ce1a320a9e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -8,7 +8,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffViewModel, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; -import { CellDiffRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -233,7 +233,7 @@ abstract class AbstractCellRenderer extends Disposable { constructor( readonly notebookEditor: INotebookTextDiffEditor, readonly cell: CellDiffViewModel, - readonly templateData: CellDiffRenderTemplate, + readonly templateData: CellDiffSingleSideRenderTemplate | CellDiffSideBySideRenderTemplate, readonly style: 'left' | 'right' | 'full', protected readonly instantiationService: IInstantiationService, protected readonly modeService: IModeService, @@ -260,112 +260,11 @@ abstract class AbstractCellRenderer extends Disposable { this._metadataEditorDisposeStore = new DisposableStore(); this._outputEditorDisposeStore = new DisposableStore(); this._register(this._metadataEditorDisposeStore); - this.initData(); - this.buildBody(templateData.container); + this.buildBody(); this._register(cell.onDidLayoutChange(e => this.onDidLayoutChange(e))); } - buildBody(container: HTMLElement) { - const body = DOM.$('.cell-body'); - DOM.append(container, body); - this._diffEditorContainer = DOM.$('.cell-diff-editor-container'); - switch (this.style) { - case 'left': - body.classList.add('left'); - break; - case 'right': - body.classList.add('right'); - break; - default: - body.classList.add('full'); - break; - } - - DOM.append(body, this._diffEditorContainer); - this._diagonalFill = DOM.append(body, DOM.$('.diagonal-fill')); - this.styleContainer(this._diffEditorContainer); - const sourceContainer = DOM.append(this._diffEditorContainer, DOM.$('.source-container')); - this.buildSourceEditor(sourceContainer); - - this._metadataHeaderContainer = DOM.append(this._diffEditorContainer, DOM.$('.metadata-header-container')); - this._metadataInfoContainer = DOM.append(this._diffEditorContainer, DOM.$('.metadata-info-container')); - - const checkIfModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && hash(this._getFormatedMetadataJSON(cell.original?.metadata || {}, cell.original?.language)) !== hash(this._getFormatedMetadataJSON(cell.modified?.metadata ?? {}, cell.modified?.language)); - }; - - if (checkIfModified(this.cell)) { - this.cell.metadataFoldingState = PropertyFoldingState.Expanded; - } - - this._metadataHeader = this.instantiationService.createInstance( - PropertyHeader, - this.cell, - this._metadataHeaderContainer, - this.notebookEditor, - { - updateInfoRendering: this.updateMetadataRendering.bind(this), - checkIfModified: (cell) => { - return checkIfModified(cell); - }, - getFoldingState: (cell) => { - return cell.metadataFoldingState; - }, - updateFoldingState: (cell, state) => { - cell.metadataFoldingState = state; - }, - unChangedLabel: 'Metadata', - changedLabel: 'Metadata changed', - prefix: 'metadata', - menuId: MenuId.NotebookDiffCellMetadataTitle - } - ); - this._register(this._metadataHeader); - this._metadataHeader.buildHeader(); - - if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { - this._layoutInfo.outputHeight = 0; - this._layoutInfo.outputStatusHeight = 0; - this.layout({}); - return; - } - - this._outputHeaderContainer = DOM.append(this._diffEditorContainer, DOM.$('.output-header-container')); - this._outputInfoContainer = DOM.append(this._diffEditorContainer, DOM.$('.output-info-container')); - - const checkIfOutputsModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); - }; - - if (checkIfOutputsModified(this.cell)) { - this.cell.outputFoldingState = PropertyFoldingState.Expanded; - } - - this._outputHeader = this.instantiationService.createInstance( - PropertyHeader, - this.cell, - this._outputHeaderContainer, - this.notebookEditor, - { - updateInfoRendering: this.updateOutputRendering.bind(this), - checkIfModified: (cell) => { - return checkIfOutputsModified(cell); - }, - getFoldingState: (cell) => { - return cell.outputFoldingState; - }, - updateFoldingState: (cell, state) => { - cell.outputFoldingState = state; - }, - unChangedLabel: 'Outputs', - changedLabel: 'Outputs changed', - prefix: 'output', - menuId: MenuId.NotebookDiffCellOutputsTitle - } - ); - this._register(this._outputHeader); - this._outputHeader.buildHeader(); - } + abstract buildBody(): void; updateMetadataRendering() { if (this.cell.metadataFoldingState === PropertyFoldingState.Expanded) { @@ -717,19 +616,158 @@ abstract class AbstractCellRenderer extends Disposable { ); } - abstract initData(): void; abstract styleContainer(container: HTMLElement): void; - abstract buildSourceEditor(sourceContainer: HTMLElement): void; + abstract updateSourceEditor(): void; abstract onDidLayoutChange(event: CellDiffViewModelLayoutChangeEvent): void; abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }): void; } -export class DeletedCell extends AbstractCellRenderer { +abstract class SingleSideCell extends AbstractCellRenderer { + constructor( + readonly notebookEditor: INotebookTextDiffEditor, + readonly cell: CellDiffViewModel, + readonly templateData: CellDiffSingleSideRenderTemplate, + readonly style: 'left' | 'right' | 'full', + protected readonly instantiationService: IInstantiationService, + protected readonly modeService: IModeService, + protected readonly modelService: IModelService, + protected readonly contextMenuService: IContextMenuService, + protected readonly keybindingService: IKeybindingService, + protected readonly notificationService: INotificationService, + protected readonly menuService: IMenuService, + protected readonly contextKeyService: IContextKeyService + + + ) { + super( + notebookEditor, + cell, + templateData, + style, + instantiationService, + modeService, + modelService, + contextMenuService, + keybindingService, + notificationService, + menuService, + contextKeyService + ); + } + + buildBody() { + const body = this.templateData.body; + this._diffEditorContainer = this.templateData.diffEditorContainer; + switch (this.style) { + case 'left': + body.classList.add('left'); + break; + case 'right': + body.classList.add('right'); + break; + default: + body.classList.add('full'); + break; + } + + this._diagonalFill = this.templateData.diagonalFill; + this.styleContainer(this._diffEditorContainer); + this.updateSourceEditor(); + + this._metadataHeaderContainer = this.templateData.metadataHeaderContainer; + this._metadataInfoContainer = this.templateData.metadataInfoContainer; + this._metadataHeaderContainer.innerText = ''; + this._metadataInfoContainer.innerText = ''; + + const checkIfModified = (cell: CellDiffViewModel) => { + return cell.type !== 'delete' && cell.type !== 'insert' && hash(this._getFormatedMetadataJSON(cell.original?.metadata || {}, cell.original?.language)) !== hash(this._getFormatedMetadataJSON(cell.modified?.metadata ?? {}, cell.modified?.language)); + }; + + if (checkIfModified(this.cell)) { + this.cell.metadataFoldingState = PropertyFoldingState.Expanded; + } + + this._metadataHeader = this.instantiationService.createInstance( + PropertyHeader, + this.cell, + this._metadataHeaderContainer, + this.notebookEditor, + { + updateInfoRendering: this.updateMetadataRendering.bind(this), + checkIfModified: (cell) => { + return checkIfModified(cell); + }, + getFoldingState: (cell) => { + return cell.metadataFoldingState; + }, + updateFoldingState: (cell, state) => { + cell.metadataFoldingState = state; + }, + unChangedLabel: 'Metadata', + changedLabel: 'Metadata changed', + prefix: 'metadata', + menuId: MenuId.NotebookDiffCellMetadataTitle + } + ); + this._register(this._metadataHeader); + this._metadataHeader.buildHeader(); + + if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { + this._layoutInfo.outputHeight = 0; + this._layoutInfo.outputStatusHeight = 0; + this.layout({}); + this.templateData.outputHeaderContainer.style.display = 'none'; + this.templateData.outputInfoContainer.style.display = 'none'; + return; + } + + this._outputHeaderContainer = this.templateData.outputHeaderContainer; + this._outputInfoContainer = this.templateData.outputInfoContainer; + + this._outputHeaderContainer.innerText = ''; + this._outputInfoContainer.innerText = ''; + + const checkIfOutputsModified = (cell: CellDiffViewModel) => { + return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); + }; + + if (checkIfOutputsModified(this.cell)) { + this.cell.outputFoldingState = PropertyFoldingState.Expanded; + } + + this._outputHeader = this.instantiationService.createInstance( + PropertyHeader, + this.cell, + this._outputHeaderContainer, + this.notebookEditor, + { + updateInfoRendering: this.updateOutputRendering.bind(this), + checkIfModified: (cell) => { + return checkIfOutputsModified(cell); + }, + getFoldingState: (cell) => { + return cell.outputFoldingState; + }, + updateFoldingState: (cell, state) => { + cell.outputFoldingState = state; + }, + unChangedLabel: 'Outputs', + changedLabel: 'Outputs changed', + prefix: 'output', + menuId: MenuId.NotebookDiffCellOutputsTitle + } + ); + this._register(this._outputHeader); + this._outputHeader.buildHeader(); + } + +} +export class DeletedCell extends SingleSideCell { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, readonly cell: CellDiffViewModel, - readonly templateData: CellDiffRenderTemplate, + readonly templateData: CellDiffSingleSideRenderTemplate, @IModeService readonly modeService: IModeService, @IModelService readonly modelService: IModelService, @IInstantiationService protected readonly instantiationService: IInstantiationService, @@ -744,29 +782,22 @@ export class DeletedCell extends AbstractCellRenderer { super(notebookEditor, cell, templateData, 'left', instantiationService, modeService, modelService, contextMenuService, keybindingService, notificationService, menuService, contextKeyService); } - initData(): void { - } - styleContainer(container: HTMLElement) { container.classList.add('removed'); } - buildSourceEditor(sourceContainer: HTMLElement): void { + updateSourceEditor(): void { const originalCell = this.cell.original!; const lineCount = originalCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; - const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); + this._editor = this.templateData.sourceEditor; + this._editor.layout({ + width: (this.notebookEditor.getLayoutInfo().width - 2 * DIFF_CELL_MARGIN) / 2 - 18, + height: editorHeight + }); - this._editor = this.instantiationService.createInstance(CodeEditorWidget, editorContainer, { - ...fixedEditorOptions, - dimension: { - width: (this.notebookEditor.getLayoutInfo().width - 2 * DIFF_CELL_MARGIN) / 2 - 18, - height: editorHeight - }, - overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode() - }, {}); this._layoutInfo.editorHeight = editorHeight; this._register(this._editor.onDidContentSizeChange((e) => { @@ -820,12 +851,12 @@ export class DeletedCell extends AbstractCellRenderer { } } -export class InsertCell extends AbstractCellRenderer { +export class InsertCell extends SingleSideCell { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, readonly cell: CellDiffViewModel, - readonly templateData: CellDiffRenderTemplate, + readonly templateData: CellDiffSingleSideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, @IModelService readonly modelService: IModelService, @@ -838,29 +869,24 @@ export class InsertCell extends AbstractCellRenderer { super(notebookEditor, cell, templateData, 'right', instantiationService, modeService, modelService, contextMenuService, keybindingService, notificationService, menuService, contextKeyService); } - initData(): void { - } - styleContainer(container: HTMLElement): void { container.classList.add('inserted'); } - buildSourceEditor(sourceContainer: HTMLElement): void { + updateSourceEditor(): void { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; - const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); - this._editor = this.instantiationService.createInstance(CodeEditorWidget, editorContainer, { - ...fixedEditorOptions, - dimension: { + this._editor = this.templateData.sourceEditor; + this._editor.layout( + { width: (this.notebookEditor.getLayoutInfo().width - 2 * DIFF_CELL_MARGIN) / 2 - 18, height: editorHeight - }, - overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), - readOnly: false - }, {}); + } + ); + this._editor.updateOptions({ readOnly: false }); this._layoutInfo.editorHeight = editorHeight; @@ -925,7 +951,7 @@ export class ModifiedCell extends AbstractCellRenderer { constructor( readonly notebookEditor: INotebookTextDiffEditor, readonly cell: CellDiffViewModel, - readonly templateData: CellDiffRenderTemplate, + readonly templateData: CellDiffSideBySideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, @IModelService readonly modelService: IModelService, @@ -938,30 +964,122 @@ export class ModifiedCell extends AbstractCellRenderer { super(notebookEditor, cell, templateData, 'full', instantiationService, modeService, modelService, contextMenuService, keybindingService, notificationService, menuService, contextKeyService); } - initData(): void { - } - styleContainer(container: HTMLElement): void { } - buildSourceEditor(sourceContainer: HTMLElement): void { + buildBody() { + const body = this.templateData.body; + this._diffEditorContainer = this.templateData.diffEditorContainer; + switch (this.style) { + case 'left': + body.classList.add('left'); + break; + case 'right': + body.classList.add('right'); + break; + default: + body.classList.add('full'); + break; + } + + this.styleContainer(this._diffEditorContainer); + this.updateSourceEditor(); + + this._metadataHeaderContainer = this.templateData.metadataHeaderContainer; + this._metadataInfoContainer = this.templateData.metadataInfoContainer; + + this._metadataHeaderContainer.innerText = ''; + this._metadataInfoContainer.innerText = ''; + + const checkIfModified = (cell: CellDiffViewModel) => { + return cell.type !== 'delete' && cell.type !== 'insert' && hash(this._getFormatedMetadataJSON(cell.original?.metadata || {}, cell.original?.language)) !== hash(this._getFormatedMetadataJSON(cell.modified?.metadata ?? {}, cell.modified?.language)); + }; + + if (checkIfModified(this.cell)) { + this.cell.metadataFoldingState = PropertyFoldingState.Expanded; + } + + this._metadataHeader = this.instantiationService.createInstance( + PropertyHeader, + this.cell, + this._metadataHeaderContainer, + this.notebookEditor, + { + updateInfoRendering: this.updateMetadataRendering.bind(this), + checkIfModified: (cell) => { + return checkIfModified(cell); + }, + getFoldingState: (cell) => { + return cell.metadataFoldingState; + }, + updateFoldingState: (cell, state) => { + cell.metadataFoldingState = state; + }, + unChangedLabel: 'Metadata', + changedLabel: 'Metadata changed', + prefix: 'metadata', + menuId: MenuId.NotebookDiffCellMetadataTitle + } + ); + this._register(this._metadataHeader); + this._metadataHeader.buildHeader(); + + if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { + this._layoutInfo.outputHeight = 0; + this._layoutInfo.outputStatusHeight = 0; + this.layout({}); + this.templateData.outputHeaderContainer.style.display = 'none'; + this.templateData.outputInfoContainer.style.display = 'none'; + return; + } + + this._outputHeaderContainer = this.templateData.outputHeaderContainer; + this._outputInfoContainer = this.templateData.outputInfoContainer; + this._outputHeaderContainer.innerText = ''; + this._outputInfoContainer.innerText = ''; + + const checkIfOutputsModified = (cell: CellDiffViewModel) => { + return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); + }; + + if (checkIfOutputsModified(this.cell)) { + this.cell.outputFoldingState = PropertyFoldingState.Expanded; + } + + this._outputHeader = this.instantiationService.createInstance( + PropertyHeader, + this.cell, + this._outputHeaderContainer, + this.notebookEditor, + { + updateInfoRendering: this.updateOutputRendering.bind(this), + checkIfModified: (cell) => { + return checkIfOutputsModified(cell); + }, + getFoldingState: (cell) => { + return cell.outputFoldingState; + }, + updateFoldingState: (cell, state) => { + cell.outputFoldingState = state; + }, + unChangedLabel: 'Outputs', + changedLabel: 'Outputs changed', + prefix: 'output', + menuId: MenuId.NotebookDiffCellOutputsTitle + } + ); + this._register(this._outputHeader); + this._outputHeader.buildHeader(); + } + + + updateSourceEditor(): void { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; - this._editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); - - this._editor = this.instantiationService.createInstance(DiffEditorWidget, this._editorContainer, { - ...fixedDiffEditorOptions, - overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), - originalEditable: false, - ignoreTrimWhitespace: false, - automaticLayout: false, - dimension: { - height: 0, - width: 0 - } - }); + this._editorContainer = this.templateData.editorContainer; + this._editor = this.templateData.sourceEditor; this._editorContainer.classList.add('diff'); this._editor.layout({ @@ -980,18 +1098,8 @@ export class ModifiedCell extends AbstractCellRenderer { this._initializeSourceDiffEditor(); - this._inputToolbarContainer = DOM.append(sourceContainer, DOM.$('.editor-input-toolbar-container')); - const cellToolbarContainer = DOM.append(this._inputToolbarContainer, DOM.$('div.property-toolbar')); - this._toolbar = new ToolBar(cellToolbarContainer, this.contextMenuService, { - actionViewItemProvider: action => { - if (action instanceof MenuItemAction) { - const item = new CodiconActionViewItem(action, this.keybindingService, this.notificationService); - return item; - } - - return undefined; - } - }); + this._inputToolbarContainer = this.templateData.inputToolbarContainer; + this._toolbar = this.templateData.toolbar; this._toolbar.context = { cell: this.cell diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 505718cea7c..8fa33af9dbe 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -9,6 +9,9 @@ import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; +import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -18,9 +21,33 @@ export interface INotebookTextDiffEditor { layoutNotebookCell(cell: CellDiffViewModel, height: number): void; } -export interface CellDiffRenderTemplate { +export interface CellDiffSingleSideRenderTemplate { readonly container: HTMLElement; + readonly body: HTMLElement; + readonly diffEditorContainer: HTMLElement; + readonly diagonalFill: HTMLElement; readonly elementDisposables: DisposableStore; + readonly sourceEditor: CodeEditorWidget; + readonly metadataHeaderContainer: HTMLElement; + readonly metadataInfoContainer: HTMLElement; + readonly outputHeaderContainer: HTMLElement; + readonly outputInfoContainer: HTMLElement; +} + + +export interface CellDiffSideBySideRenderTemplate { + readonly container: HTMLElement; + readonly body: HTMLElement; + readonly diffEditorContainer: HTMLElement; + readonly elementDisposables: DisposableStore; + readonly sourceEditor: DiffEditorWidget; + readonly editorContainer: HTMLElement; + readonly inputToolbarContainer: HTMLElement; + readonly toolbar: ToolBar; + readonly metadataHeaderContainer: HTMLElement; + readonly metadataInfoContainer: HTMLElement; + readonly outputHeaderContainer: HTMLElement; + readonly outputInfoContainer: HTMLElement; } export interface CellDiffViewModelLayoutChangeEvent { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 6c6c52dc91c..b8b529dcdf2 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -16,7 +16,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellDiffRenderer, NotebookCellTextDiffListDelegate, NotebookTextDiffList } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList'; +import { CellDiffSideBySideRenderer, CellDiffSingleSideRenderer, NotebookCellTextDiffListDelegate, NotebookTextDiffList } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { diffDiagonalFill, diffInserted, diffRemoved, editorBackground, focusBorder, foreground } from 'vs/platform/theme/common/colorRegistry'; import { INotebookEditorWorkerService } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerService'; @@ -84,16 +84,17 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._overflowContainer.classList.add('notebook-overflow-widget-container', 'monaco-editor'); DOM.append(parent, this._overflowContainer); - const renderer = this.instantiationService.createInstance(CellDiffRenderer, this); + const renderers = [ + this.instantiationService.createInstance(CellDiffSingleSideRenderer, this), + this.instantiationService.createInstance(CellDiffSideBySideRenderer, this), + ]; this._list = this.instantiationService.createInstance( NotebookTextDiffList, 'NotebookTextDiff', this._rootElement, this.instantiationService.createInstance(NotebookCellTextDiffListDelegate), - [ - renderer - ], + renderers, this.contextKeyService, { setRowLineHeight: false, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index 6e664d46aa3..93c2597bfb4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -15,9 +15,54 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/list/browser/listService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; -import { CellDiffRenderTemplate, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { isMacintosh } from 'vs/base/common/platform'; import { DeletedCell, InsertCell, ModifiedCell } from 'vs/workbench/contrib/notebook/browser/diff/cellComponents'; +import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; +import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; +import { IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions'; +import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { INotificationService } from 'vs/platform/notification/common/notification'; + +const fixedEditorOptions: IEditorOptions = { + padding: { + top: 12, + bottom: 12 + }, + scrollBeyondLastLine: false, + scrollbar: { + verticalScrollbarSize: 14, + horizontal: 'auto', + useShadows: true, + verticalHasArrows: false, + horizontalHasArrows: false, + alwaysConsumeMouseWheel: false + }, + renderLineHighlightOnlyWhenFocus: true, + overviewRulerLanes: 0, + selectOnLineNumbers: false, + wordWrap: 'off', + lineNumbers: 'off', + lineDecorationsWidth: 0, + glyphMargin: false, + fixedOverflowWidgets: true, + minimap: { enabled: false }, + renderValidationDecorations: 'on', + renderLineHighlight: 'none', + readOnly: true +}; + +const fixedDiffEditorOptions: IDiffEditorOptions = { + ...fixedEditorOptions, + glyphMargin: true, + enableSplitViewResizing: false, + renderIndicators: false, + readOnly: false, + isInEmbeddedEditor: true, +}; export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { // private readonly lineHeight: number; @@ -38,11 +83,19 @@ export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { - static readonly TEMPLATE_ID = 'cell_diff'; +export class CellDiffSingleSideRenderer implements IListRenderer { + static readonly TEMPLATE_ID = 'cell_diff_single'; constructor( readonly notebookEditor: INotebookTextDiffEditor, @@ -50,28 +103,165 @@ export class CellDiffRenderer implements IListRenderer { + static readonly TEMPLATE_ID = 'cell_diff_side_by_side'; + + constructor( + readonly notebookEditor: INotebookTextDiffEditor, + @IInstantiationService protected readonly instantiationService: IInstantiationService, + @IContextMenuService protected readonly contextMenuService: IContextMenuService, + @IKeybindingService protected readonly keybindingService: IKeybindingService, + @IMenuService protected readonly menuService: IMenuService, + @IContextKeyService protected readonly contextKeyService: IContextKeyService, + @INotificationService protected readonly notificationService: INotificationService, + ) { } + + get templateId() { + return CellDiffSideBySideRenderer.TEMPLATE_ID; + } + + renderTemplate(container: HTMLElement): CellDiffSideBySideRenderTemplate { + const body = DOM.$('.cell-body'); + DOM.append(container, body); + const diffEditorContainer = DOM.$('.cell-diff-editor-container'); + DOM.append(body, diffEditorContainer); + + const sourceContainer = DOM.append(diffEditorContainer, DOM.$('.source-container')); + const { editor, editorContainer } = this._buildSourceEditor(sourceContainer); + + const inputToolbarContainer = DOM.append(sourceContainer, DOM.$('.editor-input-toolbar-container')); + const cellToolbarContainer = DOM.append(inputToolbarContainer, DOM.$('div.property-toolbar')); + const toolbar = new ToolBar(cellToolbarContainer, this.contextMenuService, { + actionViewItemProvider: action => { + if (action instanceof MenuItemAction) { + const item = new CodiconActionViewItem(action, this.keybindingService, this.notificationService); + return item; + } + + return undefined; + } + }); + + const metadataHeaderContainer = DOM.append(diffEditorContainer, DOM.$('.metadata-header-container')); + const metadataInfoContainer = DOM.append(diffEditorContainer, DOM.$('.metadata-info-container')); + + const outputHeaderContainer = DOM.append(diffEditorContainer, DOM.$('.output-header-container')); + const outputInfoContainer = DOM.append(diffEditorContainer, DOM.$('.output-info-container')); + + return { + body, + container, + diffEditorContainer, + sourceEditor: editor, + editorContainer, + inputToolbarContainer, + toolbar, + metadataHeaderContainer, + metadataInfoContainer, + outputHeaderContainer, + outputInfoContainer, + elementDisposables: new DisposableStore() + }; + } + + private _buildSourceEditor(sourceContainer: HTMLElement) { + const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); + + const editor = this.instantiationService.createInstance(DiffEditorWidget, editorContainer, { + ...fixedDiffEditorOptions, + overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), + originalEditable: false, + ignoreTrimWhitespace: false, + automaticLayout: false, + dimension: { + height: 0, + width: 0 + } + }); + + return { + editor, + editorContainer + }; + } + + renderElement(element: CellDiffViewModel, index: number, templateData: CellDiffSideBySideRenderTemplate, height: number | undefined): void { + switch (element.type) { + case 'unchanged': + templateData.elementDisposables.add(this.instantiationService.createInstance(ModifiedCell, this.notebookEditor, element, templateData)); + return; case 'modified': templateData.elementDisposables.add(this.instantiationService.createInstance(ModifiedCell, this.notebookEditor, element, templateData)); return; @@ -80,16 +270,15 @@ export class CellDiffRenderer implements IListRenderer implements IDisposable, IStyleController { private styleElement?: HTMLStyleElement; @@ -97,7 +286,7 @@ export class NotebookTextDiffList extends WorkbenchList imple listUser: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: IListRenderer[], + renderers: IListRenderer[], contextKeyService: IContextKeyService, options: IWorkbenchListOptions, @IListService listService: IListService, From cc9616baf887188ec75f7f785935848e7f2c6530 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Nov 2020 08:46:41 +0000 Subject: [PATCH 0014/1837] use 'enablement' instead of 'preconditions' --- extensions/git/package.json | 10 +++++----- .../contrib/welcome/common/viewsWelcomeContribution.ts | 4 +++- .../welcome/common/viewsWelcomeExtensionPoint.ts | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 5b16c29b4b2..3b65b234c89 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2084,35 +2084,35 @@ "view": "scm", "contents": "%view.workbench.scm.empty%", "when": "config.git.enabled && workbenchState == empty", - "preconditions": ["git.state == initialized"], + "enablement": "git.state == initialized", "group": "2_open@1" }, { "view": "scm", "contents": "%view.workbench.scm.folder%", "when": "config.git.enabled && workbenchState == folder", - "preconditions": ["git.state == initialized"], + "enablement": "git.state == initialized", "group": "5_scm@1" }, { "view": "scm", "contents": "%view.workbench.scm.workspace%", "when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0", - "preconditions": ["git.state == initialized"], + "enablement": "git.state == initialized", "group": "5_scm@1" }, { "view": "scm", "contents": "%view.workbench.scm.emptyWorkspace%", "when": "config.git.enabled && workbenchState == workspace && workspaceFolderCount == 0", - "preconditions": ["git.state == initialized"], + "enablement": "git.state == initialized", "group": "2_open@1" }, { "view": "explorer", "contents": "%view.workbench.cloneRepository%", "when": "config.git.enabled", - "preconditions": ["git.state == initialized"], + "enablement": "git.state == initialized", "group": "5_scm@1" } ] diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index 8dc246670d3..0863bedb546 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -36,10 +36,12 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo for (const welcome of contribution.value) { const id = ViewIdentifierMap[welcome.view] ?? welcome.view; const { group, order } = parseGroupAndOrder(welcome, contribution); + const enablement = ContextKeyExpr.deserialize(welcome.enablement); const disposable = viewsRegistry.registerViewWelcomeContent(id, { content: welcome.contents, when: ContextKeyExpr.deserialize(welcome.when), - preconditions: welcome.preconditions?.map((value) => ContextKeyExpr.deserialize(value)), + // supply the enablement clause for each line in case the line defines a button + preconditions: welcome.contents.split('\n').map((_) => enablement), group, order }); diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts index 9c43fd59738..a08b7324da3 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts @@ -11,7 +11,7 @@ export enum ViewsWelcomeExtensionPointFields { contents = 'contents', when = 'when', group = 'group', - preconditions = 'preconditions', + enablement = 'enablement', } export interface ViewWelcome { @@ -19,7 +19,7 @@ export interface ViewWelcome { readonly [ViewsWelcomeExtensionPointFields.contents]: string; readonly [ViewsWelcomeExtensionPointFields.when]: string; readonly [ViewsWelcomeExtensionPointFields.group]: string; - readonly [ViewsWelcomeExtensionPointFields.preconditions]: string[]; + readonly [ViewsWelcomeExtensionPointFields.enablement]: string; } export type ViewsWelcomeExtensionPoint = ViewWelcome[]; @@ -66,9 +66,9 @@ const viewsWelcomeExtensionPointSchema = Object.freeze Date: Wed, 18 Nov 2020 16:08:01 +0800 Subject: [PATCH 0015/1837] Support greater than and less than --- .../platform/contextkey/common/contextkey.ts | 154 +++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 01bef2897ce..15802baa72b 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -32,6 +32,8 @@ export const enum ContextKeyExprType { Or = 9, In = 10, NotIn = 11, + Greater = 12, + Less = 13, } export interface IContextKeyExprMapper { @@ -57,7 +59,7 @@ export interface IContextKeyExpression { export type ContextKeyExpression = ( ContextKeyFalseExpr | ContextKeyTrueExpr | ContextKeyDefinedExpr | ContextKeyNotExpr | ContextKeyEqualsExpr | ContextKeyNotEqualsExpr | ContextKeyRegexExpr - | ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr | ContextKeyNotInExpr + | ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr | ContextKeyNotInExpr | ContextKeyGreaterExpr | ContextKeyLessExpr ); export abstract class ContextKeyExpr { @@ -102,6 +104,14 @@ export abstract class ContextKeyExpr { return ContextKeyOrExpr.create(expr); } + public static greater(key: string, value: any): ContextKeyExpression { + return ContextKeyGreaterExpr.create(key, value); + } + + public static less(key: string, value: any): ContextKeyExpression { + return ContextKeyLessExpr.create(key, value); + } + public static deserialize(serialized: string | null | undefined, strict: boolean = false): ContextKeyExpression | undefined { if (!serialized) { return undefined; @@ -143,6 +153,16 @@ export abstract class ContextKeyExpr { return ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim()); } + if (serializedOne.indexOf('>') >= 0) { + let pieces = serializedOne.split('>'); + return ContextKeyGreaterExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict)); + } + + if (serializedOne.indexOf('<') >= 0) { + let pieces = serializedOne.split('<'); + return ContextKeyLessExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict)); + } + if (/^\!\s*/.test(serializedOne)) { return ContextKeyNotExpr.create(serializedOne.substr(1).trim()); } @@ -650,6 +670,138 @@ export class ContextKeyNotExpr implements IContextKeyExpression { } } +export class ContextKeyGreaterExpr implements IContextKeyExpression { + + public static create(key: string, value: any): ContextKeyExpression { + if (typeof value === 'boolean') { + return (value ? ContextKeyDefinedExpr.create(key) : ContextKeyNotExpr.create(key)); + } + const staticValue = STATIC_VALUES.get(key); + if (typeof staticValue === 'boolean') { + const trueValue = staticValue ? 'true' : 'false'; + return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE); + } + return new ContextKeyGreaterExpr(key, value); + } + + public readonly type = ContextKeyExprType.Greater; + + private constructor(private readonly key: string, private readonly value: any) { + } + + public cmp(other: ContextKeyExpression): number { + if (other.type !== this.type) { + return this.type - other.type; + } + if (this.key < other.key) { + return -1; + } + if (this.key > other.key) { + return 1; + } + if (this.value < other.value) { + return -1; + } + if (this.value > other.value) { + return 1; + } + return 0; + } + + public equals(other: ContextKeyExpression): boolean { + if (other.type === this.type) { + return (this.key === other.key && this.value === other.value); + } + return false; + } + + public evaluate(context: IContext): boolean { + return (Number(context.getValue(this.key)) > this.value); + } + + public serialize(): string { + return `${this.key} > '${this.value}'`; + } + + public keys(): string[] { + return [this.key]; + } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { + return mapFnc.mapEquals(this.key, this.value); + } + + public negate(): ContextKeyExpression { + return ContextKeyNotEqualsExpr.create(this.key, this.value); + } +} + +export class ContextKeyLessExpr implements IContextKeyExpression { + + public static create(key: string, value: any): ContextKeyExpression { + if (typeof value === 'boolean') { + return (value ? ContextKeyDefinedExpr.create(key) : ContextKeyNotExpr.create(key)); + } + const staticValue = STATIC_VALUES.get(key); + if (typeof staticValue === 'boolean') { + const trueValue = staticValue ? 'true' : 'false'; + return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE); + } + return new ContextKeyLessExpr(key, value); + } + + public readonly type = ContextKeyExprType.Less; + + private constructor(private readonly key: string, private readonly value: any) { + } + + public cmp(other: ContextKeyExpression): number { + if (other.type !== this.type) { + return this.type - other.type; + } + if (this.key < other.key) { + return -1; + } + if (this.key > other.key) { + return 1; + } + if (this.value < other.value) { + return -1; + } + if (this.value > other.value) { + return 1; + } + return 0; + } + + public equals(other: ContextKeyExpression): boolean { + if (other.type === this.type) { + return (this.key === other.key && this.value === other.value); + } + return false; + } + + public evaluate(context: IContext): boolean { + return (Number(context.getValue(this.key)) < this.value); + } + + public serialize(): string { + return `${this.key} < '${this.value}'`; + } + + public keys(): string[] { + return [this.key]; + } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { + return mapFnc.mapEquals(this.key, this.value); + } + + public negate(): ContextKeyExpression { + return ContextKeyNotEqualsExpr.create(this.key, this.value); + } +} + export class ContextKeyRegexExpr implements IContextKeyExpression { public static create(key: string, regexp: RegExp | null): ContextKeyRegexExpr { From edf43e529a3a25133c7d59600d99ff6d0b59d2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 18 Nov 2020 10:04:55 +0100 Subject: [PATCH 0016/1837] build snap packages for linux arm --- .../linux/product-build-linux.yml | 370 +++++++++--------- build/azure-pipelines/linux/publish.sh | 14 +- .../linux/snap-build-linux.yml | 80 ++-- build/azure-pipelines/product-build.yml | 310 ++++++++------- build/gulpfile.vscode.linux.js | 1 + resources/linux/snap/snapcraft.yaml | 4 + 6 files changed, 400 insertions(+), 379 deletions(-) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 031a491648a..db92e8313b0 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,217 +1,215 @@ steps: -- script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - displayName: Prepare cache flag + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- script: | - set -e - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.14.1" + - task: NodeTool@0 + inputs: + versionSpec: "12.14.1" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling -- script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro -- script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag + - script: | + echo -n $VSCODE_ARCH > .build/arch + displayName: Prepare arch cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" -- script: | - set -e - CHILD_CONCURRENCY=1 npm_config_arch=$(NPM_ARCH) yarn --frozen-lockfile - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + set -e + CHILD_CONCURRENCY=1 npm_config_arch=$(NPM_ARCH) yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-linux-$(VSCODE_ARCH)-min-ci - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci - displayName: Build + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-linux-$(VSCODE_ARCH)-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci + displayName: Build -- script: | - set -e - service xvfb start - displayName: Start xvfb - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + service xvfb start + displayName: Start xvfb + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" - displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" + displayName: Run unit tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - DISPLAY=:10 yarn test-browser --build --browser chromium --tfs "Browser Unit Tests" - displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + DISPLAY=:10 yarn test-browser --build --browser chromium --tfs "Browser Unit Tests" + displayName: Run unit tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - # Figure out the full absolute path of the product we just built - # including the remote server and configure the integration tests - # to run with these builds instead of running out of sources. - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" - displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + # Figure out the full absolute path of the product we just built + # including the remote server and configure the integration tests + # to run with these builds instead of running out of sources. + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" + displayName: Run integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium - displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium + displayName: Run integration tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./resources/server/test/test-remote-integration.sh - displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-remote-integration.sh + displayName: Run remote integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: 'crash-dump-linux-$(VSCODE_ARCH)' - targetPath: .build/crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: "crash-dump-linux-$(VSCODE_ARCH)" + targetPath: .build/crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: and(succeededOrFailed(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: and(succeededOrFailed(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-deb" - yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm" - displayName: Build deb, rpm packages + - script: | + set -e + yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-deb" + yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm" + displayName: Build deb, rpm packages -- script: | - set -e - yarn gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap" - displayName: Prepare snap package - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - script: | + set -e + yarn gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap" + displayName: Prepare snap package -# needed for code signing -- task: UseDotNet@2 - displayName: 'Install .NET Core SDK 2.x' - inputs: - version: 2.x + # needed for code signing + - task: UseDotNet@2 + displayName: "Install .NET Core SDK 2.x" + inputs: + version: 2.x -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '.build/linux/rpm' - Pattern: '*.rpm' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-450779-Pgp", - "operationSetCode": "LinuxSign", - "parameters": [ ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 120 - displayName: Codesign rpm + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: ".build/linux/rpm" + Pattern: "*.rpm" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-450779-Pgp", + "operationSetCode": "LinuxSign", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 120 + displayName: Codesign rpm -- script: | - set -e - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - VSCODE_ARCH="$(VSCODE_ARCH)" \ - ./build/azure-pipelines/linux/publish.sh - displayName: Publish + - script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + VSCODE_ARCH="$(VSCODE_ARCH)" \ + ./build/azure-pipelines/linux/publish.sh + displayName: Publish -- task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline Artifact' - inputs: - artifactName: 'snap-$(VSCODE_ARCH)' - targetPath: .build/linux/snap-tarball - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - task: PublishPipelineArtifact@0 + displayName: "Publish Pipeline Artifact" + inputs: + artifactName: "snap-$(VSCODE_ARCH)" + targetPath: .build/linux/snap-tarball -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: "Component Detection" + continueOnError: true diff --git a/build/azure-pipelines/linux/publish.sh b/build/azure-pipelines/linux/publish.sh index 72fe2ad7b30..e0f1ade30d3 100755 --- a/build/azure-pipelines/linux/publish.sh +++ b/build/azure-pipelines/linux/publish.sh @@ -52,11 +52,9 @@ RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME" node build/azure-pipelines/common/createAsset.js "$PLATFORM_RPM" package "$RPM_FILENAME" "$RPM_PATH" -if [ "$VSCODE_ARCH" == "x64" ]; then - # Publish Snap - # Pack snap tarball artifact, in order to preserve file perms - mkdir -p $REPO/.build/linux/snap-tarball - SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz" - rm -rf $SNAP_TARBALL_PATH - (cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap) -fi +# Publish Snap +# Pack snap tarball artifact, in order to preserve file perms +mkdir -p $REPO/.build/linux/snap-tarball +SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz" +rm -rf $SNAP_TARBALL_PATH +(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap) diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 39c39e86c9e..1bf016914c3 100644 --- a/build/azure-pipelines/linux/snap-build-linux.yml +++ b/build/azure-pipelines/linux/snap-build-linux.yml @@ -1,52 +1,52 @@ steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.14.1" + - task: NodeTool@0 + inputs: + versionSpec: "12.14.1" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact' - inputs: - artifactName: snap-x64 - targetPath: .build/linux/snap-tarball + - task: DownloadPipelineArtifact@0 + displayName: "Download Pipeline Artifact" + inputs: + artifactName: snap-$(VSCODE_ARCH) + targetPath: .build/linux/snap-tarball -- script: | - set -e + - script: | + set -e - # Get snapcraft version - snapcraft --version + # Get snapcraft version + snapcraft --version - # Make sure we get latest packages - sudo apt-get update - sudo apt-get upgrade -y + # Make sure we get latest packages + sudo apt-get update + sudo apt-get upgrade -y - # Define variables - REPO="$(pwd)" - SNAP_ROOT="$REPO/.build/linux/snap/x64" + # Define variables + REPO="$(pwd)" + SNAP_ROOT="$REPO/.build/linux/snap/$(VSCODE_ARCH)" - # Install build dependencies - (cd build && yarn) + # Install build dependencies + (cd build && yarn) - # Unpack snap tarball artifact, in order to preserve file perms - SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz" - (cd .build/linux && tar -xzf $SNAP_TARBALL_PATH) + # Unpack snap tarball artifact, in order to preserve file perms + SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz" + (cd .build/linux && tar -xzf $SNAP_TARBALL_PATH) - # Create snap package - BUILD_VERSION="$(date +%s)" - SNAP_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.snap" - SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME" - (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --output "$SNAP_PATH") + # Create snap package + BUILD_VERSION="$(date +%s)" + SNAP_FILENAME="code-$VSCODE_QUALITY-$(VSCODE_ARCH)-$BUILD_VERSION.snap" + SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME" + (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --output "$SNAP_PATH") - # Publish snap package - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - node build/azure-pipelines/common/createAsset.js "linux-snap-x64" package "$SNAP_FILENAME" "$SNAP_PATH" + # Publish snap package + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + node build/azure-pipelines/common/createAsset.js "linux-snap-$(VSCODE_ARCH)" package "$SNAP_FILENAME" "$SNAP_PATH" diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 1c45de07f3e..ddbe8e29aed 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -2,162 +2,182 @@ trigger: none pr: none schedules: -- cron: "0 5 * * Mon-Fri" - displayName: Mon-Fri at 7:00 - branches: - include: - - master + - cron: "0 5 * * Mon-Fri" + displayName: Mon-Fri at 7:00 + branches: + include: + - master resources: containers: - - container: vscode-x64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:x64 - endpoint: VSCodeHub - - container: vscode-arm64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 - endpoint: VSCodeHub - - container: vscode-armhf - image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-armhf - endpoint: VSCodeHub - - container: snapcraft - image: snapcore/snapcraft:stable + - container: vscode-x64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:x64 + endpoint: VSCodeHub + - container: vscode-arm64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 + endpoint: VSCodeHub + - container: vscode-armhf + image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-armhf + endpoint: VSCodeHub + - container: snapcraft + image: snapcore/snapcraft:stable stages: -- stage: Compile - jobs: - - job: Compile - pool: - vmImage: 'Ubuntu-16.04' - container: vscode-x64 - steps: - - template: product-compile.yml + - stage: Compile + jobs: + - job: Compile + pool: + vmImage: "Ubuntu-16.04" + container: vscode-x64 + steps: + - template: product-compile.yml -- stage: Windows - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: VS2017-Win2016 - jobs: - - job: Windows - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: x64 - steps: - - template: win32/product-build-win32.yml - - - job: Windows32 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: ia32 - steps: - - template: win32/product-build-win32.yml - - - job: WindowsARM64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: arm64 - steps: - - template: win32/product-build-win32-arm64.yml - -- stage: Linux - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: 'Ubuntu-16.04' - jobs: - - job: Linux - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) - container: vscode-x64 - variables: - VSCODE_ARCH: x64 - NPM_ARCH: x64 - steps: - - template: linux/product-build-linux.yml - - - job: LinuxSnap + - stage: Windows dependsOn: - - Linux - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) - container: snapcraft - variables: - VSCODE_ARCH: x64 - steps: - - template: linux/snap-build-linux.yml + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: VS2017-Win2016 + jobs: + - job: Windows + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: x64 + steps: + - template: win32/product-build-win32.yml - - job: LinuxArmhf - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) - container: vscode-armhf - variables: - VSCODE_ARCH: armhf - NPM_ARCH: armv7l - steps: - - template: linux/product-build-linux.yml + - job: Windows32 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: ia32 + steps: + - template: win32/product-build-win32.yml - - job: LinuxArm64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) - container: vscode-arm64 - variables: - VSCODE_ARCH: arm64 - NPM_ARCH: arm64 - steps: - - template: linux/product-build-linux.yml + - job: WindowsARM64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: arm64 + steps: + - template: win32/product-build-win32-arm64.yml - - job: LinuxAlpine - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true')) - steps: - - template: linux/product-build-alpine.yml + - stage: Linux + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: "Ubuntu-16.04" + jobs: + - job: Linux + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) + container: vscode-x64 + variables: + VSCODE_ARCH: x64 + NPM_ARCH: x64 + steps: + - template: linux/product-build-linux.yml - - job: LinuxWeb - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true')) - variables: - VSCODE_ARCH: x64 - steps: - - template: web/product-build-web.yml + - job: LinuxSnap + dependsOn: + - Linux + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) + container: snapcraft + variables: + VSCODE_ARCH: x64 + steps: + - template: linux/snap-build-linux.yml -- stage: macOS - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: macOS-latest - jobs: - - job: macOS - condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: x64 - steps: - - template: darwin/product-build-darwin.yml + - job: LinuxArmhf + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) + container: vscode-armhf + variables: + VSCODE_ARCH: armhf + NPM_ARCH: armv7l + steps: + - template: linux/product-build-linux.yml -- stage: Mooncake - dependsOn: - - Windows - - Linux - - macOS - condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: 'Ubuntu-16.04' - jobs: - - job: SyncMooncake - displayName: Sync Mooncake - steps: - - template: sync-mooncake.yml + - job: LinuxSnapArmhf + dependsOn: + - LinuxArmhf + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) + container: snapcraft + variables: + VSCODE_ARCH: armhf + steps: + - template: linux/snap-build-linux.yml -- stage: Publish - dependsOn: - - Windows - - Linux - - macOS - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) - pool: - vmImage: 'Ubuntu-16.04' - jobs: - - job: BuildService - displayName: Build Service - steps: - - template: release.yml + - job: LinuxArm64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) + container: vscode-arm64 + variables: + VSCODE_ARCH: arm64 + NPM_ARCH: arm64 + steps: + - template: linux/product-build-linux.yml + + - job: LinuxSnapArm64 + dependsOn: + - LinuxArm64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) + container: snapcraft + variables: + VSCODE_ARCH: arm64 + steps: + - template: linux/snap-build-linux.yml + + - job: LinuxAlpine + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true')) + steps: + - template: linux/product-build-alpine.yml + + - job: LinuxWeb + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true')) + variables: + VSCODE_ARCH: x64 + steps: + - template: web/product-build-web.yml + + - stage: macOS + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: macOS-latest + jobs: + - job: macOS + condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: x64 + steps: + - template: darwin/product-build-darwin.yml + + - stage: Mooncake + dependsOn: + - Windows + - Linux + - macOS + condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: "Ubuntu-16.04" + jobs: + - job: SyncMooncake + displayName: Sync Mooncake + steps: + - template: sync-mooncake.yml + + - stage: Publish + dependsOn: + - Windows + - Linux + - macOS + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) + pool: + vmImage: "Ubuntu-16.04" + jobs: + - job: BuildService + displayName: Build Service + steps: + - template: release.yml diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index 1d8a09e4fe6..2833bb14a20 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -237,6 +237,7 @@ function prepareSnapPackage(arch) { const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' }) .pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@VERSION@@', commit.substr(0, 8))) + .pipe(replace('@@ARCHITECTURE@@', arch)) .pipe(rename('snap/snapcraft.yaml')); const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' }) diff --git a/resources/linux/snap/snapcraft.yaml b/resources/linux/snap/snapcraft.yaml index 046158e888e..c24d0af3ea7 100644 --- a/resources/linux/snap/snapcraft.yaml +++ b/resources/linux/snap/snapcraft.yaml @@ -6,6 +6,10 @@ description: | simplicity of a code editor with what developers need for the core edit-build-debug cycle. +architectures: + - build-on: amd64 + run-on: @@ARCHITECTURE@@ + grade: stable confinement: classic From 5dd81b4077b091818ae4397c707af37a6c429b89 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Nov 2020 11:19:51 +0100 Subject: [PATCH 0017/1837] move orderedMimeTypes and pickedMimeTypeIndex out of the domain model into the UX (its sole user) --- .../notebook/browser/notebookServiceImpl.ts | 55 +++++++++---------- .../browser/view/renderers/codeCell.ts | 26 ++++++--- .../contrib/notebook/common/notebookCommon.ts | 4 +- .../notebook/common/notebookService.ts | 5 +- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 79705df7513..c007d94a8bc 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -732,6 +732,11 @@ export class NotebookService extends Disposable implements INotebookService, ICu return Iterable.map(this._models.values(), data => data.model); } + getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[] { + // TODO@rebornix no string[] casting + return this._getOrderedMimeTypes(output, textModel.metadata.displayOrder as string[] ?? []); + } + private async transformTextModelOutputs(textModel: NotebookTextModel) { for (let i = 0; i < textModel.cells.length; i++) { const cell = textModel.cells[i]; @@ -739,11 +744,11 @@ export class NotebookService extends Disposable implements INotebookService, ICu cell.outputs.forEach((output) => { if (output.outputKind === CellOutputKind.Rich) { // TODO@rebornix no string[] casting - const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - const orderedMimeTypes = ret.orderedMimeTypes!; - const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - output.pickedMimeTypeIndex = pickedMimeTypeIndex; - output.orderedMimeTypes = orderedMimeTypes; + // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); + // const orderedMimeTypes = ret.orderedMimeTypes!; + // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; + // output.pickedMimeTypeIndex = pickedMimeTypeIndex; + // output.orderedMimeTypes = orderedMimeTypes; } }); } @@ -756,22 +761,22 @@ export class NotebookService extends Disposable implements INotebookService, ICu const outputs = cell.outputs; outputs.map((output) => { if (output.outputKind === CellOutputKind.Rich) { - const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - const orderedMimeTypes = ret.orderedMimeTypes!; - const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - output.pickedMimeTypeIndex = pickedMimeTypeIndex; - output.orderedMimeTypes = orderedMimeTypes; + // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); + // const orderedMimeTypes = ret.orderedMimeTypes!; + // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; + // output.pickedMimeTypeIndex = pickedMimeTypeIndex; + // output.orderedMimeTypes = orderedMimeTypes; } }); }); } else if (edit.editType === CellEditType.Output) { edit.outputs.map((output) => { if (output.outputKind === CellOutputKind.Rich) { - const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - const orderedMimeTypes = ret.orderedMimeTypes!; - const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - output.pickedMimeTypeIndex = pickedMimeTypeIndex; - output.orderedMimeTypes = orderedMimeTypes; + // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); + // const orderedMimeTypes = ret.orderedMimeTypes!; + // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; + // output.pickedMimeTypeIndex = pickedMimeTypeIndex; + // output.orderedMimeTypes = orderedMimeTypes; } }); } @@ -783,17 +788,17 @@ export class NotebookService extends Disposable implements INotebookService, ICu const outputs = splice[2]; outputs.map((output) => { if (output.outputKind === CellOutputKind.Rich) { - const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - const orderedMimeTypes = ret.orderedMimeTypes!; - const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - output.pickedMimeTypeIndex = pickedMimeTypeIndex; - output.orderedMimeTypes = orderedMimeTypes; + // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); + // const orderedMimeTypes = ret.orderedMimeTypes!; + // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; + // output.pickedMimeTypeIndex = pickedMimeTypeIndex; + // output.orderedMimeTypes = orderedMimeTypes; } }); }); } - private _transformMimeTypes(output: IDisplayOutput, outputId: string, documentDisplayOrder: string[]): ITransformedDisplayOutputDto { + private _getOrderedMimeTypes(output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] { const mimeTypes = Object.keys(output.data); const coreDisplayOrder = this._displayOrder; const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], documentDisplayOrder, coreDisplayOrder?.defaultOrder || []); @@ -832,13 +837,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu } }); - return { - outputKind: output.outputKind, - outputId, - data: output.data, - orderedMimeTypes: orderMimeTypes, - pickedMimeTypeIndex: 0 - }; + return orderMimeTypes; } private _findBestMatchedRenderer(mimeType: string): readonly NotebookOutputRendererInfo[] { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 640eee058dc..bebb55bb6af 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -34,6 +34,12 @@ interface IMimeTypeRenderer extends IQuickPickItem { } class OutputElement extends Disposable { + + // this isn't super proper but I couldn't find a view-model equivalent for output + // and it seems as of today we use the domain model - and pragamtically enrich it + // with UX properties + private pickedMimeTypes = new WeakMap(); + readonly resizeListener = new DisposableStore(); domNode!: HTMLElement; renderResult?: IRenderOutput; @@ -60,12 +66,15 @@ class OutputElement extends Disposable { if (this.output.outputKind === CellOutputKind.Rich) { const transformedDisplayOutput = this.output as ITransformedDisplayOutputDto; - if (transformedDisplayOutput.orderedMimeTypes!.length > 1) { + const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output); + const pick = this.pickedMimeTypes.get(this.output) ?? 0; + + if (mimeTypes.length > 1) { outputItemDiv.style.position = 'relative'; const mimeTypePicker = DOM.$('.multi-mimetype-output'); mimeTypePicker.classList.add('codicon', 'codicon-code'); mimeTypePicker.tabIndex = 0; - mimeTypePicker.title = nls.localize('mimeTypePicker', "Choose a different output mimetype, available mimetypes: {0}", transformedDisplayOutput.orderedMimeTypes!.map(mimeType => mimeType.mimeType).join(', ')); + mimeTypePicker.title = nls.localize('mimeTypePicker', "Choose a different output mimetype, available mimetypes: {0}", mimeTypes.map(mimeType => mimeType.mimeType).join(', ')); outputItemDiv.appendChild(mimeTypePicker); this.resizeListener.add(DOM.addStandardDisposableListener(mimeTypePicker, 'mousedown', async e => { if (e.leftButton) { @@ -85,7 +94,7 @@ class OutputElement extends Disposable { }))); } - const pickedMimeTypeRenderer = this.output.orderedMimeTypes![this.output.pickedMimeTypeIndex!]; + const pickedMimeTypeRenderer = mimeTypes[pick]; const innerContainer = DOM.$('.output-inner-container'); DOM.append(outputItemDiv, innerContainer); @@ -167,8 +176,12 @@ class OutputElement extends Disposable { } async pickActiveMimeTypeRenderer(output: ITransformedDisplayOutputDto) { - const currIndex = output.pickedMimeTypeIndex; - const items = output.orderedMimeTypes!.map((mimeType, index): IMimeTypeRenderer => ({ + + const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, output); + const currIndex = this.pickedMimeTypes.get(output) ?? 0; + + // const currIndex = output.pickedMimeTypeIndex; + const items = mimeTypes.map((mimeType, index): IMimeTypeRenderer => ({ label: mimeType.mimeType, id: mimeType.mimeType, index: index, @@ -205,7 +218,7 @@ class OutputElement extends Disposable { this.notebookEditor.removeInset(output); } - output.pickedMimeTypeIndex = pick; + this.pickedMimeTypes.set(output, pick); this.render(index, nextElement as HTMLElement); this.relayoutCell(); } @@ -769,4 +782,3 @@ export class CodeCell extends Disposable { super.dispose(); } } - diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 0c8d6d1ca2c..2e9b810641a 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -190,8 +190,8 @@ export interface ITransformedDisplayOutputDto { data: { [key: string]: unknown; } metadata?: NotebookCellOutputMetadata; - orderedMimeTypes?: IOrderedMimeType[]; - pickedMimeTypeIndex?: number; + // orderedMimeTypes?: IOrderedMimeType[]; + // pickedMimeTypeIndex?: number; } export function isTransformedDisplayOutput(thing: unknown): thing is ITransformedDisplayOutputDto { diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 58f4b085632..9df46ba2360 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -10,7 +10,7 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr import { Event } from 'vs/base/common/event'; import { INotebookTextModel, INotebookRendererInfo, - IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter + IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOrderedMimeType, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -49,7 +49,10 @@ export interface INotebookService { onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>; registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable; + getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[]; + /** @deprecated */ transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]): void; + /** @deprecated */ transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]): void; registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable; getContributedNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise; From 7ec1a6899cc1f9d0a715abded10751251ad0bfe6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Nov 2020 11:24:10 +0100 Subject: [PATCH 0018/1837] remove transformXYZOutput --- .../api/browser/mainThreadNotebook.ts | 4 -- .../contrib/bulkEdit/browser/bulkCellEdits.ts | 3 - .../notebook/browser/notebookServiceImpl.ts | 65 +------------------ .../notebook/common/notebookService.ts | 7 +- 4 files changed, 3 insertions(+), 76 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 93215c290b4..06ee86ff822 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -171,7 +171,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo if (!textModel) { return false; } - this._notebookService.transformEditsOutputs(textModel, cellEdits); return textModel.applyEdits(modelVersionId, cellEdits, true, undefined, () => undefined, undefined); } @@ -479,8 +478,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const edits: ICellEditOperation[] = [ { editType: CellEditType.Replace, index: 0, count: mainthreadTextModel.cells.length, cells: data.cells } ]; - - this._notebookService.transformEditsOutputs(mainthreadTextModel, edits); await new Promise(resolve => { DOM.scheduleAtNextAnimationFrame(() => { const ret = mainthreadTextModel!.applyEdits(mainthreadTextModel!.versionId, edits, true, undefined, () => undefined, undefined); @@ -606,7 +603,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo return; } - this._notebookService.transformSpliceOutputs(textModel, splices); const cell = textModel.cells.find(cell => cell.handle === cellHandle); if (!cell) { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts index 96b5e0e7e61..f058fab78c1 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts @@ -12,7 +12,6 @@ import { IProgress } from 'vs/platform/progress/common/progress'; import { UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo'; import { ICellEditOperation } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; -import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; export class ResourceNotebookCellEdit extends ResourceEdit { @@ -32,7 +31,6 @@ export class BulkCellEdits { private _undoRedoGroup: UndoRedoGroup, private readonly _progress: IProgress, private readonly _edits: ResourceNotebookCellEdit[], - @INotebookService private readonly _notebookService: INotebookService, @INotebookEditorModelResolverService private readonly _notebookModelService: INotebookEditorModelResolverService, ) { } @@ -52,7 +50,6 @@ export class BulkCellEdits { // apply edits const edits = group.map(entry => entry.cellEdit); - this._notebookService.transformEditsOutputs(ref.object.notebook, edits); ref.object.notebook.applyEdits(ref.object.notebook.versionId, edits, true, undefined, () => undefined, this._undoRedoGroup); ref.dispose(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index c007d94a8bc..c0fb96453c9 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -28,7 +28,7 @@ import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRe import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellEditType, CellKind, CellOutputKind, DisplayOrderKey, ICellEditOperation, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellOutputsSplice, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -718,8 +718,6 @@ export class NotebookService extends Disposable implements INotebookService, ICu this._models.set(uri, modelData); this._onDidAddNotebookDocument.fire(notebookModel); - // after the document is added to the store and sent to ext host, we transform the ouputs - await this.transformTextModelOutputs(notebookModel); return modelData.model; } @@ -737,67 +735,6 @@ export class NotebookService extends Disposable implements INotebookService, ICu return this._getOrderedMimeTypes(output, textModel.metadata.displayOrder as string[] ?? []); } - private async transformTextModelOutputs(textModel: NotebookTextModel) { - for (let i = 0; i < textModel.cells.length; i++) { - const cell = textModel.cells[i]; - - cell.outputs.forEach((output) => { - if (output.outputKind === CellOutputKind.Rich) { - // TODO@rebornix no string[] casting - // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - // const orderedMimeTypes = ret.orderedMimeTypes!; - // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - // output.pickedMimeTypeIndex = pickedMimeTypeIndex; - // output.orderedMimeTypes = orderedMimeTypes; - } - }); - } - } - - transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]) { - edits.forEach((edit) => { - if (edit.editType === CellEditType.Replace) { - edit.cells.forEach((cell) => { - const outputs = cell.outputs; - outputs.map((output) => { - if (output.outputKind === CellOutputKind.Rich) { - // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - // const orderedMimeTypes = ret.orderedMimeTypes!; - // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - // output.pickedMimeTypeIndex = pickedMimeTypeIndex; - // output.orderedMimeTypes = orderedMimeTypes; - } - }); - }); - } else if (edit.editType === CellEditType.Output) { - edit.outputs.map((output) => { - if (output.outputKind === CellOutputKind.Rich) { - // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - // const orderedMimeTypes = ret.orderedMimeTypes!; - // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - // output.pickedMimeTypeIndex = pickedMimeTypeIndex; - // output.orderedMimeTypes = orderedMimeTypes; - } - }); - } - }); - } - - transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]) { - splices.forEach((splice) => { - const outputs = splice[2]; - outputs.map((output) => { - if (output.outputKind === CellOutputKind.Rich) { - // const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); - // const orderedMimeTypes = ret.orderedMimeTypes!; - // const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; - // output.pickedMimeTypeIndex = pickedMimeTypeIndex; - // output.orderedMimeTypes = orderedMimeTypes; - } - }); - }); - } - private _getOrderedMimeTypes(output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] { const mimeTypes = Object.keys(output.data); const coreDisplayOrder = this._displayOrder; diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 9df46ba2360..06f77081750 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -10,7 +10,7 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr import { Event } from 'vs/base/common/event'; import { INotebookTextModel, INotebookRendererInfo, - IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOrderedMimeType, ITransformedDisplayOutputDto + IEditor, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOrderedMimeType, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -50,10 +50,7 @@ export interface INotebookService { registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable; getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[]; - /** @deprecated */ - transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]): void; - /** @deprecated */ - transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]): void; + registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable; getContributedNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise; getContributedNotebookOutputRenderers(id: string): NotebookOutputRendererInfo | undefined; From ca20be531eabc8d5a9eb26e907ff86211398d07c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Nov 2020 11:41:20 +0100 Subject: [PATCH 0019/1837] simplify ITransformedDisplayOutputDto type --- .../contrib/notebook/common/notebookCommon.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 2e9b810641a..6b8d3ec0126 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -184,27 +184,14 @@ export interface IOrderedMimeType { rendererId: string; } -export interface ITransformedDisplayOutputDto { - outputKind: CellOutputKind.Rich; +export interface ITransformedDisplayOutputDto extends IDisplayOutput { outputId: string; - data: { [key: string]: unknown; } - metadata?: NotebookCellOutputMetadata; - - // orderedMimeTypes?: IOrderedMimeType[]; - // pickedMimeTypeIndex?: number; } export function isTransformedDisplayOutput(thing: unknown): thing is ITransformedDisplayOutputDto { return (thing as ITransformedDisplayOutputDto).outputKind === CellOutputKind.Rich && !!(thing as ITransformedDisplayOutputDto).outputId; } -export interface IGenericOutput { - outputKind: CellOutputKind; - pickedMimeType?: string; - pickedRenderer?: number; - transformedOutput?: { [key: string]: IDisplayOutput }; -} - export const addIdToOutput = (output: IRawOutput, id = UUID.generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich ? ({ ...output, outputId: id }) : output; From 28d71bdbabf5bdb4447fd534408b0575dd63eaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 18 Nov 2020 12:04:07 +0100 Subject: [PATCH 0020/1837] fix snap target-arch --- build/azure-pipelines/linux/snap-build-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 1bf016914c3..9d59a83c334 100644 --- a/build/azure-pipelines/linux/snap-build-linux.yml +++ b/build/azure-pipelines/linux/snap-build-linux.yml @@ -44,7 +44,7 @@ steps: BUILD_VERSION="$(date +%s)" SNAP_FILENAME="code-$VSCODE_QUALITY-$(VSCODE_ARCH)-$BUILD_VERSION.snap" SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME" - (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --output "$SNAP_PATH") + (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --target-arch $(VSCODE_ARCH) --output "$SNAP_PATH") # Publish snap package AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ From 2a499549ce2842ad6265f2e4aabe55adbdd3df8a Mon Sep 17 00:00:00 2001 From: chanmaoooo Date: Wed, 18 Nov 2020 13:39:04 +0100 Subject: [PATCH 0021/1837] add deleteWordEntire command --- .../common/controller/cursorWordOperations.ts | 118 ++++++++++++++---- .../contrib/wordOperations/wordOperations.ts | 41 +++++- 2 files changed, 128 insertions(+), 31 deletions(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index 75c25ccc021..e4f778f7d05 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -374,6 +374,52 @@ export class WordOperations { return null; } + protected static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, wordNavigationType: WordNavigationType, position: Position, isEntire: boolean): Range { + let lineNumber = position.lineNumber; + let column = position.column; + let columnEnd = position.column; + let lineContent = model.getLineContent(position.lineNumber); + + let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); + + if (wordNavigationType === WordNavigationType.WordStart) { + if (prevWordOnLine) { + column = prevWordOnLine.start + 1; + if (isEntire) { + columnEnd = prevWordOnLine.end + 1; + const chCode = lineContent.charCodeAt(columnEnd - 1); + if (chCode === CharCode.Space || chCode === CharCode.Tab) { + columnEnd++; + } + } + } else { + if (column > 1) { + column = 1; + } else { + lineNumber--; + column = model.getLineMaxColumn(lineNumber); + } + } + } else { + if (prevWordOnLine && column <= prevWordOnLine.end + 1) { + prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1)); + } + if (prevWordOnLine) { + column = prevWordOnLine.end + 1; + } else { + if (column > 1) { + column = 1; + } else { + lineNumber--; + column = model.getLineMaxColumn(lineNumber); + } + } + } + + return new Range(lineNumber, column, position.lineNumber, columnEnd); + } + + public static deleteWordLeft(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { const wordSeparators = ctx.wordSeparators; const model = ctx.model; @@ -406,36 +452,56 @@ export class WordOperations { } } - let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); + return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, false); + } - if (wordNavigationType === WordNavigationType.WordStart) { - if (prevWordOnLine) { - column = prevWordOnLine.start + 1; - } else { - if (column > 1) { - column = 1; - } else { - lineNumber--; - column = model.getLineMaxColumn(lineNumber); - } - } - } else { - if (prevWordOnLine && column <= prevWordOnLine.end + 1) { - prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1)); - } - if (prevWordOnLine) { - column = prevWordOnLine.end + 1; - } else { - if (column > 1) { - column = 1; - } else { - lineNumber--; - column = model.getLineMaxColumn(lineNumber); - } + + protected static _deleteWordEntireWhitespace(model: ICursorSimpleModel, position: Position): Range | null { + const lineContent = model.getLineContent(position.lineNumber); + const startIndex1 = position.column - 1; // deleteRight + const startIndex2 = position.column - 2; // deleteLeft + const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex1); + const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex2); + if ((startIndex1 + 1 < firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 >= firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 <= firstNonWhitespace && lastNonWhitespace + 1 === startIndex2)) { + return new Range(position.lineNumber, lastNonWhitespace + 2, position.lineNumber, firstNonWhitespace + 1); + } + return null; + } + + + public static deleteWordEntire(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { + const wordSeparators = ctx.wordSeparators; + const model = ctx.model; + const selection = ctx.selection; + const whitespaceHeuristics = ctx.whitespaceHeuristics; + + if (!selection.isEmpty()) { + return selection; + } + + if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpen, ctx.model, [ctx.selection])) { + const position = ctx.selection.getPosition(); + return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); + } + + const position = new Position(selection.positionLineNumber, selection.positionColumn); + + let lineNumber = position.lineNumber; + let column = position.column; + + if (lineNumber === 1 && column === 1) { + // Ignore deleting at beginning of file + return null; + } + + if (whitespaceHeuristics) { + let r = this._deleteWordEntireWhitespace(model, position); + if (r) { + return r; } } - return new Range(lineNumber, column, position.lineNumber, position.column); + return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, true); } public static _deleteWordPartLeft(model: ICursorSimpleModel, selection: Selection): Range { diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index c7db9649e0f..9fbd2ebe284 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -402,6 +402,23 @@ export class DeleteWordRightCommand extends DeleteWordCommand { } } +export class DeleteWordRight extends DeleteWordRightCommand { + constructor() { + super({ + whitespaceHeuristics: true, + wordNavigationType: WordNavigationType.WordEnd, + id: 'deleteWordRight', + precondition: EditorContextKeys.writable, + kbOpts: { + kbExpr: EditorContextKeys.textInputFocus, + primary: KeyMod.CtrlCmd | KeyCode.Delete, + mac: { primary: KeyMod.Alt | KeyCode.Delete }, + weight: KeybindingWeight.EditorContrib + } + }); + } +} + export class DeleteWordStartLeft extends DeleteWordLeftCommand { constructor() { super({ @@ -463,23 +480,36 @@ export class DeleteWordEndRight extends DeleteWordRightCommand { } } -export class DeleteWordRight extends DeleteWordRightCommand { +export class DeleteWordEntireCommand extends DeleteWordCommand { + protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range { + let r = WordOperations.deleteWordEntire(ctx, wordNavigationType); + if (r) { + return r; + } + const lineCount = ctx.model.getLineCount(); + const maxColumn = ctx.model.getLineMaxColumn(lineCount); + return new Range(lineCount, maxColumn, lineCount, maxColumn); + } +} + +export class DeleteWordEntire extends DeleteWordEntireCommand { constructor() { super({ whitespaceHeuristics: true, - wordNavigationType: WordNavigationType.WordEnd, - id: 'deleteWordRight', + wordNavigationType: WordNavigationType.WordStart, + id: 'deleteWordEntire', precondition: EditorContextKeys.writable, kbOpts: { kbExpr: EditorContextKeys.textInputFocus, - primary: KeyMod.CtrlCmd | KeyCode.Delete, - mac: { primary: KeyMod.Alt | KeyCode.Delete }, + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_U, + mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.KEY_U }, weight: KeybindingWeight.EditorContrib } }); } } + registerEditorCommand(new CursorWordStartLeft()); registerEditorCommand(new CursorWordEndLeft()); registerEditorCommand(new CursorWordLeft()); @@ -502,3 +532,4 @@ registerEditorCommand(new DeleteWordLeft()); registerEditorCommand(new DeleteWordStartRight()); registerEditorCommand(new DeleteWordEndRight()); registerEditorCommand(new DeleteWordRight()); +registerEditorCommand(new DeleteWordEntire()); From 6d439732d78d80dc791e7c07f7243e8377d9021e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Nov 2020 13:54:46 +0100 Subject: [PATCH 0022/1837] Reduce diff --- .../common/controller/cursorWordOperations.ts | 198 ++++++++++-------- .../contrib/wordOperations/wordOperations.ts | 35 ++-- 2 files changed, 129 insertions(+), 104 deletions(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index e4f778f7d05..4e424786176 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -374,7 +374,118 @@ export class WordOperations { return null; } - protected static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, wordNavigationType: WordNavigationType, position: Position, isEntire: boolean): Range { + public static deleteWordLeft(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { + const wordSeparators = ctx.wordSeparators; + const model = ctx.model; + const selection = ctx.selection; + const whitespaceHeuristics = ctx.whitespaceHeuristics; + + if (!selection.isEmpty()) { + return selection; + } + + if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) { + const position = ctx.selection.getPosition(); + return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); + } + + const position = new Position(selection.positionLineNumber, selection.positionColumn); + + let lineNumber = position.lineNumber; + let column = position.column; + + if (lineNumber === 1 && column === 1) { + // Ignore deleting at beginning of file + return null; + } + + if (whitespaceHeuristics) { + let r = this._deleteWordLeftWhitespace(model, position); + if (r) { + return r; + } + } + + let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); + + if (wordNavigationType === WordNavigationType.WordStart) { + if (prevWordOnLine) { + column = prevWordOnLine.start + 1; + } else { + if (column > 1) { + column = 1; + } else { + lineNumber--; + column = model.getLineMaxColumn(lineNumber); + } + } + } else { + if (prevWordOnLine && column <= prevWordOnLine.end + 1) { + prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1)); + } + if (prevWordOnLine) { + column = prevWordOnLine.end + 1; + } else { + if (column > 1) { + column = 1; + } else { + lineNumber--; + column = model.getLineMaxColumn(lineNumber); + } + } + } + + return new Range(lineNumber, column, position.lineNumber, position.column); + } + + public static deleteWordEntire(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { + const wordSeparators = ctx.wordSeparators; + const model = ctx.model; + const selection = ctx.selection; + const whitespaceHeuristics = ctx.whitespaceHeuristics; + + if (!selection.isEmpty()) { + return selection; + } + + if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) { + const position = ctx.selection.getPosition(); + return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); + } + + const position = new Position(selection.positionLineNumber, selection.positionColumn); + + let lineNumber = position.lineNumber; + let column = position.column; + + if (lineNumber === 1 && column === 1) { + // Ignore deleting at beginning of file + return null; + } + + if (whitespaceHeuristics) { + let r = this._deleteWordEntireWhitespace(model, position); + if (r) { + return r; + } + } + + return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, true); + } + + private static _deleteWordEntireWhitespace(model: ICursorSimpleModel, position: Position): Range | null { + const lineContent = model.getLineContent(position.lineNumber); + const startIndex1 = position.column - 1; // deleteRight + const startIndex2 = position.column - 2; // deleteLeft + const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex1); + const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex2); + if ((startIndex1 + 1 < firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 >= firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 <= firstNonWhitespace && lastNonWhitespace + 1 === startIndex2)) { + return new Range(position.lineNumber, lastNonWhitespace + 2, position.lineNumber, firstNonWhitespace + 1); + } + return null; + } + + private static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, wordNavigationType: WordNavigationType, position: Position, isEntire: boolean): Range { let lineNumber = position.lineNumber; let column = position.column; let columnEnd = position.column; @@ -419,91 +530,6 @@ export class WordOperations { return new Range(lineNumber, column, position.lineNumber, columnEnd); } - - public static deleteWordLeft(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { - const wordSeparators = ctx.wordSeparators; - const model = ctx.model; - const selection = ctx.selection; - const whitespaceHeuristics = ctx.whitespaceHeuristics; - - if (!selection.isEmpty()) { - return selection; - } - - if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) { - const position = ctx.selection.getPosition(); - return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); - } - - const position = new Position(selection.positionLineNumber, selection.positionColumn); - - let lineNumber = position.lineNumber; - let column = position.column; - - if (lineNumber === 1 && column === 1) { - // Ignore deleting at beginning of file - return null; - } - - if (whitespaceHeuristics) { - let r = this._deleteWordLeftWhitespace(model, position); - if (r) { - return r; - } - } - - return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, false); - } - - - protected static _deleteWordEntireWhitespace(model: ICursorSimpleModel, position: Position): Range | null { - const lineContent = model.getLineContent(position.lineNumber); - const startIndex1 = position.column - 1; // deleteRight - const startIndex2 = position.column - 2; // deleteLeft - const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex1); - const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex2); - if ((startIndex1 + 1 < firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 >= firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 <= firstNonWhitespace && lastNonWhitespace + 1 === startIndex2)) { - return new Range(position.lineNumber, lastNonWhitespace + 2, position.lineNumber, firstNonWhitespace + 1); - } - return null; - } - - - public static deleteWordEntire(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { - const wordSeparators = ctx.wordSeparators; - const model = ctx.model; - const selection = ctx.selection; - const whitespaceHeuristics = ctx.whitespaceHeuristics; - - if (!selection.isEmpty()) { - return selection; - } - - if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpen, ctx.model, [ctx.selection])) { - const position = ctx.selection.getPosition(); - return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); - } - - const position = new Position(selection.positionLineNumber, selection.positionColumn); - - let lineNumber = position.lineNumber; - let column = position.column; - - if (lineNumber === 1 && column === 1) { - // Ignore deleting at beginning of file - return null; - } - - if (whitespaceHeuristics) { - let r = this._deleteWordEntireWhitespace(model, position); - if (r) { - return r; - } - } - - return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, true); - } - public static _deleteWordPartLeft(model: ICursorSimpleModel, selection: Selection): Range { if (!selection.isEmpty()) { return selection; diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index 9fbd2ebe284..1fe8e8a2924 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -402,23 +402,6 @@ export class DeleteWordRightCommand extends DeleteWordCommand { } } -export class DeleteWordRight extends DeleteWordRightCommand { - constructor() { - super({ - whitespaceHeuristics: true, - wordNavigationType: WordNavigationType.WordEnd, - id: 'deleteWordRight', - precondition: EditorContextKeys.writable, - kbOpts: { - kbExpr: EditorContextKeys.textInputFocus, - primary: KeyMod.CtrlCmd | KeyCode.Delete, - mac: { primary: KeyMod.Alt | KeyCode.Delete }, - weight: KeybindingWeight.EditorContrib - } - }); - } -} - export class DeleteWordStartLeft extends DeleteWordLeftCommand { constructor() { super({ @@ -480,6 +463,23 @@ export class DeleteWordEndRight extends DeleteWordRightCommand { } } +export class DeleteWordRight extends DeleteWordRightCommand { + constructor() { + super({ + whitespaceHeuristics: true, + wordNavigationType: WordNavigationType.WordEnd, + id: 'deleteWordRight', + precondition: EditorContextKeys.writable, + kbOpts: { + kbExpr: EditorContextKeys.textInputFocus, + primary: KeyMod.CtrlCmd | KeyCode.Delete, + mac: { primary: KeyMod.Alt | KeyCode.Delete }, + weight: KeybindingWeight.EditorContrib + } + }); + } +} + export class DeleteWordEntireCommand extends DeleteWordCommand { protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range { let r = WordOperations.deleteWordEntire(ctx, wordNavigationType); @@ -509,7 +509,6 @@ export class DeleteWordEntire extends DeleteWordEntireCommand { } } - registerEditorCommand(new CursorWordStartLeft()); registerEditorCommand(new CursorWordEndLeft()); registerEditorCommand(new CursorWordLeft()); From cbfd4d5a9f5bb75013365d3379506ba82e2cc2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 18 Nov 2020 14:12:01 +0100 Subject: [PATCH 0023/1837] fix snapcraft x64 --- build/azure-pipelines/linux/snap-build-linux.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 9d59a83c334..f08c7b3c3e6 100644 --- a/build/azure-pipelines/linux/snap-build-linux.yml +++ b/build/azure-pipelines/linux/snap-build-linux.yml @@ -44,7 +44,11 @@ steps: BUILD_VERSION="$(date +%s)" SNAP_FILENAME="code-$VSCODE_QUALITY-$(VSCODE_ARCH)-$BUILD_VERSION.snap" SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME" - (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --target-arch $(VSCODE_ARCH) --output "$SNAP_PATH") + case $(VSCODE_ARCH) in + x64) SNAPCRAFT_TARGET_ARGS="" ;; + *) SNAPCRAFT_TARGET_ARGS="--target-arch $(VSCODE_ARCH)" ;; + esac + (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap $SNAPCRAFT_TARGET_ARGS --output "$SNAP_PATH") # Publish snap package AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ From 5cca5c598c7b49afe663f5ac00fb53bfe49025bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 18 Nov 2020 15:03:11 +0100 Subject: [PATCH 0024/1837] empty commit From ddff206d378159eee406de225d078782e182e04b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Nov 2020 22:17:08 +0100 Subject: [PATCH 0025/1837] Simplifications: substitute constant arguments --- .../common/controller/cursorWordOperations.ts | 71 +++++-------------- .../contrib/wordOperations/wordOperations.ts | 43 +++++++---- 2 files changed, 45 insertions(+), 69 deletions(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index 4e424786176..5bbe5411e9d 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -438,39 +438,19 @@ export class WordOperations { return new Range(lineNumber, column, position.lineNumber, position.column); } - public static deleteWordEntire(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null { - const wordSeparators = ctx.wordSeparators; - const model = ctx.model; - const selection = ctx.selection; - const whitespaceHeuristics = ctx.whitespaceHeuristics; - + public static deleteWordEntire(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range | null { if (!selection.isEmpty()) { return selection; } - if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) { - const position = ctx.selection.getPosition(); - return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1); - } - const position = new Position(selection.positionLineNumber, selection.positionColumn); - let lineNumber = position.lineNumber; - let column = position.column; - - if (lineNumber === 1 && column === 1) { - // Ignore deleting at beginning of file - return null; + let r = this._deleteWordEntireWhitespace(model, position); + if (r) { + return r; } - if (whitespaceHeuristics) { - let r = this._deleteWordEntireWhitespace(model, position); - if (r) { - return r; - } - } - - return this._determineDeleteRange(wordSeparators, model, wordNavigationType, position, true); + return this._determineDeleteRange(wordSeparators, model, position); } private static _deleteWordEntireWhitespace(model: ICursorSimpleModel, position: Position): Range | null { @@ -485,7 +465,7 @@ export class WordOperations { return null; } - private static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, wordNavigationType: WordNavigationType, position: Position, isEntire: boolean): Range { + private static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Range { let lineNumber = position.lineNumber; let column = position.column; let columnEnd = position.column; @@ -493,40 +473,21 @@ export class WordOperations { let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); - if (wordNavigationType === WordNavigationType.WordStart) { - if (prevWordOnLine) { - column = prevWordOnLine.start + 1; - if (isEntire) { - columnEnd = prevWordOnLine.end + 1; - const chCode = lineContent.charCodeAt(columnEnd - 1); - if (chCode === CharCode.Space || chCode === CharCode.Tab) { - columnEnd++; - } - } - } else { - if (column > 1) { - column = 1; - } else { - lineNumber--; - column = model.getLineMaxColumn(lineNumber); - } + if (prevWordOnLine) { + column = prevWordOnLine.start + 1; + columnEnd = prevWordOnLine.end + 1; + const chCode = lineContent.charCodeAt(columnEnd - 1); + if (chCode === CharCode.Space || chCode === CharCode.Tab) { + columnEnd++; } } else { - if (prevWordOnLine && column <= prevWordOnLine.end + 1) { - prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1)); - } - if (prevWordOnLine) { - column = prevWordOnLine.end + 1; + if (column > 1) { + column = 1; } else { - if (column > 1) { - column = 1; - } else { - lineNumber--; - column = model.getLineMaxColumn(lineNumber); - } + lineNumber--; + column = model.getLineMaxColumn(lineNumber); } } - return new Range(lineNumber, column, position.lineNumber, columnEnd); } diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index 1fe8e8a2924..f798ef5d8bc 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -480,23 +480,10 @@ export class DeleteWordRight extends DeleteWordRightCommand { } } -export class DeleteWordEntireCommand extends DeleteWordCommand { - protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range { - let r = WordOperations.deleteWordEntire(ctx, wordNavigationType); - if (r) { - return r; - } - const lineCount = ctx.model.getLineCount(); - const maxColumn = ctx.model.getLineMaxColumn(lineCount); - return new Range(lineCount, maxColumn, lineCount, maxColumn); - } -} +export class DeleteWordEntire extends EditorCommand { -export class DeleteWordEntire extends DeleteWordEntireCommand { constructor() { super({ - whitespaceHeuristics: true, - wordNavigationType: WordNavigationType.WordStart, id: 'deleteWordEntire', precondition: EditorContextKeys.writable, kbOpts: { @@ -507,6 +494,34 @@ export class DeleteWordEntire extends DeleteWordEntireCommand { } }); } + + public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { + if (!editor.hasModel()) { + return; + } + const wordSeparators = getMapForWordSeparators(editor.getOption(EditorOption.wordSeparators)); + const model = editor.getModel(); + const selections = editor.getSelections(); + + const commands = selections.map((sel) => { + const deleteRange = this._delete(wordSeparators, model, sel); + return new ReplaceCommand(deleteRange, ''); + }); + + editor.pushUndoStop(); + editor.executeCommands(this.id, commands); + editor.pushUndoStop(); + } + + private _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range { + let r = WordOperations.deleteWordEntire(wordSeparators, model, selection); + if (r) { + return r; + } + const lineCount = model.getLineCount(); + const maxColumn = model.getLineMaxColumn(lineCount); + return new Range(lineCount, maxColumn, lineCount, maxColumn); + } } registerEditorCommand(new CursorWordStartLeft()); From ab4cab8ac5ec39da0c3031dc7802e599c89e1d0a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Nov 2020 22:22:29 +0100 Subject: [PATCH 0026/1837] rename to `DeleteInsideWord`, remove keybinding --- .../common/controller/cursorWordOperations.ts | 10 +++++----- .../contrib/wordOperations/wordOperations.ts | 16 +++++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index 5bbe5411e9d..6aaf4d00ac0 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -438,22 +438,22 @@ export class WordOperations { return new Range(lineNumber, column, position.lineNumber, position.column); } - public static deleteWordEntire(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range | null { + public static deleteInsideWord(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range | null { if (!selection.isEmpty()) { return selection; } const position = new Position(selection.positionLineNumber, selection.positionColumn); - let r = this._deleteWordEntireWhitespace(model, position); + let r = this._deleteInsideWordWhitespace(model, position); if (r) { return r; } - return this._determineDeleteRange(wordSeparators, model, position); + return this._deleteInsideWordDetermineDeleteRange(wordSeparators, model, position); } - private static _deleteWordEntireWhitespace(model: ICursorSimpleModel, position: Position): Range | null { + private static _deleteInsideWordWhitespace(model: ICursorSimpleModel, position: Position): Range | null { const lineContent = model.getLineContent(position.lineNumber); const startIndex1 = position.column - 1; // deleteRight const startIndex2 = position.column - 2; // deleteLeft @@ -465,7 +465,7 @@ export class WordOperations { return null; } - private static _determineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Range { + private static _deleteInsideWordDetermineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Range { let lineNumber = position.lineNumber; let column = position.column; let columnEnd = position.column; diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index f798ef5d8bc..e5f3ed382e0 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -480,18 +480,12 @@ export class DeleteWordRight extends DeleteWordRightCommand { } } -export class DeleteWordEntire extends EditorCommand { +export class DeleteInsideWord extends EditorCommand { constructor() { super({ - id: 'deleteWordEntire', - precondition: EditorContextKeys.writable, - kbOpts: { - kbExpr: EditorContextKeys.textInputFocus, - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_U, - mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.KEY_U }, - weight: KeybindingWeight.EditorContrib - } + id: 'deleteInsideWord', + precondition: EditorContextKeys.writable }); } @@ -514,7 +508,7 @@ export class DeleteWordEntire extends EditorCommand { } private _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range { - let r = WordOperations.deleteWordEntire(wordSeparators, model, selection); + let r = WordOperations.deleteInsideWord(wordSeparators, model, selection); if (r) { return r; } @@ -546,4 +540,4 @@ registerEditorCommand(new DeleteWordLeft()); registerEditorCommand(new DeleteWordStartRight()); registerEditorCommand(new DeleteWordEndRight()); registerEditorCommand(new DeleteWordRight()); -registerEditorCommand(new DeleteWordEntire()); +registerEditorCommand(new DeleteInsideWord()); From 710c859af0521482329d72aa9d20d72a69c7f78a Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 18 Nov 2020 21:27:46 -0800 Subject: [PATCH 0027/1837] Use label for "Follow link" command's tooltip --- src/vs/editor/contrib/links/links.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 283e8ef31a3..7f7e37de319 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -47,7 +47,7 @@ function getHoverMessage(link: Link, useMetaKey: boolean): MarkdownString { : nls.localize('links.navigate.kb.alt', "alt + click"); if (link.url) { - const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()}) (${kb})`); + const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()} "${label}") (${kb})`); return hoverMessage; } else { return new MarkdownString().appendText(`${label} (${kb})`); From d04f3178dc9cc8823d8f799d65cad678c4ef3309 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 19 Nov 2020 08:13:18 +0100 Subject: [PATCH 0028/1837] proper name for register function: registerFileDecorationProvider, #54938 --- extensions/git/src/decorationProvider.ts | 4 ++-- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHost.api.impl.ts | 4 ++-- src/vs/workbench/api/common/extHostDecorations.ts | 2 +- src/vs/workbench/test/browser/api/extHostDecorations.test.ts | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 1eb2faab464..63c02605192 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -26,7 +26,7 @@ class GitIgnoreDecorationProvider implements FileDecorationProvider { model.onDidCloseRepository )); - this.disposables.push(window.registerDecorationProvider(this)); + this.disposables.push(window.registerFileDecorationProvider(this)); } async provideFileDecoration(uri: Uri): Promise { @@ -100,7 +100,7 @@ class GitDecorationProvider implements FileDecorationProvider { constructor(private repository: Repository) { this.disposables.push( - window.registerDecorationProvider(this), + window.registerFileDecorationProvider(this), repository.onDidRunGitStatus(this.onDidRunGitStatus, this) ); } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 443a485a31e..deea6fc5826 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -801,7 +801,7 @@ declare module 'vscode' { } export namespace window { - export function registerDecorationProvider(provider: FileDecorationProvider): Disposable; + export function registerFileDecorationProvider(provider: FileDecorationProvider): Disposable; } //#endregion diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 42f167a6cd7..e4eee8822f6 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -617,9 +617,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerCustomEditorProvider: (viewType: string, provider: vscode.CustomTextEditorProvider | vscode.CustomReadonlyEditorProvider, options: { webviewOptions?: vscode.WebviewPanelOptions, supportsMultipleEditorsPerDocument?: boolean } = {}) => { return extHostCustomEditors.registerCustomEditorProvider(extension, viewType, provider, options); }, - registerDecorationProvider(provider: vscode.FileDecorationProvider) { + registerFileDecorationProvider(provider: vscode.FileDecorationProvider) { checkProposedApiEnabled(extension); - return extHostDecorations.registerDecorationProvider(provider, extension.identifier); + return extHostDecorations.registerFileDecorationProvider(provider, extension.identifier); }, registerUriHandler(handler: vscode.UriHandler) { return extHostUrls.registerUriHandler(extension.identifier, handler); diff --git a/src/vs/workbench/api/common/extHostDecorations.ts b/src/vs/workbench/api/common/extHostDecorations.ts index 39d293dee18..ea4858374ac 100644 --- a/src/vs/workbench/api/common/extHostDecorations.ts +++ b/src/vs/workbench/api/common/extHostDecorations.ts @@ -37,7 +37,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { this._proxy = extHostRpc.getProxy(MainContext.MainThreadDecorations); } - registerDecorationProvider(provider: vscode.FileDecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable { + registerFileDecorationProvider(provider: vscode.FileDecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable { const handle = ExtHostDecorations._handlePool++; this._provider.set(handle, { provider, extensionId }); this._proxy.$registerDecorationProvider(handle, extensionId.value); diff --git a/src/vs/workbench/test/browser/api/extHostDecorations.test.ts b/src/vs/workbench/test/browser/api/extHostDecorations.test.ts index 7f5c9f36287..4e78842c766 100644 --- a/src/vs/workbench/test/browser/api/extHostDecorations.test.ts +++ b/src/vs/workbench/test/browser/api/extHostDecorations.test.ts @@ -46,7 +46,7 @@ suite('ExtHostDecorations', function () { let calledB = false; // never returns - extHostDecorations.registerDecorationProvider({ + extHostDecorations.registerFileDecorationProvider({ provideFileDecoration() { calledA = true; @@ -55,7 +55,7 @@ suite('ExtHostDecorations', function () { }, nullExtensionDescription.identifier); // always returns - extHostDecorations.registerDecorationProvider({ + extHostDecorations.registerFileDecorationProvider({ provideFileDecoration() { calledB = true; From 47eb468acb5aa8301ad20bfe3ef76634ab4db9fb Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Nov 2020 08:16:25 +0100 Subject: [PATCH 0029/1837] sandbox - fix process in sandboxed environment (allow to run on Windows) --- src/vs/base/common/platform.ts | 5 --- src/vs/base/common/process.ts | 14 ++++++-- .../parts/sandbox/electron-browser/preload.js | 35 +++---------------- .../parts/sandbox/electron-sandbox/globals.ts | 24 ++++--------- .../electron-main/nativeHostMainService.ts | 4 +-- 5 files changed, 24 insertions(+), 58 deletions(-) diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 3361d83be5b..a28fe0e0d41 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -34,7 +34,6 @@ export interface INodeProcess { electron?: string; }; type?: string; - getuid(): number; cwd(): string; } declare const process: INodeProcess; @@ -133,10 +132,6 @@ export const isIOS = _isIOS; export const platform = _platform; export const userAgent = _userAgent; -export function isRootUser(): boolean { - return !!nodeProcess && !_isWindows && (nodeProcess.getuid() === 0); -} - /** * The language used for the user interface. The format of * the string is all lower case (e.g. zh-tw for Traditional diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts index 5e85d672116..4b9dde87290 100644 --- a/src/vs/base/common/process.ts +++ b/src/vs/base/common/process.ts @@ -16,7 +16,16 @@ if (typeof process !== 'undefined') { // Native sandbox environment else if (typeof globals.vscode !== 'undefined') { - safeProcess = globals.vscode.process; + safeProcess = { + + // Supported + get platform(): 'win32' | 'linux' | 'darwin' { return globals.vscode.process.platform; }, + get env() { return globals.vscode.process.env; }, + nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); }, + + // Unsupported + cwd(): string { return globals.vscode.process.env['VSCODE_CWD'] || globals.vscode.process.execPath.substr(0, globals.vscode.process.execPath.lastIndexOf(globals.vscode.process.platform === 'win32' ? '\\' : '/')); } + }; } // Web environment @@ -29,8 +38,7 @@ else { // Unsupported get env() { return Object.create(null); }, - cwd(): string { return '/'; }, - getuid(): number { return -1; } + cwd(): string { return '/'; } }; } diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index d6a7d0446a2..aa1eba1f6b5 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -97,12 +97,16 @@ /** * Support for a subset of access to node.js global `process`. + * + * Note: when `sandbox` is enabled, the only properties available + * are https://github.com/electron/electron/blob/master/docs/api/process.md#sandbox */ process: { get platform() { return process.platform; }, get env() { return process.env; }, get versions() { return process.versions; }, get type() { return 'renderer'; }, + get execPath() { return process.execPath; }, _whenEnvResolved: undefined, whenEnvResolved: @@ -117,35 +121,6 @@ return this._whenEnvResolved; }, - nextTick: - /** - * Adds callback to the "next tick queue". This queue is fully drained - * after the current operation on the JavaScript stack runs to completion - * and before the event loop is allowed to continue. - * - * @param {Function} callback - * @param {any[]} args - */ - function nextTick(callback, ...args) { - return process.nextTick(callback, ...args); - }, - - cwd: - /** - * @returns the current working directory. - */ - function () { - return process.cwd(); - }, - - getuid: - /** - * @returns the numeric user identity of the process - */ - function () { - return process.getuid(); - }, - getProcessMemoryInfo: /** * @returns {Promise} @@ -170,7 +145,7 @@ * Some information about the context we are running in. */ context: { - get sandbox() { return process.argv.includes('--enable-sandbox'); } + get sandbox() { return process.sandboxed; } } }; diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 923383b48db..3bd0c203e5b 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -12,32 +12,27 @@ export interface ISandboxNodeProcess extends INodeProcess { * The process.platform property returns a string identifying the operating system platform * on which the Node.js process is running. */ - platform: 'win32' | 'linux' | 'darwin'; + readonly platform: 'win32' | 'linux' | 'darwin'; /** * The type will always be Electron renderer. */ - type: 'renderer'; + readonly type: 'renderer'; /** * A list of versions for the current node.js/electron configuration. */ - versions: { [key: string]: string | undefined }; + readonly versions: { [key: string]: string | undefined }; /** * The process.env property returns an object containing the user environment. */ - env: IProcessEnvironment; + readonly env: IProcessEnvironment; /** - * The current working directory. + * The `execPath` will be the location of the executable of this application. */ - cwd(): string; - - /** - * Returns the numeric user identity of the process. - */ - getuid(): number; + readonly execPath: string; /** * Allows to await resolving the full process environment by checking for the shell environment @@ -45,13 +40,6 @@ export interface ISandboxNodeProcess extends INodeProcess { */ whenEnvResolved(): Promise; - /** - * Adds callback to the "next tick queue". This queue is fully drained - * after the current operation on the JavaScript stack runs to completion - * and before the event loop is allowed to continue. - */ - nextTick(callback: (...args: any[]) => void, ...args: any[]): void; - /** * A listener on the process. Only a small subset of listener types are allowed. */ diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index 923eabd821d..934914f8aaa 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -10,7 +10,7 @@ import { OpenContext } from 'vs/platform/windows/node/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; -import { isMacintosh, isWindows, isRootUser, isLinux } from 'vs/base/common/platform'; +import { isMacintosh, isWindows, isLinux } from 'vs/base/common/platform'; import { ICommonNativeHostService, IOSProperties, IOSStatistics } from 'vs/platform/native/common/native'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; @@ -364,7 +364,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain if (isWindows) { isAdmin = (await import('native-is-elevated'))(); } else { - isAdmin = isRootUser(); + isAdmin = process.getuid() === 0; } return isAdmin; From eb6356cfd792b2a2c16faea2a21663176c70c1b4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Nov 2020 08:20:28 +0100 Subject: [PATCH 0030/1837] debt - properly implement interface --- .../environment/electron-main/environmentMainService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/environment/electron-main/environmentMainService.ts b/src/vs/platform/environment/electron-main/environmentMainService.ts index 8240ed281c8..178b9ee68d3 100644 --- a/src/vs/platform/environment/electron-main/environmentMainService.ts +++ b/src/vs/platform/environment/electron-main/environmentMainService.ts @@ -35,7 +35,7 @@ export interface IEnvironmentMainService extends INativeEnvironmentService { disableUpdates: boolean; } -export class EnvironmentMainService extends NativeEnvironmentService { +export class EnvironmentMainService extends NativeEnvironmentService implements IEnvironmentMainService { @memoize get backupHome(): string { return join(this.userDataPath, 'Backups'); } From 23a826ff3c5e794efea0497155785a855a8a4ccb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 19 Nov 2020 08:35:51 +0100 Subject: [PATCH 0031/1837] more jsdoc for #54938 --- src/vs/vscode.proposed.d.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index deea6fc5826..606da64d9da 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -744,6 +744,9 @@ declare module 'vscode' { //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 + /** + * A file decoration represents metadata that can be rendered with a file. + */ export class FileDecoration { /** @@ -784,7 +787,10 @@ declare module 'vscode' { export interface FileDecorationProvider { /** - * An event to signal decorations for one or many files have changed. + * An optional event to signal that decorations for one or many files have changed. + * + * + * *Note* that this event should be used to propagate information about children. * * @see [EventEmitter](#EventEmitter) */ @@ -793,6 +799,10 @@ declare module 'vscode' { /** * Provide decorations for a given uri. * + * *Note* that this function is only called when a file gets rendered in the UI. + * This means a decoration from a descendent that propagates upwards must be signaled + * to the editor via the [onDidChangeFileDecorations](#FileDecorationProvider.onDidChangeFileDecorations)-event. + * * @param uri The uri of the file to provide a decoration for. * @param token A cancellation token. * @returns A decoration or a thenable that resolves to such. @@ -801,6 +811,13 @@ declare module 'vscode' { } export namespace window { + + /** + * Register a file decoration provider. + * + * @param provider A [FileDecorationProvider](#FileDecorationProvider). + * @return A [disposable](#Disposable) that unregisters the provider. + */ export function registerFileDecorationProvider(provider: FileDecorationProvider): Disposable; } From 990ca74d2251620d73006ad7c3976becaefdc505 Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Thu, 19 Nov 2020 04:48:49 -0300 Subject: [PATCH 0032/1837] Docs for FileSystemWatcher limitations (#110858) --- src/vs/vscode.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 76436647979..3d20c0e282f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -9966,6 +9966,8 @@ declare module 'vscode' { * flags to ignore certain kinds of events can be provided. To stop listening to events the watcher must be disposed. * * *Note* that only files within the current [workspace folders](#workspace.workspaceFolders) can be watched. + * *Note* that when watching for file changes such as '**​/*.js', notifications will not be sent when a parent folder is + * moved or deleted (this is a known limitation of the current implementation and may change in the future). * * @param globPattern A [glob pattern](#GlobPattern) that is applied to the absolute paths of created, changed, * and deleted files. Use a [relative pattern](#RelativePattern) to limit events to a certain [workspace folder](#WorkspaceFolder). From 06bf8e6539025943b3b22919c2faf352a73b7a16 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Nov 2020 10:11:08 +0100 Subject: [PATCH 0033/1837] editors - update readonly options when file providers change (fix #110854) --- .../browser/parts/editor/textDiffEditor.ts | 22 ++++++++++++++++++- .../files/browser/editors/textFileEditor.ts | 12 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 67e7442ffd7..1b239b03cdd 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -31,6 +31,7 @@ import { EditorActivation, IEditorOptions } from 'vs/platform/editor/common/edit import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { isEqual } from 'vs/base/common/resources'; import { multibyteAwareBtoa } from 'vs/base/browser/dom'; +import { IFileService } from 'vs/platform/files/common/files'; /** * The text editor that leverages the diff text editor for the editing experience. @@ -61,9 +62,28 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan @ITextResourceConfigurationService configurationService: ITextResourceConfigurationService, @IEditorService editorService: IEditorService, @IThemeService themeService: IThemeService, - @IEditorGroupsService editorGroupService: IEditorGroupsService + @IEditorGroupsService editorGroupService: IEditorGroupsService, + @IFileService private readonly fileService: IFileService ) { super(TextDiffEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, editorService, editorGroupService); + + // Listen to file system provider changes + this._register(this.fileService.onDidChangeFileSystemProviderCapabilities(e => this.onDidFileSystemProviderChange(e.scheme))); + this._register(this.fileService.onDidChangeFileSystemProviderRegistrations(e => this.onDidFileSystemProviderChange(e.scheme))); + } + + private onDidFileSystemProviderChange(scheme: string): void { + const control = this.getControl(); + const input = this.input; + + if (control && input instanceof DiffEditorInput) { + if (input.originalInput.resource?.scheme === scheme || input.modifiedInput.resource?.scheme === scheme) { + control.updateOptions({ + readOnly: input.modifiedInput.isReadonly(), + originalEditable: !input.originalInput.isReadonly() + }); + } + } } protected onWillCloseEditorInGroup(editor: IEditorInput): void { diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 2ba73b76a95..82731d702fa 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -60,6 +60,10 @@ export class TextFileEditor extends BaseTextEditor { // Move view state for moved files this._register(this.fileService.onDidRunOperation(e => this.onDidRunOperation(e))); + + // Listen to file system provider changes + this._register(this.fileService.onDidChangeFileSystemProviderCapabilities(e => this.onDidFileSystemProviderChange(e.scheme))); + this._register(this.fileService.onDidChangeFileSystemProviderRegistrations(e => this.onDidFileSystemProviderChange(e.scheme))); } private onDidFilesChange(e: FileChangesEvent): void { @@ -75,6 +79,14 @@ export class TextFileEditor extends BaseTextEditor { } } + private onDidFileSystemProviderChange(scheme: string): void { + const control = this.getControl(); + const input = this.input; + if (control && input?.resource.scheme === scheme) { + control.updateOptions({ readOnly: input.isReadonly() }); + } + } + protected onWillCloseEditorInGroup(editor: IEditorInput): void { // React to editors closing to preserve or clear view state. This needs to happen From 71fce013c91ced683dd5b3694f19773941555c2a Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Nov 2020 10:25:02 +0100 Subject: [PATCH 0034/1837] Weird on-type-rename-decoration. Fixes #110878 --- src/vs/editor/contrib/rename/media/onTypeRename.css | 10 ---------- src/vs/editor/contrib/rename/onTypeRename.ts | 1 - 2 files changed, 11 deletions(-) delete mode 100644 src/vs/editor/contrib/rename/media/onTypeRename.css diff --git a/src/vs/editor/contrib/rename/media/onTypeRename.css b/src/vs/editor/contrib/rename/media/onTypeRename.css deleted file mode 100644 index 16bb0178528..00000000000 --- a/src/vs/editor/contrib/rename/media/onTypeRename.css +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.monaco-editor .on-type-rename-decoration { - border-left: 1px solid transparent; - /* So border can be transparent */ - background-clip: padding-box; -} diff --git a/src/vs/editor/contrib/rename/onTypeRename.ts b/src/vs/editor/contrib/rename/onTypeRename.ts index e6b164f35d3..b0bfc7c585d 100644 --- a/src/vs/editor/contrib/rename/onTypeRename.ts +++ b/src/vs/editor/contrib/rename/onTypeRename.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/onTypeRename'; import * as nls from 'vs/nls'; import { registerEditorContribution, registerModelAndPositionCommand, EditorAction, EditorCommand, ServicesAccessor, registerEditorAction, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; import * as arrays from 'vs/base/common/arrays'; From cf3194d1845fdd0b0efed8a05cea7268dba55d1c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 10:51:02 +0100 Subject: [PATCH 0035/1837] Add tests and improve the implementation --- .../common/controller/cursorWordOperations.ts | 119 +++++++++++++---- .../test/wordOperations.test.ts | 121 +++++++++++++++++- .../contrib/wordOperations/wordOperations.ts | 12 +- 3 files changed, 212 insertions(+), 40 deletions(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index 6aaf4d00ac0..73820f9af30 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -438,7 +438,7 @@ export class WordOperations { return new Range(lineNumber, column, position.lineNumber, position.column); } - public static deleteInsideWord(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range | null { + public static deleteInsideWord(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range { if (!selection.isEmpty()) { return selection; } @@ -453,42 +453,105 @@ export class WordOperations { return this._deleteInsideWordDetermineDeleteRange(wordSeparators, model, position); } + private static _charAtIsWhitespace(str: string, index: number): boolean { + const charCode = str.charCodeAt(index); + return (charCode === CharCode.Space || charCode === CharCode.Tab); + } + private static _deleteInsideWordWhitespace(model: ICursorSimpleModel, position: Position): Range | null { const lineContent = model.getLineContent(position.lineNumber); - const startIndex1 = position.column - 1; // deleteRight - const startIndex2 = position.column - 2; // deleteLeft - const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex1); - const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex2); - if ((startIndex1 + 1 < firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 >= firstNonWhitespace && lastNonWhitespace + 1 < startIndex2) || (startIndex1 + 1 <= firstNonWhitespace && lastNonWhitespace + 1 === startIndex2)) { - return new Range(position.lineNumber, lastNonWhitespace + 2, position.lineNumber, firstNonWhitespace + 1); + const lineContentLength = lineContent.length; + + if (lineContentLength === 0) { + // empty line + return null; } - return null; + + let leftIndex = Math.max(position.column - 2, 0); + if (!this._charAtIsWhitespace(lineContent, leftIndex)) { + // touches a non-whitespace character to the left + return null; + } + + let rightIndex = Math.min(position.column - 1, lineContentLength - 1); + if (!this._charAtIsWhitespace(lineContent, rightIndex)) { + // touches a non-whitespace character to the right + return null; + } + + // walk over whitespace to the left + while (leftIndex > 0 && this._charAtIsWhitespace(lineContent, leftIndex - 1)) { + leftIndex--; + } + + // walk over whitespace to the right + while (rightIndex + 1 < lineContentLength && this._charAtIsWhitespace(lineContent, rightIndex + 1)) { + rightIndex++; + } + + return new Range(position.lineNumber, leftIndex + 1, position.lineNumber, rightIndex + 2); } private static _deleteInsideWordDetermineDeleteRange(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Range { - let lineNumber = position.lineNumber; - let column = position.column; - let columnEnd = position.column; - let lineContent = model.getLineContent(position.lineNumber); - - let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); - - if (prevWordOnLine) { - column = prevWordOnLine.start + 1; - columnEnd = prevWordOnLine.end + 1; - const chCode = lineContent.charCodeAt(columnEnd - 1); - if (chCode === CharCode.Space || chCode === CharCode.Tab) { - columnEnd++; - } - } else { - if (column > 1) { - column = 1; + const lineContent = model.getLineContent(position.lineNumber); + const lineLength = lineContent.length; + if (lineLength === 0) { + // empty line + if (position.lineNumber > 1) { + return new Range(position.lineNumber - 1, model.getLineMaxColumn(position.lineNumber - 1), position.lineNumber, 1); } else { - lineNumber--; - column = model.getLineMaxColumn(lineNumber); + if (position.lineNumber < model.getLineCount()) { + return new Range(position.lineNumber, 1, position.lineNumber + 1, 1); + } else { + // empty model + return new Range(position.lineNumber, 1, position.lineNumber, 1); + } } } - return new Range(lineNumber, column, position.lineNumber, columnEnd); + + const touchesWord = (word: IFindWordResult) => { + return (word.start + 1 <= position.column && position.column <= word.end + 1); + }; + const createRangeWithPosition = (startColumn: number, endColumn: number) => { + startColumn = Math.min(startColumn, position.column); + endColumn = Math.max(endColumn, position.column); + return new Range(position.lineNumber, startColumn, position.lineNumber, endColumn); + }; + const deleteWordAndAdjacentWhitespace = (word: IFindWordResult) => { + let startColumn = word.start + 1; + let endColumn = word.end + 1; + let expandedToTheRight = false; + while (endColumn - 1 < lineLength && this._charAtIsWhitespace(lineContent, endColumn - 1)) { + expandedToTheRight = true; + endColumn++; + } + if (!expandedToTheRight) { + while (startColumn > 1 && this._charAtIsWhitespace(lineContent, startColumn - 2)) { + startColumn--; + } + } + return createRangeWithPosition(startColumn, endColumn); + }; + + const prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); + if (prevWordOnLine && touchesWord(prevWordOnLine)) { + return deleteWordAndAdjacentWhitespace(prevWordOnLine); + } + const nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, position); + if (nextWordOnLine && touchesWord(nextWordOnLine)) { + return deleteWordAndAdjacentWhitespace(nextWordOnLine); + } + if (prevWordOnLine && nextWordOnLine) { + return createRangeWithPosition(prevWordOnLine.end + 1, nextWordOnLine.start + 1); + } + if (prevWordOnLine) { + return createRangeWithPosition(prevWordOnLine.start + 1, prevWordOnLine.end + 1); + } + if (nextWordOnLine) { + return createRangeWithPosition(nextWordOnLine.start + 1, nextWordOnLine.end + 1); + } + + return createRangeWithPosition(1, lineLength + 1); } public static _deleteWordPartLeft(model: ICursorSimpleModel, selection: Selection): Range { diff --git a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts index ad2afd196a8..292390454bb 100644 --- a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts +++ b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts @@ -9,7 +9,7 @@ import { EditorCommand } from 'vs/editor/browser/editorExtensions'; import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { deserializePipePositions, serializePipePositions, testRepeatedActionAndExtractPositions } from 'vs/editor/contrib/wordOperations/test/wordTestUtils'; -import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight, CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect } from 'vs/editor/contrib/wordOperations/wordOperations'; +import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight, CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect, DeleteInsideWord } from 'vs/editor/contrib/wordOperations/wordOperations'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; @@ -42,6 +42,7 @@ suite('WordOperations', () => { const _deleteWordRight = new DeleteWordRight(); const _deleteWordStartRight = new DeleteWordStartRight(); const _deleteWordEndRight = new DeleteWordEndRight(); + const _deleteInsideWord = new DeleteInsideWord(); function runEditorCommand(editor: ICodeEditor, command: EditorCommand): void { command.runEditorCommand(null, editor, null); @@ -88,6 +89,9 @@ suite('WordOperations', () => { function deleteWordEndRight(editor: ICodeEditor): void { runEditorCommand(editor, _deleteWordEndRight); } + function deleteInsideWord(editor: ICodeEditor): void { + runEditorCommand(editor, _deleteInsideWord); + } test('cursorWordLeft - simple', () => { const EXPECTED = [ @@ -750,4 +754,119 @@ suite('WordOperations', () => { model.dispose(); mode.dispose(); }); + + test('deleteInsideWord - empty line', () => { + withTestCodeEditor([ + 'Line1', + '', + 'Line2' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(2, 1)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'Line1\nLine2'); + }); + }); + + test('deleteInsideWord - in whitespace 1', () => { + withTestCodeEditor([ + 'Just some text.' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 6)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'Justsome text.'); + }); + }); + + test('deleteInsideWord - in whitespace 2', () => { + withTestCodeEditor([ + 'Just some text.' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 6)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'Justsome text.'); + }); + }); + + test('deleteInsideWord - in whitespace 3', () => { + withTestCodeEditor([ + 'Just "some text.' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 6)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'Just"some text.'); + deleteInsideWord(editor); + assert.equal(model.getValue(), '"some text.'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'some text.'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'text.'); + deleteInsideWord(editor); + assert.equal(model.getValue(), '.'); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + }); + }); + + test('deleteInsideWord - in non-words', () => { + withTestCodeEditor([ + 'x=3+4+5+6' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 7)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'x=3+45+6'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'x=3++6'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'x=36'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'x='); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'x'); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + }); + }); + + test('deleteInsideWord - in words 1', () => { + withTestCodeEditor([ + 'This is interesting' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 7)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'This interesting'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'This'); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + }); + }); + + test('deleteInsideWord - in words 2', () => { + withTestCodeEditor([ + 'This is interesting' + ], {}, (editor, _) => { + const model = editor.getModel()!; + editor.setPosition(new Position(1, 7)); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'This interesting'); + deleteInsideWord(editor); + assert.equal(model.getValue(), 'This'); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + deleteInsideWord(editor); + assert.equal(model.getValue(), ''); + }); + }); }); diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index e5f3ed382e0..6b0cedb1dcd 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -498,7 +498,7 @@ export class DeleteInsideWord extends EditorCommand { const selections = editor.getSelections(); const commands = selections.map((sel) => { - const deleteRange = this._delete(wordSeparators, model, sel); + const deleteRange = WordOperations.deleteInsideWord(wordSeparators, model, sel); return new ReplaceCommand(deleteRange, ''); }); @@ -506,16 +506,6 @@ export class DeleteInsideWord extends EditorCommand { editor.executeCommands(this.id, commands); editor.pushUndoStop(); } - - private _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection): Range { - let r = WordOperations.deleteInsideWord(wordSeparators, model, selection); - if (r) { - return r; - } - const lineCount = model.getLineCount(); - const maxColumn = model.getLineMaxColumn(lineCount); - return new Range(lineCount, maxColumn, lineCount, maxColumn); - } } registerEditorCommand(new CursorWordStartLeft()); From 8374d6a4c7f29a8d8e9e20bb5ae40f4f52c509a7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 19 Nov 2020 10:54:19 +0100 Subject: [PATCH 0036/1837] Detect ports to forward more often Part of microsoft/vscode-remote-release#4021 --- .../api/browser/mainThreadTunnelService.ts | 20 +------ .../workbench/api/common/extHost.protocol.ts | 5 +- .../api/common/extHostTunnelService.ts | 6 -- .../api/node/extHostTunnelService.ts | 28 +++++----- .../contrib/remote/browser/tunnelView.ts | 31 ----------- .../remote/common/remoteExplorerService.ts | 55 +++++++------------ 6 files changed, 36 insertions(+), 109 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index e5577d55cd3..3b91d45d95a 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -47,8 +47,8 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun }); } - async $registerCandidateFinder(): Promise { - this.remoteExplorerService.registerCandidateFinder(() => this._proxy.$findCandidatePorts()); + async $onFoundNewCandidates(candidates: { host: string, port: number, detail: string }[]): Promise { + this.remoteExplorerService.onFoundNewCandidates(candidates); } async $tunnelServiceReady(): Promise { @@ -78,22 +78,6 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun this.tunnelService.setTunnelProvider(tunnelProvider); } - async $setCandidateFilter(): Promise { - this._register(this.remoteExplorerService.setCandidateFilter(async (candidates: { host: string, port: number, detail: string }[]): Promise<{ host: string, port: number, detail: string }[]> => { - const filters: boolean[] = await this._proxy.$filterCandidates(candidates); - const filteredCandidates: { host: string, port: number, detail: string }[] = []; - if (filters.length !== candidates.length) { - return candidates; - } - for (let i = 0; i < candidates.length; i++) { - if (filters[i]) { - filteredCandidates.push(candidates[i]); - } - } - return filteredCandidates; - })); - } - dispose(): void { } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 8c0dbb34885..f26830c9607 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -949,10 +949,9 @@ export interface MainThreadTunnelServiceShape extends IDisposable { $openTunnel(tunnelOptions: TunnelOptions): Promise; $closeTunnel(remote: { host: string, port: number }): Promise; $getTunnels(): Promise; - $registerCandidateFinder(): Promise; $setTunnelProvider(): Promise; - $setCandidateFilter(): Promise; $tunnelServiceReady(): Promise; + $onFoundNewCandidates(candidates: { host: string, port: number, detail: string }[]): Promise; } export interface MainThreadTimelineShape extends IDisposable { @@ -1742,8 +1741,6 @@ export interface MainThreadThemingShape extends IDisposable { } export interface ExtHostTunnelServiceShape { - $findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]>; - $filterCandidates(candidates: { host: string, port: number, detail: string }[]): Promise; $forwardPort(tunnelOptions: TunnelOptions): Promise | undefined; $closeTunnel(remote: { host: string, port: number }, silent?: boolean): Promise; $onDidTunnelsChange(): Promise; diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index ca249267d38..2ac455c6acf 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -57,12 +57,6 @@ export class ExtHostTunnelService implements IExtHostTunnelService { async getTunnels(): Promise { return []; } - async $findCandidatePorts(): Promise<{ host: string, port: number; detail: string; }[]> { - return []; - } - async $filterCandidates(candidates: { host: string, port: number, detail: string }[]): Promise { - return candidates.map(() => true); - } async setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise { await this._proxy.$tunnelServiceReady(); return { dispose: () => { } }; diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 5a72fa3cfed..c9faff3d01f 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -69,21 +69,25 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe return this._proxy.$getTunnels(); } - registerCandidateFinder(): Promise { - return this._proxy.$registerCandidateFinder(); - } - - $filterCandidates(candidates: { host: string, port: number, detail: string }[]): Promise { - return Promise.all(candidates.map(candidate => { - return this._showCandidatePort(candidate.host, candidate.port, candidate.detail); - })); + registerCandidateFinder(): void { + // Every two seconds, scan to see if the candidate ports have changed; + if (isLinux) { + let oldPorts: { host: string, port: number, detail: string }[] | undefined = undefined; + setInterval(async () => { + const newPorts = await this.findCandidatePorts(); + if (!oldPorts || (JSON.stringify(oldPorts) !== JSON.stringify(newPorts))) { + oldPorts = newPorts; + this._proxy.$onFoundNewCandidates(oldPorts.filter(async (candidate) => await this._showCandidatePort(candidate.host, candidate.port, candidate.detail))); + return; + } + }, 2000); + } } async setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise { if (provider) { if (provider.showCandidatePort) { this._showCandidatePort = provider.showCandidatePort; - await this._proxy.$setCandidateFilter(); } if (provider.tunnelFactory) { this._forwardPortProvider = provider.tunnelFactory; @@ -133,11 +137,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe } - async $findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]> { - if (!isLinux) { - return []; - } - + async findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]> { const ports: { host: string, port: number, detail: string }[] = []; let tcp: string = ''; let tcp6: string = ''; diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index db29396d773..52018fae5a6 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -936,18 +936,6 @@ namespace CopyAddressAction { } } -namespace RefreshTunnelViewAction { - export const ID = 'remote.tunnel.refresh'; - export const LABEL = nls.localize('remote.tunnel.refreshView', "Refresh"); - - export function handler(): ICommandHandler { - return (accessor, arg) => { - const remoteExplorerService = accessor.get(IRemoteExplorerService); - return remoteExplorerService.refresh(); - }; - } -} - namespace ChangeLocalPortAction { export const ID = 'remote.tunnel.changeLocalPort'; export const LABEL = nls.localize('remote.tunnel.changeLocalPort', "Change Local Port"); @@ -1022,7 +1010,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: CopyAddressAction.inlineHandler() }); CommandsRegistry.registerCommand(CopyAddressAction.COMMANDPALETTE_ID, CopyAddressAction.commandPaletteHandler()); -CommandsRegistry.registerCommand(RefreshTunnelViewAction.ID, RefreshTunnelViewAction.handler()); CommandsRegistry.registerCommand(ChangeLocalPortAction.ID, ChangeLocalPortAction.handler()); MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ @@ -1055,15 +1042,6 @@ MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({ icon: { id: 'codicon/plus' } } })); -MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({ - group: 'navigation', - order: 1, - command: { - id: RefreshTunnelViewAction.ID, - title: RefreshTunnelViewAction.LABEL, - icon: { id: 'codicon/refresh' } - } -})); MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ group: '0_manage', order: 0, @@ -1109,15 +1087,6 @@ MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ }, when: ContextKeyExpr.or(TunnelTypeContextKey.isEqualTo(TunnelType.Candidate), TunnelTypeContextKey.isEqualTo(TunnelType.Add)) })); -MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ - group: '0_manage', - order: 2, - command: { - id: RefreshTunnelViewAction.ID, - title: RefreshTunnelViewAction.LABEL, - }, - when: TunnelTypeContextKey.isEqualTo(TunnelType.Candidate) -})); MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ group: '1_manage', order: 1, diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 2ec634e046d..de784029338 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -90,7 +90,6 @@ export class TunnelModel extends Disposable { private _onPortName: Emitter<{ host: string, port: number }> = new Emitter(); public onPortName: Event<{ host: string, port: number }> = this._onPortName.event; private _candidates: { host: string, port: number, detail: string }[] = []; - private _candidateFinder: (() => Promise<{ host: string, port: number, detail: string }[]>) | undefined; private _onCandidatesChanged: Emitter = new Emitter(); public onCandidatesChanged: Event = this._onCandidatesChanged.event; private _candidateFilter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined; @@ -217,40 +216,29 @@ export class TunnelModel extends Disposable { this._onForwardPort.fire(); } - registerCandidateFinder(finder: () => Promise<{ host: string, port: number, detail: string }[]>): void { - this._candidateFinder = finder; - this._onCandidatesChanged.fire(); - } - setCandidateFilter(filter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined): void { this._candidateFilter = filter; } - get candidates(): Promise<{ host: string, port: number, detail: string }[]> { - return this.updateCandidates().then(() => this._candidates); - } - - private async updateCandidates(): Promise { - if (this._candidateFinder) { - let candidates = await this._candidateFinder(); - if (this._candidateFilter && (candidates.length > 0)) { - candidates = await this._candidateFilter(candidates); - } - this._candidates = candidates.map(value => { - const nullIndex = value.detail.indexOf('\0'); - const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim(); - return { - host: value.host, - port: value.port, - detail - }; - }); + async setCandidates(candidates: { host: string, port: number, detail: string }[]) { + let processedCandidates = candidates; + if (this._candidateFilter) { + processedCandidates = await this._candidateFilter(candidates); } + this._candidates = processedCandidates.map(value => { + const nullIndex = value.detail.indexOf('\0'); + const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim(); + return { + host: value.host, + port: value.port, + detail + }; + }); + this._onCandidatesChanged.fire(); } - async refresh(): Promise { - await this.updateCandidates(); - this._onCandidatesChanged.fire(); + get candidates(): { host: string, port: number, detail: string }[] { + return this._candidates; } } @@ -265,9 +253,8 @@ export interface IRemoteExplorerService { forward(remote: { host: string, port: number }, localPort?: number, name?: string): Promise; close(remote: { host: string, port: number }): Promise; setTunnelInformation(tunnelInformation: TunnelInformation | undefined): void; - registerCandidateFinder(finder: () => Promise<{ host: string, port: number, detail: string }[]>): void; setCandidateFilter(filter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined): IDisposable; - refresh(): Promise; + onFoundNewCandidates(candidates: { host: string, port: number, detail: string }[]): void; restore(): Promise; } @@ -340,10 +327,6 @@ class RemoteExplorerService implements IRemoteExplorerService { this._editable.data : undefined; } - registerCandidateFinder(finder: () => Promise<{ host: string, port: number, detail: string }[]>): void { - this.tunnelModel.registerCandidateFinder(finder); - } - setCandidateFilter(filter: (candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>): IDisposable { if (!filter) { return { @@ -358,8 +341,8 @@ class RemoteExplorerService implements IRemoteExplorerService { }; } - refresh(): Promise { - return this.tunnelModel.refresh(); + onFoundNewCandidates(candidates: { host: string, port: number, detail: string }[]): void { + this.tunnelModel.setCandidates(candidates); } restore(): Promise { From 3665005621c68ce13176cc1843e8438d36f78b81 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 19 Nov 2020 11:16:16 +0100 Subject: [PATCH 0037/1837] add undo options (undo group id, isUndoing) to working copy service and bulk edit logic --- .../browser/services/bulkEditService.ts | 1 + .../api/browser/mainThreadBulkEdits.ts | 4 +- .../mainThreadFileSystemEventService.ts | 10 +++-- .../workbench/api/common/extHost.protocol.ts | 4 +- .../common/extHostFileSystemEventService.ts | 12 +++--- .../bulkEdit/browser/bulkEditService.ts | 32 +++++++++++++--- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 36 +++++++++++------- .../workingCopyFileOperationParticipant.ts | 4 +- .../common/workingCopyFileService.ts | 38 ++++++++++--------- 9 files changed, 89 insertions(+), 52 deletions(-) diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts index 82806436eb5..62deab309e2 100644 --- a/src/vs/editor/browser/services/bulkEditService.ts +++ b/src/vs/editor/browser/services/bulkEditService.ts @@ -70,6 +70,7 @@ export interface IBulkEditOptions { label?: string; quotableLabel?: string; undoRedoSource?: UndoRedoSource; + undoRedoGroupId?: number; } export interface IBulkEditResult { diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts index b6ee8cacf0e..5e1331caaad 100644 --- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts @@ -37,8 +37,8 @@ export class MainThreadBulkEdits implements MainThreadBulkEditsShape { dispose(): void { } - $tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise { + $tryApplyWorkspaceEdit(dto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise { const edits = reviveWorkspaceEditDto2(dto); - return this._bulkEditService.apply(edits).then(() => true, _err => false); + return this._bulkEditService.apply(edits, { undoRedoGroupId }).then(() => true, _err => false); } } diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index ca2c751ed56..b6e0a210a30 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -54,11 +54,13 @@ export class MainThreadFileSystemEventService { // BEFORE file operation - workingCopyFileService.addFileOperationParticipant({ - participate: (files, operation, progress, timeout, token) => { - return proxy.$onWillRunFileOperation(operation, files, timeout, token); + this._listener.add(workingCopyFileService.addFileOperationParticipant({ + participate: async (files, operation, undoRedoGroupId, isUndoing, _progress, timeout, token) => { + if (!isUndoing) { + return proxy.$onWillRunFileOperation(operation, files, undoRedoGroupId, timeout, token); + } } - }); + })); // AFTER file operation this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.files))); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 8c0dbb34885..7bcb59868b3 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -269,7 +269,7 @@ export interface ITextDocumentShowOptions { } export interface MainThreadBulkEditsShape extends IDisposable { - $tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto): Promise; + $tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise; } export interface MainThreadTextEditorsShape extends IDisposable { @@ -1139,7 +1139,7 @@ export interface SourceTargetPair { export interface ExtHostFileSystemEventServiceShape { $onFileEvent(events: FileSystemEvents): void; - $onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise; + $onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise; $onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void; } diff --git a/src/vs/workbench/api/common/extHostFileSystemEventService.ts b/src/vs/workbench/api/common/extHostFileSystemEventService.ts index c576f8f5e4c..0503a131b93 100644 --- a/src/vs/workbench/api/common/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/common/extHostFileSystemEventService.ts @@ -178,23 +178,23 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ }; } - async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise { + async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise { switch (operation) { case FileOperation.MOVE: - await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token); + await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, undoRedoGroupId, timeout, token); break; case FileOperation.DELETE: - await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token); + await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token); break; case FileOperation.CREATE: - await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token); + await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token); break; default: //ignore, dont send } } - private async _fireWillEvent(emitter: AsyncEmitter, data: Omit, timeout: number, token: CancellationToken): Promise { + private async _fireWillEvent(emitter: AsyncEmitter, data: Omit, undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise { const edits: WorkspaceEdit[] = []; @@ -222,7 +222,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors); dto.edits = dto.edits.concat(edits); } - return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto); + return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto, undoRedoGroupId); } } } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index f4a6e579404..100a96523e2 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -17,6 +17,7 @@ import { BulkTextEdits } from 'vs/workbench/contrib/bulkEdit/browser/bulkTextEdi import { BulkFileEdits } from 'vs/workbench/contrib/bulkEdit/browser/bulkFileEdits'; import { BulkCellEdits, ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; import { UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; +import { LinkedList } from 'vs/base/common/linkedList'; class BulkEdit { @@ -25,6 +26,7 @@ class BulkEdit { private readonly _editor: ICodeEditor | undefined, private readonly _progress: IProgress, private readonly _edits: ResourceEdit[], + private readonly _undoRedoGroup: UndoRedoGroup, private readonly _undoRedoSource: UndoRedoSource | undefined, @IInstantiationService private readonly _instaService: IInstantiationService, @ILogService private readonly _logService: ILogService, @@ -62,17 +64,15 @@ class BulkEdit { this._progress.report({ total: this._edits.length }); const progress: IProgress = { report: _ => this._progress.report({ increment: 1 }) }; - const undoRedoGroup = new UndoRedoGroup(); - let index = 0; for (let range of ranges) { const group = this._edits.slice(index, index + range); if (group[0] instanceof ResourceFileEdit) { - await this._performFileEdits(group, undoRedoGroup, this._undoRedoSource, progress); + await this._performFileEdits(group, this._undoRedoGroup, this._undoRedoSource, progress); } else if (group[0] instanceof ResourceTextEdit) { - await this._performTextEdits(group, undoRedoGroup, this._undoRedoSource, progress); + await this._performTextEdits(group, this._undoRedoGroup, this._undoRedoSource, progress); } else if (group[0] instanceof ResourceNotebookCellEdit) { - await this._performCellEdits(group, undoRedoGroup, this._undoRedoSource, progress); + await this._performCellEdits(group, this._undoRedoGroup, this._undoRedoSource, progress); } else { console.log('UNKNOWN EDIT'); } @@ -103,6 +103,7 @@ export class BulkEditService implements IBulkEditService { declare readonly _serviceBrand: undefined; + private readonly _activeUndoRedoGroups = new LinkedList(); private _previewHandler?: IBulkEditPreviewHandler; constructor( @@ -148,11 +149,30 @@ export class BulkEditService implements IBulkEditService { codeEditor = undefined; } + // undo-redo-group: if a group id is passed then try to find it + // in the list of active edits. otherwise (or when not found) + // create a separate undo-redo-group + let undoRedoGroup: UndoRedoGroup | undefined; + let undoRedoGroupRemove = () => { }; + if (typeof options?.undoRedoGroupId === 'number') { + for (let candidate of this._activeUndoRedoGroups) { + if (candidate.id === options.undoRedoGroupId) { + undoRedoGroup = candidate; + break; + } + } + } + if (!undoRedoGroup) { + undoRedoGroup = new UndoRedoGroup(); + undoRedoGroupRemove = this._activeUndoRedoGroups.push(undoRedoGroup); + } + const bulkEdit = this._instaService.createInstance( BulkEdit, options?.quotableLabel || options?.label, codeEditor, options?.progress ?? Progress.None, edits, + undoRedoGroup, options?.undoRedoSource ); @@ -164,6 +184,8 @@ export class BulkEditService implements IBulkEditService { // console.log(err); this._logService.error(err); throw err; + } finally { + undoRedoGroupRemove(); } } } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index f1c29e46af9..96036bd6ad4 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -17,6 +17,11 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import * as resources from 'vs/base/common/resources'; +interface IFileOperationUndoRedoInfo { + undoRedoGroupId?: number; + isUndoing?: boolean; +} + interface IFileOperation { uris: URI[]; perform(): Promise; @@ -36,6 +41,7 @@ class RenameOperation implements IFileOperation { readonly newUri: URI, readonly oldUri: URI, readonly options: WorkspaceFileEditOptions, + readonly undoRedoInfo: IFileOperationUndoRedoInfo, @IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService, @IFileService private readonly _fileService: IFileService, ) { } @@ -50,8 +56,8 @@ class RenameOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } - await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite }); - return new RenameOperation(this.oldUri, this.newUri, this.options, this._workingCopyFileService, this._fileService); + await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }); + return new RenameOperation(this.oldUri, this.newUri, this.options, { isUndoing: true }, this._workingCopyFileService, this._fileService); } toString(): string { @@ -70,6 +76,7 @@ class CopyOperation implements IFileOperation { readonly newUri: URI, readonly oldUri: URI, readonly options: WorkspaceFileEditOptions, + readonly undoRedoInfo: IFileOperationUndoRedoInfo, @IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService, @IFileService private readonly _fileService: IFileService, @IInstantiationService private readonly _instaService: IInstantiationService @@ -85,8 +92,8 @@ class CopyOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } - await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite }); - return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, true); + await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }); + return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, true); } toString(): string { @@ -99,6 +106,7 @@ class CreateOperation implements IFileOperation { constructor( readonly newUri: URI, readonly options: WorkspaceFileEditOptions, + readonly undoRedoInfo: IFileOperationUndoRedoInfo, readonly contents: VSBuffer | undefined, @IFileService private readonly _fileService: IFileService, @IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService, @@ -115,11 +123,11 @@ class CreateOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } if (this.options.folder) { - await this._workingCopyFileService.createFolder(this.newUri); + await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo }); } else { - await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite }); + await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }); } - return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, !this.options.folder); + return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder); } toString(): string { @@ -133,6 +141,7 @@ class DeleteOperation implements IFileOperation { constructor( readonly oldUri: URI, readonly options: WorkspaceFileEditOptions, + readonly undoRedoInfo: IFileOperationUndoRedoInfo, private readonly _undoesCreateOperation: boolean, @IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService, @IFileService private readonly _fileService: IFileService, @@ -164,8 +173,8 @@ class DeleteOperation implements IFileOperation { } const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); - await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive }); - return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, contents); + await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }); + return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, { isUndoing: true }, contents); } toString(): string { @@ -221,6 +230,7 @@ export class BulkFileEdits { async apply(): Promise { const undoOperations: IFileOperation[] = []; + const undoRedoInfo = { undoRedoGroupId: this._undoRedoGroup.id }; for (const edit of this._edits) { this._progress.report(undefined); @@ -228,15 +238,15 @@ export class BulkFileEdits { let op: IFileOperation | undefined; if (edit.newResource && edit.oldResource && !options.copy) { // rename - op = this._instaService.createInstance(RenameOperation, edit.newResource, edit.oldResource, options); + op = this._instaService.createInstance(RenameOperation, edit.newResource, edit.oldResource, options, undoRedoInfo); } else if (edit.newResource && edit.oldResource && options.copy) { - op = this._instaService.createInstance(CopyOperation, edit.newResource, edit.oldResource, options); + op = this._instaService.createInstance(CopyOperation, edit.newResource, edit.oldResource, options, undoRedoInfo); } else if (!edit.newResource && edit.oldResource) { // delete file - op = this._instaService.createInstance(DeleteOperation, edit.oldResource, options, false); + op = this._instaService.createInstance(DeleteOperation, edit.oldResource, options, undoRedoInfo, false); } else if (edit.newResource && !edit.oldResource) { // create file - op = this._instaService.createInstance(CreateOperation, edit.newResource, options, undefined); + op = this._instaService.createInstance(CreateOperation, edit.newResource, options, undoRedoInfo, undefined); } if (op) { const undoOp = await op.perform(); diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index 7d60ea29d7f..d7723c151a4 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -33,7 +33,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { return toDisposable(() => remove()); } - async participate(files: { source?: URI, target: URI }[], operation: FileOperation): Promise { + async participate(files: { source?: URI, target: URI }[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise { const timeout = this.configurationService.getValue('files.participants.timeout'); if (timeout <= 0) { return; // disabled @@ -53,7 +53,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { } try { - const promise = participant.participate(files, operation, progress, timeout, cts.token); + const promise = participant.participate(files, operation, undoRedoGroupId, isUndoing, progress, timeout, cts.token); await raceTimeout(promise, timeout, () => cts.dispose(true /* cancel */)); } catch (err) { this.logService.warn(err); diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 82123eccbb5..568268969e1 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -60,6 +60,8 @@ export interface IWorkingCopyFileOperationParticipant { participate( files: SourceTargetPair[], operation: FileOperation, + undoRedoGroupId: number | undefined, + isUndoing: boolean | undefined, progress: IProgress, timeout: number, token: CancellationToken @@ -130,7 +132,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise; + create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; /** * Will create a folder and any parent folder that needs to be created. @@ -141,7 +143,7 @@ export interface IWorkingCopyFileService { * Note: events will only be emitted for the provided resource, but not any * parent folders that are being created as part of the operation. */ - createFolder(resource: URI): Promise; + createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }): Promise; /** * Will move working copies matching the provided resources and corresponding children @@ -150,7 +152,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - move(files: Required[], options?: { overwrite?: boolean }): Promise; + move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; /** * Will copy working copies matching the provided resources and corresponding children @@ -159,7 +161,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - copy(files: Required[], options?: { overwrite?: boolean }): Promise; + copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; /** * Will delete working copies matching the provided resources and children @@ -168,7 +170,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean }): Promise; + delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; //#endregion @@ -237,15 +239,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi //#region File operations - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise { + create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { return this.doCreateFileOrFolder(resource, true, contents, options); } - createFolder(resource: URI, options?: { overwrite?: boolean }): Promise { - return this.doCreateFileOrFolder(resource, false); + createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { + return this.doCreateFileOrFolder(resource, false, undefined, options); } - async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise { + async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { // validate create operation before starting if (isFile) { @@ -256,7 +258,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi } // file operation participant - await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE); + await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options?.undoRedoGroupId, options?.isUndoing); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] }; @@ -284,15 +286,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stat; } - async move(files: Required[], options?: { overwrite?: boolean }): Promise { + async move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { return this.doMoveOrCopy(files, true, options); } - async copy(files: Required[], options?: { overwrite?: boolean }): Promise { + async copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { return this.doMoveOrCopy(files, false, options); } - private async doMoveOrCopy(files: Required[], move: boolean, options?: { overwrite?: boolean }): Promise { + private async doMoveOrCopy(files: Required[], move: boolean, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { const overwrite = options?.overwrite; const stats: IFileStatWithMetadata[] = []; @@ -305,7 +307,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi } // file operation participant - await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY); + await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, options?.undoRedoGroupId, options?.isUndoing); // before event const event = { correlationId: this.correlationIds++, operation: move ? FileOperation.MOVE : FileOperation.COPY, files }; @@ -344,7 +346,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stats; } - async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean }): Promise { + async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { // validate delete operation before starting for (const resource of resources) { @@ -356,7 +358,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi // file operation participant const files = resources.map(target => ({ target })); - await this.runFileOperationParticipants(files, FileOperation.DELETE); + await this.runFileOperationParticipants(files, FileOperation.DELETE, options?.undoRedoGroupId, options?.isUndoing); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.DELETE, files }; @@ -398,8 +400,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return this.fileOperationParticipants.addFileOperationParticipant(participant); } - private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation): Promise { - return this.fileOperationParticipants.participate(files, operation); + private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise { + return this.fileOperationParticipants.participate(files, operation, undoRedoGroupId, isUndoing); } //#endregion From 4a1cea9306d2d0fc39e608a035e331cb9b0c0189 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 19 Nov 2020 11:39:41 +0100 Subject: [PATCH 0038/1837] fix suggest explain mode for complex labels --- src/vs/editor/contrib/suggest/suggestWidgetDetails.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts b/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts index 5d0b4b8930d..9eed3c9900c 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts @@ -128,7 +128,7 @@ export class SuggestDetailsWidget { if (explainMode) { let md = ''; - md += `score: ${item.score[0]}${item.word ? `, compared '${item.completion.filterText && (item.completion.filterText + ' (filterText)') || item.completion.label}' with '${item.word}'` : ' (no prefix)'}\n`; + md += `score: ${item.score[0]}${item.word ? `, compared '${item.completion.filterText && (item.completion.filterText + ' (filterText)') || typeof item.completion.label === 'string' ? item.completion.label : item.completion.label.name}' with '${item.word}'` : ' (no prefix)'}\n`; md += `distance: ${item.distance}, see localityBonus-setting\n`; md += `index: ${item.idx}, based on ${item.completion.sortText && `sortText: "${item.completion.sortText}"` || 'label'}\n`; md += `commit characters: ${item.completion.commitCharacters}\n`; From 56c3caa68015bed30debf75c3a6ae19cccc36e09 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 19 Nov 2020 11:47:58 +0100 Subject: [PATCH 0039/1837] fix https://github.com/microsoft/vscode/issues/110666 --- src/vs/editor/contrib/suggest/suggestMemory.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestMemory.ts b/src/vs/editor/contrib/suggest/suggestMemory.ts index ffce8f095c2..dfb293635a2 100644 --- a/src/vs/editor/contrib/suggest/suggestMemory.ts +++ b/src/vs/editor/contrib/suggest/suggestMemory.ts @@ -82,8 +82,7 @@ export class LRUMemory extends Memory { private _seq = 0; memorize(model: ITextModel, pos: IPosition, item: CompletionItem): void { - const { label } = item.completion; - const key = `${model.getLanguageIdentifier().language}/${label}`; + const key = `${model.getLanguageIdentifier().language}/${item.textLabel}`; this._cache.set(key, { touch: this._seq++, type: item.completion.kind, @@ -111,7 +110,7 @@ export class LRUMemory extends Memory { // consider only top items break; } - const key = `${model.getLanguageIdentifier().language}/${items[i].completion.label}`; + const key = `${model.getLanguageIdentifier().language}/${items[i].textLabel}`; const item = this._cache.peek(key); if (item && item.touch > seq && item.type === items[i].completion.kind && item.insertText === items[i].completion.insertText) { seq = item.touch; From 76e1b21f4f8b8889ccc50da100e4d27091533cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 19 Nov 2020 12:19:55 +0100 Subject: [PATCH 0040/1837] fixes #110800 --- extensions/git/src/commands.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index e086c22ffc3..f3b830a6b04 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1841,8 +1841,8 @@ export class CommandCenter { @command('git.merge', { repository: true }) async merge(repository: Repository): Promise { const config = workspace.getConfiguration('git'); - const checkoutType = config.get('checkoutType') || 'all'; - const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; + const checkoutType = config.get('checkoutType'); + const includeRemotes = checkoutType === 'all' || checkoutType === 'remote' || checkoutType?.includes('remote'); const heads = repository.refs.filter(ref => ref.type === RefType.Head) .filter(ref => ref.name || ref.commit) @@ -1866,8 +1866,8 @@ export class CommandCenter { @command('git.rebase', { repository: true }) async rebase(repository: Repository): Promise { const config = workspace.getConfiguration('git'); - const checkoutType = config.get('checkoutType') || 'all'; - const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; + const checkoutType = config.get('checkoutType'); + const includeRemotes = checkoutType === 'all' || checkoutType === 'remote' || checkoutType?.includes('remote'); const heads = repository.refs.filter(ref => ref.type === RefType.Head) .filter(ref => ref.name !== repository.HEAD?.name) From 835ce347fe275bb8fe721c039e00295444cee8bd Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Nov 2020 12:38:22 +0100 Subject: [PATCH 0041/1837] bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b04d7ae8db6..77814f795c6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "ebde2b744571d0896f5fda65c5a180fa7d42d20a", + "distro": "0f63f1a9daa36740896d733b4b6b096825834ed5", "author": { "name": "Microsoft Corporation" }, From 22895e98562799b5a2ce9cc932c541c42fa4b3db Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 12:54:19 +0100 Subject: [PATCH 0042/1837] Introduce a server method to check if extensions are ready on server --- src/vs/code/node/cliProcessMain.ts | 2 +- .../workbench/electron-sandbox/sandbox.simpleservices.ts | 1 + .../services/remote/common/abstractRemoteAgentService.ts | 7 +++++++ .../remote/common/remoteAgentEnvironmentChannel.ts | 4 ++++ .../workbench/services/remote/common/remoteAgentService.ts | 2 ++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 4bbccf92de2..ccb82385ff2 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -126,7 +126,7 @@ export class Main { extensions.forEach(e => console.log(getId(e.manifest, showVersions))); } - private async installExtensions(extensions: string[], builtinExtensionIds: string[], isMachineScoped: boolean, force: boolean): Promise { + async installExtensions(extensions: string[], builtinExtensionIds: string[], isMachineScoped: boolean, force: boolean): Promise { const failed: string[] = []; const installedExtensionsManifests: IExtensionManifest[] = []; if (extensions.length) { diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index ab7e03cc712..8efc2ba91e0 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -427,6 +427,7 @@ export class SimpleRemoteAgentService implements IRemoteAgentService { async getRawEnvironment(): Promise { return null; } async scanExtensions(skipExtensions?: ExtensionIdentifier[]): Promise { return []; } async scanSingleExtension(extensionLocation: URI, isBuiltin: boolean): Promise { return null; } + async whenExtensionsReady(): Promise { } } //#endregion diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index 80662202397..1feea3dd9d3 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -74,6 +74,13 @@ export abstract class AbstractRemoteAgentService extends Disposable implements I return this._environment; } + whenExtensionsReady(): Promise { + return this._withChannel( + channel => RemoteExtensionEnvironmentChannelClient.whenExtensionsReady(channel), + undefined + ); + } + scanExtensions(skipExtensions: ExtensionIdentifier[] = []): Promise { return this._withChannel( (channel, connection) => RemoteExtensionEnvironmentChannelClient.scanExtensions(channel, connection.remoteAuthority, this._environmentService.extensionDevelopmentLocationURI, skipExtensions), diff --git a/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts b/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts index 5ed9d1e29bf..710c7589795 100644 --- a/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts +++ b/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts @@ -67,6 +67,10 @@ export class RemoteExtensionEnvironmentChannelClient { }; } + static async whenExtensionsReady(channel: IChannel): Promise { + await channel.call('whenExtensionsReady'); + } + static async scanExtensions(channel: IChannel, remoteAuthority: string, extensionDevelopmentPath: URI[] | undefined, skipExtensions: ExtensionIdentifier[]): Promise { const args: IScanExtensionsArguments = { language: platform.language, diff --git a/src/vs/workbench/services/remote/common/remoteAgentService.ts b/src/vs/workbench/services/remote/common/remoteAgentService.ts index b67d70a8708..3f7c05ea43c 100644 --- a/src/vs/workbench/services/remote/common/remoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/remoteAgentService.ts @@ -31,6 +31,8 @@ export interface IRemoteAgentService { * Get the remote environment. Can return an error. */ getRawEnvironment(): Promise; + + whenExtensionsReady(): Promise; /** * Scan remote extensions. */ From b0d577c1b76d28c621a7fbfa166b1cac1d65fc29 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 13:04:21 +0100 Subject: [PATCH 0043/1837] update doc --- src/vs/code/node/cliProcessMain.ts | 2 +- src/vs/platform/environment/node/argv.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index ccb82385ff2..b1dd54b6b9f 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -144,7 +144,7 @@ export class Main { const installedExtension = installed.find(i => areSameExtensions(i.identifier, { id })); if (installedExtension) { if (!version && !force) { - console.log(localize('alreadyInstalled-checkAndUpdate', "Extension '{0}' is already installed. Use '--force' option to check and update to newer version.", id)); + console.log(localize('alreadyInstalled-checkAndUpdate', "Extension '{0}' v{1} is already installed. Use '--force' option to update to latest version or provide `@${version}` to install a specific version, for example: '{2}@1.2.3'.", id, installedExtension.manifest.version, id)); continue; } if (version && installedExtension.manifest.version === version) { diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index e7b4a45e43d..637ce482401 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -55,7 +55,7 @@ export const OPTIONS: OptionDescriptions> = { 'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") }, 'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") }, 'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") }, - 'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id[@version] | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts. The identifier of an extension is always `${publisher}.${name}`. To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.") }, + 'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id[@version] | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. The identifier of an extension is always `${publisher}.${name}`. Use `--force` argument to update to latest version. To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.") }, 'uninstall-extension': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") }, 'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") }, From 83246704d4a035f667902ed2d5b0f1d954ad9a88 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 13:33:42 +0100 Subject: [PATCH 0044/1837] update distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 77814f795c6..f63dc5841b3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "0f63f1a9daa36740896d733b4b6b096825834ed5", + "distro": "bbac5f0265d748c479a89354eda09dcf92b8f4ee", "author": { "name": "Microsoft Corporation" }, @@ -195,4 +195,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file From a245552aa9daa8f9734a1ff12de7af86001ee541 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 16:04:12 +0100 Subject: [PATCH 0045/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f63dc5841b3..78b631db1fa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "bbac5f0265d748c479a89354eda09dcf92b8f4ee", + "distro": "272c364107e05252fcd164b8bd7fe476e2a02b0a", "author": { "name": "Microsoft Corporation" }, From d99a9ade8aac3a441fea60a17706d3727684270f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 16:33:37 +0100 Subject: [PATCH 0046/1837] Update to latest loader --- src/vs/loader.js | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/vs/loader.js b/src/vs/loader.js index 5a97ccfcc9a..571bb67f650 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -618,7 +618,7 @@ var AMDLoader; }; return OnlyOnceScriptLoader; }()); - var trustedTypesPolyfill = new /** @class */(function () { + var trustedTypesPolyfill = new /** @class */ (function () { function class_1() { } class_1.prototype.installIfNeeded = function () { @@ -673,7 +673,7 @@ var AMDLoader; BrowserScriptLoader.prototype.load = function (moduleManager, scriptSrc, callback, errorback) { if (/^node\|/.test(scriptSrc)) { var opts = moduleManager.getConfig().getOptionsLiteral(); - var nodeRequire = (opts.nodeRequire || AMDLoader.global.nodeRequire); + var nodeRequire = ensureRecordedNodeRequire(moduleManager.getRecorder(), (opts.nodeRequire || AMDLoader.global.nodeRequire)); var pieces = scriptSrc.split('|'); var moduleExports_1 = null; try { @@ -815,7 +815,7 @@ var AMDLoader; NodeScriptLoader.prototype.load = function (moduleManager, scriptSrc, callback, errorback) { var _this = this; var opts = moduleManager.getConfig().getOptionsLiteral(); - var nodeRequire = (opts.nodeRequire || AMDLoader.global.nodeRequire); + var nodeRequire = ensureRecordedNodeRequire(moduleManager.getRecorder(), (opts.nodeRequire || AMDLoader.global.nodeRequire)); var nodeInstrumenter = (opts.nodeInstrumenter || function (c) { return c; }); this._init(nodeRequire); this._initNodeRequire(nodeRequire, moduleManager); @@ -1022,6 +1022,24 @@ var AMDLoader; NodeScriptLoader._SUFFIX = '\n});'; return NodeScriptLoader; }()); + function ensureRecordedNodeRequire(recorder, _nodeRequire) { + if (_nodeRequire.__$__isRecorded) { + // it is already recorded + return _nodeRequire; + } + var nodeRequire = function nodeRequire(what) { + recorder.record(33 /* NodeBeginNativeRequire */, what); + try { + return _nodeRequire(what); + } + finally { + recorder.record(34 /* NodeEndNativeRequire */, what); + } + }; + nodeRequire.__$__isRecorded = true; + return nodeRequire; + } + AMDLoader.ensureRecordedNodeRequire = ensureRecordedNodeRequire; function createScriptLoader(env) { return new OnlyOnceScriptLoader(env); } @@ -1853,18 +1871,10 @@ var AMDLoader; }; function init() { if (typeof AMDLoader.global.require !== 'undefined' || typeof require !== 'undefined') { - var _nodeRequire_1 = (AMDLoader.global.require || require); - if (typeof _nodeRequire_1 === 'function' && typeof _nodeRequire_1.resolve === 'function') { + var _nodeRequire = (AMDLoader.global.require || require); + if (typeof _nodeRequire === 'function' && typeof _nodeRequire.resolve === 'function') { // re-expose node's require function - var nodeRequire = function (what) { - moduleManager.getRecorder().record(33 /* NodeBeginNativeRequire */, what); - try { - return _nodeRequire_1(what); - } - finally { - moduleManager.getRecorder().record(34 /* NodeEndNativeRequire */, what); - } - }; + var nodeRequire = AMDLoader.ensureRecordedNodeRequire(moduleManager.getRecorder(), _nodeRequire); AMDLoader.global.nodeRequire = nodeRequire; RequireFunc.nodeRequire = nodeRequire; RequireFunc.__$__nodeRequire = nodeRequire; From 508ef0928cc2aeb141475e92ffdd85bc4bf97b93 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 16:34:55 +0100 Subject: [PATCH 0047/1837] Better loader configuration for nodejs processes --- src/bootstrap-amd.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap-amd.js b/src/bootstrap-amd.js index 228c3d59e63..58355aebdba 100644 --- a/src/bootstrap-amd.js +++ b/src/bootstrap-amd.js @@ -18,7 +18,9 @@ loader.config({ catchError: true, nodeRequire: require, nodeMain: __filename, - 'vs/nls': nlsConfig + 'vs/nls': nlsConfig, + amdModulesPattern: /^vs\//, + recordStats: true }); // Running in Electron From d72f3fba3bba49bcb2957b094ac129d401e0895f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 16:35:47 +0100 Subject: [PATCH 0048/1837] Move LoaderStats down to `/base/` --- src/vs/base/common/amd.ts | 131 ++++++++++++++++++ .../performance/browser/perfviewEditor.ts | 126 +---------------- 2 files changed, 133 insertions(+), 124 deletions(-) diff --git a/src/vs/base/common/amd.ts b/src/vs/base/common/amd.ts index d8ce68b55e2..a0ee6f54d0c 100644 --- a/src/vs/base/common/amd.ts +++ b/src/vs/base/common/amd.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { mergeSort } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; /** @@ -18,3 +19,133 @@ export function getPathFromAmdModule(requirefn: typeof require, relativePath: st export function getUriFromAmdModule(requirefn: typeof require, relativePath: string): URI { return URI.parse(requirefn.toUrl(relativePath)); } + +export abstract class LoaderStats { + abstract get amdLoad(): [string, number][]; + abstract get amdInvoke(): [string, number][]; + abstract get nodeRequire(): [string, number][]; + abstract get nodeEval(): [string, number][]; + abstract get nodeRequireTotal(): number; + + + static get(): LoaderStats { + + + const amdLoadScript = new Map(); + const amdInvokeFactory = new Map(); + const nodeRequire = new Map(); + const nodeEval = new Map(); + + function mark(map: Map, stat: LoaderEvent) { + if (map.has(stat.detail)) { + // console.warn('BAD events, DOUBLE start', stat); + // map.delete(stat.detail); + return; + } + map.set(stat.detail, -stat.timestamp); + } + + function diff(map: Map, stat: LoaderEvent) { + let duration = map.get(stat.detail); + if (!duration) { + // console.warn('BAD events, end WITHOUT start', stat); + // map.delete(stat.detail); + return; + } + if (duration >= 0) { + // console.warn('BAD events, DOUBLE end', stat); + // map.delete(stat.detail); + return; + } + map.set(stat.detail, duration + stat.timestamp); + } + + const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp); + + for (const stat of stats) { + switch (stat.type) { + case LoaderEventType.BeginLoadingScript: + mark(amdLoadScript, stat); + break; + case LoaderEventType.EndLoadingScriptOK: + case LoaderEventType.EndLoadingScriptError: + diff(amdLoadScript, stat); + break; + + case LoaderEventType.BeginInvokeFactory: + mark(amdInvokeFactory, stat); + break; + case LoaderEventType.EndInvokeFactory: + diff(amdInvokeFactory, stat); + break; + + case LoaderEventType.NodeBeginNativeRequire: + mark(nodeRequire, stat); + break; + case LoaderEventType.NodeEndNativeRequire: + diff(nodeRequire, stat); + break; + + case LoaderEventType.NodeBeginEvaluatingScript: + mark(nodeEval, stat); + break; + case LoaderEventType.NodeEndEvaluatingScript: + diff(nodeEval, stat); + break; + } + } + + let nodeRequireTotal = 0; + nodeRequire.forEach(value => nodeRequireTotal += value); + + function to2dArray(map: Map): [string, number][] { + let res: [string, number][] = []; + map.forEach((value, index) => res.push([index, value])); + return res; + } + + return { + amdLoad: to2dArray(amdLoadScript), + amdInvoke: to2dArray(amdInvokeFactory), + nodeRequire: to2dArray(nodeRequire), + nodeEval: to2dArray(nodeEval), + nodeRequireTotal + }; + } + + static toMarkdownTable(header: string[], rows: Array>): string { + let result = ''; + + let lengths: number[] = []; + header.forEach((cell, ci) => { + lengths[ci] = cell.length; + }); + rows.forEach(row => { + row.forEach((cell, ci) => { + if (typeof cell === 'undefined') { + cell = row[ci] = '-'; + } + const len = cell.toString().length; + lengths[ci] = Math.max(len, lengths[ci]); + }); + }); + + // header + header.forEach((cell, ci) => { result += `| ${cell + ' '.repeat(lengths[ci] - cell.toString().length)} `; }); + result += '|\n'; + header.forEach((_cell, ci) => { result += `| ${'-'.repeat(lengths[ci])} `; }); + result += '|\n'; + + // cells + rows.forEach(row => { + row.forEach((cell, ci) => { + if (typeof cell !== 'undefined') { + result += `| ${cell + ' '.repeat(lengths[ci] - cell.toString().length)} `; + } + }); + result += '|\n'; + }); + + return result; + } +} diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index edb7b3b6778..65af94d0c35 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -18,7 +18,7 @@ import * as perf from 'vs/base/common/performance'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { writeTransientState } from 'vs/workbench/contrib/codeEditor/browser/toggleWordWrap'; -import { mergeSort } from 'vs/base/common/arrays'; +import { LoaderStats } from 'vs/base/common/amd'; import { IProductService } from 'vs/platform/product/common/productService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -279,100 +279,6 @@ class PerfModelContentProvider implements ITextModelContentProvider { } } -abstract class LoaderStats { - abstract get amdLoad(): (string | number)[][]; - abstract get amdInvoke(): (string | number)[][]; - abstract get nodeRequire(): (string | number)[][]; - abstract get nodeEval(): (string | number)[][]; - abstract get nodeRequireTotal(): number; - - - static get(): LoaderStats { - - - const amdLoadScript = new Map(); - const amdInvokeFactory = new Map(); - const nodeRequire = new Map(); - const nodeEval = new Map(); - - function mark(map: Map, stat: LoaderEvent) { - if (map.has(stat.detail)) { - // console.warn('BAD events, DOUBLE start', stat); - // map.delete(stat.detail); - return; - } - map.set(stat.detail, -stat.timestamp); - } - - function diff(map: Map, stat: LoaderEvent) { - let duration = map.get(stat.detail); - if (!duration) { - // console.warn('BAD events, end WITHOUT start', stat); - // map.delete(stat.detail); - return; - } - if (duration >= 0) { - // console.warn('BAD events, DOUBLE end', stat); - // map.delete(stat.detail); - return; - } - map.set(stat.detail, duration + stat.timestamp); - } - - const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp); - - for (const stat of stats) { - switch (stat.type) { - case LoaderEventType.BeginLoadingScript: - mark(amdLoadScript, stat); - break; - case LoaderEventType.EndLoadingScriptOK: - case LoaderEventType.EndLoadingScriptError: - diff(amdLoadScript, stat); - break; - - case LoaderEventType.BeginInvokeFactory: - mark(amdInvokeFactory, stat); - break; - case LoaderEventType.EndInvokeFactory: - diff(amdInvokeFactory, stat); - break; - - case LoaderEventType.NodeBeginNativeRequire: - mark(nodeRequire, stat); - break; - case LoaderEventType.NodeEndNativeRequire: - diff(nodeRequire, stat); - break; - - case LoaderEventType.NodeBeginEvaluatingScript: - mark(nodeEval, stat); - break; - case LoaderEventType.NodeEndEvaluatingScript: - diff(nodeEval, stat); - break; - } - } - - let nodeRequireTotal = 0; - nodeRequire.forEach(value => nodeRequireTotal += value); - - function to2dArray(map: Map): (string | number)[][] { - let res: (string | number)[][] = []; - map.forEach((value, index) => res.push([index, value])); - return res; - } - - return { - amdLoad: to2dArray(amdLoadScript), - amdInvoke: to2dArray(amdInvokeFactory), - nodeRequire: to2dArray(nodeRequire), - nodeEval: to2dArray(nodeEval), - nodeRequireTotal - }; - } -} - class MarkdownBuilder { value: string = ''; @@ -393,34 +299,6 @@ class MarkdownBuilder { } table(header: string[], rows: Array>) { - let lengths: number[] = []; - header.forEach((cell, ci) => { - lengths[ci] = cell.length; - }); - rows.forEach(row => { - row.forEach((cell, ci) => { - if (typeof cell === 'undefined') { - cell = row[ci] = '-'; - } - const len = cell.toString().length; - lengths[ci] = Math.max(len, lengths[ci]); - }); - }); - - // header - header.forEach((cell, ci) => { this.value += `| ${cell + ' '.repeat(lengths[ci] - cell.toString().length)} `; }); - this.value += '|\n'; - header.forEach((_cell, ci) => { this.value += `| ${'-'.repeat(lengths[ci])} `; }); - this.value += '|\n'; - - // cells - rows.forEach(row => { - row.forEach((cell, ci) => { - if (typeof cell !== 'undefined') { - this.value += `| ${cell + ' '.repeat(lengths[ci] - cell.toString().length)} `; - } - }); - this.value += '|\n'; - }); + this.value += LoaderStats.toMarkdownTable(header, rows); } } From 3946a0a314827d6305e40335eecd1b1ec83a8fae Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 19 Nov 2020 16:56:38 +0100 Subject: [PATCH 0049/1837] fix another variation of the "palette" typo... --- .github/workflows/author-verified.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/author-verified.yml b/.github/workflows/author-verified.yml index c326fee3da5..72b56f59110 100644 --- a/.github/workflows/author-verified.yml +++ b/.github/workflows/author-verified.yml @@ -34,7 +34,7 @@ jobs: with: appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}} token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}} - requestVerificationComment: "This bug has been fixed in to the latest release of [VS Code Insiders](https://code.visualstudio.com/insiders/)!\n\n@${author}, you can help us out by commenting `/verified` if things are now working as expected.\n\nIf things still don't seem right, please ensure you're on version ${commit} of Insiders (today's or later - you can use `Help: About` in the command pallette to check), and leave a comment letting us know what isn't working as expected.\n\nHappy Coding!" + requestVerificationComment: "This bug has been fixed in to the latest release of [VS Code Insiders](https://code.visualstudio.com/insiders/)!\n\n@${author}, you can help us out by commenting `/verified` if things are now working as expected.\n\nIf things still don't seem right, please ensure you're on version ${commit} of Insiders (today's or later - you can use `Help: About` in the command palette to check), and leave a comment letting us know what isn't working as expected.\n\nHappy Coding!" pendingReleaseLabel: awaiting-insiders-release verifiedLabel: verified authorVerificationRequestedLabel: author-verification-requested From 145c6e5beba5ad249150673feb79e539a1570cc4 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 18:31:53 +0100 Subject: [PATCH 0050/1837] #110905 also optimise for builtin extensions arg --- src/vs/code/node/cliProcessMain.ts | 31 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index b1dd54b6b9f..985d9a3d33b 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -134,6 +134,20 @@ export class Main { } const installed = await this.extensionManagementService.getInstalled(ExtensionType.User); + const checkIfNotInstalled = (id: string, version?: string): boolean => { + const installedExtension = installed.find(i => areSameExtensions(i.identifier, { id })); + if (installedExtension) { + if (!version && !force) { + console.log(localize('alreadyInstalled-checkAndUpdate', "Extension '{0}' v{1} is already installed. Use '--force' option to update to latest version or provide '@' to install a specific version, for example: '{2}@1.2.3'.", id, installedExtension.manifest.version, id)); + return false; + } + if (version && installedExtension.manifest.version === version) { + console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", `${id}@${version}`)); + return false; + } + } + return true; + }; const vsixs: string[] = []; const installExtensionInfos: InstallExtensionInfo[] = []; for (const extension of extensions) { @@ -141,23 +155,16 @@ export class Main { vsixs.push(extension); } else { const [id, version] = getIdAndVersion(extension); - const installedExtension = installed.find(i => areSameExtensions(i.identifier, { id })); - if (installedExtension) { - if (!version && !force) { - console.log(localize('alreadyInstalled-checkAndUpdate', "Extension '{0}' v{1} is already installed. Use '--force' option to update to latest version or provide `@${version}` to install a specific version, for example: '{2}@1.2.3'.", id, installedExtension.manifest.version, id)); - continue; - } - if (version && installedExtension.manifest.version === version) { - console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", `${id}@${version}`)); - continue; - } + if (checkIfNotInstalled(id, version)) { + installExtensionInfos.push({ id, version, installOptions: { isBuiltin: false, isMachineScoped } }); } - installExtensionInfos.push({ id, version, installOptions: { isBuiltin: false, isMachineScoped } }); } } for (const extension of builtinExtensionIds) { const [id, version] = getIdAndVersion(extension); - installExtensionInfos.push({ id, version, installOptions: { isBuiltin: true, isMachineScoped: false } }); + if (checkIfNotInstalled(id, version)) { + installExtensionInfos.push({ id, version, installOptions: { isBuiltin: true, isMachineScoped: false } }); + } } if (vsixs.length) { From 692e61eda110a1d2ded2da53e0888868251222da Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 19:59:44 +0100 Subject: [PATCH 0051/1837] Fix #110702 --- .../services/views/common/viewContainerModel.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index b26eaa3fe08..efc522907b8 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -375,7 +375,7 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode const added: IAddedViewDescriptorRef[] = []; const removed: IViewDescriptorRef[] = []; - for (const { visibleIndex, viewDescriptorItem, visible, size } of viewDescriptors.map(({ id, visible, size }) => ({ ...this.find(id), visible, size }))) { + for (const { visibleIndex, viewDescriptorItem, visible, size } of viewDescriptors.map(({ id, visible, size }) => ({ ...this.findAndIgnoreIfNotFound(id), visible, size }))) { const viewDescriptor = viewDescriptorItem.viewDescriptor; if (!viewDescriptor.canToggleVisibility) { @@ -619,6 +619,14 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode } private find(id: string): { index: number, visibleIndex: number, viewDescriptorItem: IViewDescriptorItem; } { + const result = this.findAndIgnoreIfNotFound(id); + if (result) { + return result; + } + throw new Error(`view descriptor ${id} not found`); + } + + private findAndIgnoreIfNotFound(id: string): { index: number, visibleIndex: number, viewDescriptorItem: IViewDescriptorItem; } | undefined { for (let i = 0, visibleIndex = 0; i < this.viewDescriptorItems.length; i++) { const viewDescriptorItem = this.viewDescriptorItems[i]; if (viewDescriptorItem.viewDescriptor.id === id) { @@ -628,7 +636,7 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode visibleIndex++; } } - throw new Error(`view descriptor ${id} not found`); + return undefined; } private compareViewDescriptors(a: IViewDescriptorItem, b: IViewDescriptorItem): number { From 2fb9c3d5ce7904ec18d8c8cb3d57dd16f5420b55 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 20:04:59 +0100 Subject: [PATCH 0052/1837] Fix #110702 --- .../workbench/services/views/common/viewContainerModel.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index efc522907b8..524d938e4c1 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -375,7 +375,13 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode const added: IAddedViewDescriptorRef[] = []; const removed: IViewDescriptorRef[] = []; - for (const { visibleIndex, viewDescriptorItem, visible, size } of viewDescriptors.map(({ id, visible, size }) => ({ ...this.findAndIgnoreIfNotFound(id), visible, size }))) { + 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) { From 195779a054748ccdf226c89b4aa8c0385872a534 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Nov 2020 20:16:54 +0100 Subject: [PATCH 0053/1837] Fix #110870 --- .../workbench/contrib/extensions/browser/extensionsViewlet.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 3136404e1a8..06d74acce15 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -212,7 +212,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio viewDescriptors.push({ id: 'workbench.views.extensions.enabled', name: localize('enabledExtensions', "Enabled"), - ctorDescriptor: new SyncDescriptor(EnabledExtensionsView, []), + ctorDescriptor: new SyncDescriptor(EnabledExtensionsView, [{}]), when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions')), hideByDefault: true, weight: 40, @@ -227,7 +227,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio viewDescriptors.push({ id: 'workbench.views.extensions.disabled', name: localize('disabledExtensions', "Disabled"), - ctorDescriptor: new SyncDescriptor(DisabledExtensionsView, []), + ctorDescriptor: new SyncDescriptor(DisabledExtensionsView, [{}]), when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions')), hideByDefault: true, weight: 10, From 5ebe7eb5f6df4c074396a2268a4be636ae92c928 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 11:54:10 -0800 Subject: [PATCH 0054/1837] fix #110750. --- .../notebook/browser/notebookServiceImpl.ts | 17 ++++++++++++----- .../notebook/browser/view/renderers/codeCell.ts | 5 +++-- .../contrib/notebook/common/notebookCommon.ts | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index c0fb96453c9..dc6bf626860 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -28,7 +28,7 @@ import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRe import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -767,10 +767,17 @@ export class NotebookService extends Disposable implements INotebookService, ICu }); } } else { - orderMimeTypes.push({ - mimeType: mimeType, - rendererId: BUILTIN_RENDERER_ID - }); + if (mimeTypeSupportedByCore(mimeType)) { + orderMimeTypes.push({ + mimeType: mimeType, + rendererId: BUILTIN_RENDERER_ID + }); + } else { + orderMimeTypes.push({ + mimeType: mimeType, + rendererId: RENDERER_NOT_AVAILABLE + }); + } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 1e5637f32ff..4ffd99ae1d9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -23,7 +23,7 @@ import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/ import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { BUILTIN_RENDERER_ID, CellOutputKind, CellUri, IInsetRenderOutput, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { BUILTIN_RENDERER_ID, CellOutputKind, CellUri, IInsetRenderOutput, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, outputHasDynamicHeight, RENDERER_NOT_AVAILABLE, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; @@ -67,7 +67,8 @@ class OutputElement extends Disposable { const transformedDisplayOutput = this.output as ITransformedDisplayOutputDto; const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output); - const pick = this.pickedMimeTypes.get(this.output) ?? 0; + + const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE), 0); if (mimeTypes.length > 1) { outputItemDiv.style.position = 'relative'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 6b8d3ec0126..f0e6804ea71 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -58,6 +58,7 @@ export const ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER = [ ]; export const BUILTIN_RENDERER_ID = '_builtin'; +export const RENDERER_NOT_AVAILABLE = '_notAvailable'; export enum NotebookRunState { Running = 1, From f0ed8aa2e926eab29799a38fd85edf625f9caef3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Nov 2020 21:34:05 +0100 Subject: [PATCH 0055/1837] named codicons for views (for #92791) --- src/vs/platform/theme/common/themeService.ts | 27 +++++++++++++++++-- .../api/browser/mainThreadComments.ts | 11 +++++--- .../api/browser/viewsExtensionPoint.ts | 11 ++++---- .../parts/activitybar/activitybarPart.ts | 18 ++++++------- .../browser/parts/views/viewPaneContainer.ts | 8 +++--- src/vs/workbench/common/views.ts | 10 ++++--- .../browser/preview/bulkEdit.contribution.ts | 9 ++++--- .../debug/browser/debug.contribution.ts | 21 ++++++++------- .../contrib/debug/browser/debugIcons.ts | 15 +++++++++++ .../browser/extensions.contribution.ts | 6 ++++- .../contrib/files/browser/explorerViewlet.ts | 14 +++++----- .../markers/browser/markers.contribution.ts | 9 ++++--- .../outline/browser/outline.contribution.ts | 6 ++++- .../output/browser/output.contribution.ts | 10 ++++--- .../contrib/remote/browser/remote.ts | 6 +++-- .../contrib/scm/browser/scm.contribution.ts | 11 +++++--- .../search/browser/search.contribution.ts | 5 ++-- .../contrib/search/browser/searchIcons.ts | 3 ++- .../terminal/browser/terminal.contribution.ts | 8 ++++-- .../timeline/browser/timeline.contribution.ts | 7 ++++- .../userDataSync/browser/userDataSync.ts | 6 ++--- .../userDataSync/common/userDataSync.ts | 3 +++ .../views/browser/viewDescriptorService.ts | 5 ++-- .../views/common/viewContainerModel.ts | 20 ++++++++++---- 24 files changed, 173 insertions(+), 76 deletions(-) create mode 100644 src/vs/workbench/contrib/debug/browser/debugIcons.ts diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 0ae9c30fe60..4ea8b3978e0 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -11,6 +11,7 @@ import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { Codicon } from 'vs/base/common/codicons'; export const IThemeService = createDecorator('themeService'); @@ -18,6 +19,12 @@ export interface ThemeColor { id: string; } +export namespace ThemeColor { + export function isThemeColor(obj: any): obj is ThemeColor { + return obj && typeof obj === 'object' && typeof (obj).id === 'string'; + } +} + export function themeColorFromId(id: ColorIdentifier) { return { id }; } @@ -29,8 +36,8 @@ export interface ThemeIcon { } export namespace ThemeIcon { - export function isThemeIcon(obj: any): obj is ThemeIcon | { id: string } { - return obj && typeof obj === 'object' && typeof (obj).id === 'string'; + export function isThemeIcon(obj: any): obj is ThemeIcon { + return obj && typeof obj === 'object' && typeof (obj).id === 'string' && (typeof (obj).color === 'undefined' || ThemeColor.isThemeColor((obj).color)); } const _regexFromString = /^\$\(([a-z.]+\/)?([a-z-~]+)\)$/i; @@ -47,6 +54,15 @@ export namespace ThemeIcon { return { id: owner + name }; } + export function fromCodicon(codicon: Codicon): ThemeIcon { + return { id: codicon.id }; + } + + + export function isEqual(ti1: ThemeIcon, ti2: ThemeIcon): boolean { + return ti1.id === ti2.id && ti1.color?.id === ti2.color?.id; + } + const _regexAsClassName = /^(codicon\/)?([a-z-]+)(~[a-z]+)?$/i; export function asClassName(icon: ThemeIcon): string | undefined { @@ -62,6 +78,13 @@ export namespace ThemeIcon { } return className; } + + export function revive(icon: any): ThemeIcon | undefined { + if (ThemeIcon.isThemeIcon(icon)) { + return { id: icon.id, color: icon.color ? { id: icon.color.id } : undefined }; + } + return undefined; + } } export const FileThemeIcon = { id: 'file' }; diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index b6b32841290..80c9a3948c7 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -20,7 +20,9 @@ import { COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE } from 'vs/workbench/contrib/comm import { ViewContainer, IViewContainersRegistry, Extensions as ViewExtensions, ViewContainerLocation, IViewsRegistry, IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class MainThreadCommentThread implements modes.CommentThread { @@ -351,6 +353,9 @@ export class MainThreadCommentController { } } + +const commentsViewIcon = registerIcon('comments-view-icon', Codicon.commentDiscussion, localize('commentsViewIcon', 'View icon of the comments view.')); + @extHostNamedCustomer(MainContext.MainThreadComments) export class MainThreadComments extends Disposable implements MainThreadCommentsShape { private readonly _proxy: ExtHostCommentsShape; @@ -472,7 +477,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: COMMENTS_VIEW_TITLE, hideIfEmpty: true, - icon: Codicon.commentDiscussion.classNames, + icon: ThemeIcon.fromCodicon(commentsViewIcon), order: 10, }, ViewContainerLocation.Panel); @@ -482,7 +487,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(CommentsPanel), canMoveView: true, - containerIcon: Codicon.commentDiscussion.classNames, + containerIcon: ThemeIcon.fromCodicon(commentsViewIcon), focusCommand: { id: 'workbench.action.focusCommentsPanel' } diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index b46dc66f486..611a5b121c8 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -8,7 +8,7 @@ import { forEach } from 'vs/base/common/collections'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import * as resources from 'vs/base/common/resources'; import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation } from 'vs/workbench/common/views'; +import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation, testViewIcon } from 'vs/workbench/common/views'; import { CustomTreeView, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { coalesce, } from 'vs/base/common/arrays'; @@ -30,7 +30,6 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { Codicon } from 'vs/base/common/codicons'; import { WebviewViewPane } from 'vs/workbench/contrib/webviewView/browser/webviewViewPane'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -321,7 +320,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { private registerTestViewContainer(): void { const title = localize('test', "Test"); - const icon = Codicon.beaker.classNames; + const icon = ThemeIcon.fromCodicon(testViewIcon); this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, undefined, ViewContainerLocation.Sidebar); } @@ -357,8 +356,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution { private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number, existingViewContainers: ViewContainer[], location: ViewContainerLocation): number { containers.forEach(descriptor => { const themeIcon = ThemeIcon.fromString(descriptor.icon); - const className = themeIcon ? ThemeIcon.asClassName(themeIcon) : undefined; - const icon = className || resources.joinPath(extension.extensionLocation, descriptor.icon); + + const icon = themeIcon || resources.joinPath(extension.extensionLocation, descriptor.icon); const id = `workbench.view.extension.${descriptor.id}`; const viewContainer = this.registerCustomViewContainer(id, descriptor.title, icon, order++, extension.identifier, location); @@ -378,7 +377,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { return order; } - private registerCustomViewContainer(id: string, title: string, icon: URI | string, order: number, extensionId: ExtensionIdentifier | undefined, location: ViewContainerLocation): ViewContainer { + private registerCustomViewContainer(id: string, title: string, icon: URI | ThemeIcon, order: number, extensionId: ExtensionIdentifier | undefined, location: ViewContainerLocation): ViewContainer { let viewContainer = this.viewContainersRegistry.get(id); if (!viewContainer) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 12a44078831..c7286d2c661 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -14,7 +14,7 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions'; -import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; @@ -25,7 +25,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions'; import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation, IViewsService } from 'vs/workbench/common/views'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types'; +import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Schemas } from 'vs/base/common/network'; @@ -47,7 +47,7 @@ interface IPlaceholderViewContainer { id: string; name?: string; iconUrl?: UriComponents; - iconCSS?: string; + themeIcon?: ThemeIcon; views?: { when?: string }[]; } @@ -61,7 +61,7 @@ interface IPinnedViewContainer { interface ICachedViewContainer { id: string; name?: string; - icon?: URI | string; + icon?: URI | ThemeIcon; pinned: boolean; order?: number; visible: boolean; @@ -717,7 +717,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id); } - private static toActivity(id: string, name: string, icon: URI | string | undefined, keybindingId: string | undefined): IActivity { + private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined): IActivity { let cssClass: string | undefined = undefined; let iconUrl: URI | undefined = undefined; if (URI.isUri(icon)) { @@ -730,8 +730,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; -webkit-mask-size: 24px; `); - } else if (isString(icon)) { - cssClass = icon; + } else if (ThemeIcon.isThemeIcon(icon)) { + cssClass = ThemeIcon.asClassName(icon); } return { id, name, cssClass, iconUrl, keybindingId }; } @@ -911,7 +911,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { const cachedViewContainer = this._cachedViewContainers.filter(cached => cached.id === placeholderViewContainer.id)[0]; if (cachedViewContainer) { cachedViewContainer.name = placeholderViewContainer.name; - cachedViewContainer.icon = placeholderViewContainer.iconCSS ? placeholderViewContainer.iconCSS : + cachedViewContainer.icon = placeholderViewContainer.themeIcon ? ThemeIcon.revive(placeholderViewContainer.themeIcon) : placeholderViewContainer.iconUrl ? URI.revive(placeholderViewContainer.iconUrl) : undefined; cachedViewContainer.views = placeholderViewContainer.views; } @@ -930,7 +930,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.setPlaceholderViewContainers(cachedViewContainers.map(({ id, icon, name, views }) => ({ id, iconUrl: URI.isUri(icon) ? icon : undefined, - iconCSS: isString(icon) ? icon : undefined, + themeIcon: ThemeIcon.isThemeIcon(icon) ? icon : undefined, name, views }))); diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index e04b9594386..a5e4e36b614 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -18,12 +18,12 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; +import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { PaneView, IPaneViewOptions, IPaneOptions, Pane, IPaneStyles } from 'vs/base/browser/ui/splitview/paneview'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel } from 'vs/workbench/common/views'; +import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined, isString } from 'vs/base/common/types'; @@ -338,8 +338,8 @@ export abstract class ViewPane extends Pane implements IView { } } - private getIcon(): string | URI { - return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || 'codicon-window'; + private getIcon(): ThemeIcon | URI { + return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); } protected renderHeaderTitle(container: HTMLElement, title: string): void { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 24f43b1d740..95d534a587e 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -25,8 +25,12 @@ import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { mixin } from 'vs/base/common/objects'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test'; +export const testViewIcon = registerIcon('test-view-icon', Codicon.beaker, localize('testViewIcon', 'View icon of the test view.')); + +export const defaultViewIcon = registerIcon('default-view-icon', Codicon.window, localize('defaultViewIcon', 'Default view icon.')); export namespace Extensions { export const ViewContainersRegistry = 'workbench.registry.view.containers'; @@ -48,7 +52,7 @@ export interface IViewContainerDescriptor { readonly storageId?: string; - readonly icon?: string | URI; + readonly icon?: ThemeIcon | URI; readonly alwaysUseContainerInfo?: boolean; @@ -216,7 +220,7 @@ export interface IViewDescriptor { readonly canMoveView?: boolean; - readonly containerIcon?: string | URI; + readonly containerIcon?: ThemeIcon | URI; readonly containerTitle?: string; @@ -252,7 +256,7 @@ export interface IAddedViewDescriptorState { export interface IViewContainerModel { readonly title: string; - readonly icon: string | URI | undefined; + readonly icon: ThemeIcon | URI | undefined; readonly onDidChangeContainerInfo: Event<{ title?: boolean, icon?: boolean }>; readonly allViewDescriptors: ReadonlyArray; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts index 139ee6ddbc3..5177edd043a 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts @@ -27,7 +27,8 @@ import type { ServicesAccessor } from 'vs/platform/instantiation/common/instanti import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; async function getBulkEditPane(viewsService: IViewsService): Promise { const view = await viewsService.openView(BulkEditPane.ID, true); @@ -341,6 +342,8 @@ Registry.as(WorkbenchExtensions.Workbench).regi BulkEditPreviewContribution, LifecyclePhase.Ready ); +const refactorPreviewViewIcon = registerIcon('refactor-preview-view-icon', Codicon.lightbulb, localize('refactorPreviewViewIcon', 'View icon of the refactor preview view.')); + const container = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: BulkEditPane.ID, name: localize('panel', "Refactor Preview"), @@ -349,7 +352,7 @@ const container = Registry.as(ViewContainerExtensions.V ViewPaneContainer, [BulkEditPane.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }] ), - icon: Codicon.lightbulb.classNames, + icon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), storageId: BulkEditPane.ID }, ViewContainerLocation.Panel); @@ -358,5 +361,5 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews name: localize('panel', "Refactor Preview"), when: BulkEditPreviewContribution.ctxEnabled, ctorDescriptor: new SyncDescriptor(BulkEditPane), - containerIcon: Codicon.lightbulb.classNames, + containerIcon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), }], container); diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index a26cea18ba4..fff513dedcb 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -49,10 +49,10 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { StartDebugQuickAccessProvider } from 'vs/workbench/contrib/debug/browser/debugQuickAccess'; import { DebugProgressContribution } from 'vs/workbench/contrib/debug/browser/debugProgress'; import { DebugTitleContribution } from 'vs/workbench/contrib/debug/browser/debugTitle'; -import { Codicon } from 'vs/base/common/codicons'; import { registerColors } from 'vs/workbench/contrib/debug/browser/debugColors'; import { DebugEditorContribution } from 'vs/workbench/contrib/debug/browser/debugEditorContribution'; import { FileAccess } from 'vs/base/common/network'; +import { breakpointsViewIcon, callStackViewIcon, debugConsoleViewIcon, loadedScriptsViewIcon, runViewIcon, variablesViewIcon, watchViewIcon } from 'vs/workbench/contrib/debug/browser/debugIcons'; const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); const debugCategory = nls.localize('debugCategory', "Debug"); @@ -460,7 +460,7 @@ function registerDebugPanel(): void { const VIEW_CONTAINER: ViewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: DEBUG_PANEL_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - icon: Codicon.debugConsole.classNames, + icon: ThemeIcon.fromCodicon(debugConsoleViewIcon), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: DEBUG_PANEL_ID, focusCommand: { id: OpenDebugConsoleAction.ID }, @@ -471,7 +471,7 @@ function registerDebugPanel(): void { Registry.as(ViewExtensions.ViewsRegistry).registerViews([{ id: REPL_VIEW_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - containerIcon: Codicon.debugConsole.classNames, + containerIcon: ThemeIcon.fromCodicon(debugConsoleViewIcon), canToggleVisibility: false, canMoveView: true, when: CONTEXT_DEBUGGERS_AVAILABLE, @@ -481,12 +481,13 @@ function registerDebugPanel(): void { registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenDebugConsoleAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y }), 'View: Debug Console', CATEGORIES.View.value, CONTEXT_DEBUGGERS_AVAILABLE); } + function registerDebugView(): void { const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: nls.localize('run', "Run"), ctorDescriptor: new SyncDescriptor(DebugViewPaneContainer), - icon: Codicon.debugAlt.classNames, + icon: ThemeIcon.fromCodicon(runViewIcon), alwaysUseContainerInfo: true, order: 2 }, ViewContainerLocation.Sidebar); @@ -494,12 +495,12 @@ function registerDebugView(): void { // Register default debug views const viewsRegistry = Registry.as(ViewExtensions.ViewsRegistry); - viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); - viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); - viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: ThemeIcon.fromCodicon(variablesViewIcon), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: ThemeIcon.fromCodicon(watchViewIcon), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: ThemeIcon.fromCodicon(callStackViewIcon), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: ThemeIcon.fromCodicon(breakpointsViewIcon), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: ThemeIcon.fromCodicon(runViewIcon), ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); + viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: ThemeIcon.fromCodicon(loadedScriptsViewIcon), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); } function registerConfiguration(): void { diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts new file mode 100644 index 00000000000..4c5923d9694 --- /dev/null +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; + +export const debugConsoleViewIcon = registerIcon('debug-console-view-icon', Codicon.debugConsole, localize('debugConsoleViewIcon', 'View icon of the debug console view.')); +export const runViewIcon = registerIcon('run-view-icon', Codicon.debugAlt, localize('runViewIcon', 'View icon of the run view.')); +export const variablesViewIcon = registerIcon('variables-view-icon', Codicon.debugAlt, localize('variablesViewIcon', 'View icon of the variables view.')); +export const watchViewIcon = registerIcon('watch-view-icon', Codicon.debugAlt, localize('watchViewIcon', 'View icon of the watch view.')); +export const callStackViewIcon = registerIcon('callstack-view-icon', Codicon.debugAlt, localize('callStackViewIcon', 'View icon of the call stack view.')); +export const breakpointsViewIcon = registerIcon('breakpoints-view-icon', Codicon.debugAlt, localize('breakpointsViewIcon', 'View icon of the breakpoints view.')); +export const loadedScriptsViewIcon = registerIcon('loaded-scripts-view-icon', Codicon.debugAlt, localize('loadedScriptsViewIcon', 'View icon of the loaded scripts view.')); diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 6a3d5c45faf..0354706380a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -64,6 +64,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -102,12 +104,14 @@ Registry.as(EditorExtensions.Editors).registerEditor( new SyncDescriptor(ExtensionsInput) ]); +const extensionsViewIcon = registerIcon('extensions-view-icon', Codicon.extensions, localize('extensionsViewIcon', 'View icon of the extensions view.')); + Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, name: localize('extensions', "Extensions"), ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer), - icon: 'codicon-extensions', + icon: ThemeIcon.fromCodicon(extensionsViewIcon), order: 4, rejectAddedViews: true, alwaysUseContainerInfo: true diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 54912b106eb..313ba7adc97 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -18,7 +18,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, ViewContentGroups } from 'vs/workbench/common/views'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -37,7 +37,9 @@ import { WorkbenchStateContext, RemoteNameContext } from 'vs/workbench/browser/c import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { AddRootFolderAction, OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; import { isMacintosh } from 'vs/base/common/platform'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; + +const explorerViewIcon = registerIcon('explorer-view-icon', Codicon.files, localize('explorerViewIcon', 'View icon of the explorer view.')); export class ExplorerViewletViewsContribution extends Disposable implements IWorkbenchContribution { @@ -108,7 +110,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor id: OpenEditorsView.ID, name: OpenEditorsView.NAME, ctorDescriptor: new SyncDescriptor(OpenEditorsView), - containerIcon: 'codicon-files', + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), order: 0, when: OpenEditorsVisibleContext, canToggleVisibility: true, @@ -125,7 +127,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: EmptyView.ID, name: EmptyView.NAME, - containerIcon: Codicon.files.classNames, + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), ctorDescriptor: new SyncDescriptor(EmptyView), order: 1, canToggleVisibility: true, @@ -139,7 +141,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: VIEW_ID, name: localize('folders', "Folders"), - containerIcon: Codicon.files.classNames, + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), ctorDescriptor: new SyncDescriptor(ExplorerView), order: 1, canToggleVisibility: false, @@ -267,7 +269,7 @@ export const VIEW_CONTAINER: ViewContainer = viewContainerRegistry.registerViewC name: localize('explore', "Explorer"), ctorDescriptor: new SyncDescriptor(ExplorerViewPaneContainer), storageId: 'workbench.explorer.views.state', - icon: Codicon.files.classNames, + icon: ThemeIcon.fromCodicon(explorerViewIcon), alwaysUseContainerInfo: true, order: 0 }, ViewContainerLocation.Sidebar, true); diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index e046732264e..ac6c5837298 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -32,7 +32,8 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import type { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); @@ -124,11 +125,13 @@ class ToggleMarkersPanelAction extends ToggleViewAction { } } +const markersViewIcon = registerIcon('markers-view-icon', Codicon.warning, localize('markersViewIcon', 'View icon of the markers view.')); + // markers view container const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: Constants.MARKERS_CONTAINER_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, - icon: Codicon.warning.classNames, + icon: ThemeIcon.fromCodicon(markersViewIcon), hideIfEmpty: true, order: 0, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), @@ -142,7 +145,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: Constants.MARKERS_VIEW_ID, - containerIcon: Codicon.warning.classNames, + containerIcon: ThemeIcon.fromCodicon(markersViewIcon), name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, canToggleVisibility: false, canMoveView: true, diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 3dc1cf7fb70..5fb485fa404 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -11,13 +11,17 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const PANEL_ID = 'panel.view.outline'; +const outlineViewIcon = registerIcon('outline-view-icon', Codicon.symbolClass, localize('outlineViewIcon', 'View icon of the outline view.')); + const _outlineDesc = { id: OutlineViewId, name: localize('name', "Outline"), - containerIcon: 'codicon-symbol-class', + containerIcon: ThemeIcon.fromCodicon(outlineViewIcon), ctorDescriptor: new SyncDescriptor(OutlinePane), canToggleVisibility: true, canMoveView: true, diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index 04d655a94e6..058a20f3483 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -32,8 +32,9 @@ import { assertIsDefined } from 'vs/base/common/types'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register Service registerSingleton(IOutputService, OutputService); @@ -60,10 +61,13 @@ const toggleOutputActionKeybindings = { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_H) // On Ubuntu Ctrl+Shift+U is taken by some global OS command } }; + +const outputViewIcon = registerIcon('output-view-icon', Codicon.output, nls.localize('outputViewIcon', 'View icon of the output view.')); + const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - icon: Codicon.output.classNames, + icon: ThemeIcon.fromCodicon(outputViewIcon), order: 1, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: OUTPUT_VIEW_ID, @@ -74,7 +78,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - containerIcon: Codicon.output.classNames, + containerIcon: ThemeIcon.fromCodicon(outputViewIcon), canMoveView: true, canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(OutputViewPane), diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 6db1f59653b..bf67431a503 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -13,7 +13,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet'; @@ -552,6 +552,8 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements } +const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); + Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, @@ -583,7 +585,7 @@ Registry.as(Extensions.ViewContainersRegistry).register return; } }, - icon: 'codicon-remote-explorer', + icon: ThemeIcon.fromCodicon(remoteExplorerViewIcon), order: 4 }, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 5a8ede45558..3358221ade6 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -22,12 +22,13 @@ import { IViewContainersRegistry, ViewContainerLocation, Extensions as ViewConta import { SCMViewPaneContainer } from 'vs/workbench/contrib/scm/browser/scmViewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane'; import { SCMViewService } from 'vs/workbench/contrib/scm/browser/scmViewService'; import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRepositoriesViewPane'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Context as SuggestContext } from 'vs/editor/contrib/suggest/suggest'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; ModesRegistry.registerLanguage({ id: 'scminput', @@ -38,12 +39,14 @@ ModesRegistry.registerLanguage({ Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(DirtyDiffWorkbenchController, LifecyclePhase.Restored); +const sourceControlViewIcon = registerIcon('source-control-view-icon', Codicon.sourceControl, localize('sourceControlViewIcon', 'View icon of the source control view.')); + const viewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('source control', "Source Control"), ctorDescriptor: new SyncDescriptor(SCMViewPaneContainer), storageId: 'workbench.scm.views.state', - icon: Codicon.sourceControl.classNames, + icon: ThemeIcon.fromCodicon(sourceControlViewIcon), alwaysUseContainerInfo: true, order: 2, hideIfEmpty: true @@ -65,7 +68,7 @@ viewsRegistry.registerViews([{ canMoveView: true, weight: 80, order: -999, - containerIcon: Codicon.sourceControl.classNames + containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) }], viewContainer); viewsRegistry.registerViews([{ @@ -80,7 +83,7 @@ viewsRegistry.registerViews([{ order: -1000, when: ContextKeyExpr.and(ContextKeyExpr.has('scm.providerCount'), ContextKeyExpr.notEquals('scm.providerCount', 0)), // readonly when = ContextKeyExpr.or(ContextKeyExpr.equals('config.scm.alwaysShowProviders', true), ContextKeyExpr.and(ContextKeyExpr.notEquals('scm.providerCount', 0), ContextKeyExpr.notEquals('scm.providerCount', 1))); - containerIcon: Codicon.sourceControl.classNames + containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) }], viewContainer); Registry.as(WorkbenchExtensions.Workbench) diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index cf0f24f260e..84ecac2c414 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -55,6 +55,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess'; import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; import { searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true); registerSingleton(ISearchHistoryService, SearchHistoryService, true); @@ -509,11 +510,11 @@ const viewContainer = Registry.as(ViewExtensions.ViewCo name: nls.localize('name', "Search"), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), hideIfEmpty: true, - icon: searchViewIcon.classNames, + icon: ThemeIcon.fromCodicon(searchViewIcon), order: 1 }, ViewContainerLocation.Sidebar); -const viewDescriptor = { id: VIEW_ID, containerIcon: 'codicon-search', name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; +const viewDescriptor = { id: VIEW_ID, containerIcon: ThemeIcon.fromCodicon(searchViewIcon), name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; // Register search default location to sidebar Registry.as(ViewExtensions.ViewsRegistry).registerViews([viewDescriptor], viewContainer); diff --git a/src/vs/workbench/contrib/search/browser/searchIcons.ts b/src/vs/workbench/contrib/search/browser/searchIcons.ts index 2138fbaa30f..2c264dbf1e4 100644 --- a/src/vs/workbench/contrib/search/browser/searchIcons.ts +++ b/src/vs/workbench/contrib/search/browser/searchIcons.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; export const searchDetailsIcon = registerIcon('search-details', Codicon.ellipsis); @@ -20,7 +21,7 @@ export const searchExpandAllIcon = registerIcon('search-expand-results', Codicon export const searchClearIcon = registerIcon('search-clear-results', Codicon.clearAll); export const searchStopIcon = Codicon.searchStop; -export const searchViewIcon = Codicon.search; +export const searchViewIcon = registerIcon('search-view-icon', Codicon.search, localize('searchViewIcon', 'View icon of the search view.')); export const searchNewEditorIcon = registerIcon('search-new-editor', Codicon.newFile); export const searchGotoFileIcon = registerIcon('search-goto-file', Codicon.goToFile); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 807c77c271a..67ad70e5ec0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -36,6 +36,8 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { terminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register services registerSingleton(ITerminalService, TerminalService, true); @@ -59,11 +61,13 @@ CommandsRegistry.registerCommand({ id: quickAccessNavigatePreviousInTerminalPick const configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration(terminalConfiguration); +const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nls.localize('terminalViewIcon', 'View icon of the terminal view.')); + // Register views const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - icon: 'codicon-terminal', + icon: ThemeIcon.fromCodicon(terminalViewIcon), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: TERMINAL_VIEW_ID, focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS }, @@ -74,7 +78,7 @@ Registry.as(panel.Extensions.Panels).setDefaultPanelId(TERM Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - containerIcon: 'codicon-terminal', + containerIcon: ThemeIcon.fromCodicon(terminalViewIcon), canToggleVisibility: false, canMoveView: true, ctorDescriptor: new SyncDescriptor(TerminalViewPane) diff --git a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts index b7ca9dbb216..4caef263d11 100644 --- a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts +++ b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts @@ -18,11 +18,16 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ResourceContextKey } from 'vs/workbench/common/resources'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; + + +const timelineViewIcon = registerIcon('timeline-view-icon', Codicon.history, localize('timelineViewIcon', 'View icon of the timeline view.')); export class TimelinePaneDescriptor implements IViewDescriptor { readonly id = TimelinePaneId; readonly name = TimelinePane.TITLE; - readonly containerIcon = 'codicon-history'; + readonly containerIcon = ThemeIcon.fromCodicon(timelineViewIcon); readonly ctorDescriptor = new SyncDescriptor(TimelinePane); readonly order = 2; readonly weight = 30; diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 0c6f5ad1695..206d8500858 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -50,10 +50,10 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { Codicon } from 'vs/base/common/codicons'; import { ViewContainerLocation, IViewContainersRegistry, Extensions, ViewContainer } from 'vs/workbench/common/views'; import { UserDataSyncViewPaneContainer, UserDataSyncDataViews } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncViews'; -import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE, SYNC_VIEW_ICON } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const CONTEXT_CONFLICTS_SOURCES = new RawContextKey('conflictsSources', ''); @@ -1125,7 +1125,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo UserDataSyncViewPaneContainer, [SYNC_VIEW_CONTAINER_ID] ), - icon: Codicon.sync.classNames, + icon: ThemeIcon.fromCodicon(SYNC_VIEW_ICON), hideIfEmpty: true, }, ViewContainerLocation.Sidebar); } diff --git a/src/vs/workbench/services/userDataSync/common/userDataSync.ts b/src/vs/workbench/services/userDataSync/common/userDataSync.ts index 4e0e54f6252..bf587f2544b 100644 --- a/src/vs/workbench/services/userDataSync/common/userDataSync.ts +++ b/src/vs/workbench/services/userDataSync/common/userDataSync.ts @@ -9,6 +9,7 @@ import { Event } from 'vs/base/common/event'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; export interface IUserDataSyncAccount { readonly authenticationProviderId: string; @@ -81,6 +82,8 @@ export const enum AccountStatus { export const SYNC_TITLE = localize('sync category', "Settings Sync"); +export const SYNC_VIEW_ICON = registerIcon('settings-sync-view-icon', Codicon.sync, localize('syncViewIcon', 'View icon of the settings sync view.')); + // Contexts export const CONTEXT_SYNC_STATE = new RawContextKey('syncStatus', SyncStatus.Uninitialized); export const CONTEXT_SYNC_ENABLEMENT = new RawContextKey('syncEnabled', false); diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index 9d15e838755..d9d2bf79326 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState } from 'vs/workbench/common/views'; +import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState, defaultViewIcon } from 'vs/workbench/common/views'; import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -19,6 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { getViewsStateStorageId, ViewContainerModel } from 'vs/workbench/services/views/common/viewContainerModel'; import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions'; import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; interface ICachedViewContainerInfo { containerId: string; @@ -460,7 +461,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor id, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), name: 'Custom Views', // we don't want to see this, so no need to localize - icon: location === ViewContainerLocation.Sidebar ? 'codicon-window' : undefined, + icon: location === ViewContainerLocation.Sidebar ? ThemeIcon.fromCodicon(defaultViewIcon) : undefined, storageId: getViewContainerStorageId(id), hideIfEmpty: true }, location); diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 524d938e4c1..d736bc82ff0 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState } from 'vs/workbench/common/views'; +import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState, defaultViewIcon } from 'vs/workbench/common/views'; import { IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -14,6 +14,7 @@ import { URI } from 'vs/base/common/uri'; 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'; export function getViewsStateStorageId(viewContainerStorageId: string): string { return `${viewContainerStorageId}.hidden`; } @@ -286,8 +287,8 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode // Container Info private _title!: string; get title(): string { return this._title; } - private _icon: URI | string | undefined; - get icon(): URI | string | undefined { return this._icon; } + private _icon: URI | ThemeIcon | undefined; + get icon(): URI | ThemeIcon | undefined { return this._icon; } private _onDidChangeContainerInfo = this._register(new Emitter<{ title?: boolean, icon?: boolean }>()); readonly onDidChangeContainerInfo = this._onDidChangeContainerInfo.event; @@ -347,9 +348,9 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode titleChanged = true; } - const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || 'codicon-window'; + const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); let iconChanged: boolean = false; - if (URI.isUri(icon) && URI.isUri(this._icon) ? isEqual(icon, this._icon) : this._icon !== icon) { + if (!this.isEqualIcon(icon)) { this._icon = icon; iconChanged = true; } @@ -359,6 +360,15 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode } } + private isEqualIcon(icon: URI | ThemeIcon | undefined): boolean { + if (URI.isUri(icon)) { + return URI.isUri(this._icon) && isEqual(icon, this._icon); + } else if (ThemeIcon.isThemeIcon(icon)) { + return ThemeIcon.isThemeIcon(this._icon) && ThemeIcon.isEqual(icon, this._icon); + } + return icon === this._icon; + } + isVisible(id: string): boolean { const viewDescriptorItem = this.viewDescriptorItems.filter(v => v.viewDescriptor.id === id)[0]; if (!viewDescriptorItem) { From 8b720d67408637ed658e97f938a40be995c98ab3 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 19 Nov 2020 13:39:57 -0800 Subject: [PATCH 0056/1837] chore: bump keytar@7.2.0 (#110977) --- package.json | 4 ++-- yarn.lock | 66 ++++++++++++++++++++++++++-------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 78b631db1fa..c9530f5c5c0 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "https-proxy-agent": "^2.2.3", "iconv-lite-umd": "0.6.8", "jschardet": "2.2.1", - "keytar": "^7.1.0", + "keytar": "7.2.0", "minimist": "^1.2.5", "native-is-elevated": "0.4.1", "native-keymap": "2.2.1", @@ -195,4 +195,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 4bdd622f5d5..061960377ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -160,34 +160,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@shiftkey/node-abi@2.19.2-pre": - version "2.19.2-pre" - resolved "https://registry.yarnpkg.com/@shiftkey/node-abi/-/node-abi-2.19.2-pre.tgz#02599b37253e414f8f6ef3c67ea704e37da640a9" - integrity sha512-+LfXo6nd2uZ8cGSJ66zL3OuddvG2oMWMc9GzpDoX2ZNMLmYpu+ReoEKXtmoKVwd6JSavDymldebCxSJh9NQ9cg== - dependencies: - semver "^5.4.1" - -"@shiftkey/prebuild-install@6.0.1-pre2": - version "6.0.1-pre2" - resolved "https://registry.yarnpkg.com/@shiftkey/prebuild-install/-/prebuild-install-6.0.1-pre2.tgz#8cea022dd9aa0eb064164987b6ab12539efb892e" - integrity sha512-wDV1DgFxi0F+kTpyGNdnDctdw3Rb9aP8RBAGFE2wXr1+pXSCJRRA+Qh5ko5dKc0LeNIBZzjEECjmtAykajv+Xw== - dependencies: - "@shiftkey/node-abi" "2.19.2-pre" - detect-libc "^1.0.3" - 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" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -5436,13 +5408,13 @@ just-debounce@^1.0.0: resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= -keytar@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.1.0.tgz#961e6c5cf0615f2c184a48752d3265063e492925" - integrity sha512-ciDrtCcvhKpmVfPMVAiKSeKKQd+8S2VWOIcJP0Rdwz/ezSxHxYrycpwufDGpEHJqLyi/F7C7iwoz0eKGllzcMw== +keytar@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.2.0.tgz#4db2bec4f9700743ffd9eda22eebb658965c8440" + integrity sha512-ECSaWvoLKI5SI0pGpZQeUV1/lpBYfkaxvoSp3zkiPOz05VavwSfLi8DdEaa9N2ekQZv3Chy+o7aP6n9mairBgw== dependencies: - "@shiftkey/prebuild-install" "6.0.1-pre2" node-addon-api "^3.0.0" + prebuild-install "^6.0.0" keyv@^3.0.0: version "3.1.0" @@ -6265,6 +6237,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== +node-abi@^2.7.0: + version "2.19.3" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d" + integrity sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg== + dependencies: + semver "^5.4.1" + node-addon-api@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" @@ -7376,6 +7355,27 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0. source-map "^0.6.1" supports-color "^6.1.0" +prebuild-install@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.0.0.tgz#669022bcde57c710a869e39c5ca6bf9cd207f316" + integrity sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw== + dependencies: + detect-libc "^1.0.3" + 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.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" From ffacef4727ef6896823b895d5684f7e9e3df27fb Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Thu, 19 Nov 2020 13:44:11 -0800 Subject: [PATCH 0057/1837] Fix #58600, Format Emmet package.json (#110891) --- extensions/emmet/package.json | 891 +++++++++--------- extensions/emmet/package.nls.json | 1 + extensions/emmet/src/emmetCommon.ts | 6 +- .../browser/actions/expandAbbreviation.ts | 43 - .../emmet/browser/emmet.contribution.ts | 4 +- ...tActions.ts => expandEmmetAbbreviation.ts} | 64 +- ...est.ts => expandEmmetAbbreviation.test.ts} | 52 +- 7 files changed, 517 insertions(+), 544 deletions(-) delete mode 100644 src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts rename src/vs/workbench/contrib/emmet/browser/{emmetActions.ts => expandEmmetAbbreviation.ts} (69%) rename src/vs/workbench/contrib/emmet/test/browser/{emmetAction.test.ts => expandEmmetAbbreviation.test.ts} (57%) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 12178fa8b56..a0a22505f85 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -1,446 +1,461 @@ { - "name": "emmet", - "displayName": "Emmet", - "description": "%description%", - "version": "1.0.0", - "publisher": "vscode", - "license": "MIT", - "engines": { - "vscode": "^1.13.0" - }, - "icon": "images/icon.png", - "categories": [ - "Other" - ], - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-emmet" - }, - "activationEvents": [ - "*", - "onCommand:emmet.expandAbbreviation", - "onLanguage:html", - "onLanguage:css", - "onLanguage:scss", - "onLanguage:less" - ], - "main": "./out/node/emmetNodeMain", - "browser": "./dist/browser/emmetBrowserMain", - "contributes": { - "configuration": { - "type": "object", - "title": "Emmet", - "properties": { - "emmet.showExpandedAbbreviation": { - "type": [ - "string" - ], - "enum": [ - "never", - "always", - "inMarkupAndStylesheetFilesOnly" - ], - "default": "always", - "markdownDescription": "%emmetShowExpandedAbbreviation%" - }, - "emmet.showAbbreviationSuggestions": { - "type": "boolean", - "default": true, - "markdownDescription": "%emmetShowAbbreviationSuggestions%" - }, - "emmet.includeLanguages": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "default": {}, - "markdownDescription": "%emmetIncludeLanguages%" - }, - "emmet.variables": { - "type": "object", - "properties": { - "lang": { - "type": "string", - "default": "en" - }, - "charset": { - "type": "string", - "default": "UTF-8" - } - }, - "default": {}, - "description": "%emmetVariables%" - }, - "emmet.syntaxProfiles": { - "type": "object", - "default": {}, - "description": "%emmetSyntaxProfiles%" - }, - "emmet.excludeLanguages": { - "type": "array", - "default": [ - "markdown" - ], - "description": "%emmetExclude%" - }, - "emmet.extensionsPath": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "%emmetExtensionsPath%" - }, - "emmet.triggerExpansionOnTab": { - "type": "boolean", - "default": false, - "description": "%emmetTriggerExpansionOnTab%" - }, - "emmet.preferences": { - "type": "object", - "default": {}, - "description": "%emmetPreferences%", - "properties": { - "css.intUnit": { - "type": "string", - "default": "px", - "description": "%emmetPreferencesIntUnit%" - }, - "css.floatUnit": { - "type": "string", - "default": "em", - "description": "%emmetPreferencesFloatUnit%" - }, - "css.propertyEnd": { - "type": "string", - "default": ";", - "description": "%emmetPreferencesCssAfter%" - }, - "sass.propertyEnd": { - "type": "string", - "default": "", - "description": "%emmetPreferencesSassAfter%" - }, - "stylus.propertyEnd": { - "type": "string", - "default": "", - "description": "%emmetPreferencesStylusAfter%" - }, - "css.valueSeparator": { - "type": "string", - "default": ": ", - "description": "%emmetPreferencesCssBetween%" - }, - "sass.valueSeparator": { - "type": "string", - "default": ": ", - "description": "%emmetPreferencesSassBetween%" - }, - "stylus.valueSeparator": { - "type": "string", - "default": " ", - "description": "%emmetPreferencesStylusBetween%" - }, - "bem.elementSeparator": { - "type": "string", - "default": "__", - "description": "%emmetPreferencesBemElementSeparator%" - }, - "bem.modifierSeparator": { - "type": "string", - "default": "_", - "description": "%emmetPreferencesBemModifierSeparator%" - }, - "filter.commentBefore": { - "type": "string", - "default": "", - "description": "%emmetPreferencesFilterCommentBefore%" - }, - "filter.commentAfter": { - "type": "string", - "default": "\n", - "description": "%emmetPreferencesFilterCommentAfter%" - }, - "filter.commentTrigger": { - "type": "array", - "default": [ - "id", - "class" - ], - "description": "%emmetPreferencesFilterCommentTrigger%" - }, - "format.noIndentTags": { - "type": "array", - "default": [ - "html" - ], - "description": "%emmetPreferencesFormatNoIndentTags%" - }, - "format.forceIndentationForTags": { - "type": "array", - "default": [ - "body" - ], - "description": "%emmetPreferencesFormatForceIndentTags%" - }, - "profile.allowCompactBoolean": { - "type": "boolean", - "default": false, - "description": "%emmetPreferencesAllowCompactBoolean%" - }, - "css.webkitProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssWebkitProperties%" - }, - "css.mozProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssMozProperties%" - }, - "css.oProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssOProperties%" - }, - "css.msProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssMsProperties%" - }, - "css.fuzzySearchMinScore": { - "type": "number", - "default": 0.3, - "description": "%emmetPreferencesCssFuzzySearchMinScore%" - } - } - }, - "emmet.showSuggestionsAsSnippets": { - "type": "boolean", - "default": false, - "markdownDescription": "%emmetShowSuggestionsAsSnippets%" - }, - "emmet.optimizeStylesheetParsing": { - "type": "boolean", - "default": true, - "markdownDescription": "%emmetOptimizeStylesheetParsing%" - } - } + "name": "emmet", + "displayName": "Emmet", + "description": "%description%", + "version": "1.0.0", + "publisher": "vscode", + "license": "MIT", + "engines": { + "vscode": "^1.13.0" + }, + "icon": "images/icon.png", + "categories": [ + "Other" + ], + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-emmet" + }, + "activationEvents": [ + "*", + "onCommand:emmet.expandAbbreviation", + "onLanguage:html", + "onLanguage:css", + "onLanguage:scss", + "onLanguage:less" + ], + "main": "./out/node/emmetNodeMain", + "browser": "./dist/browser/emmetBrowserMain", + "contributes": { + "configuration": { + "type": "object", + "title": "Emmet", + "properties": { + "emmet.showExpandedAbbreviation": { + "type": [ + "string" + ], + "enum": [ + "never", + "always", + "inMarkupAndStylesheetFilesOnly" + ], + "default": "always", + "markdownDescription": "%emmetShowExpandedAbbreviation%" }, - "commands": [ - { - "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation", - "title": "%command.wrapIndividualLinesWithAbbreviation%", - "category": "Emmet" + "emmet.showAbbreviationSuggestions": { + "type": "boolean", + "default": true, + "markdownDescription": "%emmetShowAbbreviationSuggestions%" + }, + "emmet.includeLanguages": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "default": {}, + "markdownDescription": "%emmetIncludeLanguages%" + }, + "emmet.variables": { + "type": "object", + "properties": { + "lang": { + "type": "string", + "default": "en" }, - { - "command": "editor.emmet.action.wrapWithAbbreviation", - "title": "%command.wrapWithAbbreviation%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.removeTag", - "title": "%command.removeTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.updateTag", - "title": "%command.updateTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.matchTag", - "title": "%command.matchTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.balanceIn", - "title": "%command.balanceIn%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.balanceOut", - "title": "%command.balanceOut%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.prevEditPoint", - "title": "%command.prevEditPoint%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.nextEditPoint", - "title": "%command.nextEditPoint%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.mergeLines", - "title": "%command.mergeLines%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.selectPrevItem", - "title": "%command.selectPrevItem%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.selectNextItem", - "title": "%command.selectNextItem%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.splitJoinTag", - "title": "%command.splitJoinTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.toggleComment", - "title": "%command.toggleComment%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.evaluateMathExpression", - "title": "%command.evaluateMathExpression%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.updateImageSize", - "title": "%command.updateImageSize%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByOneTenth", - "title": "%command.incrementNumberByOneTenth%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByOne", - "title": "%command.incrementNumberByOne%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByTen", - "title": "%command.incrementNumberByTen%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByOneTenth", - "title": "%command.decrementNumberByOneTenth%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByOne", - "title": "%command.decrementNumberByOne%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByTen", - "title": "%command.decrementNumberByTen%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.reflectCSSValue", - "title": "%command.reflectCSSValue%", - "category": "Emmet" - }, - { - "command": "workbench.action.showEmmetCommands", - "title": "%command.showEmmetCommands%", - "category": "" + "charset": { + "type": "string", + "default": "UTF-8" } - ], - "menus": { - "commandPalette": [ - { - "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation" - }, - { - "command": "editor.emmet.action.wrapWithAbbreviation" - }, - { - "command": "editor.emmet.action.removeTag" - }, - { - "command": "editor.emmet.action.updateTag" - }, - { - "command": "editor.emmet.action.matchTag" - }, - { - "command": "editor.emmet.action.balanceIn" - }, - { - "command": "editor.emmet.action.balanceOut" - }, - { - "command": "editor.emmet.action.prevEditPoint" - }, - { - "command": "editor.emmet.action.nextEditPoint" - }, - { - "command": "editor.emmet.action.mergeLines" - }, - { - "command": "editor.emmet.action.selectPrevItem" - }, - { - "command": "editor.emmet.action.selectNextItem" - }, - { - "command": "editor.emmet.action.splitJoinTag" - }, - { - "command": "editor.emmet.action.toggleComment" - }, - { - "command": "editor.emmet.action.evaluateMathExpression" - }, - { - "command": "editor.emmet.action.updateImageSize", - "when": "resourceScheme =~ /^file$/" - }, - { - "command": "editor.emmet.action.incrementNumberByOneTenth" - }, - { - "command": "editor.emmet.action.incrementNumberByOne" - }, - { - "command": "editor.emmet.action.incrementNumberByTen" - }, - { - "command": "editor.emmet.action.decrementNumberByOneTenth" - }, - { - "command": "editor.emmet.action.decrementNumberByOne" - }, - { - "command": "editor.emmet.action.decrementNumberByTen" - }, - { - "command": "editor.emmet.action.reflectCSSValue" - } - ] + }, + "default": {}, + "description": "%emmetVariables%" + }, + "emmet.syntaxProfiles": { + "type": "object", + "default": {}, + "description": "%emmetSyntaxProfiles%" + }, + "emmet.excludeLanguages": { + "type": "array", + "default": [ + "markdown" + ], + "description": "%emmetExclude%" + }, + "emmet.extensionsPath": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "%emmetExtensionsPath%" + }, + "emmet.triggerExpansionOnTab": { + "type": "boolean", + "default": false, + "description": "%emmetTriggerExpansionOnTab%" + }, + "emmet.preferences": { + "type": "object", + "default": {}, + "description": "%emmetPreferences%", + "properties": { + "css.intUnit": { + "type": "string", + "default": "px", + "description": "%emmetPreferencesIntUnit%" + }, + "css.floatUnit": { + "type": "string", + "default": "em", + "description": "%emmetPreferencesFloatUnit%" + }, + "css.propertyEnd": { + "type": "string", + "default": ";", + "description": "%emmetPreferencesCssAfter%" + }, + "sass.propertyEnd": { + "type": "string", + "default": "", + "description": "%emmetPreferencesSassAfter%" + }, + "stylus.propertyEnd": { + "type": "string", + "default": "", + "description": "%emmetPreferencesStylusAfter%" + }, + "css.valueSeparator": { + "type": "string", + "default": ": ", + "description": "%emmetPreferencesCssBetween%" + }, + "sass.valueSeparator": { + "type": "string", + "default": ": ", + "description": "%emmetPreferencesSassBetween%" + }, + "stylus.valueSeparator": { + "type": "string", + "default": " ", + "description": "%emmetPreferencesStylusBetween%" + }, + "bem.elementSeparator": { + "type": "string", + "default": "__", + "description": "%emmetPreferencesBemElementSeparator%" + }, + "bem.modifierSeparator": { + "type": "string", + "default": "_", + "description": "%emmetPreferencesBemModifierSeparator%" + }, + "filter.commentBefore": { + "type": "string", + "default": "", + "description": "%emmetPreferencesFilterCommentBefore%" + }, + "filter.commentAfter": { + "type": "string", + "default": "\n", + "description": "%emmetPreferencesFilterCommentAfter%" + }, + "filter.commentTrigger": { + "type": "array", + "default": [ + "id", + "class" + ], + "description": "%emmetPreferencesFilterCommentTrigger%" + }, + "format.noIndentTags": { + "type": "array", + "default": [ + "html" + ], + "description": "%emmetPreferencesFormatNoIndentTags%" + }, + "format.forceIndentationForTags": { + "type": "array", + "default": [ + "body" + ], + "description": "%emmetPreferencesFormatForceIndentTags%" + }, + "profile.allowCompactBoolean": { + "type": "boolean", + "default": false, + "description": "%emmetPreferencesAllowCompactBoolean%" + }, + "css.webkitProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssWebkitProperties%" + }, + "css.mozProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssMozProperties%" + }, + "css.oProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssOProperties%" + }, + "css.msProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssMsProperties%" + }, + "css.fuzzySearchMinScore": { + "type": "number", + "default": 0.3, + "description": "%emmetPreferencesCssFuzzySearchMinScore%" + } + } + }, + "emmet.showSuggestionsAsSnippets": { + "type": "boolean", + "default": false, + "markdownDescription": "%emmetShowSuggestionsAsSnippets%" + }, + "emmet.optimizeStylesheetParsing": { + "type": "boolean", + "default": true, + "markdownDescription": "%emmetOptimizeStylesheetParsing%" } + } }, - "scripts": { - "watch": "gulp watch-extension:emmet", - "compile": "gulp compile-extension:emmet", - "deps": "yarn add vscode-emmet-helper" - }, - "devDependencies": { - "@types/node": "^12.11.7", - "mocha-junit-reporter": "^1.17.0", - "mocha-multi-reporters": "^1.1.7", - "vscode": "1.0.1" - }, - "dependencies": { - "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", - "@emmetio/html-matcher": "^0.3.3", - "@emmetio/math-expression": "^1.0.4", - "image-size": "^0.5.2", - "vscode-emmet-helper": "~2.0.0", - "vscode-html-languageservice": "^3.0.3" + "commands": [ + { + "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation", + "title": "%command.wrapIndividualLinesWithAbbreviation%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.wrapWithAbbreviation", + "title": "%command.wrapWithAbbreviation%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.expandAbbreviation", + "title": "%command.expandAbbreviation%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.removeTag", + "title": "%command.removeTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.updateTag", + "title": "%command.updateTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.matchTag", + "title": "%command.matchTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.balanceIn", + "title": "%command.balanceIn%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.balanceOut", + "title": "%command.balanceOut%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.prevEditPoint", + "title": "%command.prevEditPoint%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.nextEditPoint", + "title": "%command.nextEditPoint%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.mergeLines", + "title": "%command.mergeLines%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.selectPrevItem", + "title": "%command.selectPrevItem%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.selectNextItem", + "title": "%command.selectNextItem%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.splitJoinTag", + "title": "%command.splitJoinTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.toggleComment", + "title": "%command.toggleComment%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.evaluateMathExpression", + "title": "%command.evaluateMathExpression%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.updateImageSize", + "title": "%command.updateImageSize%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByOneTenth", + "title": "%command.incrementNumberByOneTenth%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByOne", + "title": "%command.incrementNumberByOne%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByTen", + "title": "%command.incrementNumberByTen%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByOneTenth", + "title": "%command.decrementNumberByOneTenth%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByOne", + "title": "%command.decrementNumberByOne%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByTen", + "title": "%command.decrementNumberByTen%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.reflectCSSValue", + "title": "%command.reflectCSSValue%", + "category": "Emmet" + }, + { + "command": "workbench.action.showEmmetCommands", + "title": "%command.showEmmetCommands%", + "category": "" + } + ], + "keybindings": [ + { + "key": "tab", + "command": "editor.emmet.action.expandAbbreviation", + "when": "config.emmet.triggerExpansionOnTab && editorTextFocus && !editorReadonly && !editorTabMovesFocus" + } + ], + "menus": { + "commandPalette": [ + { + "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation" + }, + { + "command": "editor.emmet.action.wrapWithAbbreviation" + }, + { + "command": "editor.emmet.action.expandAbbreviation" + }, + { + "command": "editor.emmet.action.removeTag" + }, + { + "command": "editor.emmet.action.updateTag" + }, + { + "command": "editor.emmet.action.matchTag" + }, + { + "command": "editor.emmet.action.balanceIn" + }, + { + "command": "editor.emmet.action.balanceOut" + }, + { + "command": "editor.emmet.action.prevEditPoint" + }, + { + "command": "editor.emmet.action.nextEditPoint" + }, + { + "command": "editor.emmet.action.mergeLines" + }, + { + "command": "editor.emmet.action.selectPrevItem" + }, + { + "command": "editor.emmet.action.selectNextItem" + }, + { + "command": "editor.emmet.action.splitJoinTag" + }, + { + "command": "editor.emmet.action.toggleComment" + }, + { + "command": "editor.emmet.action.evaluateMathExpression" + }, + { + "command": "editor.emmet.action.updateImageSize", + "when": "resourceScheme =~ /^file$/" + }, + { + "command": "editor.emmet.action.incrementNumberByOneTenth" + }, + { + "command": "editor.emmet.action.incrementNumberByOne" + }, + { + "command": "editor.emmet.action.incrementNumberByTen" + }, + { + "command": "editor.emmet.action.decrementNumberByOneTenth" + }, + { + "command": "editor.emmet.action.decrementNumberByOne" + }, + { + "command": "editor.emmet.action.decrementNumberByTen" + }, + { + "command": "editor.emmet.action.reflectCSSValue" + } + ] } + }, + "scripts": { + "watch": "gulp watch-extension:emmet", + "compile": "gulp compile-extension:emmet", + "deps": "yarn add vscode-emmet-helper" + }, + "devDependencies": { + "@types/node": "^12.11.7", + "mocha-junit-reporter": "^1.17.0", + "mocha-multi-reporters": "^1.1.7", + "vscode": "1.0.1" + }, + "dependencies": { + "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", + "@emmetio/html-matcher": "^0.3.3", + "@emmetio/math-expression": "^1.0.4", + "image-size": "^0.5.2", + "vscode-emmet-helper": "~2.0.0", + "vscode-html-languageservice": "^3.0.3" + } } diff --git a/extensions/emmet/package.nls.json b/extensions/emmet/package.nls.json index 2a1add8935e..4d4090c2b1f 100644 --- a/extensions/emmet/package.nls.json +++ b/extensions/emmet/package.nls.json @@ -2,6 +2,7 @@ "description": "Emmet support for VS Code", "command.wrapWithAbbreviation": "Wrap with Abbreviation", "command.wrapIndividualLinesWithAbbreviation": "Wrap Individual Lines with Abbreviation", + "command.expandAbbreviation": "Expand Abbreviation", "command.removeTag": "Remove Tag", "command.updateTag": "Update Tag", "command.matchTag": "Go to Matching Pair", diff --git a/extensions/emmet/src/emmetCommon.ts b/extensions/emmet/src/emmetCommon.ts index e768b03afd6..a458433057c 100644 --- a/extensions/emmet/src/emmetCommon.ts +++ b/extensions/emmet/src/emmetCommon.ts @@ -31,10 +31,14 @@ export function activateEmmetExtension(context: vscode.ExtensionContext) { wrapIndividualLinesWithAbbreviation(args); })); - context.subscriptions.push(vscode.commands.registerCommand('emmet.expandAbbreviation', (args) => { + context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.expandAbbreviationInternal', (args) => { expandEmmetAbbreviation(args); })); + context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.expandAbbreviation', () => { + vscode.commands.executeCommand('workbench.action.expandEmmetAbbreviation'); + })); + context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.removeTag', () => { return removeTag(); })); diff --git a/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts b/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts deleted file mode 100644 index b6129b8a6ae..00000000000 --- a/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts +++ /dev/null @@ -1,43 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; -import { EmmetEditorAction } from 'vs/workbench/contrib/emmet/browser/emmetActions'; -import { registerEditorAction } from 'vs/editor/browser/editorExtensions'; -import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { KeyCode } from 'vs/base/common/keyCodes'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { MenuId } from 'vs/platform/actions/common/actions'; - -class ExpandAbbreviationAction extends EmmetEditorAction { - - constructor() { - super({ - id: 'editor.emmet.action.expandAbbreviation', - label: nls.localize('expandAbbreviationAction', "Emmet: Expand Abbreviation"), - alias: 'Emmet: Expand Abbreviation', - precondition: EditorContextKeys.writable, - actionName: 'expand_abbreviation', - kbOpts: { - primary: KeyCode.Tab, - kbExpr: ContextKeyExpr.and( - EditorContextKeys.editorTextFocus, - EditorContextKeys.tabDoesNotMoveFocus, - ContextKeyExpr.has('config.emmet.triggerExpansionOnTab') - ), - weight: KeybindingWeight.EditorContrib - }, - menuOpts: { - menuId: MenuId.MenubarEditMenu, - group: '5_insert', - title: nls.localize({ key: 'miEmmetExpandAbbreviation', comment: ['&& denotes a mnemonic'] }, "Emmet: E&&xpand Abbreviation"), - order: 3 - } - }); - - } -} - -registerEditorAction(ExpandAbbreviationAction); diff --git a/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts b/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts index f29d6b2c022..8d64955f6de 100644 --- a/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts +++ b/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts @@ -3,5 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import './actions/expandAbbreviation'; +import { registerEditorCommand } from 'vs/editor/browser/editorExtensions'; +import { expandEmmetAbbreviationCommand } from './expandEmmetAbbreviation'; +registerEditorCommand(expandEmmetAbbreviationCommand); diff --git a/src/vs/workbench/contrib/emmet/browser/emmetActions.ts b/src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts similarity index 69% rename from src/vs/workbench/contrib/emmet/browser/emmetActions.ts rename to src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts index 607da869cc3..008f63c289f 100644 --- a/src/vs/workbench/contrib/emmet/browser/emmetActions.ts +++ b/src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorAction, ServicesAccessor, IActionOptions } from 'vs/editor/browser/editorExtensions'; +import { ServicesAccessor, EditorCommand } from 'vs/editor/browser/editorExtensions'; import { grammarsExtPoint, ITMSyntaxExtensionPoint } from 'vs/workbench/services/textMate/common/TMGrammars'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IExtensionService, ExtensionPointContribution } from 'vs/workbench/services/extensions/common/extensions'; @@ -24,7 +24,6 @@ export interface ILanguageIdentifierResolver { } class GrammarContributions implements IGrammarContributions { - private static _grammars: ModeScopeMap = {}; constructor(contributions: ExtensionPointContribution[]) { @@ -48,20 +47,12 @@ class GrammarContributions implements IGrammarContributions { } } -export interface IEmmetActionOptions extends IActionOptions { - actionName: string; -} - -export abstract class EmmetEditorAction extends EditorAction { - - protected emmetActionName: string; - - constructor(opts: IEmmetActionOptions) { - super(opts); - this.emmetActionName = opts.actionName; +export class ExpandEmmetAbbreviationCommand extends EditorCommand { + constructor() { + super({ id: 'workbench.action.expandEmmetAbbreviation', precondition: undefined }); } - private static readonly emmetSupportedModes = ['html', 'css', 'xml', 'xsl', 'haml', 'jade', 'jsx', 'slim', 'scss', 'sass', 'less', 'stylus', 'styl', 'svg']; + private static readonly emmetSupportedModes = ['html', 'xml', 'xsl', 'jsx', 'js', 'pug', 'slim', 'haml', 'css', 'sass', 'scss', 'less', 'sss', 'stylus']; private _lastGrammarContributions: Promise | null = null; private _lastExtensionService: IExtensionService | null = null; @@ -75,20 +66,21 @@ export abstract class EmmetEditorAction extends EditorAction { return this._lastGrammarContributions || Promise.resolve(null); } - public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise { + public runEditorCommand(accessor: ServicesAccessor | null, editor: ICodeEditor, args: any): void | Promise { + if (!accessor) { + return; + } + const extensionService = accessor.get(IExtensionService); const modeService = accessor.get(IModeService); const commandService = accessor.get(ICommandService); return this._withGrammarContributions(extensionService).then((grammarContributions) => { - - if (this.id === 'editor.emmet.action.expandAbbreviation' && grammarContributions) { - return commandService.executeCommand('emmet.expandAbbreviation', EmmetEditorAction.getLanguage(modeService, editor, grammarContributions)); + if (this.id === 'workbench.action.expandEmmetAbbreviation' && grammarContributions) { + return commandService.executeCommand('editor.emmet.action.expandAbbreviationInternal', ExpandEmmetAbbreviationCommand.getLanguage(modeService, editor, grammarContributions)); } - return undefined; }); - } public static getLanguage(languageIdentifierResolver: ILanguageIdentifierResolver, editor: ICodeEditor, grammars: IGrammarContributions) { @@ -104,24 +96,34 @@ export abstract class EmmetEditorAction extends EditorAction { const languageId = model.getLanguageIdAtPosition(position.lineNumber, position.column); const languageIdentifier = languageIdentifierResolver.getLanguageIdentifier(languageId); const language = languageIdentifier ? languageIdentifier.language : ''; - const syntax = language.split('.').pop(); + let syntax = language.split('.').pop(); if (!syntax) { return null; } - let checkParentMode = (): string => { - let languageGrammar = grammars.getGrammar(syntax); + // map to something Emmet understands + if (['jsx-tags', 'javascriptreact', 'typescriptreact'].includes(syntax)) { + syntax = 'jsx'; + } + + const getParentMode = (syntax: string): string => { + if (syntax === 'jsx') { + // return otherwise getGrammar gives a string that Emmet doesn't understand + return syntax; + } + + const languageGrammar = grammars.getGrammar(syntax); if (!languageGrammar) { return syntax; } - let languages = languageGrammar.split('.'); - if (languages.length < 2) { + const languages = languageGrammar.split('.'); + if (languages.length <= 1) { return syntax; } - for (let i = 1; i < languages.length; i++) { - const language = languages[languages.length - i]; - if (this.emmetSupportedModes.indexOf(language) !== -1) { + for (let i = languages.length - 1; i >= 1; i--) { + const language = languages[i]; + if (this.emmetSupportedModes.includes(language)) { return language; } } @@ -130,9 +132,9 @@ export abstract class EmmetEditorAction extends EditorAction { return { language: syntax, - parentMode: checkParentMode() + parentMode: getParentMode(syntax) }; } - - } + +export const expandEmmetAbbreviationCommand = new ExpandEmmetAbbreviationCommand(); diff --git a/src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts b/src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts similarity index 57% rename from src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts rename to src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts index c56afa2d157..885e1a5064e 100644 --- a/src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts +++ b/src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts @@ -3,29 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IGrammarContributions, ILanguageIdentifierResolver, EmmetEditorAction } from 'vs/workbench/contrib/emmet/browser/emmetActions'; +import { IGrammarContributions, ILanguageIdentifierResolver, ExpandEmmetAbbreviationCommand } from 'vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import * as assert from 'assert'; import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; -// -// To run the emmet tests only change .vscode/launch.json -// { -// "name": "Stacks Tests", -// "type": "node", -// "request": "launch", -// "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", -// "stopOnEntry": false, -// "args": [ -// "--timeout", -// "999999", -// "--colors", -// "-g", -// "Stacks" <<<--- Emmet -// ], -// Select the 'Stacks Tests' launch config and F5 -// - class MockGrammarContributions implements IGrammarContributions { private scopeName: string; @@ -33,16 +15,14 @@ class MockGrammarContributions implements IGrammarContributions { this.scopeName = scopeName; } - public getGrammar(mode: string): string { + public getGrammar(_: string): string { return this.scopeName; } } -suite('Emmet', () => { - - test('Get language mode and parent mode for emmet', () => { +suite('Emmet expandAbbreviation command', () => { + test('gets language mode and parent mode for Emmet', () => { withTestCodeEditor([], {}, (editor) => { - function testIsEnabled(mode: string, scopeName: string, expectedLanguage?: string, expectedParentLanguage?: string) { const languageIdentifier = new LanguageIdentifier(mode, 73); const languageIdentifierResolver: ILanguageIdentifierResolver = { @@ -59,13 +39,13 @@ suite('Emmet', () => { } model.setMode(languageIdentifier); - let langOutput = EmmetEditorAction.getLanguage(languageIdentifierResolver, editor, new MockGrammarContributions(scopeName)); + const langOutput = ExpandEmmetAbbreviationCommand.getLanguage(languageIdentifierResolver, editor, new MockGrammarContributions(scopeName)); if (!langOutput) { assert.fail('langOutput not found'); } - assert.equal(langOutput.language, expectedLanguage); - assert.equal(langOutput.parentMode, expectedParentLanguage); + assert.strictEqual(langOutput.language, expectedLanguage); + assert.strictEqual(langOutput.parentMode, expectedParentLanguage); } // syntaxes mapped using the scope name of the grammar @@ -74,10 +54,22 @@ suite('Emmet', () => { testIsEnabled('nunjucks', 'text.html.nunjucks', 'nunjucks', 'html'); testIsEnabled('laravel-blade', 'text.html.php.laravel-blade', 'laravel-blade', 'html'); - // languages that have different Language Id and scopeName - // testIsEnabled('razor', 'text.html.cshtml', 'razor', 'html'); - // testIsEnabled('HTML (Eex)', 'text.html.elixir', 'boo', 'html'); + // basic syntaxes + testIsEnabled('html', 'text.html.derivative', 'html', 'html'); + testIsEnabled('css', 'source.css', 'css', 'css'); + testIsEnabled('scss', 'source.css.scss', 'scss', 'scss'); + testIsEnabled('xml', 'text.xml', 'xml', 'xml'); + testIsEnabled('xsl', 'text.xml.xsl', 'xsl', 'xsl'); + // syntaxes that combine HTML and TS/JS + // expanding inside of HTML tags within jsx/tsx + testIsEnabled('jsx-tags', 'source.js.jsx', 'jsx', 'jsx'); + // expanding outside of HTML tags within jsx/tsx + testIsEnabled('javascriptreact', 'source.js.jsx', 'jsx', 'jsx'); + testIsEnabled('typescriptreact', 'source.tsx', 'jsx', 'jsx'); + + // syntaxes that combine HTML and some other language + testIsEnabled('razor', 'text.html.cshtml', 'razor', 'html'); }); }); }); From c833899a84fbef6731d3add8adceee36f7ee9959 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Thu, 19 Nov 2020 17:13:10 -0500 Subject: [PATCH 0058/1837] adds @features: settings search type and dropdown option to Configure Terminal Settings (#110874) --- .../preferences/browser/settingsEditor2.ts | 8 ++- .../preferences/browser/settingsLayout.ts | 13 ++-- .../preferences/browser/settingsTree.ts | 12 ++-- .../preferences/browser/settingsTreeModels.ts | 63 +++++++++++++++++-- .../contrib/preferences/browser/tocTree.ts | 5 +- .../contrib/preferences/common/preferences.ts | 2 +- .../test/browser/settingsTreeModels.test.ts | 32 +++++++++- .../terminal/browser/terminalActions.ts | 26 +++++++- .../contrib/terminal/common/terminal.ts | 1 + 9 files changed, 135 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 98bf56067ba..790e22901d5 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -46,7 +46,7 @@ import { AbstractSettingRenderer, ISettingLinkClickEvent, ISettingOverrideClickE import { ISettingsEditorViewState, parseQuery, SearchResultIdx, SearchResultModel, SettingsTreeElement, SettingsTreeGroupChild, SettingsTreeGroupElement, SettingsTreeModel, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels'; import { settingsTextInputBorder } from 'vs/workbench/contrib/preferences/browser/settingsWidgets'; import { createTOCIterator, TOCTree, TOCTreeModel } from 'vs/workbench/contrib/preferences/browser/tocTree'; -import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingsEditorOptions, SettingValueType } from 'vs/workbench/services/preferences/common/preferences'; import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; @@ -90,7 +90,7 @@ export class SettingsEditor2 extends EditorPane { private static CONFIG_SCHEMA_UPDATE_DELAYER = 500; private static readonly SUGGESTIONS: string[] = [ - `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${EXTENSION_SETTING_TAG}` + `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` ]; private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean { @@ -1134,18 +1134,20 @@ export class SettingsEditor2 extends EditorPane { private triggerSearch(query: string): Promise { this.viewState.tagFilters = new Set(); this.viewState.extensionFilters = new Set(); + this.viewState.featureFilters = new Set(); if (query) { const parsedQuery = parseQuery(query); query = parsedQuery.query; parsedQuery.tags.forEach(tag => this.viewState.tagFilters!.add(tag)); parsedQuery.extensionFilters.forEach(extensionId => this.viewState.extensionFilters!.add(extensionId)); + parsedQuery.featureFilters!.forEach(feature => this.viewState.featureFilters!.add(feature)); } if (query && query !== '@') { query = this.parseSettingFromJSON(query) || query; return this.triggerFilterPreferences(query); } else { - if ((this.viewState.tagFilters && this.viewState.tagFilters.size) || (this.viewState.extensionFilters && this.viewState.extensionFilters.size)) { + if (this.viewState.tagFilters.size || this.viewState.extensionFilters.size || this.viewState.featureFilters.size) { this.searchResultModel = this.createFilterModel(); } else { this.searchResultModel = null; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts index bc258efa43e..86b50e98946 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts @@ -4,23 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { ISetting } from 'vs/workbench/services/preferences/common/preferences'; - -export interface ITOCEntry { +export interface ITOCEntry { id: string; label: string; - - children?: ITOCEntry[]; - settings?: Array; + children?: ITOCEntry[]; + settings?: Array; } -export const commonlyUsedData: ITOCEntry = { +export const commonlyUsedData: ITOCEntry = { id: 'commonlyUsed', label: localize('commonlyUsed', "Commonly Used"), settings: ['files.autoSave', 'editor.fontSize', 'editor.fontFamily', 'editor.tabSize', 'editor.renderWhitespace', 'editor.cursorStyle', 'editor.multiCursorModifier', 'editor.insertSpaces', 'editor.wordWrap', 'files.exclude', 'files.associations', 'workbench.editor.enablePreview'] }; -export const tocData: ITOCEntry = { +export const tocData: ITOCEntry = { id: 'root', label: 'root', children: [ diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 6c3114a0f92..6e09eb02531 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -258,7 +258,7 @@ function getListDisplayValue(element: SettingsTreeSettingElement): IListDataItem }); } -export function resolveSettingsTree(tocData: ITOCEntry, coreSettingsGroups: ISettingsGroup[], logService: ILogService): { tree: ITOCEntry, leftoverSettings: Set } { +export function resolveSettingsTree(tocData: ITOCEntry, coreSettingsGroups: ISettingsGroup[], logService: ILogService): { tree: ITOCEntry, leftoverSettings: Set } { const allSettings = getFlatSettings(coreSettingsGroups); return { tree: _resolveSettingsTree(tocData, allSettings, logService), @@ -266,7 +266,7 @@ export function resolveSettingsTree(tocData: ITOCEntry, coreSettingsGroups: ISet }; } -export function resolveExtensionsSettings(groups: ISettingsGroup[]): ITOCEntry { +export function resolveExtensionsSettings(groups: ISettingsGroup[]): ITOCEntry { const settingsGroupToEntry = (group: ISettingsGroup) => { const flatSettings = arrays.flatten( group.sections.map(section => section.settings)); @@ -289,8 +289,8 @@ export function resolveExtensionsSettings(groups: ISettingsGroup[]): ITOCEntry { }; } -function _resolveSettingsTree(tocData: ITOCEntry, allSettings: Set, logService: ILogService): ITOCEntry { - let children: ITOCEntry[] | undefined; +function _resolveSettingsTree(tocData: ITOCEntry, allSettings: Set, logService: ILogService): ITOCEntry { + let children: ITOCEntry[] | undefined; if (tocData.children) { children = tocData.children .map(child => _resolveSettingsTree(child, allSettings, logService)) @@ -299,7 +299,7 @@ function _resolveSettingsTree(tocData: ITOCEntry, allSettings: Set, lo let settings: ISetting[] | undefined; if (tocData.settings) { - settings = arrays.flatten(tocData.settings.map(pattern => getMatchingSettings(allSettings, pattern, logService))); + settings = arrays.flatten(tocData.settings.map(pattern => getMatchingSettings(allSettings, pattern, logService))); } if (!children && !settings) { @@ -333,7 +333,7 @@ function getMatchingSettings(allSettings: Set, pattern: string, logSer const settingPatternCache = new Map(); -function createSettingMatchRegExp(pattern: string): RegExp { +export function createSettingMatchRegExp(pattern: string): RegExp { pattern = escapeRegExpCharacters(pattern) .replace(/\\\*/g, '.*'); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 12a988e5543..d29c79e2937 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { ConfigurationTarget, IConfigurationService, IConfigurationValue } from 'vs/platform/configuration/common/configuration'; import { SettingsTarget } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; -import { ITOCEntry, knownAcronyms, knownTermMappings } from 'vs/workbench/contrib/preferences/browser/settingsLayout'; +import { ITOCEntry, knownAcronyms, knownTermMappings, tocData } from 'vs/workbench/contrib/preferences/browser/settingsLayout'; import { MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences'; import { IExtensionSetting, ISearchResult, ISetting, SettingValueType } from 'vs/workbench/services/preferences/common/preferences'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -18,6 +18,7 @@ import { FOLDER_SCOPES, WORKSPACE_SCOPES, REMOTE_MACHINE_SCOPES, LOCAL_MACHINE_S import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; +import { createSettingMatchRegExp } from 'vs/workbench/contrib/preferences/browser/settingsTree'; export const ONLINE_SERVICES_SETTING_TAG = 'usesOnlineServices'; @@ -25,6 +26,7 @@ export interface ISettingsEditorViewState { settingsTarget: SettingsTarget; tagFilters?: Set; extensionFilters?: Set; + featureFilters?: Set; filterToCategory?: SettingsTreeGroupElement; } @@ -288,12 +290,34 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { return Array.from(extensionFilters).some(extensionId => extensionId.toLowerCase() === this.setting.extensionInfo!.id.toLowerCase()); } + + matchesAnyFeature(featureFilters?: Set): boolean { + if (!featureFilters || !featureFilters.size) { + return true; + } + + const features = tocData.children!.find(child => child.id === 'features'); + + return Array.from(featureFilters).some(filter => { + if (features && features.children) { + const feature = features.children.find(feature => 'features/' + filter === feature.id); + if (feature) { + const patterns = feature.settings?.map(setting => createSettingMatchRegExp(setting)); + return patterns && !this.setting.extensionInfo && patterns.some(pattern => pattern.test(this.setting.key.toLowerCase())); + } else { + return false; + } + } else { + return false; + } + }); + } } export class SettingsTreeModel { protected _root!: SettingsTreeGroupElement; private _treeElementsBySettingName = new Map(); - private _tocRoot!: ITOCEntry; + private _tocRoot!: ITOCEntry; constructor( protected _viewState: ISettingsEditorViewState, @@ -349,14 +373,14 @@ export class SettingsTreeModel { }); } - private createSettingsTreeGroupElement(tocEntry: ITOCEntry, parent?: SettingsTreeGroupElement): SettingsTreeGroupElement { + private createSettingsTreeGroupElement(tocEntry: ITOCEntry, parent?: SettingsTreeGroupElement): SettingsTreeGroupElement { const depth = parent ? this.getDepth(parent) + 1 : 0; const element = new SettingsTreeGroupElement(tocEntry.id, undefined, tocEntry.label, depth, false); const children: SettingsTreeGroupChild[] = []; if (tocEntry.settings) { - const settingChildren = tocEntry.settings.map(s => this.createSettingsTreeSettingElement(s, element)) + const settingChildren = tocEntry.settings.map(s => this.createSettingsTreeSettingElement(s, element)) .filter(el => el.setting.deprecationMessage ? el.isConfigured : true); children.push(...settingChildren); } @@ -608,8 +632,9 @@ export class SearchResultModel extends SettingsTreeModel { // Save time, filter children in the search model instead of relying on the tree filter, which still requires heights to be calculated. const isRemote = !!this.environmentService.remoteAuthority; + this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters)); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches @@ -623,6 +648,22 @@ export class SearchResultModel extends SettingsTreeModel { } } + private containsValidFeature(): boolean { + if (!this._viewState.featureFilters || !this._viewState.featureFilters.size || !tocData.children) { + return false; + } + + const features = tocData.children.find(child => child.id === 'features'); + + if (features && features.children) { + return Array.from(this._viewState.featureFilters).some(filter => { + return features.children?.find(feature => 'features/' + filter === feature.id); + }); + } else { + return false; + } + } + private getFlatSettings(): ISetting[] { const flatSettings: ISetting[] = []; arrays.coalesce(this.getUniqueResults()) @@ -639,13 +680,16 @@ export interface IParsedQuery { tags: string[]; query: string; extensionFilters: string[]; + featureFilters: string[]; } const tagRegex = /(^|\s)@tag:("([^"]*)"|[^"]\S*)/g; const extensionRegex = /(^|\s)@ext:("([^"]*)"|[^"]\S*)?/g; +const featureRegex = /(^|\s)@feature:("([^"]*)"|[^"]\S*)?/g; export function parseQuery(query: string): IParsedQuery { const tags: string[] = []; const extensions: string[] = []; + const features: string[] = []; query = query.replace(tagRegex, (_, __, quotedTag, tag) => { tags.push(tag || quotedTag); return ''; @@ -664,11 +708,20 @@ export function parseQuery(query: string): IParsedQuery { return ''; }); + query = query.replace(featureRegex, (_, __, quotedFeature, feature) => { + const featureQuery: string = feature || quotedFeature; + if (featureQuery) { + features.push(...featureQuery.split(',').map(s => s.trim()).filter(s => !isFalsyOrWhitespace(s))); + } + return ''; + }); + query = query.trim(); return { tags, extensionFilters: extensions, + featureFilters: features, query }; } diff --git a/src/vs/workbench/contrib/preferences/browser/tocTree.ts b/src/vs/workbench/contrib/preferences/browser/tocTree.ts index 4413f074aac..3888aad4803 100644 --- a/src/vs/workbench/contrib/preferences/browser/tocTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/tocTree.ts @@ -90,7 +90,10 @@ export class TOCTreeModel { // Check everything that the SettingsFilter checks except whether it's filtered by a category const isRemote = !!this.environmentService.remoteAuthority; - return child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAllTags(this._viewState.tagFilters) && child.matchesAnyExtension(this._viewState.extensionFilters); + return child.matchesScope(this._viewState.settingsTarget, isRemote) && + child.matchesAllTags(this._viewState.tagFilters) && + child.matchesAnyFeature(this._viewState.featureFilters) && + child.matchesAnyExtension(this._viewState.extensionFilters); }).length; } } diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index c2eae65be42..ca97a3d6414 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -70,5 +70,5 @@ export const KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS = 'keybindings.editor.show export const MODIFIED_SETTING_TAG = 'modified'; export const EXTENSION_SETTING_TAG = 'ext:'; - +export const FEATURE_SETTING_TAG = 'feature:'; export const KEYBOARD_LAYOUT_OPEN_PICKER = 'workbench.action.openKeyboardLayoutPicker'; diff --git a/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts b/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts index 8113f3d377b..7387f4519cb 100644 --- a/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts +++ b/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts @@ -147,6 +147,7 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: [], + featureFilters: [], query: '' }); @@ -155,6 +156,7 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + featureFilters: [], query: '' }); @@ -163,6 +165,7 @@ suite('SettingsTree', () => { { tags: ['foo'], extensionFilters: [], + featureFilters: [], query: '' }); @@ -171,6 +174,7 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + featureFilters: [], query: 'foo' }); @@ -179,6 +183,7 @@ suite('SettingsTree', () => { { tags: ['foo', 'modified'], extensionFilters: [], + featureFilters: [], query: '' }); @@ -187,6 +192,7 @@ suite('SettingsTree', () => { { tags: ['foo', 'modified'], extensionFilters: [], + featureFilters: [], query: 'my query' }); @@ -195,6 +201,7 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + featureFilters: [], query: 'test query' }); @@ -203,6 +210,7 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + featureFilters: [], query: 'test' }); @@ -211,7 +219,8 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: [], - query: 'query has @ for some reason' + query: 'query has @ for some reason', + featureFilters: [], }); testParseQuery( @@ -219,6 +228,7 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: ['github.vscode-pull-request-github'], + featureFilters: [], query: '' }); @@ -227,7 +237,25 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: ['github.vscode-pull-request-github', 'vscode.git'], + featureFilters: [], + query: '' + }); + testParseQuery( + '@feature:scm', + { + tags: [], + extensionFilters: [], + featureFilters: ['scm'], + query: '' + }); + + testParseQuery( + '@feature:scm,terminal', + { + tags: [], + extensionFilters: [], + featureFilters: ['scm', 'terminal'], query: '' }); }); -}); \ No newline at end of file +}); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 51e40e4fc74..166378ba3b6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -41,6 +41,7 @@ import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewIte import { FindInFilesCommand, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions'; import { ILabelService } from 'vs/platform/label/common/label'; import { RemoteNameContext } from 'vs/workbench/browser/contextkeys'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; async function getCwdForSplit(configHelper: ITerminalConfigHelper, instance: ITerminalInstance, folders?: IWorkspaceFolder[], commandService?: ICommandService): Promise { switch (configHelper.config.splitCwd) { @@ -295,6 +296,23 @@ export class SelectDefaultShellWindowsTerminalAction extends Action { } } +export class ConfigureTerminalSettingsAction extends Action { + + public static readonly ID = TERMINAL_COMMAND_ID.CONFIGURE_TERMINAL_SETTINGS; + public static readonly LABEL = localize('workbench.action.terminal.openSettings', "Configure Terminal Settings"); + + constructor( + id: string, label: string, + @IPreferencesService private readonly _preferencesService: IPreferencesService + ) { + super(id, label); + } + + async run() { + this._preferencesService.openSettings(false, '@feature:terminal'); + } +} + const terminalIndexRe = /^([0-9]+): /; export class SwitchTerminalAction extends Action { @@ -307,6 +325,7 @@ export class SwitchTerminalAction extends Action { @ITerminalService private readonly _terminalService: ITerminalService, @ITerminalContributionService private readonly _contributions: ITerminalContributionService, @ICommandService private readonly _commands: ICommandService, + @IPreferencesService private readonly preferencesService: IPreferencesService ) { super(id, label, 'terminal-action switch-terminal'); } @@ -323,7 +342,11 @@ export class SwitchTerminalAction extends Action { this._terminalService.refreshActiveTab(); return this._terminalService.selectDefaultShell(); } - + if (item === ConfigureTerminalSettingsAction.LABEL) { + const settingsAction = new ConfigureTerminalSettingsAction(ConfigureTerminalSettingsAction.ID, ConfigureTerminalSettingsAction.LABEL, this.preferencesService); + settingsAction.run(); + this._terminalService.refreshActiveTab(); + } const indexMatches = terminalIndexRe.exec(item); if (indexMatches) { this._terminalService.setActiveTabByIndex(Number(indexMatches[1]) - 1); @@ -386,6 +409,7 @@ function getTerminalSelectOpenItems(terminalService: ITerminalService, contribut } items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL }); + items.push({ text: ConfigureTerminalSettingsAction.LABEL }); return items; } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 73a390bdf8f..edd076f6391 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -489,6 +489,7 @@ export const enum TERMINAL_COMMAND_ID { TOGGLE = 'workbench.action.terminal.toggleTerminal', KILL = 'workbench.action.terminal.kill', QUICK_KILL = 'workbench.action.terminal.quickKill', + CONFIGURE_TERMINAL_SETTINGS = 'workbench.action.terminal.openSettings', COPY_SELECTION = 'workbench.action.terminal.copySelection', SELECT_ALL = 'workbench.action.terminal.selectAll', DELETE_WORD_LEFT = 'workbench.action.terminal.deleteWordLeft', From 59428623f912c9f15b3074601c965fa79a45b3b9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 12 Nov 2020 14:39:10 -0800 Subject: [PATCH 0059/1837] Cancel encodedSemanticClassifications-full on resource change For #102161 --- .../src/languageFeatures/semanticTokens.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts index 3c2dd7a6458..202ed4d4ae1 100644 --- a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts +++ b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts @@ -75,7 +75,9 @@ class DocumentSemanticTokensProvider implements vscode.DocumentSemanticTokensPro let versionBeforeRequest = document.version; - const response = await (this.client as ExperimentalProtocol.IExtendedTypeScriptServiceClient).execute('encodedSemanticClassifications-full', requestArg, token); + const response = await (this.client as ExperimentalProtocol.IExtendedTypeScriptServiceClient).execute('encodedSemanticClassifications-full', requestArg, token, { + cancelOnResourceChange: document.uri + }); if (response.type !== 'response' || !response.body) { return null; } From 5d75857c59db9a0d254edadf88a3c23377a3279e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Nov 2020 14:14:03 -0800 Subject: [PATCH 0060/1837] Update marked cgmanifest entry --- src/vs/base/common/marked/cgmanifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/common/marked/cgmanifest.json b/src/vs/base/common/marked/cgmanifest.json index f3477931d13..15e641cb567 100644 --- a/src/vs/base/common/marked/cgmanifest.json +++ b/src/vs/base/common/marked/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "marked", "repositoryUrl": "https://github.com/markedjs/marked", - "commitHash": "529a8d4e185a8aa561e4d8d2891f8556b5717cd4" + "commitHash": "8cfa29ccd2a2759e8e60fe0d8d6df8c022beda4e" } }, "license": "MIT", - "version": "0.6.2" + "version": "1.1.0" } ], "version": 1 From 1dcbd67f00809754dc26217a939210f21bfce680 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 23:46:43 +0100 Subject: [PATCH 0061/1837] Load `applicationinsights` lazily --- .../telemetry/node/appInsightsAppender.ts | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index b288c282ab8..0001e177217 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as appInsights from 'applicationinsights'; +import { onUnexpectedError } from 'vs/base/common/errors'; import { mixin } from 'vs/base/common/objects'; import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils'; -function getClient(aiKey: string): appInsights.TelemetryClient { - +async function getClient(aiKey: string): Promise { + const appInsights = await import('applicationinsights'); let client: appInsights.TelemetryClient; if (appInsights.defaultClient) { client = new appInsights.TelemetryClient(aiKey); @@ -36,7 +37,8 @@ function getClient(aiKey: string): appInsights.TelemetryClient { export class AppInsightsAppender implements ITelemetryAppender { - private _aiClient?: appInsights.TelemetryClient; + private _aiClient: string | appInsights.TelemetryClient | undefined; + private _asyncAIClient: Promise | null; constructor( private _eventPrefix: string, @@ -47,11 +49,37 @@ export class AppInsightsAppender implements ITelemetryAppender { this._defaultData = Object.create(null); } - if (typeof aiKeyOrClientFactory === 'string') { - this._aiClient = getClient(aiKeyOrClientFactory); - } else if (typeof aiKeyOrClientFactory === 'function') { + if (typeof aiKeyOrClientFactory === 'function') { this._aiClient = aiKeyOrClientFactory(); + } else { + this._aiClient = aiKeyOrClientFactory; } + this._asyncAIClient = null; + } + + private _withAIClient(callback: (aiClient: appInsights.TelemetryClient) => void): void { + if (!this._aiClient) { + return; + } + + if (typeof this._aiClient !== 'string') { + callback(this._aiClient); + return; + } + + if (!this._asyncAIClient) { + this._asyncAIClient = getClient(this._aiClient); + } + + this._asyncAIClient.then( + (aiClient) => { + callback(aiClient); + }, + (err) => { + onUnexpectedError(err); + console.error(err); + } + ); } log(eventName: string, data?: any): void { @@ -61,22 +89,24 @@ export class AppInsightsAppender implements ITelemetryAppender { data = mixin(data, this._defaultData); data = validateTelemetryData(data); - this._aiClient.trackEvent({ + this._withAIClient((aiClient) => aiClient.trackEvent({ name: this._eventPrefix + '/' + eventName, properties: data.properties, measurements: data.measurements - }); + })); } flush(): Promise { if (this._aiClient) { return new Promise(resolve => { - this._aiClient!.flush({ - callback: () => { - // all data flushed - this._aiClient = undefined; - resolve(undefined); - } + this._withAIClient((aiClient) => { + aiClient.flush({ + callback: () => { + // all data flushed + this._aiClient = undefined; + resolve(undefined); + } + }); }); }); } From ea4d99921cc790d49194e897021faee02a1847f7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Nov 2020 23:50:53 +0100 Subject: [PATCH 0062/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c9530f5c5c0..29a262d3910 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "272c364107e05252fcd164b8bd7fe476e2a02b0a", + "distro": "e289d0d793bde8f8b5632625e01c50c218e7e127", "author": { "name": "Microsoft Corporation" }, From 67b0e2d72d23b5cd6c44cf71240ab1fe3b04bbe8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Nov 2020 22:09:44 -0800 Subject: [PATCH 0063/1837] Pick up TS 4.1 final release Fixes #111000 --- extensions/package.json | 2 +- extensions/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/package.json b/extensions/package.json index 98261d09a58..7abc2e1e6b8 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "4.1.1-rc" + "typescript": "4.1.2" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 059ea7481b6..9e9d4faf70b 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -typescript@4.1.1-rc: - version "4.1.1-rc" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.1-rc.tgz#4a335244b9b2754995849ca4b607c74d6ee73719" - integrity sha512-tgNcFrLIjlaMWEc7bKC0bxLNIt8BIAauY/HLUOQDyTP75HGskETtXOt46x4EKAHRKhWVLMc7yM02puTHa/yhCA== +typescript@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" + integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== From b4c0cfb5131963c3cee1d428ca7dbb1b51674e6a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Nov 2020 22:19:32 -0800 Subject: [PATCH 0064/1837] Better note current version in TS version UI Fixes #111001 --- .../typescript-language-features/src/tsServer/versionStatus.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/tsServer/versionStatus.ts b/extensions/typescript-language-features/src/tsServer/versionStatus.ts index 5d5650ba4a4..1d4e128942c 100644 --- a/extensions/typescript-language-features/src/tsServer/versionStatus.ts +++ b/extensions/typescript-language-features/src/tsServer/versionStatus.ts @@ -72,7 +72,7 @@ class ProjectStatusCommand implements Command { private getVersionItem(): QuickPickItem { return { label: localize('projectQuickPick.version.label', "Select TypeScript Version..."), - description: this._client.apiVersion.displayName, + description: localize('projectQuickPick.version.description', "[current = {0}]", this._client.apiVersion.displayName), run: () => { this._client.showVersionPicker(); } From caf01baa45b9816e2e1d8a2de22b40cf89459c03 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Nov 2020 22:39:04 -0800 Subject: [PATCH 0065/1837] Copy createSettingMatchRegExp locally to fix cycle --- .../contrib/preferences/browser/settingsTreeModels.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index d29c79e2937..94cf0a3cb1b 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as arrays from 'vs/base/common/arrays'; -import { isFalsyOrWhitespace } from 'vs/base/common/strings'; +import { escapeRegExpCharacters, isFalsyOrWhitespace } from 'vs/base/common/strings'; import { isArray, withUndefinedAsNull, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; @@ -18,7 +18,6 @@ import { FOLDER_SCOPES, WORKSPACE_SCOPES, REMOTE_MACHINE_SCOPES, LOCAL_MACHINE_S import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; -import { createSettingMatchRegExp } from 'vs/workbench/contrib/preferences/browser/settingsTree'; export const ONLINE_SERVICES_SETTING_TAG = 'usesOnlineServices'; @@ -314,6 +313,14 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } } + +function createSettingMatchRegExp(pattern: string): RegExp { + pattern = escapeRegExpCharacters(pattern) + .replace(/\\\*/g, '.*'); + + return new RegExp(`^${pattern}$`, 'i'); +} + export class SettingsTreeModel { protected _root!: SettingsTreeGroupElement; private _treeElementsBySettingName = new Map(); From acfd724aacb10e81ca71e1d49ee9025c24a595b3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Nov 2020 22:42:12 -0800 Subject: [PATCH 0066/1837] Pick up latest TS 4.2 for building VS Code Also fixes a newly identified error in terminal where function calls were missing --- build/package.json | 2 +- build/yarn.lock | 8 ++++---- package.json | 2 +- src/vs/workbench/contrib/terminal/node/terminal.ts | 2 +- yarn.lock | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/package.json b/build/package.json index 5de4f23887b..188bcf0c2f4 100644 --- a/build/package.json +++ b/build/package.json @@ -48,7 +48,7 @@ "minimist": "^1.2.3", "request": "^2.85.0", "terser": "4.3.8", - "typescript": "^4.2.0-dev.20201104", + "typescript": "^4.2.0-dev.20201119", "vsce": "1.48.0", "vscode-telemetry-extractor": "^1.6.0", "xml2js": "^0.4.17" diff --git a/build/yarn.lock b/build/yarn.lock index bdf8fa7d994..96d7054300f 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -3349,10 +3349,10 @@ typescript@^3.0.1: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== -typescript@^4.2.0-dev.20201104: - version "4.2.0-dev.20201104" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201104.tgz#9dca362fd423ac9391ef4a67bdc6f18537e9593c" - integrity sha512-MEnAcd0iwQySO+8F19KXGsX8WaHMda48j66I4qqUO8bknueGJUH/FdG9MakpApXd2Lzd9tlUMlOyT07dxeNsSQ== +typescript@^4.2.0-dev.20201119: + version "4.2.0-dev.20201119" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201119.tgz#d4a43511cd9931adac05e1a47b6425f6b0e76cc3" + integrity sha512-HIgv+D/0VpVYRTbcVVf9oac/0GtLKMqaufTcPgohNaFWlCOh4lq8syefANgENXTG5Q4VEC6xwDGzHW6EJAVr3A== typical@^4.0.0: version "4.0.0" diff --git a/package.json b/package.json index 29a262d3910..9c91d083c3e 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "style-loader": "^1.0.0", "ts-loader": "^4.4.2", "tsec": "googleinterns/tsec", - "typescript": "^4.2.0-dev.20201104", + "typescript": "^4.2.0-dev.20201119", "typescript-formatter": "7.1.0", "underscore": "^1.8.2", "vinyl": "^2.0.0", diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 8dc3b6c1533..4a006c386e2 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -152,7 +152,7 @@ async function validateShellPaths(label: string, potentialPaths: string[]): Prom } try { const result = await stat(normalize(current)); - if (result.isFile || result.isSymbolicLink) { + if (result.isFile() || result.isSymbolicLink()) { return { label, path: current diff --git a/yarn.lock b/yarn.lock index 061960377ea..a3f05fe9cb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9296,10 +9296,10 @@ typescript@^2.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q= -typescript@^4.2.0-dev.20201104: - version "4.2.0-dev.20201104" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201104.tgz#9dca362fd423ac9391ef4a67bdc6f18537e9593c" - integrity sha512-MEnAcd0iwQySO+8F19KXGsX8WaHMda48j66I4qqUO8bknueGJUH/FdG9MakpApXd2Lzd9tlUMlOyT07dxeNsSQ== +typescript@^4.2.0-dev.20201119: + version "4.2.0-dev.20201119" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201119.tgz#d4a43511cd9931adac05e1a47b6425f6b0e76cc3" + integrity sha512-HIgv+D/0VpVYRTbcVVf9oac/0GtLKMqaufTcPgohNaFWlCOh4lq8syefANgENXTG5Q4VEC6xwDGzHW6EJAVr3A== uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" From c89f78331948b309d8720d56cae7998dec8db13c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Nov 2020 09:31:39 +0100 Subject: [PATCH 0067/1837] Fix installing forever bug in server --- .../common/extensionManagementIpc.ts | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index da354045436..caa8e8364cf 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -5,11 +5,12 @@ import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension, IExtensionTipsService, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IURITransformer, DefaultURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; import { cloneAndChange } from 'vs/base/common/objects'; import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { Disposable } from 'vs/base/common/lifecycle'; function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI { return URI.revive(transformer ? transformer.transformIncoming(uri) : uri); @@ -77,18 +78,31 @@ export class ExtensionManagementChannel implements IServerChannel { } } -export class ExtensionManagementChannelClient implements IExtensionManagementService { +export class ExtensionManagementChannelClient extends Disposable implements IExtensionManagementService { declare readonly _serviceBrand: undefined; + private readonly _onInstallExtension = this._register(new Emitter()); + readonly onInstallExtension = this._onInstallExtension.event; + + private readonly _onDidInstallExtension = this._register(new Emitter()); + readonly onDidInstallExtension = this._onDidInstallExtension.event; + + private readonly _onUninstallExtension = this._register(new Emitter()); + readonly onUninstallExtension = this._onUninstallExtension.event; + + private readonly _onDidUninstallExtension = this._register(new Emitter()); + readonly onDidUninstallExtension = this._onDidUninstallExtension.event; + constructor( private readonly channel: IChannel, - ) { } - - get onInstallExtension(): Event { return this.channel.listen('onInstallExtension'); } - get onDidInstallExtension(): Event { return Event.map(this.channel.listen('onDidInstallExtension'), i => ({ ...i, local: i.local ? transformIncomingExtension(i.local, null) : i.local })); } - get onUninstallExtension(): Event { return this.channel.listen('onUninstallExtension'); } - get onDidUninstallExtension(): Event { return this.channel.listen('onDidUninstallExtension'); } + ) { + super(); + this._register(this.channel.listen('onInstallExtension')(e => this._onInstallExtension.fire(e))); + this._register(this.channel.listen('onDidInstallExtension')(e => this._onDidInstallExtension.fire({ ...e, local: e.local ? transformIncomingExtension(e.local, null) : e.local }))); + this._register(this.channel.listen('onUninstallExtension')(e => this._onUninstallExtension.fire(e))); + this._register(this.channel.listen('onDidUninstallExtension')(e => this._onDidUninstallExtension.fire(e))); + } zip(extension: ILocalExtension): Promise { return Promise.resolve(this.channel.call('zip', [extension]).then(result => URI.revive(result))); From 6541e52b5b5bc0292c938faa6e6c46175e3b670e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 20 Nov 2020 09:43:59 +0100 Subject: [PATCH 0068/1837] icons: remote polish --- src/vs/workbench/contrib/remote/browser/remote.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index bf67431a503..58b510c028d 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -154,6 +154,7 @@ const documentationIcon = registerIcon('remote-explorer-documentation', Codicon. const feedbackIcon = registerIcon('remote-explorer-feedback', Codicon.twitter); const reviewIssuesIcon = registerIcon('remote-explorer-review-issues', Codicon.issues); const reportIssuesIcon = registerIcon('remote-explorer-report-issues', Codicon.comment); +const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); interface IHelpItem { icon: Codicon, @@ -552,8 +553,6 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements } -const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); - Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, From 6fdc79d81a90adf7b2d4552c36e2b9fc11462925 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 09:59:23 +0100 Subject: [PATCH 0069/1837] env - set timeout back to 10s but show warning when it takes long --- .../parts/sandbox/electron-browser/preload.js | 8 ----- .../electron-browser/workbench/workbench.js | 2 +- src/vs/code/electron-main/app.ts | 29 ++++++++++++++----- src/vs/code/node/cli.ts | 4 --- src/vs/code/node/shellEnv.ts | 16 ++++++---- src/vs/platform/environment/common/argv.ts | 2 +- src/vs/platform/environment/node/argv.ts | 2 +- .../platform/windows/electron-main/windows.ts | 3 +- .../electron-main/windowsMainService.ts | 11 ++++++- src/vs/workbench/electron-sandbox/window.ts | 12 ++++++-- 10 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index aa1eba1f6b5..dfad98f286d 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -203,15 +203,7 @@ */ function resolveEnv() { return new Promise(function (resolve) { - const handle = setTimeout(function () { - console.warn('Preload: Unable to resolve shell environment in a reasonable time'); - - // It took too long to fetch the shell environment, return - resolve(); - }, 3000); - ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { - clearTimeout(handle); // Assign all keys of the shell environment to our process environment Object.assign(process.env, shellEnv); diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 3dd6691d3a0..3999f28558c 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -187,5 +187,5 @@ } //#endregion - + }()); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 1b8424f8247..f3dd84ea104 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -263,17 +263,32 @@ export class CodeApplication extends Disposable { ipc.on('vscode:fetchShellEnv', async (event: IpcMainEvent) => { const webContents = event.sender; + const window = this.windowsMainService?.getWindowByWebContents(event.sender); + if (!window) { + return; + } + + let replied = false; + + function acceptShellEnv(env: NodeJS.ProcessEnv): void { + clearTimeout(shellEnvTimeoutWarningHandle); + + if (!replied) { + webContents.send('vscode:acceptShellEnv', env); + replied = true; + } + } + + const shellEnvTimeoutWarningHandle = setTimeout(function () { + window.sendWhenReady('vscode:showShellEnvTimeoutWarningMessage'); + acceptShellEnv({}); + }, 10000); try { const shellEnv = await getShellEnvironment(this.logService, this.environmentService); - - if (!webContents.isDestroyed()) { - webContents.send('vscode:acceptShellEnv', shellEnv); - } + acceptShellEnv(shellEnv); } catch (error) { - if (!webContents.isDestroyed()) { - webContents.send('vscode:acceptShellEnv', {}); - } + acceptShellEnv({}); this.logService.error('Error fetching shell env', error); } diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index c93e5a6169e..c6415a551c8 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -123,10 +123,6 @@ export async function main(argv: string[]): Promise { 'ELECTRON_NO_ATTACH_CONSOLE': '1' }; - if (args['force-user-env']) { - env['VSCODE_FORCE_USER_ENV'] = '1'; - } - delete env['ELECTRON_RUN_AS_NODE']; const processCallbacks: ((child: ChildProcess) => Promise)[] = []; diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 619886d0fd3..d1dd0bc6dfb 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -91,17 +91,21 @@ let shellEnvPromise: Promise | undefined = undefined; */ export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise { if (!shellEnvPromise) { - if (environmentService.args['disable-user-env-probe']) { - logService.trace('getShellEnvironment: disable-user-env-probe set, skipping'); + if (environmentService.args['force-disable-user-env']) { + logService.trace('getShellEnvironment(): skipped (--force-disable-user-env)'); shellEnvPromise = Promise.resolve({}); } else if (isWindows) { - logService.trace('getShellEnvironment: running on Windows, skipping'); + logService.trace('getShellEnvironment(): skipped (Windows)'); shellEnvPromise = Promise.resolve({}); - } else if (process.env['VSCODE_CLI'] === '1' && process.env['VSCODE_FORCE_USER_ENV'] !== '1') { - logService.trace('getShellEnvironment: running on CLI, skipping'); + } else if (process.env['VSCODE_CLI'] === '1' && !environmentService.args['force-user-env']) { + logService.trace('getShellEnvironment(): skipped (VSCODE_CLI is set)'); shellEnvPromise = Promise.resolve({}); } else { - logService.trace('getShellEnvironment: running on Unix'); + if (process.env['VSCODE_CLI'] === '1') { + logService.trace('getShellEnvironment(): running (--force-user-env)'); + } else { + logService.trace('getShellEnvironment(): running (macOS/Linux)'); + } shellEnvPromise = getUnixShellEnvironment(logService); } } diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts index 434804ca643..e719e129c60 100644 --- a/src/vs/platform/environment/common/argv.ts +++ b/src/vs/platform/environment/common/argv.ts @@ -72,10 +72,10 @@ export interface NativeParsedArgs { 'driver'?: string; 'driver-verbose'?: boolean; 'remote'?: string; - 'disable-user-env-probe'?: boolean; 'force'?: boolean; 'do-not-sync'?: boolean; 'force-user-env'?: boolean; + 'force-disable-user-env'?: boolean; 'sync'?: 'on' | 'off'; '__sandbox'?: boolean; 'logsPath'?: string; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 637ce482401..7263bcbf756 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -97,7 +97,6 @@ export const OPTIONS: OptionDescriptions> = { 'disable-crash-reporter': { type: 'boolean' }, 'crash-reporter-directory': { type: 'string' }, 'crash-reporter-id': { type: 'string' }, - 'disable-user-env-probe': { type: 'boolean' }, 'skip-add-to-recently-opened': { type: 'boolean' }, 'unity-launch': { type: 'boolean' }, 'open-url': { type: 'boolean' }, @@ -111,6 +110,7 @@ export const OPTIONS: OptionDescriptions> = { 'trace-category-filter': { type: 'string' }, 'trace-options': { type: 'string' }, 'force-user-env': { type: 'boolean' }, + 'force-disable-user-env': { type: 'boolean' }, 'open-devtools': { type: 'boolean' }, '__sandbox': { type: 'boolean' }, 'logsPath': { type: 'string' }, diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index e1f5be82b02..c9e740bd59e 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -12,7 +12,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { URI } from 'vs/base/common/uri'; -import { Rectangle, BrowserWindow } from 'electron'; +import { Rectangle, BrowserWindow, WebContents } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; export interface IWindowState { @@ -113,6 +113,7 @@ export interface IWindowsMainService { getLastActiveWindow(): ICodeWindow | undefined; getWindowById(windowId: number): ICodeWindow | undefined; + getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined; getWindows(): ICodeWindow[]; getWindowCount(): number; } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 679accfd132..cc1d0a1288b 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -14,7 +14,7 @@ import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/e import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateService } from 'vs/platform/state/node/state'; import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; -import { screen, BrowserWindow, MessageBoxOptions, Display, app } from 'electron'; +import { screen, BrowserWindow, MessageBoxOptions, Display, app, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; @@ -1700,6 +1700,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return arrays.firstOrDefault(res); } + getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined { + const browserWindow = BrowserWindow.fromWebContents(webContents); + if (!browserWindow) { + return undefined; + } + + return this.getWindowById(browserWindow.id); + } + getWindows(): ICodeWindow[] { return WindowsMainService.WINDOWS; } diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index bb569ca8995..96da9d6389b 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -185,9 +185,15 @@ export class NativeWindow extends Disposable { ipcRenderer.on('vscode:addFolders', (event: unknown, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); // Message support - ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => { - this.notificationService.info(message); - }); + ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => this.notificationService.info(message)); + ipcRenderer.on('vscode:showShellEnvTimeoutWarningMessage', () => this.notificationService.prompt( + Severity.Warning, + nls.localize('shellEnvTimeoutWarning', "It took more than 10s to resolve your shell environment. Please review your shell configuration."), + [{ + label: nls.localize('learnMode', "Learn More"), + run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667') + }] + )); // Display change events ipcRenderer.on('vscode:displayChanged', () => { From 9103955a6d1aa47a40ac7b15570d71572aa5b4bc Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 20 Nov 2020 10:02:05 +0100 Subject: [PATCH 0070/1837] [themes] wait applying settings until user data initialization is completed. Fixes #111009 --- .../services/themes/browser/workbenchThemeService.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index c5bc2f83bff..a97100a720f 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -38,6 +38,7 @@ import { ColorScheme } from 'vs/platform/theme/common/theme'; import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; import { CodiconStyles } from 'vs/base/browser/ui/codicons/codiconStyles'; import { RunOnceScheduler, Sequencer } from 'vs/base/common/async'; +import { IUserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit'; // implementation @@ -112,6 +113,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { @IWorkbenchLayoutService readonly layoutService: IWorkbenchLayoutService, @ILogService private readonly logService: ILogService, @IHostColorSchemeService private readonly hostColorService: IHostColorSchemeService, + @IUserDataInitializationService readonly userDataInitializationService: IUserDataInitializationService ) { this.container = layoutService.container; this.settings = new ThemeConfiguration(configurationService); @@ -167,7 +169,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.applyAndSetProductIconTheme(productIconData, true); } - extensionService.whenInstalledExtensionsRegistered().then(_ => { + Promise.all([extensionService.whenInstalledExtensionsRegistered(), userDataInitializationService.whenInitializationFinished()]).then(_ => { this.installConfigurationListener(); this.installPreferredSchemeListener(); this.installRegistryListeners(); From a81ea8c4fa4ef2c71744342dac07dfc8205fe83c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Nov 2020 10:03:02 +0100 Subject: [PATCH 0071/1837] fix tests --- .../extensionsActions.test.ts | 19 +++++++----- .../electron-browser/extensionsViews.test.ts | 29 ++++++++++--------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts index 978a22905ed..750878b2d0b 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts @@ -38,7 +38,6 @@ import { ExtensionIdentifier, IExtensionContributions, ExtensionType, IExtension import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ILabelService, IFormatterChangeEvent } from 'vs/platform/label/common/label'; -import { ExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/electron-browser/extensionManagementServerService'; import { IProductService } from 'vs/platform/product/common/productService'; import { Schemas } from 'vs/base/common/network'; import { IProgressService } from 'vs/platform/progress/common/progress'; @@ -99,14 +98,18 @@ async function setupTest() { instantiationService.stub(IRemoteAgentService, RemoteAgentService); - instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService { - #localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' }; - constructor() { - super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService); + const localExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' }; + instantiationService.stub(IExtensionManagementServerService, >{ + get localExtensionManagementServer(): IExtensionManagementServer { + return localExtensionManagementServer; + }, + getExtensionManagementServer(extension: IExtension): IExtensionManagementServer | null { + if (extension.location.scheme === Schemas.file) { + return localExtensionManagementServer; + } + throw new Error(`Invalid Extension ${extension.location}`); } - get localExtensionManagementServer(): IExtensionManagementServer { return this.#localExtensionManagementServer; } - set localExtensionManagementServer(server: IExtensionManagementServer) { } - }()); + }); instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService)); instantiationService.stub(ILabelService, { onDidChangeFormatters: new Emitter().event }); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts index 78e72d26625..cde013f45a3 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts @@ -36,15 +36,14 @@ import { SinonStub } from 'sinon'; import { IExperimentService, ExperimentState, ExperimentActionType, ExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; -import { ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, IExtension, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { ExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/electron-browser/extensionManagementServerService'; -import { ILabelService } from 'vs/platform/label/common/label'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { IMenuService } from 'vs/platform/actions/common/actions'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views'; +import { Schemas } from 'vs/base/common/network'; suite('ExtensionsListView Tests', () => { @@ -101,14 +100,18 @@ suite('ExtensionsListView Tests', () => { instantiationService.stub(IContextKeyService, new MockContextKeyService()); instantiationService.stub(IMenuService, new TestMenuService()); - instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService { - #localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' }; - constructor() { - super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService); + const localExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' }; + instantiationService.stub(IExtensionManagementServerService, >{ + get localExtensionManagementServer(): IExtensionManagementServer { + return localExtensionManagementServer; + }, + getExtensionManagementServer(extension: IExtension): IExtensionManagementServer | null { + if (extension.location.scheme === Schemas.file) { + return localExtensionManagementServer; + } + throw new Error(`Invalid Extension ${extension.location}`); } - get localExtensionManagementServer(): IExtensionManagementServer { return this.#localExtensionManagementServer; } - set localExtensionManagementServer(server: IExtensionManagementServer) { } - }()); + }); instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService)); @@ -181,7 +184,7 @@ suite('ExtensionsListView Tests', () => { await (instantiationService.get(IWorkbenchExtensionEnablementService)).setEnablement([localDisabledLanguage], EnablementState.DisabledGlobally); instantiationService.set(IExtensionsWorkbenchService, instantiationService.createInstance(ExtensionsWorkbenchService)); - testableView = instantiationService.createInstance(ExtensionsListView, {}); + testableView = instantiationService.createInstance(ExtensionsListView, {}, {}); }); teardown(() => { @@ -483,7 +486,7 @@ suite('ExtensionsListView Tests', () => { }]); testableView.dispose(); - testableView = instantiationService.createInstance(ExtensionsListView, {}); + testableView = instantiationService.createInstance(ExtensionsListView, {}, {}); return testableView.show('search-me').then(result => { const options: IQueryOptions = queryTarget.args[0][0]; @@ -510,7 +513,7 @@ suite('ExtensionsListView Tests', () => { const queryTarget = instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...realResults)); testableView.dispose(); - testableView = instantiationService.createInstance(ExtensionsListView, {}); + testableView = instantiationService.createInstance(ExtensionsListView, {}, {}); return testableView.show('search-me @sort:installs').then(result => { const options: IQueryOptions = queryTarget.args[0][0]; From 936048e0288f7bb8db8f8bc1d5a8816c4d85647c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 10:03:28 +0100 Subject: [PATCH 0072/1837] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c91d083c3e..47482dc85f9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "e289d0d793bde8f8b5632625e01c50c218e7e127", + "distro": "4c0d11b5ca2164ffa3d402ef1425211aac630f38", "author": { "name": "Microsoft Corporation" }, From d84b5eb2da266c608c7d94e239e6b23ae0d8ed03 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Nov 2020 10:36:50 +0100 Subject: [PATCH 0073/1837] bulkFileEdits: do not use file trash flag --- src/vs/editor/common/modes.ts | 1 + src/vs/monaco.d.ts | 1 + src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 2 +- src/vs/workbench/contrib/files/browser/fileActions.ts | 3 +-- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 5a74bd1613e..fb1015bcd93 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1387,6 +1387,7 @@ export interface WorkspaceFileEditOptions { recursive?: boolean; copy?: boolean; folder?: boolean; + doNotUseTrash?: boolean; } export interface WorkspaceFileEdit { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 529e1fe793a..ecdeff75145 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -6262,6 +6262,7 @@ declare namespace monaco.languages { recursive?: boolean; copy?: boolean; folder?: boolean; + doNotUseTrash?: boolean; } export interface WorkspaceFileEdit { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 96036bd6ad4..a642aa70336 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -172,7 +172,7 @@ class DeleteOperation implements IFileOperation { } } - const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); + const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash') && !this.options.doNotUseTrash; await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }); return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, { isUndoing: true }, contents); } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index cf72ca8e11c..5bfc41397e3 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -226,8 +226,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I // Call function try { - const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true })); - // TODO@Isidor respect the useTrash parameter + const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, doNotUseTrash: !useTrash })); await bulkEditService.apply(resourceFileEdits, { undoRedoSource: explorerService.undoRedoSource, label: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name) From bb7b7dc7f2a3f77135f920c37357b33f9cd7fdd2 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 20 Nov 2020 10:44:49 +0100 Subject: [PATCH 0074/1837] Fix doc comment for CustomExecution api Fixes #110981 --- src/vs/vscode.d.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 3d20c0e282f..117744ceb92 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6186,14 +6186,13 @@ declare module 'vscode' { */ export class CustomExecution { /** - * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the + * Constructs a CustomExecution task object. The callback will be executed when the task is run, at which point the * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). - * @param process The [Pseudoterminal](#Pseudoterminal) to be used by the task to display output. * @param callback The callback that will be called when the task is started by a user. Any ${} style variables that - * were in the task definition will be resolved and passed into the callback. + * were in the task definition will be resolved and passed into the callback as `resolvedDefinition`. */ constructor(callback: (resolvedDefinition: TaskDefinition) => Thenable); } @@ -9966,7 +9965,7 @@ declare module 'vscode' { * flags to ignore certain kinds of events can be provided. To stop listening to events the watcher must be disposed. * * *Note* that only files within the current [workspace folders](#workspace.workspaceFolders) can be watched. - * *Note* that when watching for file changes such as '**​/*.js', notifications will not be sent when a parent folder is + * *Note* that when watching for file changes such as '**​/*.js', notifications will not be sent when a parent folder is * moved or deleted (this is a known limitation of the current implementation and may change in the future). * * @param globPattern A [glob pattern](#GlobPattern) that is applied to the absolute paths of created, changed, From c8e59100c4e29e08eb530521625a333cd0d25a0d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 10:29:41 +0100 Subject: [PATCH 0075/1837] Validate line numbers --- src/vs/editor/browser/widget/diffEditorWidget.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 2109ea9f6c5..31b375893d8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -2488,6 +2488,9 @@ function createFakeLinesDiv(): HTMLElement { } function getViewRange(model: ITextModel, viewModel: IViewModel, startLineNumber: number, endLineNumber: number): Range { + const lineCount = model.getLineCount(); + startLineNumber = Math.min(lineCount, Math.max(1, startLineNumber)); + endLineNumber = Math.min(lineCount, Math.max(1, endLineNumber)); return viewModel.coordinatesConverter.convertModelRangeToViewRange(new Range( startLineNumber, model.getLineMinColumn(startLineNumber), endLineNumber, model.getLineMaxColumn(endLineNumber) From 8a6fea66c06e26fc1fd4aed4ca735dfd337613c3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 10:45:23 +0100 Subject: [PATCH 0076/1837] Fixes #107636 --- .../runtimeExtensionsEditor.ts | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 0e4312af5ea..101597bdee2 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -104,9 +104,7 @@ export class RuntimeExtensionsEditor extends EditorPane { private _list: WorkbenchList | null; private _profileInfo: IExtensionHostProfile | null; - private _elements: IRuntimeExtension[] | null; - private _extensionsDescriptions: IExtensionDescription[]; private _updateSoon: RunOnceScheduler; private _profileSessionState: IContextKey; private _extensionsHostRecorded: IContextKey; @@ -133,6 +131,11 @@ export class RuntimeExtensionsEditor extends EditorPane { this._list = null; this._profileInfo = this._extensionHostProfileService.lastProfile; + this._elements = null; + this._updateSoon = this._register(new RunOnceScheduler(() => this._updateExtensions(), 200)); + this._profileSessionState = CONTEXT_PROFILE_SESSION_STATE.bindTo(contextKeyService); + this._extensionsHostRecorded = CONTEXT_EXTENSION_HOST_PROFILE_RECORDED.bindTo(contextKeyService); + this._register(this._extensionHostProfileService.onDidChangeLastProfile(() => { this._profileInfo = this._extensionHostProfileService.lastProfile; this._extensionsHostRecorded.set(!!this._profileInfo); @@ -142,25 +145,9 @@ export class RuntimeExtensionsEditor extends EditorPane { const state = this._extensionHostProfileService.state; this._profileSessionState.set(ProfileSessionState[state].toLowerCase()); })); - - this._elements = null; - - this._extensionsDescriptions = []; - this._updateExtensions(); - - this._profileSessionState = CONTEXT_PROFILE_SESSION_STATE.bindTo(contextKeyService); - this._extensionsHostRecorded = CONTEXT_EXTENSION_HOST_PROFILE_RECORDED.bindTo(contextKeyService); - - this._updateSoon = this._register(new RunOnceScheduler(() => this._updateExtensions(), 200)); - - this._extensionService.getExtensions().then((extensions) => { - // We only deal with extensions with source code! - this._extensionsDescriptions = extensions.filter((extension) => { - return Boolean(extension.main) || Boolean(extension.browser); - }); - this._updateExtensions(); - }); this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule())); + + this._updateExtensions(); } private async _updateExtensions(): Promise { @@ -171,6 +158,10 @@ export class RuntimeExtensionsEditor extends EditorPane { } private async _resolveExtensions(): Promise { + // We only deal with extensions with source code! + const extensionsDescriptions = (await this._extensionService.getExtensions()).filter((extension) => { + return Boolean(extension.main) || Boolean(extension.browser); + }); let marketplaceMap: { [id: string]: IExtension; } = Object.create(null); const marketPlaceExtensions = await this._extensionsWorkbenchService.queryLocal(); for (let extension of marketPlaceExtensions) { @@ -201,8 +192,8 @@ export class RuntimeExtensionsEditor extends EditorPane { } let result: IRuntimeExtension[] = []; - for (let i = 0, len = this._extensionsDescriptions.length; i < len; i++) { - const extensionDescription = this._extensionsDescriptions[i]; + for (let i = 0, len = extensionsDescriptions.length; i < len; i++) { + const extensionDescription = extensionsDescriptions[i]; let profileInfo: IExtensionProfileInformation | null = null; if (this._profileInfo) { From 7207ee201f01f169bcb6ef8fe9e1f2f1ec5e061c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 10:47:38 +0100 Subject: [PATCH 0077/1837] env - also surface shell env resolve errors to users --- src/vs/code/electron-main/app.ts | 10 +++++---- src/vs/workbench/electron-sandbox/window.ts | 24 +++++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index f3dd84ea104..b357b99a730 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -83,6 +83,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService'; import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; +import { toErrorMessage } from 'vs/base/common/errorMessage'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -280,7 +281,7 @@ export class CodeApplication extends Disposable { } const shellEnvTimeoutWarningHandle = setTimeout(function () { - window.sendWhenReady('vscode:showShellEnvTimeoutWarningMessage'); + window.sendWhenReady('vscode:showShellEnvTimeoutWarning'); acceptShellEnv({}); }, 10000); @@ -288,6 +289,7 @@ export class CodeApplication extends Disposable { const shellEnv = await getShellEnvironment(this.logService, this.environmentService); acceptShellEnv(shellEnv); } catch (error) { + window.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); acceptShellEnv({}); this.logService.error('Error fetching shell env', error); @@ -826,6 +828,9 @@ export class CodeApplication extends Disposable { updateService.initialize(); } + // Start to fetch shell environment after window has opened + getShellEnvironment(this.logService, this.environmentService); + // If enable-crash-reporter argv is undefined then this is a fresh start, // based on telemetry.enableCrashreporter settings, generate a UUID which // will be used as crash reporter id and also update the json file. @@ -853,9 +858,6 @@ export class CodeApplication extends Disposable { } catch (error) { this.logService.error(error); } - - // Start to fetch shell environment after window has opened - getShellEnvironment(this.logService, this.environmentService); } private handleRemoteAuthorities(): void { diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index 96da9d6389b..9062e49737c 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -32,7 +32,7 @@ import { IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/wo import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity'; import { isWindows, isMacintosh } from 'vs/base/common/platform'; import { IProductService } from 'vs/platform/product/common/productService'; -import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; @@ -186,13 +186,23 @@ export class NativeWindow extends Disposable { // Message support ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => this.notificationService.info(message)); - ipcRenderer.on('vscode:showShellEnvTimeoutWarningMessage', () => this.notificationService.prompt( + + // Shell Environment Issue Notifications + const choices: IPromptChoice[] = [{ + label: nls.localize('learnMode', "Learn More"), + run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667') + }]; + + ipcRenderer.on('vscode:showShellEnvError', (event: unknown, error: string) => this.notificationService.prompt( + Severity.Error, + nls.localize('shellEnvError', "Unable to resolve your shell environment: {0}", error), + choices + )); + + ipcRenderer.on('vscode:showShellEnvTimeoutWarning', () => this.notificationService.prompt( Severity.Warning, - nls.localize('shellEnvTimeoutWarning', "It took more than 10s to resolve your shell environment. Please review your shell configuration."), - [{ - label: nls.localize('learnMode', "Learn More"), - run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667') - }] + nls.localize('shellEnvTimeoutWarning', "Unable to resolve your shell environment in a reasonable time. Please review your shell configuration."), + choices )); // Display change events From 185212db534fccc6ee2c38068a93b6068f118230 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 10:54:28 +0100 Subject: [PATCH 0078/1837] Revisit explicit use of ConfigurationTarget.USER when updating config (#109373) --- src/vs/workbench/browser/parts/editor/editorCommands.ts | 6 +++--- src/vs/workbench/browser/parts/editor/editorStatus.ts | 4 ++-- .../codeEditor/browser/accessibility/accessibility.ts | 4 ++-- .../contrib/codeEditor/browser/diffEditorHelper.ts | 2 +- .../contrib/codeEditor/browser/toggleColumnSelection.ts | 4 ++-- .../workbench/contrib/codeEditor/browser/toggleMinimap.ts | 4 ++-- .../contrib/codeEditor/browser/toggleMultiCursorModifier.ts | 4 ++-- .../codeEditor/browser/toggleRenderControlCharacter.ts | 4 ++-- .../contrib/codeEditor/browser/toggleRenderWhitespace.ts | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 12f5af00a47..5d9e68ebc39 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -19,7 +19,7 @@ import { List } from 'vs/base/browser/ui/list/listWidget'; import { distinct, coalesce } from 'vs/base/common/arrays'; import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredSideBySideGroupDirection, EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess'; @@ -363,14 +363,14 @@ function registerDiffEditorCommands(): void { const configurationService = accessor.get(IConfigurationService); const newValue = !configurationService.getValue('diffEditor.renderSideBySide'); - configurationService.updateValue('diffEditor.renderSideBySide', newValue, ConfigurationTarget.USER); + configurationService.updateValue('diffEditor.renderSideBySide', newValue); } function toggleDiffIgnoreTrimWhitespace(accessor: ServicesAccessor): void { const configurationService = accessor.get(IConfigurationService); const newValue = !configurationService.getValue('diffEditor.ignoreTrimWhitespace'); - configurationService.updateValue('diffEditor.ignoreTrimWhitespace', newValue, ConfigurationTarget.USER); + configurationService.updateValue('diffEditor.ignoreTrimWhitespace', newValue); } KeybindingsRegistry.registerCommandAndKeybindingRule({ diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 0e3e18c8842..30ef71397b8 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -346,12 +346,12 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { [{ label: nls.localize('screenReaderDetectedExplanation.answerYes', "Yes"), run: () => { - this.configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER); + this.configurationService.updateValue('editor.accessibilitySupport', 'on'); } }, { label: nls.localize('screenReaderDetectedExplanation.answerNo', "No"), run: () => { - this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER); + this.configurationService.updateValue('editor.accessibilitySupport', 'off'); } }], { sticky: true } diff --git a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.ts b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.ts index 1779568eb1f..87cbcc7d54e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.ts @@ -21,7 +21,7 @@ import { IEditorOptions, EditorOption } from 'vs/editor/common/config/editorOpti import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -120,7 +120,7 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_E)) { alert(nls.localize('emergencyConfOn', "Now changing the setting `editor.accessibilitySupport` to 'on'.")); - this._configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER); + this._configurationService.updateValue('editor.accessibilitySupport', 'on'); e.preventDefault(); e.stopPropagation(); diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts index d01c06d5e59..c3ede411a52 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -50,7 +50,7 @@ class DiffEditorHelperContribution extends Disposable implements IDiffEditorCont [{ label: nls.localize('removeTimeout', "Remove limit"), run: () => { - this._configurationService.updateValue('diffEditor.maxComputationTime', 0, ConfigurationTarget.USER); + this._configurationService.updateValue('diffEditor.maxComputationTime', 0); } }], {} diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts index ef2018bcd53..858bf7be6fd 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; @@ -42,7 +42,7 @@ export class ToggleColumnSelectionAction extends Action { public async run(): Promise { const oldValue = this._configurationService.getValue('editor.columnSelection'); const codeEditor = this._getCodeEditor(); - await this._configurationService.updateValue('editor.columnSelection', !oldValue, ConfigurationTarget.USER); + await this._configurationService.updateValue('editor.columnSelection', !oldValue); const newValue = this._configurationService.getValue('editor.columnSelection'); if (!codeEditor || codeEditor !== this._getCodeEditor() || oldValue === newValue || !codeEditor.hasModel()) { return; diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts index d40ee948fc5..fbd79e0004d 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; @@ -25,7 +25,7 @@ export class ToggleMinimapAction extends Action { public run(): Promise { const newValue = !this._configurationService.getValue('editor.minimap.enabled'); - return this._configurationService.updateValue('editor.minimap.enabled', newValue, ConfigurationTarget.USER); + return this._configurationService.updateValue('editor.minimap.enabled', newValue); } } diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts index 2c340ac02b3..36a63179bf7 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import * as platform from 'vs/base/common/platform'; import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -33,7 +33,7 @@ export class ToggleMultiCursorModifierAction extends Action { const editorConf = this.configurationService.getValue<{ multiCursorModifier: 'ctrlCmd' | 'alt' }>('editor'); const newValue: 'ctrlCmd' | 'alt' = (editorConf.multiCursorModifier === 'ctrlCmd' ? 'alt' : 'ctrlCmd'); - return this.configurationService.updateValue(ToggleMultiCursorModifierAction.multiCursorModifierConfigurationKey, newValue, ConfigurationTarget.USER); + return this.configurationService.updateValue(ToggleMultiCursorModifierAction.multiCursorModifierConfigurationKey, newValue); } } diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts index cc439ce45c5..d530f1a875e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; @@ -26,7 +26,7 @@ export class ToggleRenderControlCharacterAction extends Action { public run(): Promise { let newRenderControlCharacters = !this._configurationService.getValue('editor.renderControlCharacters'); - return this._configurationService.updateValue('editor.renderControlCharacters', newRenderControlCharacters, ConfigurationTarget.USER); + return this._configurationService.updateValue('editor.renderControlCharacters', newRenderControlCharacters); } } diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts index 80a26aee466..5a5174b899f 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; @@ -34,7 +34,7 @@ export class ToggleRenderWhitespaceAction extends Action { newRenderWhitespace = 'none'; } - return this._configurationService.updateValue('editor.renderWhitespace', newRenderWhitespace, ConfigurationTarget.USER); + return this._configurationService.updateValue('editor.renderWhitespace', newRenderWhitespace); } } From bffd7a6ad80bec305c2638cee9c0e8d5cfe6ab1b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Nov 2020 10:55:33 +0100 Subject: [PATCH 0079/1837] Fix #111014 --- .../common/extensionsStorageSync.ts | 18 ++-------- .../userDataSync/common/extensionsSync.ts | 34 +++++++++++++------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/vs/platform/userDataSync/common/extensionsStorageSync.ts b/src/vs/platform/userDataSync/common/extensionsStorageSync.ts index 4b6fb78b9b7..37846e053f3 100644 --- a/src/vs/platform/userDataSync/common/extensionsStorageSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsStorageSync.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IStringDictionary } from 'vs/base/common/collections'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -22,7 +21,7 @@ export interface IExtensionsStorageSyncService { readonly onDidChangeExtensionsStorage: Event; setKeysForSync(extensionIdWithVersion: IExtensionIdWithVersion, keys: string[]): void; - getStorageForSync(extensionIdWithVersion: IExtensionIdWithVersion): IStringDictionary | undefined; + getKeysForSync(extensionIdWithVersion: IExtensionIdWithVersion): string[] | undefined; } @@ -91,19 +90,8 @@ export class ExtensionsStorageSyncService extends Disposable implements IExtensi this.storageService.store(ExtensionsStorageSyncService.toKey(extensionIdWithVersion), JSON.stringify(keys), StorageScope.GLOBAL, StorageTarget.MACHINE); } - getStorageForSync(extensionIdWithVersion: IExtensionIdWithVersion): IStringDictionary | undefined { + getKeysForSync(extensionIdWithVersion: IExtensionIdWithVersion): string[] | undefined { const keysForSyncValue = this.storageService.get(ExtensionsStorageSyncService.toKey(extensionIdWithVersion), StorageScope.GLOBAL); - if (keysForSyncValue) { - const keys = JSON.parse(keysForSyncValue); - const extensionStorageValue = this.storageService.get(extensionIdWithVersion.id, StorageScope.GLOBAL) || '{}'; - const extensionStorageState = JSON.parse(extensionStorageValue); - return Object.keys(extensionStorageState).reduce((state: IStringDictionary, key) => { - if (keys.includes(key)) { - state[key] = extensionStorageState[key]; - } - return state; - }, {}); - } - return undefined; + return keysForSyncValue ? JSON.parse(keysForSyncValue) : undefined; } } diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index 28dc26f5d3d..cb447e33233 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -25,7 +25,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { CancellationToken } from 'vs/base/common/cancellation'; import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions'; import { getErrorMessage } from 'vs/base/common/errors'; -import { forEach } from 'vs/base/common/collections'; +import { forEach, IStringDictionary } from 'vs/base/common/collections'; import { IExtensionsStorageSyncService } from 'vs/platform/userDataSync/common/extensionsStorageSync'; interface IExtensionResourceMergeResult extends IAcceptResult { @@ -363,9 +363,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse // Builtin Extension Sync: Enablement & State if (installedExtension && installedExtension.isBuiltin) { if (e.state && installedExtension.manifest.version === e.version) { - const extensionState = JSON.parse(this.storageService.get(e.identifier.id, StorageScope.GLOBAL) || '{}'); - forEach(e.state, ({ key, value }) => extensionState[key] = value); - this.storageService.store(e.identifier.id, JSON.stringify(extensionState), StorageScope.GLOBAL, StorageTarget.MACHINE); + this.updateExtensionState(e.state, e.identifier.id, installedExtension.manifest.version); } if (e.disabled) { this.logService.trace(`${this.syncResourceLogLabel}: Disabling extension...`, e.identifier.id); @@ -391,9 +389,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse (installedExtension ? installedExtension.manifest.version === e.version /* Installed and has same version */ : !!extension /* Installable */) ) { - const extensionState = JSON.parse(this.storageService.get(e.identifier.id, StorageScope.GLOBAL) || '{}'); - forEach(e.state, ({ key, value }) => extensionState[key] = value); - this.storageService.store(e.identifier.id, JSON.stringify(extensionState), StorageScope.GLOBAL, StorageTarget.MACHINE); + this.updateExtensionState(e.state, e.identifier.id, installedExtension?.manifest.version); } if (extension) { @@ -440,6 +436,17 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse return newSkippedExtensions; } + private updateExtensionState(state: IStringDictionary, id: string, version?: string): void { + const extensionState = JSON.parse(this.storageService.get(id, StorageScope.GLOBAL) || '{}'); + const keys = version ? this.extensionsStorageSyncService.getKeysForSync({ id, version }) : undefined; + if (keys) { + keys.forEach(key => extensionState[key] = state[key]); + } else { + forEach(state, ({ key, value }) => extensionState[key] = value); + } + this.storageService.store(id, JSON.stringify(extensionState), StorageScope.GLOBAL, StorageTarget.MACHINE); + } + private parseExtensions(syncData: ISyncData): ISyncExtension[] { return JSON.parse(syncData.content); } @@ -456,9 +463,16 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse syncExntesion.installed = true; } try { - const state = this.extensionsStorageSyncService.getStorageForSync({ id: identifier.id, version: manifest.version }); - if (state) { - syncExntesion.state = state; + const keys = this.extensionsStorageSyncService.getKeysForSync({ id: identifier.id, version: manifest.version }); + if (keys) { + const extensionStorageValue = this.storageService.get(identifier.id, StorageScope.GLOBAL) || '{}'; + const extensionStorageState = JSON.parse(extensionStorageValue); + syncExntesion.state = Object.keys(extensionStorageState).reduce((state: IStringDictionary, key) => { + if (keys.includes(key)) { + state[key] = extensionStorageState[key]; + } + return state; + }, {}); } } catch (error) { this.logService.info(`${this.syncResourceLogLabel}: Error while parsing extension state`, getErrorMessage(error)); From fe65b26426b2ba16b803509a2a1a0fb6ceffd07a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 11:06:24 +0100 Subject: [PATCH 0080/1837] perf - add ellapsedWaitForShellEnv to measure blocked time on startup //cc @jrieken --- src/vs/code/electron-browser/workbench/workbench.js | 2 ++ src/vs/code/electron-main/window.ts | 2 +- .../contrib/performance/browser/perfviewEditor.ts | 1 + .../workbench/services/timer/browser/timerService.ts | 10 ++++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 3999f28558c..e71e4a031b1 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -34,7 +34,9 @@ performance.mark('workbench-start'); // Wait for process environment being fully resolved + perf.mark('willWaitForShellEnv'); await whenEnvResolved; + perf.mark('didWaitForShellEnv'); perf.mark('main/startup'); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index bd434c85190..6aa77d125fd 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -7,6 +7,7 @@ import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as objects from 'vs/base/common/objects'; import * as nls from 'vs/nls'; +import * as perf from 'vs/base/common/performance'; import { Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, Details } from 'electron'; @@ -24,7 +25,6 @@ import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; -import * as perf from 'vs/base/common/performance'; import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService'; import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService'; import { RunOnceScheduler } from 'vs/base/common/async'; diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index 65af94d0c35..c7bb057a334 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -171,6 +171,7 @@ class PerfModelContentProvider implements ITextModelContentProvider { table.push(['app.isReady => window.loadUrl()', metrics.timers.ellapsedWindowLoad, '[main]', `initial startup: ${metrics.initialStartup}`]); table.push(['window.loadUrl() => begin to require(workbench.desktop.main.js)', metrics.timers.ellapsedWindowLoadToRequire, '[main->renderer]', StartupKindToString(metrics.windowKind)]); table.push(['require(workbench.desktop.main.js)', metrics.timers.ellapsedRequire, '[renderer]', `cached data: ${(metrics.didUseCachedData ? 'YES' : 'NO')}${stats ? `, node_modules took ${stats.nodeRequireTotal}ms` : ''}`]); + table.push(['wait for shell environment', metrics.timers.ellapsedWaitForShellEnv, '[renderer]', undefined]); table.push(['require & init workspace storage', metrics.timers.ellapsedWorkspaceStorageInit, '[renderer]', undefined]); table.push(['init workspace service', metrics.timers.ellapsedWorkspaceServiceInit, '[renderer]', undefined]); table.push(['register extensions & spawn extension host', metrics.timers.ellapsedExtensions, '[renderer]', undefined]); diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index cab6c54f0b9..b63386aa9f2 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -186,6 +186,15 @@ export interface IStartupMetrics { */ readonly ellapsedWindowLoadToRequire: number; + /** + * The time it took to wait for resolving the shell environment. This time the workbench + * will not continue to load and be blocked entirely. + * + * * Happens in the renderer-process + * * Measured with the `willWaitForShellEnv` and `didWaitForShellEnv` performance marks. + */ + readonly ellapsedWaitForShellEnv?: number; + /** * The time it took to require the workspace storage DB, connect to it * and load the initial set of values. @@ -388,6 +397,7 @@ export abstract class AbstractTimerService implements ITimerService { ellapsedWindowLoad: initialStartup ? perf.getDuration('main:appReady', 'main:loadWindow') : undefined, ellapsedWindowLoadToRequire: perf.getDuration('main:loadWindow', 'willLoadWorkbenchMain'), ellapsedRequire: perf.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain'), + ellapsedWaitForShellEnv: perf.getDuration('willWaitForShellEnv', 'didWaitForShellEnv'), ellapsedWorkspaceStorageInit: perf.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage'), ellapsedWorkspaceServiceInit: perf.getDuration('willInitWorkspaceService', 'didInitWorkspaceService'), ellapsedExtensions: perf.getDuration('willLoadExtensions', 'didLoadExtensions'), From 69de6464ceef070df04d28514a006ad184c0fd65 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Nov 2020 11:27:30 +0100 Subject: [PATCH 0081/1837] explorer: pass the folder flag when deleting directories --- src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 2 +- src/vs/workbench/contrib/files/browser/fileActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 96036bd6ad4..b2840faac3c 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -164,7 +164,7 @@ class DeleteOperation implements IFileOperation { } let contents: VSBuffer | undefined; - if (!this._undoesCreateOperation) { + if (!this._undoesCreateOperation && !this.options.folder) { try { contents = (await this._fileService.readFile(this.oldUri)).value; } catch (err) { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index cf72ca8e11c..ae951190e2b 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -226,7 +226,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I // Call function try { - const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true })); + const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory })); // TODO@Isidor respect the useTrash parameter await bulkEditService.apply(resourceFileEdits, { undoRedoSource: explorerService.undoRedoSource, From 6f3fcd2ce0002ffd876b7b43bff42a912edddaae Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 11:57:19 +0100 Subject: [PATCH 0082/1837] env - move shell env into bootstrap-window and let user env win over shell env --- src/bootstrap-window.js | 71 ++++++++++++------- .../parts/sandbox/electron-browser/preload.js | 26 ++++--- .../parts/sandbox/electron-sandbox/globals.ts | 14 +++- .../electron-browser/workbench/workbench.js | 29 ++------ src/vs/code/electron-main/app.ts | 7 +- .../electron-sandbox/workbench/workbench.js | 27 ++----- 6 files changed, 85 insertions(+), 89 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 38867c15c49..0981fe0baaf 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -26,6 +26,11 @@ const sandbox = preloadGlobals.context.sandbox; const webFrame = preloadGlobals.webFrame; const safeProcess = sandbox ? preloadGlobals.process : process; + const configuration = parseWindowConfiguration(); + + // Start to resolve process.env before anything gets load + // so that we can run loading and resolving in parallel + const whenEnvResolved = preloadGlobals.process.resolveEnv(configuration.userEnv); /** * @param {string[]} modulePaths @@ -33,18 +38,6 @@ * @param {{ forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config: object) => void, beforeLoaderConfig?: (config: object, loaderConfig: object) => void, beforeRequire?: () => void }=} options */ function load(modulePaths, resultCallback, options) { - const args = parseURLQueryArgs(); - /** - * // configuration: INativeWindowConfiguration - * @type {{ - * zoomLevel?: number, - * extensionDevelopmentPath?: string[], - * extensionTestsPath?: string, - * userEnv?: { [key: string]: string | undefined }, - * appRoot: string, - * nodeCachedDataDir?: string - * }} */ - const configuration = JSON.parse(args['config'] || '{}') || {}; // Apply zoom level early to avoid glitches const zoomLevel = configuration.zoomLevel; @@ -64,11 +57,6 @@ developerToolsUnbind = registerDeveloperKeybindings(options && options.disallowReloadKeybinding); } - // Correctly inherit the parent's environment (TODO@sandbox non-sandboxed only) - if (!sandbox) { - Object.assign(safeProcess.env, configuration.userEnv); - } - // Enable ASAR support (TODO@sandbox non-sandboxed only) if (!sandbox) { globalThis.MonacoBootstrap.enableASARSupport(configuration.appRoot); @@ -150,8 +138,16 @@ options.beforeRequire(); } - require(modulePaths, result => { + require(modulePaths, async result => { try { + + // Wait for process environment being fully resolved + const perf = perfLib(); + perf.mark('willWaitForShellEnv'); + await whenEnvResolved; + perf.mark('didWaitForShellEnv'); + + // Callback only after process environment is resolved const callbackResult = resultCallback(result, configuration); if (callbackResult && typeof callbackResult.then === 'function') { callbackResult.then(() => { @@ -169,16 +165,26 @@ } /** - * @returns {{[param: string]: string }} + * Parses the contents of the `INativeWindowConfiguration` that + * is passed into the URL from the `electron-main` side. + * + * @returns {{ + * zoomLevel?: number, + * extensionDevelopmentPath?: string[], + * extensionTestsPath?: string, + * userEnv?: { [key: string]: string | undefined }, + * appRoot: string, + * nodeCachedDataDir?: string + * }} */ - function parseURLQueryArgs() { - const search = window.location.search || ''; - - return search.split(/[?&]/) + function parseWindowConfiguration() { + const rawConfiguration = (window.location.search || '').split(/[?&]/) .filter(function (param) { return !!param; }) .map(function (param) { return param.split('='); }) .filter(function (param) { return param.length === 2; }) .reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {}); + + return JSON.parse(rawConfiguration['config'] || '{}') || {}; } /** @@ -256,8 +262,25 @@ return window.vscode; } + /** + * @return {{ mark: (name: string) => void }} + */ + function perfLib() { + globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || []; + + return { + /** + * @param {string} name + */ + mark(name) { + globalThis.MonacoPerformanceMarks.push(name, Date.now()); + } + }; + } + return { load, - globals + globals, + perfLib }; })); diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index dfad98f286d..702a28ea652 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -108,17 +108,18 @@ get type() { return 'renderer'; }, get execPath() { return process.execPath; }, - _whenEnvResolved: undefined, - whenEnvResolved: + _resolveEnv: undefined, + resolveEnv: /** - * @returns when the shell environment has been resolved. + * @param userEnv {{[key: string]: string}} + * @returns {Promise} */ - function () { - if (!this._whenEnvResolved) { - this._whenEnvResolved = resolveEnv(); + function (userEnv) { + if (!this._resolveEnv) { + this._resolveEnv = resolveEnv(userEnv); } - return this._whenEnvResolved; + return this._resolveEnv; }, getProcessMemoryInfo: @@ -199,14 +200,21 @@ * all development related environment variables. We do this from the * main process because it may involve spawning a shell. * + * @param userEnv {{[key: string]: string}} * @returns {Promise} */ - function resolveEnv() { + function resolveEnv(userEnv) { + + // Apply `userEnv` directly + Object.assign(process.env, userEnv); + + // Resolve `shellEnv` from the main side return new Promise(function (resolve) { ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { // Assign all keys of the shell environment to our process environment - Object.assign(process.env, shellEnv); + // But make sure that the user environment wins in the end + Object.assign(process.env, shellEnv, userEnv); resolve(); }); diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 3bd0c203e5b..1116cf2135f 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -35,10 +35,18 @@ export interface ISandboxNodeProcess extends INodeProcess { readonly execPath: string; /** - * Allows to await resolving the full process environment by checking for the shell environment - * of the OS in certain cases (e.g. when the app is started from the Dock on macOS). + * Resolve the true process environment to use. There are different layers of environment + * that will apply: + * - `process.env`: this is the actual environment of the process + * - `shellEnv` : if the program was not started from a terminal, we resolve all shell + * variables to get the same experience as if the program was started from + * a terminal (Linux, macOS) + * - `userEnv` : this is instance specific environment, e.g. if the user started the program + * from a terminal and changed certain variables + * + * The order of overwrites is `process.env` < `shellEnv` < `userEnv`. */ - whenEnvResolved(): Promise; + resolveEnv(userEnv: IProcessEnvironment): Promise; /** * A listener on the process. Only a small subset of listener types are allowed. diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index e71e4a031b1..dc0b08b093a 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -9,15 +9,12 @@ 'use strict'; (function () { + const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - const perf = perfLib(); + const perf = bootstrapWindow.perfLib(); perf.mark('renderer/started'); - // Load environment in parallel to workbench loading to avoid waterfall - const bootstrapWindow = bootstrapWindowLib(); - const whenEnvResolved = bootstrapWindow.globals().process.whenEnvResolved(); - // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because // we know for a fact that workbench.desktop.main will depend on @@ -32,12 +29,6 @@ // Mark start of workbench perf.mark('didLoadWorkbenchMain'); performance.mark('workbench-start'); - - // Wait for process environment being fully resolved - perf.mark('willWaitForShellEnv'); - await whenEnvResolved; - perf.mark('didWaitForShellEnv'); - perf.mark('main/startup'); // @ts-ignore @@ -60,23 +51,11 @@ //region Helpers - function perfLib() { - globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || []; - - return { - /** - * @param {string} name - */ - mark(name) { - globalThis.MonacoPerformanceMarks.push(name, Date.now()); - } - }; - } - /** * @returns {{ * load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown, - * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals') + * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals'), + * perfLib: () => { mark: (name: string) => void } * }} */ function bootstrapWindowLib() { diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index b357b99a730..390317f4391 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -265,9 +265,6 @@ export class CodeApplication extends Disposable { ipc.on('vscode:fetchShellEnv', async (event: IpcMainEvent) => { const webContents = event.sender; const window = this.windowsMainService?.getWindowByWebContents(event.sender); - if (!window) { - return; - } let replied = false; @@ -281,7 +278,7 @@ export class CodeApplication extends Disposable { } const shellEnvTimeoutWarningHandle = setTimeout(function () { - window.sendWhenReady('vscode:showShellEnvTimeoutWarning'); + window?.sendWhenReady('vscode:showShellEnvTimeoutWarning'); // notify inside window if we have one acceptShellEnv({}); }, 10000); @@ -289,7 +286,7 @@ export class CodeApplication extends Disposable { const shellEnv = await getShellEnvironment(this.logService, this.environmentService); acceptShellEnv(shellEnv); } catch (error) { - window.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); + window?.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); // notify inside window if we have one acceptShellEnv({}); this.logService.error('Error fetching shell env', error); diff --git a/src/vs/code/electron-sandbox/workbench/workbench.js b/src/vs/code/electron-sandbox/workbench/workbench.js index 3966a9d0eac..162e40bf593 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.js +++ b/src/vs/code/electron-sandbox/workbench/workbench.js @@ -9,15 +9,12 @@ 'use strict'; (function () { + const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - const perf = perfLib(); + const perf = bootstrapWindow.perfLib(); perf.mark('renderer/started'); - // Load environment in parallel to workbench loading to avoid waterfall - const bootstrapWindow = bootstrapWindowLib(); - const whenEnvResolved = bootstrapWindow.globals().process.whenEnvResolved(); - // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because // we know for a fact that workbench.desktop.sandbox.main will depend on @@ -32,10 +29,6 @@ // Mark start of workbench perf.mark('didLoadWorkbenchMain'); performance.mark('workbench-start'); - - // Wait for process environment being fully resolved - await whenEnvResolved; - perf.mark('main/startup'); // @ts-ignore @@ -58,23 +51,11 @@ //region Helpers - function perfLib() { - globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || []; - - return { - /** - * @param {string} name - */ - mark(name) { - globalThis.MonacoPerformanceMarks.push(name, Date.now()); - } - }; - } - /** * @returns {{ * load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown, - * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals') + * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals'), + * perfLib: () => { mark: (name: string) => void } * }} */ function bootstrapWindowLib() { From 1273299f3d5849b0966cb3187035b378871889f3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 12:08:07 +0100 Subject: [PATCH 0083/1837] :lipstick: bootstrap-window --- src/bootstrap-window.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 0981fe0baaf..8036d457adf 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -25,12 +25,12 @@ const preloadGlobals = globals(); const sandbox = preloadGlobals.context.sandbox; const webFrame = preloadGlobals.webFrame; - const safeProcess = sandbox ? preloadGlobals.process : process; + const safeProcess = preloadGlobals.process; const configuration = parseWindowConfiguration(); // Start to resolve process.env before anything gets load // so that we can run loading and resolving in parallel - const whenEnvResolved = preloadGlobals.process.resolveEnv(configuration.userEnv); + const whenEnvResolved = safeProcess.resolveEnv(configuration.userEnv); /** * @param {string[]} modulePaths @@ -149,14 +149,12 @@ // Callback only after process environment is resolved const callbackResult = resultCallback(result, configuration); - if (callbackResult && typeof callbackResult.then === 'function') { - callbackResult.then(() => { - if (developerToolsUnbind && options && options.removeDeveloperKeybindingsAfterLoad) { - developerToolsUnbind(); - } - }, error => { - onUnexpectedError(error, enableDeveloperTools); - }); + if (callbackResult instanceof Promise) { + await callbackResult; + + if (developerToolsUnbind && options && options.removeDeveloperKeybindingsAfterLoad) { + developerToolsUnbind(); + } } } catch (error) { onUnexpectedError(error, enableDeveloperTools); From 542a82754c2e68164d190b8316392a82a7fb6e0f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 20 Nov 2020 14:06:37 +0100 Subject: [PATCH 0084/1837] yarn watch: save errors in separate files, make error regex multiline aware --- build/gulpfile.editor.js | 2 +- build/gulpfile.extensions.js | 2 +- build/lib/reporter.ts | 113 ++++++++++++++++++++--------------- 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index aa0282bff57..118fe6e8113 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -434,7 +434,7 @@ function createTscCompileTask(watch) { // stdio: [null, 'pipe', 'inherit'] }); let errors = []; - let reporter = createReporter(); + let reporter = createReporter('monaco'); let report; // eslint-disable-next-line no-control-regex let magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 6ae72e4cf06..c204e84fd8c 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -64,7 +64,7 @@ const tasks = compilations.map(function (tsconfigFile) { } function createPipeline(build, emitError) { - const reporter = createReporter(); + const reporter = createReporter('extensions'); overrideOptions.inlineSources = Boolean(build); overrideOptions.base = path.dirname(absolutePath); diff --git a/build/lib/reporter.ts b/build/lib/reporter.ts index ec908817518..f875fce908a 100644 --- a/build/lib/reporter.ts +++ b/build/lib/reporter.ts @@ -12,72 +12,89 @@ import * as ansiColors from 'ansi-colors'; import * as fs from 'fs'; import * as path from 'path'; -const allErrors: string[][] = []; -let startTime: number | null = null; -let count = 0; +class ErrorLog { + constructor(public id: string) { + } + allErrors: string[][] = []; + startTime: number | null = null; + count = 0; -function onStart(): void { - if (count++ > 0) { - return; + onStart(): void { + if (this.count++ > 0) { + return; + } + + this.startTime = new Date().getTime(); + fancyLog(`Starting ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''}...`); } - startTime = new Date().getTime(); - fancyLog(`Starting ${ansiColors.green('compilation')}...`); -} + onEnd(): void { + if (--this.count > 0) { + return; + } -function onEnd(): void { - if (--count > 0) { - return; + this.log(); + } + + log(): void { + const errors = _.flatten(this.allErrors); + const seen = new Set(); + + errors.map(err => { + if (!seen.has(err)) { + seen.add(err); + fancyLog(`${ansiColors.red('Error')}: ${err}`); + } + }); + + fancyLog(`Finished ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - this.startTime!) + ' ms')}`); + + const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/s; + const messages = errors + .map(err => regex.exec(err)) + .filter(match => !!match) + .map(x => x as string[]) + .map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message })); + + try { + const logFileName = 'log' + (this.id ? `_${this.id}` : ''); + fs.writeFileSync(path.join(buildLogFolder, logFileName), JSON.stringify(messages)); + } catch (err) { + //noop + } } - log(); } -const buildLogPath = path.join(path.dirname(path.dirname(__dirname)), '.build', 'log'); +const errorLogsById = new Map(); +function getErrorLog(id: string = '') { + let errorLog = errorLogsById.get(id); + if (!errorLog) { + errorLog = new ErrorLog(id); + errorLogsById.set(id, errorLog); + } + return errorLog; +} + +const buildLogFolder = path.join(path.dirname(path.dirname(__dirname)), '.build'); try { - fs.mkdirSync(path.dirname(buildLogPath)); + fs.mkdirSync(buildLogFolder); } catch (err) { // ignore } -function log(): void { - const errors = _.flatten(allErrors); - const seen = new Set(); - - errors.map(err => { - if (!seen.has(err)) { - seen.add(err); - fancyLog(`${ansiColors.red('Error')}: ${err}`); - } - }); - - const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/; - const messages = errors - .map(err => regex.exec(err)) - .filter(match => !!match) - .map(x => x as string[]) - .map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message })); - - try { - - fs.writeFileSync(buildLogPath, JSON.stringify(messages)); - } catch (err) { - //noop - } - - fancyLog(`Finished ${ansiColors.green('compilation')} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - startTime!) + ' ms')}`); -} - export interface IReporter { (err: string): void; hasErrors(): boolean; end(emitError: boolean): NodeJS.ReadWriteStream; } -export function createReporter(): IReporter { +export function createReporter(id?: string): IReporter { + const errorLog = getErrorLog(id); + const errors: string[] = []; - allErrors.push(errors); + errorLog.allErrors.push(errors); const result = (err: string) => errors.push(err); @@ -85,14 +102,14 @@ export function createReporter(): IReporter { result.end = (emitError: boolean): NodeJS.ReadWriteStream => { errors.length = 0; - onStart(); + errorLog.onStart(); return es.through(undefined, function () { - onEnd(); + errorLog.onEnd(); if (emitError && errors.length > 0) { if (!(errors as any).__logged__) { - log(); + errorLog.log(); } (errors as any).__logged__ = true; From fb277edc0f2531ca2b9e2b0bb9261b79e5fca4fe Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 15:21:59 +0100 Subject: [PATCH 0085/1837] env - take window configuration into account when resolving shellEnv --- src/vs/code/electron-main/app.ts | 28 +++++++++-- src/vs/code/node/shellEnv.ts | 81 +++++++++++++++++++------------- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 390317f4391..9fdb90b0295 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -9,7 +9,7 @@ import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMai import { IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { getShellEnvironment } from 'vs/code/node/shellEnv'; +import { resolveShellEnv } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; import { UpdateChannel } from 'vs/platform/update/electron-main/updateIpc'; import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main'; @@ -84,6 +84,7 @@ import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encry import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -283,7 +284,24 @@ export class CodeApplication extends Disposable { }, 10000); try { - const shellEnv = await getShellEnvironment(this.logService, this.environmentService); + + // Prefer to use the args and env from the target window + // when resolving the shell env. It is possible that + // a first window was opened from the UI but a second + // from the CLI and that has implications for wether to + // resolve the shell environment or not. + let args: NativeParsedArgs; + let env: NodeJS.ProcessEnv; + if (window?.config) { + args = window.config; + env = { ...process.env, ...window.config.userEnv }; + } else { + args = this.environmentService.args; + env = process.env; + } + + // Resolve shell env + const shellEnv = await resolveShellEnv(this.logService, args, env); acceptShellEnv(shellEnv); } catch (error) { window?.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); // notify inside window if we have one @@ -368,7 +386,7 @@ export class CodeApplication extends Disposable { }); this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => { this._register(new RunOnceScheduler(async () => { - sharedProcess.spawn(await getShellEnvironment(this.logService, this.environmentService)); + sharedProcess.spawn(await resolveShellEnv(this.logService, this.environmentService.args, process.env)); }, 3000)).schedule(); }); @@ -825,8 +843,8 @@ export class CodeApplication extends Disposable { updateService.initialize(); } - // Start to fetch shell environment after window has opened - getShellEnvironment(this.logService, this.environmentService); + // Start to fetch shell environment (if needed) after window has opened + resolveShellEnv(this.logService, this.environmentService.args, process.env); // If enable-crash-reporter argv is undefined then this is a fresh start, // based on telemetry.enableCrashreporter settings, generate a UUID which diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index d1dd0bc6dfb..a7422f5357a 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -7,9 +7,55 @@ import { spawn } from 'child_process'; import { generateUuid } from 'vs/base/common/uuid'; import { isWindows } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; -import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; +import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -function getUnixShellEnvironment(logService: ILogService): Promise { +/** + * We need to get the environment from a user's shell. + * This should only be done when Code itself is not launched + * from within a shell. + */ +export async function resolveShellEnv(logService: ILogService, args: NativeParsedArgs, env: NodeJS.ProcessEnv): Promise { + + // Skip if --force-disable-user-env + if (args['force-disable-user-env']) { + logService.trace('resolveShellEnv(): skipped (--force-disable-user-env)'); + + return {}; + } + + // Skip on windows + else if (isWindows) { + logService.trace('resolveShellEnv(): skipped (Windows)'); + + return {}; + } + + // Skip if running from CLI already + else if (env['VSCODE_CLI'] === '1' && !args['force-user-env']) { + logService.trace('resolveShellEnv(): skipped (VSCODE_CLI is set)'); + + return {}; + } + + // Otherwise resolve (macOS, Linux) + else { + if (env['VSCODE_CLI'] === '1') { + logService.trace('resolveShellEnv(): running (--force-user-env)'); + } else { + logService.trace('resolveShellEnv(): running (macOS/Linux)'); + } + + if (!unixShellEnvPromise) { + unixShellEnvPromise = doResolveUnixShellEnv(logService); + } + + return unixShellEnvPromise; + } +} + +let unixShellEnvPromise: Promise | undefined = undefined; + +function doResolveUnixShellEnv(logService: ILogService): Promise { const promise = new Promise((resolve, reject) => { const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; logService.trace('getUnixShellEnvironment#runAsNode', runAsNode); @@ -81,34 +127,3 @@ function getUnixShellEnvironment(logService: ILogService): Promise ({})); } - -let shellEnvPromise: Promise | undefined = undefined; - -/** - * We need to get the environment from a user's shell. - * This should only be done when Code itself is not launched - * from within a shell. - */ -export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise { - if (!shellEnvPromise) { - if (environmentService.args['force-disable-user-env']) { - logService.trace('getShellEnvironment(): skipped (--force-disable-user-env)'); - shellEnvPromise = Promise.resolve({}); - } else if (isWindows) { - logService.trace('getShellEnvironment(): skipped (Windows)'); - shellEnvPromise = Promise.resolve({}); - } else if (process.env['VSCODE_CLI'] === '1' && !environmentService.args['force-user-env']) { - logService.trace('getShellEnvironment(): skipped (VSCODE_CLI is set)'); - shellEnvPromise = Promise.resolve({}); - } else { - if (process.env['VSCODE_CLI'] === '1') { - logService.trace('getShellEnvironment(): running (--force-user-env)'); - } else { - logService.trace('getShellEnvironment(): running (macOS/Linux)'); - } - shellEnvPromise = getUnixShellEnvironment(logService); - } - } - - return shellEnvPromise; -} From 1568c0ca452a611bb4db0f8a7ea7d39f4841c733 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 15:25:49 +0100 Subject: [PATCH 0086/1837] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47482dc85f9..2e40d6c7161 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "4c0d11b5ca2164ffa3d402ef1425211aac630f38", + "distro": "eec03a44a38591e43680fe058326dbf2d2015518", "author": { "name": "Microsoft Corporation" }, From 690d0e33c15e900d825661df8fea2466ecbe96a9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 15:49:45 +0100 Subject: [PATCH 0087/1837] window - cleanup reload() method --- src/vs/code/electron-main/window.ts | 22 +++++++++---------- .../electron-main/lifecycleMainService.ts | 2 +- .../platform/windows/electron-main/windows.ts | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 6aa77d125fd..9eea5509673 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -5,7 +5,6 @@ import * as os from 'os'; import * as path from 'vs/base/common/path'; -import * as objects from 'vs/base/common/objects'; import * as nls from 'vs/nls'; import * as perf from 'vs/base/common/performance'; import { Emitter } from 'vs/base/common/event'; @@ -111,8 +110,6 @@ export class CodeWindow extends Disposable implements ICodeWindow { private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[]; - private pendingLoadConfig?: INativeWindowConfiguration; - private marketplaceHeadersPromise: Promise; private readonly touchBarGroups: TouchBarSegmentedControl[]; @@ -286,6 +283,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.registerListeners(); } + private pendingLoadConfig: INativeWindowConfiguration | undefined; + private currentConfig: INativeWindowConfiguration | undefined; get config(): INativeWindowConfiguration | undefined { return this.currentConfig; } @@ -297,11 +296,11 @@ export class CodeWindow extends Disposable implements ICodeWindow { get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; } - get isExtensionDevelopmentHost(): boolean { return !!(this.config && this.config.extensionDevelopmentPath); } + get isExtensionDevelopmentHost(): boolean { return !!(this.currentConfig?.extensionDevelopmentPath); } - get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); } + get isExtensionTestHost(): boolean { return !!(this.currentConfig?.extensionTestsPath); } - get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.config?.debugId; } + get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.currentConfig?.debugId; } setRepresentedFilename(filename: string): void { if (isMacintosh) { @@ -739,10 +738,10 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._onLoad.fire(); } - reload(configurationIn?: INativeWindowConfiguration, cli?: NativeParsedArgs): void { + reload(cli?: NativeParsedArgs): void { - // If config is not provided, copy our current one - const configuration = configurationIn ? configurationIn : objects.mixin({}, this.currentConfig); + // Copy our current config for reuse + const configuration = Object.assign({}, this.currentConfig); // Delete some properties we do not want during reload delete configuration.filesToOpenOrCreate; @@ -820,10 +819,9 @@ export class CodeWindow extends Disposable implements ICodeWindow { // large depending on user configuration, so we can only remove it in that case. let configUrl = this.doGetUrl(config); if (configUrl.length > CodeWindow.MAX_URL_LENGTH) { - delete config.userEnv; this.logService.warn('Application URL exceeds maximum of 2MB and was shortened.'); - configUrl = this.doGetUrl(config); + configUrl = this.doGetUrl({ ...config, userEnv: undefined }); if (configUrl.length > CodeWindow.MAX_URL_LENGTH) { this.logService.error('Application URL exceeds maximum of 2MB and cannot be loaded.'); @@ -1139,7 +1137,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } private getMenuBarVisibility(): MenuBarVisibility { - let menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService, !!this.config?.extensionDevelopmentPath); + let menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService, !!this.currentConfig?.extensionDevelopmentPath); if (['visible', 'toggle', 'hidden'].indexOf(menuBarVisibility) < 0) { menuBarVisibility = 'default'; } diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index 48ad05b7b4c..955d52f6789 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -371,7 +371,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe // Only reload when the window has not vetoed this const veto = await this.unload(window, UnloadReason.RELOAD); if (!veto) { - window.reload(undefined, cli); + window.reload(cli); } } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index c9e740bd59e..801435cf777 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -59,7 +59,7 @@ export interface ICodeWindow extends IDisposable { addTabbedWindow(window: ICodeWindow): void; load(config: INativeWindowConfiguration, isReload?: boolean): void; - reload(configuration?: INativeWindowConfiguration, cli?: NativeParsedArgs): void; + reload(cli?: NativeParsedArgs): void; focus(options?: { force: boolean }): void; close(): void; From 7d1cd1ff33a1e8972188a291bca09c6f6aeaf2e3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 16:01:59 +0100 Subject: [PATCH 0088/1837] Fixes #99313 --- src/vs/code/electron-main/app.ts | 6 +++ src/vs/code/electron-main/window.ts | 3 -- .../display/common/displayMainService.ts | 11 +++++ .../electron-main/displayMainService.ts | 47 +++++++++++++++++++ .../codeEditor.contribution.ts | 1 + .../displayChangeRemeasureFonts.ts | 28 +++++++++++ src/vs/workbench/electron-sandbox/window.ts | 6 --- 7 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 src/vs/platform/display/common/displayMainService.ts create mode 100644 src/vs/platform/display/electron-main/displayMainService.ts create mode 100644 src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 9fdb90b0295..33db58c922f 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -85,6 +85,7 @@ import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; +import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -464,6 +465,7 @@ export class CodeApplication extends Disposable { services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); services.set(IEncryptionMainService, new SyncDescriptor(EncryptionMainService, [machineId])); services.set(IKeyboardLayoutMainService, new SyncDescriptor(KeyboardLayoutMainService)); + services.set(IDisplayMainService, new SyncDescriptor(DisplayMainService)); services.set(INativeHostMainService, new SyncDescriptor(NativeHostMainService)); services.set(IWebviewManagerService, new SyncDescriptor(WebviewMainService)); services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService)); @@ -558,6 +560,10 @@ export class CodeApplication extends Disposable { const keyboardLayoutChannel = createChannelReceiver(keyboardLayoutMainService); electronIpcServer.registerChannel('keyboardLayout', keyboardLayoutChannel); + const displayMainService = accessor.get(IDisplayMainService); + const displayChannel = createChannelReceiver(displayMainService); + electronIpcServer.registerChannel('display', displayChannel); + const nativeHostMainService = this.nativeHostMainService = accessor.get(INativeHostMainService); const nativeHostChannel = createChannelReceiver(this.nativeHostMainService); electronIpcServer.registerChannel('nativeHost', nativeHostChannel); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 9eea5509673..f8fe899ca4b 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -468,9 +468,6 @@ export class CodeWindow extends Disposable implements ICodeWindow { return; // disposed } - // Notify renderers about displays changed - this.sendWhenReady('vscode:displayChanged'); - // Simple fullscreen doesn't resize automatically when the resolution changes so as a workaround // we need to detect when display metrics change or displays are added/removed and toggle the // fullscreen manually. diff --git a/src/vs/platform/display/common/displayMainService.ts b/src/vs/platform/display/common/displayMainService.ts new file mode 100644 index 00000000000..44d79f8d545 --- /dev/null +++ b/src/vs/platform/display/common/displayMainService.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. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; + +export interface IDisplayMainService { + readonly _serviceBrand: undefined; + readonly onDidDisplayChanged: Event; +} diff --git a/src/vs/platform/display/electron-main/displayMainService.ts b/src/vs/platform/display/electron-main/displayMainService.ts new file mode 100644 index 00000000000..e360fc48693 --- /dev/null +++ b/src/vs/platform/display/electron-main/displayMainService.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisplayMainService as ICommonDisplayMainService } from 'vs/platform/display/common/displayMainService'; +import { Emitter } from 'vs/base/common/event'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { app, Display, screen } from 'electron'; +import { RunOnceScheduler } from 'vs/base/common/async'; + +export const IDisplayMainService = createDecorator('displayMainService'); + +export interface IDisplayMainService extends ICommonDisplayMainService { } + +export class DisplayMainService extends Disposable implements ICommonDisplayMainService { + + declare readonly _serviceBrand: undefined; + + private readonly _onDidDisplayChanged = this._register(new Emitter()); + readonly onDidDisplayChanged = this._onDidDisplayChanged.event; + + constructor() { + super(); + + const displayChangedScheduler = this._register(new RunOnceScheduler(() => { + this._onDidDisplayChanged.fire(); + }, 100)); + + app.whenReady().then(() => { + + const displayChangedListener = (event: Event, display: Display, changedMetrics?: string[]) => { + displayChangedScheduler.schedule(); + }; + + screen.on('display-metrics-changed', displayChangedListener); + this._register(toDisposable(() => screen.removeListener('display-metrics-changed', displayChangedListener))); + + screen.on('display-added', displayChangedListener); + this._register(toDisposable(() => screen.removeListener('display-added', displayChangedListener))); + + screen.on('display-removed', displayChangedListener); + this._register(toDisposable(() => screen.removeListener('display-removed', displayChangedListener))); + }); + } +} diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts index 08763754187..d544a687a80 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import './displayChangeRemeasureFonts'; import './inputClipboardActions'; import './selectionClipboard'; import './sleepResumeRepaintMinimap'; diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts new file mode 100644 index 00000000000..efcdd8981df --- /dev/null +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { IDisplayMainService } from 'vs/platform/display/common/displayMainService'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { clearAllFontInfos } from 'vs/editor/browser/config/configuration'; + +class DisplayChangeRemeasureFonts extends Disposable implements IWorkbenchContribution { + + constructor( + @IMainProcessService mainProcessService: IMainProcessService + ) { + super(); + const displayMainService = createChannelSender(mainProcessService.getChannel('display')); + displayMainService.onDidDisplayChanged(() => { + clearAllFontInfos(); + }); + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DisplayChangeRemeasureFonts, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index 9062e49737c..aabf783b310 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -59,7 +59,6 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { Event } from 'vs/base/common/event'; -import { clearAllFontInfos } from 'vs/editor/browser/config/configuration'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IAddressProvider, IAddress } from 'vs/platform/remote/common/remoteAgentConnection'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -205,11 +204,6 @@ export class NativeWindow extends Disposable { choices )); - // Display change events - ipcRenderer.on('vscode:displayChanged', () => { - clearAllFontInfos(); - }); - // Fullscreen Events ipcRenderer.on('vscode:enterFullScreen', async () => { await this.lifecycleService.when(LifecyclePhase.Ready); From ff1887be3e07b5d16760376106d6234cad5356a6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Nov 2020 16:08:19 +0100 Subject: [PATCH 0089/1837] Preserve per-window environment variables between workspace changes (fix #108571) --- src/vs/code/electron-main/app.ts | 3 ++- src/vs/code/electron-main/window.ts | 11 +++++++++++ src/vs/code/node/shellEnv.ts | 5 +++-- src/vs/platform/environment/node/argvHelper.ts | 8 ++++++-- .../platform/environment/node/environmentService.ts | 2 +- .../launch/electron-main/launchMainService.ts | 3 ++- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 33db58c922f..597c45bad02 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -86,6 +86,7 @@ import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platfo import { toErrorMessage } from 'vs/base/common/errorMessage'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; +import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -703,7 +704,7 @@ export class CodeApplication extends Disposable { // Open our first window const args = this.environmentService.args; const macOpenFiles: string[] = (global).macOpenFiles; - const context = !!process.env['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; + const context = isLaunchedFromCli(process.env) ? OpenContext.CLI : OpenContext.DESKTOP; const hasCliArgs = args._.length; const hasFolderURIs = !!args['folder-uri']; const hasFileURIs = !!args['file-uri']; diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index f8fe899ca4b..6019f2d2062 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -35,6 +35,7 @@ import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifec import { IStorageMainService } from 'vs/platform/storage/node/storageMainService'; import { ByteSize, IFileService } from 'vs/platform/files/common/files'; import { FileAccess, Schemas } from 'vs/base/common/network'; +import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; export interface IWindowCreationOptions { state: IWindowState; @@ -677,6 +678,16 @@ export class CodeWindow extends Disposable implements ICodeWindow { load(config: INativeWindowConfiguration, isReload?: boolean, disableExtensions?: boolean): void { + // If this window was loaded before from the command line + // (as indicated by VSCODE_CLI environment), make sure to + // preserve that user environment in subsequent loads, + // unless the new configuration context was also a CLI + // (for https://github.com/microsoft/vscode/issues/108571) + const currentUserEnv = (this.currentConfig ?? this.pendingLoadConfig)?.userEnv; + if (currentUserEnv && isLaunchedFromCli(currentUserEnv) && !isLaunchedFromCli(config.userEnv)) { + config.userEnv = currentUserEnv; + } + // If this is the first time the window is loaded, we associate the paths // directly with the window because we assume the loading will just work if (this._readyState === ReadyState.NONE) { diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index a7422f5357a..79ba3d252fe 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -8,6 +8,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { isWindows } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; +import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; /** * We need to get the environment from a user's shell. @@ -31,7 +32,7 @@ export async function resolveShellEnv(logService: ILogService, args: NativeParse } // Skip if running from CLI already - else if (env['VSCODE_CLI'] === '1' && !args['force-user-env']) { + else if (isLaunchedFromCli(env) && !args['force-user-env']) { logService.trace('resolveShellEnv(): skipped (VSCODE_CLI is set)'); return {}; @@ -39,7 +40,7 @@ export async function resolveShellEnv(logService: ILogService, args: NativeParse // Otherwise resolve (macOS, Linux) else { - if (env['VSCODE_CLI'] === '1') { + if (isLaunchedFromCli(env)) { logService.trace('resolveShellEnv(): running (--force-user-env)'); } else { logService.trace('resolveShellEnv(): running (macOS/Linux)'); diff --git a/src/vs/platform/environment/node/argvHelper.ts b/src/vs/platform/environment/node/argvHelper.ts index a3c16f98de7..3ace20cfc45 100644 --- a/src/vs/platform/environment/node/argvHelper.ts +++ b/src/vs/platform/environment/node/argvHelper.ts @@ -52,7 +52,7 @@ export function parseMainProcessArgv(processArgv: string[]): NativeParsedArgs { } // If called from CLI, don't report warnings as they are already reported. - let reportWarnings = !process.env['VSCODE_CLI']; + const reportWarnings = !isLaunchedFromCli(process.env); return parseAndValidate(args, reportWarnings); } @@ -60,7 +60,7 @@ export function parseMainProcessArgv(processArgv: string[]): NativeParsedArgs { * Use this to parse raw code CLI process.argv such as: `Electron cli.js . --verbose --wait` */ export function parseCLIProcessArgv(processArgv: string[]): NativeParsedArgs { - let [, , ...args] = processArgv; // remove the first non-option argument: it's always the app location + const [, , ...args] = processArgv; // remove the first non-option argument: it's always the app location return parseAndValidate(args, true); } @@ -78,3 +78,7 @@ export function addArg(argv: string[], ...args: string[]): string[] { return argv; } + +export function isLaunchedFromCli(env: NodeJS.ProcessEnv): boolean { + return env['VSCODE_CLI'] === '1'; +} diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 76e81a13ce7..cef263622d4 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as os from 'os'; import { IDebugParams, IExtensionHostDebugParams, INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import * as paths from 'vs/base/node/paths'; -import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as resources from 'vs/base/common/resources'; import { memoize } from 'vs/base/common/decorators'; diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index ac0c66cf600..069bb585c19 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -19,6 +19,7 @@ import { BrowserWindow, ipcMain, Event as IpcEvent, app } from 'electron'; import { coalesce } from 'vs/base/common/arrays'; import { IDiagnosticInfoOptions, IDiagnosticInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { IMainProcessInfo, IWindowInfo } from 'vs/platform/launch/node/launch'; +import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; export const ID = 'launchMainService'; export const ILaunchMainService = createDecorator(ID); @@ -112,7 +113,7 @@ export class LaunchMainService implements ILaunchMainService { } private startOpenWindow(args: NativeParsedArgs, userEnv: IProcessEnvironment): Promise { - const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; + const context = isLaunchedFromCli(userEnv) ? OpenContext.CLI : OpenContext.DESKTOP; let usedWindows: ICodeWindow[] = []; const waitMarkerFileURI = args.wait && args.waitMarkerFilePath ? URI.file(args.waitMarkerFilePath) : undefined; From d1280418d7276fb4f950c8caf75b3493a6dfec77 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 20 Nov 2020 08:31:35 -0800 Subject: [PATCH 0090/1837] testing: initial api implementation * wip * wip * wip * wip * wip * wip --- .eslintrc.json | 1 + src/vs/base/common/arrays.ts | 14 + src/vs/vscode.proposed.d.ts | 289 ++++++++ .../api/browser/extensionHost.contribution.ts | 1 + .../api/browser/mainThreadTesting.ts | 77 +++ .../workbench/api/common/extHost.api.impl.ts | 27 +- .../workbench/api/common/extHost.protocol.ts | 29 +- src/vs/workbench/api/common/extHostTesting.ts | 623 ++++++++++++++++++ .../api/common/extHostTypeConverters.ts | 62 ++ src/vs/workbench/api/common/extHostTypes.ts | 44 ++ .../testing/browser/testing.contribution.ts | 10 + .../contrib/testing/common/testCollection.ts | 197 ++++++ .../contrib/testing/common/testService.ts | 30 + .../contrib/testing/common/testServiceImpl.ts | 128 ++++ .../test/browser/api/extHostTesting.test.ts | 200 ++++++ src/vs/workbench/workbench.common.main.ts | 3 + 16 files changed, 1732 insertions(+), 3 deletions(-) create mode 100644 src/vs/workbench/api/browser/mainThreadTesting.ts create mode 100644 src/vs/workbench/api/common/extHostTesting.ts create mode 100644 src/vs/workbench/contrib/testing/browser/testing.contribution.ts create mode 100644 src/vs/workbench/contrib/testing/common/testCollection.ts create mode 100644 src/vs/workbench/contrib/testing/common/testService.ts create mode 100644 src/vs/workbench/contrib/testing/common/testServiceImpl.ts create mode 100644 src/vs/workbench/test/browser/api/extHostTesting.test.ts diff --git a/.eslintrc.json b/.eslintrc.json index 055bc22f8e4..fd72f0e58f1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -983,6 +983,7 @@ "collapse", "create", "delete", + "discover", "dispose", "edit", "end", diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index bc0aa40a685..c4820d9cf6f 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -588,3 +588,17 @@ export function asArray(x: T | T[]): T[] { export function getRandomElement(arr: T[]): T | undefined { return arr[Math.floor(Math.random() * arr.length)]; } + +/** + * Returns the first mapped value of the array which is not undefined. + */ +export function mapFind(array: Iterable, mapFn: (value: T) => R | undefined): R | undefined { + for (const value of array) { + const mapped = mapFn(value); + if (mapped !== undefined) { + return mapped; + } + } + + return undefined; +} diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 606da64d9da..1b4dd21140a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2149,4 +2149,293 @@ declare module 'vscode' { notebook: NotebookDocument | undefined; } //#endregion + + //#region https://github.com/microsoft/vscode/issues/107467 + /* + General activation events: + - `onLanguage:*` most test extensions will want to activate when their + language is opened to provide code lenses. + - `onTests:*` new activation event very simiular to `workspaceContains`, + but only fired when the user wants to run tests or opens the test explorer. + */ + export namespace test { + /** + * Registers a provider that discovers tests for the given document + * selectors. It is activated when either tests need to be enumerated, or + * a document matching the selector is opened. + */ + export function registerTestProvider(testProvider: TestProvider): Disposable; + + /** + * Runs tests with the given options. If no options are given, then + * all tests are run. Returns the resulting test run. + */ + export function runTests(options: TestRunOptions): Thenable; + + /** + * Returns an observer that retrieves tests in the given workspace folder. + */ + export function createWorkspaceTestObserver(workspaceFolder: WorkspaceFolder): TestObserver; + + /** + * Returns an observer that retrieves tests in the given text document. + */ + export function createDocumentTestObserver(document: TextDocument): TestObserver; + } + + export interface TestObserver { + /** + * List of tests returned by test provider for files in the workspace. + */ + readonly tests: ReadonlyArray; + + /** + * An event that fires when an existing test in the collection changes, or + * null if a top-level test was added or removed. When fired, the consumer + * should check the test item and all its children for changes. + */ + readonly onDidChangeTest: Event; + + /** + * An event the fires when all test providers have signalled that the tests + * the observer references have been discovered. Providers may continue to + * watch for changes and cause {@link onDidChangeTest} to fire as files + * change, until the observer is disposed. + * + * @todo as below + */ + readonly onDidDiscoverInitialTests: Event; + + /** + * Dispose of the observer, allowing VS Code to eventually tell test + * providers that they no longer need to update tests. + */ + dispose(): void; + } + + /** + * Tree of tests returned from the provide methods in the {@link TestProvider}. + */ + export interface TestHierarchy { + /** + * Root node for tests. The `testRoot` instance must not be replaced over + * the lifespan of the TestHierarchy, since you will need to reference it + * in `onDidChangeTest` when a test is added or removed. + */ + readonly root: T; + + /** + * An event that fires when an existing test under the `root` changes. + * This can be a result of a state change in a test run, a property update, + * or an update to its children. Changes made to tests will not be visible + * to {@link TestObserver} instances until this event is fired. + * + * This will signal a change recursively to all children of the given node. + * For example, firing the event with the {@link testRoot} will refresh + * all tests. + */ + readonly onDidChangeTest: Event; + + /** + * An event that should be fired when all tests that are currently defined + * have been discovered. The provider should continue to watch for changes + * and fire `onDidChangeTest` until the hierarchy is disposed. + * + * @todo can this be covered by existing progress apis? Or return a promise + */ + readonly onDidDiscoverInitialTests: Event; + + /** + * Dispose will be called when there are no longer observers interested + * in the hierarchy. + */ + dispose(): void; + } + + /** + * Discovers and provides tests. It's expected that the TestProvider will + * ambiently listen to {@link vscode.window.onDidChangeVisibleTextEditors} to + * provide test information about the open files for use in code lenses and + * other file-specific UI. + * + * Additionally, the UI may request it to discover tests for the workspace + * via `addWorkspaceTests`. + * + * @todo rename from provider + */ + export interface TestProvider { + /** + * Requests that tests be provided for the given workspace. This will + * generally be called when tests need to be enumerated for the + * workspace. + * + * It's guaranteed that this method will not be called again while + * there is a previous undisposed watcher for the given workspace folder. + */ + createWorkspaceTestHierarchy?(workspace: WorkspaceFolder): TestHierarchy; + + /** + * Requests that tests be provided for the given document. This will + * be called when tests need to be enumerated for a single open file, + * for instance by code lens UI. + */ + createDocumentTestHierarchy?(document: TextDocument): TestHierarchy; + + /** + * Starts a test run. This should cause {@link onDidChangeTest} to + * fire with update test states during the run. + * @todo this will eventually need to be able to return a summary report, coverage for example. + */ + runTests?(options: TestRunOptions, cancellationToken: CancellationToken): ProviderResult; + } + + /** + * Options given to `TestProvider.runTests` + */ + export interface TestRunOptions { + /** + * Array of specific tests to run. The {@link TestProvider.testRoot} may + * be provided as an indication to run all tests. + */ + tests: T[]; + + /** + * Whether or not tests in this run should be debugged. + */ + debug: boolean; + } + + /** + * A test item is an item shown in the "test explorer" view. It encompasses + * both a suite and a test, since they have almost or identical capabilities. + */ + export interface TestItem { + /** + * Display name describing the test case. + */ + label: string; + + /** + * Optional description that appears next to the label. + */ + description?: string; + + /** + * Whether this test item can be run individually, defaults to `true` + * if not provided. + * + * In some cases, like Go's tests, test can have children but these + * children cannot be run independently. + */ + runnable?: boolean; + + /** + * Whether this test item can be debugged. + */ + debuggable?: boolean; + + /** + * VS Code location. + */ + location?: Location; + + /** + * Optional list of nested tests for this item. + */ + children?: TestItem[]; + + /** + * Test run state. Will generally be {@link TestRunState.Unset} by + * default. + */ + state: TestState; + } + + export enum TestRunState { + // Initial state + Unset = 0, + // Test is currently running + Running = 1, + // Test run has passed + Passed = 2, + // Test run has failed (on an assertion) + Failed = 3, + // Test run has been skipped + Skipped = 4, + // Test run failed for some other reason (compilation error, timeout, etc) + Errored = 5 + } + + /** + * TestState includes a test and its run state. This is included in the + * {@link TestItem} and is immutable; it should be replaced in th TestItem + * in order to update it. This allows consumers to quickly and easily check + * for changes via object identity. + */ + export class TestState { + /** + * Current state of the test. + */ + readonly runState: TestRunState; + + /** + * Optional duration of the test run, in milliseconds. + */ + readonly duration?: number; + + /** + * Associated test run message. Can, for example, contain assertion + * failure information if the test fails. + */ + readonly messages: ReadonlyArray>; + + /** + * @param state Run state to hold in the test state + * @param messages List of associated messages for the test + * @param duration Length of time the test run took, if appropriate. + */ + constructor(runState: TestRunState, messages?: TestMessage[], duration?: number); + } + + /** + * Represents the severity of test messages. + */ + export enum TestMessageSeverity { + Error = 0, + Warning = 1, + Information = 2, + Hint = 3 + } + + /** + * Message associated with the test state. Can be linked to a specific + * source range -- useful for assertion failures, for example. + */ + export interface TestMessage { + /** + * Human-readable message text to display. + */ + message: string | MarkdownString; + + /** + * Message severity. Defaults to "Error", if not provided. + */ + severity?: TestMessageSeverity; + + /** + * Expected test output. If given with `actual`, a diff view will be shown. + */ + expectedOutput?: string; + + /** + * Actual test output. If given with `actual`, a diff view will be shown. + */ + actualOutput?: string; + + /** + * Associated file location. + */ + location?: Location; + } + //#endregion } diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index a4df8523631..3b4c8a66c27 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -64,6 +64,7 @@ import './mainThreadLabelService'; import './mainThreadTunnelService'; import './mainThreadAuthentication'; import './mainThreadTimeline'; +import './mainThreadTesting'; import 'vs/workbench/api/common/apiCommands'; export class ExtensionPoints implements IWorkbenchContribution { diff --git a/src/vs/workbench/api/browser/mainThreadTesting.ts b/src/vs/workbench/api/browser/mainThreadTesting.ts new file mode 100644 index 00000000000..52185f8dd91 --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadTesting.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { getTestSubscriptionKey, RunTestsRequest, RunTestsResult, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; +import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; +import { ExtHostContext, ExtHostTestingResource, ExtHostTestingShape, IExtHostContext, MainContext, MainThreadTestingShape } from '../common/extHost.protocol'; +import { URI, UriComponents } from 'vs/base/common/uri'; + +@extHostNamedCustomer(MainContext.MainThreadTesting) +export class MainThreadTesting extends Disposable implements MainThreadTestingShape { + private readonly proxy: ExtHostTestingShape; + private readonly testSubscriptions = new Map(); + + constructor( + extHostContext: IExtHostContext, + @ITestService private readonly testService: ITestService, + ) { + super(); + this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostTesting); + this._register(this.testService.onShouldSubscribe(args => this.proxy.$subscribeToTests(args.resource, args.uri))); + this._register(this.testService.onShouldUnsubscribe(args => this.proxy.$unsubscribeFromTests(args.resource, args.uri))); + } + + /** + * @inheritdoc + */ + public $registerTestProvider(id: string) { + this.testService.registerTestController(id, { + runTests: req => this.proxy.$runTestsForProvider(req), + }); + } + + /** + * @inheritdoc + */ + public $unregisterTestProvider(id: string) { + this.testService.unregisterTestController(id); + } + + /** + * @inheritdoc + */ + $subscribeToDiffs(resource: ExtHostTestingResource, uriComponents: UriComponents): void { + const uri = URI.revive(uriComponents); + const disposable = this.testService.subscribeToDiffs(resource, uri, + diff => this.proxy.$acceptDiff(resource, uriComponents, diff)); + this.testSubscriptions.set(getTestSubscriptionKey(resource, uri), disposable); + } + + /** + * @inheritdoc + */ + public $unsubscribeFromDiffs(resource: ExtHostTestingResource, uriComponents: UriComponents): void { + const key = getTestSubscriptionKey(resource, URI.revive(uriComponents)); + this.testSubscriptions.get(key)?.dispose(); + this.testSubscriptions.delete(key); + } + + /** + * @inheritdoc + */ + public $publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void { + this.testService.publishDiff(resource, URI.revive(uri), diff); + } + + public $runTests(req: RunTestsRequest): Promise { + return this.testService.runTests(req); + } + + public dispose() { + // no-op + } +} diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index e4eee8822f6..ee9a8ef8c3c 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -81,6 +81,7 @@ import { ExtHostCustomEditors } from 'vs/workbench/api/common/extHostCustomEdito import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels'; import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits'; import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo'; +import { ExtHostTesting } from 'vs/workbench/api/common/extHostTesting'; export interface IExtensionApiFactory { (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; @@ -152,6 +153,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace)); const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels)); const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews)); + const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol, extHostDocumentsAndEditors, extHostWorkspace)); // Check that no named customers are missing const expected: ProxyIdentifier[] = values(ExtHostContext); @@ -333,6 +335,25 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ? extHostTypes.ExtensionKind.Workspace : extHostTypes.ExtensionKind.UI; + const test: typeof vscode.test = { + registerTestProvider(provider) { + checkProposedApiEnabled(extension); + return extHostTesting.registerTestProvider(provider); + }, + createDocumentTestObserver(document) { + checkProposedApiEnabled(extension); + return extHostTesting.createTextDocumentTestObserver(document); + }, + createWorkspaceTestObserver(workspaceFolder) { + checkProposedApiEnabled(extension); + return extHostTesting.createWorkspaceTestObserver(workspaceFolder); + }, + runTests(provider) { + checkProposedApiEnabled(extension); + return extHostTesting.runTests(provider); + }, + }; + // namespace: extensions const extensions: typeof vscode.extensions = { getExtension(extensionId: string): Extension | undefined { @@ -1072,6 +1093,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I extensions, languages, scm, + test, comment, comments, tasks, @@ -1197,7 +1219,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I NotebookEditorRevealType: extHostTypes.NotebookEditorRevealType, NotebookCellOutput: extHostTypes.NotebookCellOutput, NotebookCellOutputItem: extHostTypes.NotebookCellOutputItem, - OnTypeRenameRanges: extHostTypes.OnTypeRenameRanges + OnTypeRenameRanges: extHostTypes.OnTypeRenameRanges, + TestRunState: extHostTypes.TestRunState, + TestMessageSeverity: extHostTypes.TestMessageSeverity, + TestState: extHostTypes.TestState, }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b4359816ea4..6ca43431728 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -57,6 +57,7 @@ import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensionsStorageSync'; +import { RunTestForProviderRequest, RunTestsRequest, RunTestsResult, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; export interface IEnvironment { isExtensionDevelopmentDebug: boolean; @@ -1750,6 +1751,28 @@ export interface ExtHostTimelineShape { $getTimeline(source: string, uri: UriComponents, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise; } +export const enum ExtHostTestingResource { + Workspace, + TextDocument +} + +export interface ExtHostTestingShape { + $runTestsForProvider(req: RunTestForProviderRequest): Promise; + $subscribeToTests(resource: ExtHostTestingResource, uri: UriComponents): void; + $unsubscribeFromTests(resource: ExtHostTestingResource, uri: UriComponents): void; + + $acceptDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void; +} + +export interface MainThreadTestingShape { + $registerTestProvider(id: string): void; + $unregisterTestProvider(id: string): void; + $subscribeToDiffs(resource: ExtHostTestingResource, uri: UriComponents): void; + $unsubscribeFromDiffs(resource: ExtHostTestingResource, uri: UriComponents): void; + $publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void; + $runTests(req: RunTestsRequest): Promise; +} + // --- proxy identifiers export const MainContext = { @@ -1799,7 +1822,8 @@ export const MainContext = { MainThreadNotebook: createMainId('MainThreadNotebook'), MainThreadTheming: createMainId('MainThreadTheming'), MainThreadTunnelService: createMainId('MainThreadTunnelService'), - MainThreadTimeline: createMainId('MainThreadTimeline') + MainThreadTimeline: createMainId('MainThreadTimeline'), + MainThreadTesting: createMainId('MainThreadTesting'), }; export const ExtHostContext = { @@ -1842,5 +1866,6 @@ export const ExtHostContext = { ExtHostTheming: createMainId('ExtHostTheming'), ExtHostTunnelService: createMainId('ExtHostTunnelService'), ExtHostAuthentication: createMainId('ExtHostAuthentication'), - ExtHostTimeline: createMainId('ExtHostTimeline') + ExtHostTimeline: createMainId('ExtHostTimeline'), + ExtHostTesting: createMainId('ExtHostTesting'), }; diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts new file mode 100644 index 00000000000..270f66a8847 --- /dev/null +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -0,0 +1,623 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { mapFind } from 'vs/base/common/arrays'; +import { disposableTimeout } from 'vs/base/common/async'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { throttle } from 'vs/base/common/decorators'; +import { Emitter } from 'vs/base/common/event'; +import { once } from 'vs/base/common/functional'; +import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { isDefined } from 'vs/base/common/types'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { generateUuid } from 'vs/base/common/uuid'; +import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; +import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; +import { Disposable } from 'vs/workbench/api/common/extHostTypes'; +import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; +import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import type * as vscode from 'vscode'; + +const getTestSubscriptionKey = (resource: ExtHostTestingResource, uri: URI) => `${resource}:${uri.toString()}`; + +export class ExtHostTesting implements ExtHostTestingShape { + private readonly providers = new Map(); + private readonly proxy: MainThreadTestingShape; + private readonly ownedTests = new OwnedTestCollection(); + private readonly testSubscriptions = new Map(); + + private workspaceObservers: WorkspaceFolderTestObserverFactory; + private textDocumentObservers: TextDocumentTestObserverFactory; + + constructor(@IExtHostRpcService rpc: IExtHostRpcService, @IExtHostDocumentsAndEditors private readonly documents: IExtHostDocumentsAndEditors, @IExtHostWorkspace private readonly workspace: IExtHostWorkspace) { + this.proxy = rpc.getProxy(MainContext.MainThreadTesting); + this.workspaceObservers = new WorkspaceFolderTestObserverFactory(this.proxy); + this.textDocumentObservers = new TextDocumentTestObserverFactory(this.proxy, documents); + } + + /** + * Implements vscode.test.registerTestProvider + */ + public registerTestProvider(provider: vscode.TestProvider): vscode.Disposable { + const providerId = generateUuid(); + this.providers.set(providerId, provider); + this.proxy.$registerTestProvider(providerId); + + return new Disposable(() => { + this.providers.delete(providerId); + this.proxy.$unregisterTestProvider(providerId); + }); + } + + /** + * Implements vscode.test.createTextDocumentTestObserver + */ + public createTextDocumentTestObserver(document: vscode.TextDocument) { + return this.textDocumentObservers.checkout(document.uri); + } + + /** + * Implements vscode.test.createWorkspaceTestObserver + */ + public createWorkspaceTestObserver(workspaceFolder: vscode.WorkspaceFolder) { + return this.workspaceObservers.checkout(workspaceFolder.uri); + } + + /** + * Implements vscode.test.runTests + */ + public async runTests(req: vscode.TestRunOptions) { + await this.proxy.$runTests({ + tests: req.tests + // Find workspace items first, then owned tests, then document tests. + // If a test instance exists in both the workspace and document, prefer + // the workspace because it's less ephemeral. + .map(test => this.workspaceObservers.getMirroredTestDataByReference(test) + ?? mapFind(this.testSubscriptions.values(), c => c.collection.getTestByReference(test)) + ?? this.textDocumentObservers.getMirroredTestDataByReference(test)) + .filter(isDefined) + .map(item => ({ providerId: item.providerId, testId: item.id })), + debug: req.debug + }); + } + + /** + * Handles a request to read tests for a file, or workspace. + * @override + */ + public $subscribeToTests(resource: ExtHostTestingResource, uriComponents: UriComponents) { + const uri = URI.revive(uriComponents); + const subscriptionKey = getTestSubscriptionKey(resource, uri); + if (this.testSubscriptions.has(subscriptionKey)) { + return; + } + + let method: undefined | ((p: vscode.TestProvider) => vscode.TestHierarchy | undefined); + if (resource === ExtHostTestingResource.TextDocument) { + const document = this.documents.getDocument(uri); + if (document) { + method = p => p.createDocumentTestHierarchy?.(document.document); + } + } else { + const folder = this.workspace.getWorkspaceFolder(uri, false); + if (folder) { + method = p => p.createWorkspaceTestHierarchy?.(folder); + } + } + + if (!method) { + return; + } + + const disposable = new DisposableStore(); + const collection = disposable.add(this.ownedTests.createForHierarchy(diff => this.proxy.$publishDiff(resource, uriComponents, diff))); + for (const [id, provider] of this.providers) { + try { + const hierarchy = method(provider); + if (!hierarchy) { + continue; + } + + disposable.add(hierarchy); + collection.addRoot(hierarchy.root, id); + hierarchy.onDidChangeTest(e => collection.onItemChange(e, id)); + } catch (e) { + console.error(e); + } + } + + this.testSubscriptions.set(subscriptionKey, { store: disposable, collection }); + } + + /** + * Disposes of a previous subscription to tests. + * @override + */ + public $unsubscribeFromTests(resource: ExtHostTestingResource, uriComponents: UriComponents) { + const uri = URI.revive(uriComponents); + const subscriptionKey = getTestSubscriptionKey(resource, uri); + this.testSubscriptions.get(subscriptionKey)?.store.dispose(); + this.testSubscriptions.delete(subscriptionKey); + } + + /** + * Receives a test update from the main thread. Called (eventually) whenever + * tests change. + * @override + */ + public $acceptDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void { + if (resource === ExtHostTestingResource.TextDocument) { + this.textDocumentObservers.acceptDiff(URI.revive(uri), diff); + } else { + this.workspaceObservers.acceptDiff(URI.revive(uri), diff); + } + } + + /** + * Runs tests with the given set of IDs. Allows for test from multiple + * providers to be run. + * @override + */ + public async $runTestsForProvider(req: RunTestForProviderRequest): Promise { + const provider = this.providers.get(req.providerId); + if (!provider || !provider.runTests) { + return EMPTY_TEST_RESULT; + } + + const tests = req.ids.map(id => this.ownedTests.getTestById(id)?.actual).filter(isDefined); + if (!tests.length) { + return EMPTY_TEST_RESULT; + } + + await provider.runTests({ tests, debug: req.debug }, CancellationToken.None); + return EMPTY_TEST_RESULT; + } +} + +const keyMap: { [K in keyof Omit, 'children'>]: null } = { + label: null, + location: null, + state: null, + debuggable: null, + description: null, + runnable: null +}; + +const simpleProps = Object.keys(keyMap) as ReadonlyArray; + +const itemEqualityComparator = (a: vscode.TestItem) => { + const values: unknown[] = []; + for (const prop of simpleProps) { + values.push(a[prop]); + } + + return (b: vscode.TestItem) => { + for (let i = 0; i < simpleProps.length; i++) { + if (values[i] !== b[simpleProps[i]]) { + return false; + } + } + + return true; + }; +}; + +/** + * @private + */ +export interface OwnedCollectionTestItem extends InternalTestItem { + actual: vscode.TestItem; + previousChildren: Set; + previousEquals: (v: vscode.TestItem) => boolean; +} + +export class OwnedTestCollection { + protected readonly testIdToInternal = new Map(); + + /** + * Gets test information by ID, if it was defined and still exists in this + * extension host. + */ + public getTestById(id: string) { + return this.testIdToInternal.get(id); + } + + /** + * Creates a new test collection for a specific hierarchy for a workspace + * or document observation. + */ + public createForHierarchy(publishDiff: (diff: TestsDiff) => void = () => undefined) { + return new SingleUseTestCollection(this.testIdToInternal, publishDiff); + } +} + +/** + * Maintains tests created and registered for a single set of hierarchies + * for a workspace or document. + * @private + */ +export class SingleUseTestCollection implements IDisposable { + protected readonly testItemToInternal = new Map(); + protected diff: TestsDiff = []; + private disposed = false; + + constructor(private readonly testIdToInternal: Map, private readonly publishDiff: (diff: TestsDiff) => void) { } + + /** + * Adds a new root node to the collection. + */ + public addRoot(item: vscode.TestItem, providerId: string) { + this.addItem(item, providerId, null); + this.throttleSendDiff(); + } + + /** + * Gets test information by its reference, if it was defined and still exists + * in this extension host. + */ + public getTestByReference(item: vscode.TestItem) { + return this.testItemToInternal.get(item); + } + + /** + * Should be called when an item change is fired on the test provider. + */ + public onItemChange(item: vscode.TestItem, providerId: string) { + const existing = this.testItemToInternal.get(item); + if (!existing) { + if (!this.disposed) { + console.warn(`Received a TestProvider.onDidChangeTest for a test that wasn't seen before as a child.`); + } + return; + } + + this.addItem(item, providerId, existing.parent); + this.throttleSendDiff(); + } + + /** + * Gets a diff of all changes that have been made, and clears the diff queue. + */ + public collectDiff() { + const diff = this.diff; + this.diff = []; + return diff; + } + + public dispose() { + for (const item of this.testItemToInternal.values()) { + this.testIdToInternal.delete(item.id); + } + + this.testIdToInternal.clear(); + this.diff = []; + this.disposed = true; + } + + protected getId(): string { + return generateUuid(); + } + + private addItem(actual: vscode.TestItem, providerId: string, parent: string | null) { + let internal = this.testItemToInternal.get(actual); + if (!internal) { + internal = { + actual, + id: this.getId(), + parent, + item: TestItem.from(actual), + providerId, + previousChildren: new Set(), + previousEquals: itemEqualityComparator(actual), + }; + + this.testItemToInternal.set(actual, internal); + this.testIdToInternal.set(internal.id, internal); + this.diff.push([TestDiffOpType.Add, { id: internal.id, parent, providerId, item: internal.item }]); + } else if (!internal.previousEquals(actual)) { + internal.item = TestItem.from(actual); + internal.previousEquals = itemEqualityComparator(actual); + this.diff.push([TestDiffOpType.Update, { id: internal.id, parent, providerId, item: internal.item }]); + } + + // If there are children, track which ones are deleted + // and recursively and/update them. + if (actual.children) { + const deletedChildren = internal.previousChildren; + const currentChildren = new Set(); + for (const child of actual.children) { + const c = this.addItem(child, providerId, internal.id); + deletedChildren.delete(c.id); + currentChildren.add(c.id); + } + + for (const child of deletedChildren) { + this.removeItembyId(child); + } + + internal.previousChildren = currentChildren; + } + + + return internal; + } + + private removeItembyId(id: string) { + this.diff.push([TestDiffOpType.Remove, id]); + + const queue = [this.testIdToInternal.get(id)]; + while (queue.length) { + const item = queue.pop(); + if (!item) { + continue; + } + + this.testIdToInternal.delete(item.id); + this.testItemToInternal.delete(item.actual); + for (const child of item.previousChildren) { + queue.push(this.testIdToInternal.get(child)); + } + } + } + + @throttle(200) + protected throttleSendDiff() { + const diff = this.collectDiff(); + if (diff.length) { + this.publishDiff(diff); + } + } +} + +/** + * @private + */ +interface MirroredCollectionTestItem extends IncrementalTestCollectionItem { + revived: vscode.TestItem; + wrapped?: vscode.TestItem; +} + +/** + * Maintains tests in this extension host sent from the main thread. + * @private + */ +export class MirroredTestCollection extends AbstractIncrementalTestCollection { + private changeEmitter = new Emitter(); + + /** + * Change emitter that fires with the same sematics as `TestObserver.onDidChangeTests`. + */ + public readonly onDidChangeTests = this.changeEmitter.event; + + /** + * Mapping of mirrored test items to their underlying ID. Given here to avoid + * exposing them to extensions. + */ + protected readonly mirroredTestIds = new WeakMap(); + + /** + * Gets a list of root test items. + */ + public get rootTestItems() { + return this.getAllAsTestItem([...this.roots]); + } + + /** + * Translates the item IDs to TestItems for exposure to extensions. + */ + public getAllAsTestItem(itemIds: ReadonlyArray): vscode.TestItem[] { + return itemIds.map(itemId => { + const item = this.items.get(itemId); + return item && this.createCollectionItemWrapper(item); + }).filter(isDefined); + } + + /** + * If the test item is a mirrored test item, returns its underlying ID. + */ + public getMirroredTestDataByReference(item: vscode.TestItem) { + const itemId = this.mirroredTestIds.get(item); + return itemId ? this.items.get(itemId) : undefined; + } + + /** + * @override + */ + protected createItem(item: InternalTestItem): MirroredCollectionTestItem { + return { ...item, revived: TestItem.to(item.item), children: new Set() }; + } + + /** + * @override + */ + protected onChange(item: MirroredCollectionTestItem | null) { + if (item) { + Object.assign(item.revived, TestItem.to(item.item)); + } + + this.changeEmitter.fire(item ? this.createCollectionItemWrapper(item) : null); + } + + private createCollectionItemWrapper(item: MirroredCollectionTestItem): vscode.TestItem { + if (!item.wrapped) { + item.wrapped = createMirroredTestItem(item, this); + this.mirroredTestIds.set(item.wrapped, item.id); + } + + return item.wrapped; + } +} + +const createMirroredTestItem = (internal: MirroredCollectionTestItem, collection: MirroredTestCollection): vscode.TestItem => { + const obj = {}; + + Object.defineProperty(obj, 'children', { + enumerable: true, + configurable: false, + get: () => collection.getAllAsTestItem([...internal.children]) + }); + + simpleProps.forEach(prop => Object.defineProperty(obj, prop, { + enumerable: true, + configurable: false, + get: () => internal.revived[prop], + })); + + return obj as any; +}; + +interface IObserverData { + observers: number; + tests: MirroredTestCollection; + listener: IDisposable; + pendingDeletion?: IDisposable; +} + +abstract class AbstractTestObserverFactory { + private readonly resources = new Map(); + + public checkout(resourceUri: URI): vscode.TestObserver { + const resourceKey = resourceUri.toString(); + const resource = this.resources.get(resourceKey) ?? this.createObserverData(resourceUri); + + resource.observers++; + + return { + onDidChangeTest: resource.tests.onDidChangeTests, + onDidDiscoverInitialTests: new Emitter().event, // todo@connor4312 + get tests() { + return resource.tests.rootTestItems; + }, + dispose: once(() => { + if (!--resource.observers) { + resource.pendingDeletion = this.eventuallyDispose(resourceUri); + } + }), + }; + } + + /** + * Gets the internal test data by its reference, in any observer. + */ + public getMirroredTestDataByReference(ref: vscode.TestItem) { + for (const { tests } of this.resources.values()) { + const v = tests.getMirroredTestDataByReference(ref); + if (v) { + return v; + } + } + + return undefined; + } + + /** + * Called when no observers are listening for the resource any more. Should + * defer unlistening on the resource, and return a disposiable + * to halt the process in case new listeners come in. + */ + protected eventuallyDispose(resourceUri: URI) { + return disposableTimeout(() => this.unlisten(resourceUri), 10 * 1000); + } + + /** + * Starts listening to test information for the given resource. + */ + protected abstract listen(resourceUri: URI, onDiff: (diff: TestsDiff) => void): Disposable; + + private createObserverData(resourceUri: URI): IObserverData { + const tests = new MirroredTestCollection(); + const listener = this.listen(resourceUri, diff => tests.apply(diff)); + const data: IObserverData = { observers: 0, tests, listener }; + this.resources.set(resourceUri.toString(), data); + return data; + } + + /** + * Called when a resource is no longer in use. + */ + protected unlisten(resourceUri: URI) { + const key = resourceUri.toString(); + const resource = this.resources.get(key); + if (resource) { + resource.observers = -1; + resource.pendingDeletion?.dispose(); + resource.listener.dispose(); + this.resources.delete(key); + } + } +} + +class WorkspaceFolderTestObserverFactory extends AbstractTestObserverFactory { + private diffListeners = new Map void>(); + + constructor(private readonly proxy: MainThreadTestingShape) { + super(); + } + + /** + * Publishees the diff for the workspace folder with the given uri. + */ + public acceptDiff(resourceUri: URI, diff: TestsDiff) { + this.diffListeners.get(resourceUri.toString())?.(diff); + } + + /** + * @override + */ + public listen(resourceUri: URI, onDiff: (diff: TestsDiff) => void) { + this.proxy.$subscribeToDiffs(ExtHostTestingResource.Workspace, resourceUri); + + const uriString = resourceUri.toString(); + this.diffListeners.set(uriString, onDiff); + + return new Disposable(() => { + this.proxy.$unsubscribeFromDiffs(ExtHostTestingResource.Workspace, resourceUri); + this.diffListeners.delete(uriString); + }); + } +} + +class TextDocumentTestObserverFactory extends AbstractTestObserverFactory { + private diffListeners = new Map void>(); + + constructor(private readonly proxy: MainThreadTestingShape, private documents: IExtHostDocumentsAndEditors) { + super(); + } + + /** + * Publishees the diff for the document with the given uri. + */ + public acceptDiff(resourceUri: URI, diff: TestsDiff) { + this.diffListeners.get(resourceUri.toString())?.(diff); + } + + /** + * @override + */ + public listen(resourceUri: URI, onDiff: (diff: TestsDiff) => void) { + const document = this.documents.getDocument(resourceUri); + if (!document) { + return new Disposable(() => undefined); + } + + const uriString = resourceUri.toString(); + this.diffListeners.set(uriString, onDiff); + + const disposeListener = this.documents.onDidRemoveDocuments(evt => { + if (evt.some(delta => delta.document.uri.toString() === uriString)) { + this.unlisten(resourceUri); + } + }); + + this.proxy.$subscribeToDiffs(ExtHostTestingResource.TextDocument, resourceUri); + return new Disposable(() => { + this.proxy.$unsubscribeFromDiffs(ExtHostTestingResource.TextDocument, resourceUri); + disposeListener.dispose(); + this.diffListeners.delete(uriString); + }); + } +} diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index f68ee495a27..e82a7c10759 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -32,6 +32,7 @@ import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions'; import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands'; import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook'; import { CellOutputKind, IDisplayOutput, INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ITestItem, ITestState } from 'vs/workbench/contrib/testing/common/testCollection'; export interface PositionLike { line: number; @@ -1396,3 +1397,64 @@ export namespace NotebookDecorationRenderOptions { }; } } + +export namespace TestState { + export function from(item: vscode.TestState): ITestState { + return { + runState: item.runState, + duration: item.duration, + messages: item.messages.map(message => ({ + message: MarkdownString.fromStrict(message.message) || '', + severity: message.severity, + expectedOutput: message.expectedOutput, + actualOutput: message.actualOutput, + location: message.location ? location.from(message.location) : undefined, + })), + }; + } + + export function to(item: ITestState): vscode.TestState { + return new types.TestState( + item.runState, + item.messages.map(message => ({ + message: typeof message.message === 'string' ? message.message : MarkdownString.to(message.message), + severity: message.severity, + expectedOutput: message.expectedOutput, + actualOutput: message.actualOutput, + location: message.location && location.to({ + range: message.location.range, + uri: URI.revive(message.location.uri) + }), + })), + item.duration, + ); + } +} + + +export namespace TestItem { + export function from(item: vscode.TestItem): ITestItem { + return { + label: item.label, + location: item.location ? location.from(item.location) : undefined, + debuggable: item.debuggable, + description: item.description, + runnable: item.runnable, + state: TestState.from(item.state), + }; + } + + export function to(item: ITestItem): vscode.TestItem { + return { + label: item.label, + location: item.location && location.to({ + range: item.location.range, + uri: URI.revive(item.location.uri) + }), + debuggable: item.debuggable, + description: item.description, + runnable: item.runnable, + state: TestState.to(item.state), + }; + } +} diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index f216ca35dcd..1013635962d 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2897,3 +2897,47 @@ export class OnTypeRenameRanges { constructor(public readonly ranges: Range[], public readonly wordPattern?: RegExp) { } } + +//#region Testing +export enum TestRunState { + Unset = 0, + Running = 1, + Passed = 2, + Failed = 3, + Skipped = 4, + Errored = 5 +} + +export enum TestMessageSeverity { + Error = 0, + Warning = 1, + Information = 2, + Hint = 3 +} + +@es5ClassCompat +export class TestState { + #runState: TestRunState; + #duration?: number; + #messages: ReadonlyArray>; + + public get runState() { + return this.#runState; + } + + public get duration() { + return this.#duration; + } + + public get messages() { + return this.#messages; + } + + constructor(runState: TestRunState, messages: vscode.TestMessage[] = [], duration?: number) { + this.#runState = runState; + this.#messages = Object.freeze(messages.map(m => Object.freeze(m))); + this.#duration = duration; + } +} + +//#endregion diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts new file mode 100644 index 00000000000..4e541bc83e8 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; +import { TestService } from 'vs/workbench/contrib/testing/common/testServiceImpl'; + +registerSingleton(ITestService, TestService); diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts new file mode 100644 index 00000000000..398294aaec3 --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -0,0 +1,197 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { URI } from 'vs/base/common/uri'; +import { Location as ModeLocation } from 'vs/editor/common/modes'; +import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; +import { TestMessageSeverity, TestRunState } from 'vs/workbench/api/common/extHostTypes'; + +/** + * Request to them main thread to run a set of tests. + */ +export interface RunTestsRequest { + tests: { testId: string; providerId: string }[]; + debug: boolean; +} + +/** + * Request from the main thread to run tests for a single provider. + */ +export interface RunTestForProviderRequest { + providerId: string; + ids: string[]; + debug: boolean; +} + +/** + * Response to a {@link RunTestsRequest} + */ +export interface RunTestsResult { + // todo +} + +export const EMPTY_TEST_RESULT: RunTestsResult = {}; + +export const collectTestResults = (results: ReadonlyArray) => { + return results[0] || {}; // todo +}; + +export interface ITestMessage { + message: string | IMarkdownString; + severity: TestMessageSeverity | undefined; + expectedOutput: string | undefined; + actualOutput: string | undefined; + location: ModeLocation | undefined; +} + +export interface ITestState { + runState: TestRunState; + duration: number | undefined; + messages: ITestMessage[]; +} + +/** + * The TestItem from .d.ts, as a plain object without children. + */ +export interface ITestItem { + label: string; + children?: never; + location: ModeLocation | undefined; + description: string | undefined; + runnable: boolean | undefined; + debuggable: boolean | undefined; + state: ITestState; +} + +/** + * TestItem-like shape, butm with an ID and children as strings. + */ +export interface InternalTestItem { + id: string; + providerId: string; + parent: string | null; + item: ITestItem; +} + +export const enum TestDiffOpType { + Add, + Update, + Remove, +} + +export type TestsDiffOp = + | [op: TestDiffOpType.Add, item: InternalTestItem] + | [op: TestDiffOpType.Update, item: InternalTestItem] + | [op: TestDiffOpType.Remove, itemId: string]; + +/** + * Utility function to get a unique string for a subscription to a resource, + * useful to keep maps of document or workspace folder subscription info. + */ +export const getTestSubscriptionKey = (resource: ExtHostTestingResource, uri: URI) => `${resource}:${uri.toString()}`; + +/** + * Request from the ext host or main thread to indicate that tests have + * changed. It's assumed that any item upserted *must* have its children + * previously also upserted, or upserted as part of the same operation. + * Children that no longer exist in an upserted item will be removed. + */ +export type TestsDiff = TestsDiffOp[]; + +/** + * @private + */ +export interface IncrementalTestCollectionItem extends InternalTestItem { + children: Set; +} + +/** + * Maintains tests in this extension host sent from the main thread. + */ +export abstract class AbstractIncrementalTestCollection { + /** + * Map of item IDs to test item objects. + */ + protected readonly items = new Map(); + + /** + * ID of test root items. + */ + protected readonly roots = new Set(); + + /** + * Applies the diff to the collection. + */ + public apply(diff: TestsDiff) { + for (const op of diff) { + switch (op[0]) { + case TestDiffOpType.Add: { + const item = op[1]; + if (!item.parent) { + this.roots.add(item.id); + this.items.set(item.id, this.createItem(item)); + this.onChange(null); + } else if (this.items.has(item.parent)) { + const parent = this.items.get(item.parent)!; + parent.children.add(item.id); + this.items.set(item.id, this.createItem(item)); + this.onChange(parent); + } + break; + } + + case TestDiffOpType.Update: { + const item = op[1]; + const existing = this.items.get(item.id); + if (existing) { + Object.assign(existing.item, item.item); + this.onChange(existing); + } + break; + } + + case TestDiffOpType.Remove: { + const toRemove = this.items.get(op[1]); + if (!toRemove) { + break; + } + + if (toRemove.parent) { + this.items.get(toRemove.parent)!.children.delete(toRemove.id); + } else { + this.roots.delete(toRemove.id); + } + + const queue: Iterable[] = [[op[1]]]; + while (queue.length) { + for (const itemId of queue.pop()!) { + const existing = this.items.get(itemId); + if (existing) { + queue.push(existing.children); + this.items.delete(itemId); + } + } + } + + this.onChange(toRemove); + } + } + } + } + + /** + * Called when an item in the collection changes, with the same semantics + * as `onDidChangeTests` in vscode.d.ts. + */ + protected onChange(item: T | null): void { + // no-op + } + + /** + * Creates a new item for the collection from the internal test item. + */ + protected abstract createItem(internal: InternalTestItem): T; +} diff --git a/src/vs/workbench/contrib/testing/common/testService.ts b/src/vs/workbench/contrib/testing/common/testService.ts new file mode 100644 index 00000000000..f4d84d583e0 --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/testService.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; +import { RunTestForProviderRequest, RunTestsRequest, RunTestsResult, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; + +export const ITestService = createDecorator('testService'); + +export interface MainTestController { + runTests(request: RunTestForProviderRequest): Promise; +} + +export type TestDiffListener = (diff: TestsDiff) => void; + +export interface ITestService { + readonly _serviceBrand: undefined; + readonly onShouldSubscribe: Event<{ resource: ExtHostTestingResource, uri: URI }>; + readonly onShouldUnsubscribe: Event<{ resource: ExtHostTestingResource, uri: URI }>; + registerTestController(id: string, controller: MainTestController): void; + unregisterTestController(id: string): void; + runTests(req: RunTestsRequest): Promise; + publishDiff(resource: ExtHostTestingResource, uri: URI, diff: TestsDiff): void; + subscribeToDiffs(resource: ExtHostTestingResource, uri: URI, acceptDiff: TestDiffListener): IDisposable; +} diff --git a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts new file mode 100644 index 00000000000..845534dd816 --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts @@ -0,0 +1,128 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { groupBy } from 'vs/base/common/arrays'; +import { Emitter } from 'vs/base/common/event'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { isDefined } from 'vs/base/common/types'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; +import { AbstractIncrementalTestCollection, collectTestResults, getTestSubscriptionKey, IncrementalTestCollectionItem, InternalTestItem, RunTestsRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestService, MainTestController, TestDiffListener } from 'vs/workbench/contrib/testing/common/testService'; + +export class TestService extends Disposable implements ITestService { + declare readonly _serviceBrand: undefined; + private testControllers = new Map(); + private readonly testSubscriptions = new Map; + listeners: number; + }>(); + private readonly subscribeEmitter = new Emitter<{ resource: ExtHostTestingResource, uri: URI }>(); + private readonly unsubscribeEmitter = new Emitter<{ resource: ExtHostTestingResource, uri: URI }>(); + + /** + * Fired when extension hosts should pull events from their test factories. + */ + public readonly onShouldSubscribe = this.subscribeEmitter.event; + + /** + * Fired when extension hosts should stop pulling events from their test factories. + */ + public readonly onShouldUnsubscribe = this.unsubscribeEmitter.event; + + /** + * @inheritdoc + */ + async runTests(req: RunTestsRequest): Promise { + const tests = groupBy(req.tests, (a, b) => a.providerId === b.providerId ? 0 : 1); + const requests = tests.map(group => { + const providerId = group[0].providerId; + const controller = this.testControllers.get(providerId); + return controller?.runTests({ providerId, debug: req.debug, ids: group.map(t => t.testId) }); + }).filter(isDefined); + + return collectTestResults(await Promise.all(requests)); + } + + /** + * @inheritdoc + */ + public subscribeToDiffs(resource: ExtHostTestingResource, uri: URI, acceptDiff: TestDiffListener) { + const subscriptionKey = getTestSubscriptionKey(resource, uri); + let subscription = this.testSubscriptions.get(subscriptionKey); + if (!subscription) { + subscription = { collection: new MainThreadTestCollection(), listeners: 0, onDiff: new Emitter() }; + this.subscribeEmitter.fire({ resource, uri }); + this.testSubscriptions.set(subscriptionKey, subscription); + } + + subscription.listeners++; + + const revive = subscription.collection.getReviverDiff(); + if (revive.length) { + acceptDiff(revive); + } + + const listener = subscription.onDiff.event(acceptDiff); + return toDisposable(() => { + listener.dispose(); + + if (!--subscription!.listeners) { + this.unsubscribeEmitter.fire({ resource, uri }); + this.testSubscriptions.delete(subscriptionKey); + } + }); + } + + /** + * @inheritdoc + */ + public publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff) { + const sub = this.testSubscriptions.get(getTestSubscriptionKey(resource, URI.revive(uri))); + if (sub) { + sub.collection.apply(diff); + sub.onDiff.fire(diff); + } + } + + /** + * @inheritdoc + */ + public registerTestController(id: string, controller: MainTestController): void { + this.testControllers.set(id, controller); + } + + /** + * @inheritdoc + */ + public unregisterTestController(id: string): void { + this.testControllers.delete(id); + } +} + +class MainThreadTestCollection extends AbstractIncrementalTestCollection { + /** + * Gets a diff that adds all items currently in the tree to a new collection, + * allowing it to fully hydrate. + */ + public getReviverDiff() { + const ops: TestsDiff = []; + const queue = [this.roots]; + while (queue.length) { + for (const child of queue.pop()!) { + const item = this.items.get(child)!; + ops.push([TestDiffOpType.Add, { id: item.id, providerId: item.providerId, item: item.item, parent: item.parent }]); + queue.push(item.children); + } + } + + return ops; + } + + protected createItem(internal: InternalTestItem): IncrementalTestCollectionItem { + return { ...internal, children: new Set() }; + } +} diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts new file mode 100644 index 00000000000..2c784c043d8 --- /dev/null +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -0,0 +1,200 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { MirroredTestCollection, OwnedTestCollection, SingleUseTestCollection } from 'vs/workbench/api/common/extHostTesting'; +import * as convert from 'vs/workbench/api/common/extHostTypeConverters'; +import { TestRunState, TestState } from 'vs/workbench/api/common/extHostTypes'; +import { TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestItem } from 'vscode'; + +suite('ExtHost Testing', () => { + let single: TestSingleUseCollection; + let owned: TestOwnedTestCollection; + setup(() => { + owned = new TestOwnedTestCollection(); + single = owned.createForHierarchy(d => single.setDiff(d /* don't clear during testing */)); + }); + + teardown(() => { + single.dispose(); + assert.deepEqual(owned.idToInternal.size, 0, 'expected owned ids to be empty after dispose'); + }); + + suite('OwnedTestCollection', () => { + test('adds a root recursively', () => { + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + assert.deepStrictEqual(single.collectDiff(), [ + [TestDiffOpType.Add, { id: '0', providerId: 'pid', parent: null, item: convert.TestItem.from(stubTest('root')) }], + [TestDiffOpType.Add, { id: '1', providerId: 'pid', parent: '0', item: convert.TestItem.from(stubTest('a')) }], + [TestDiffOpType.Add, { id: '2', providerId: 'pid', parent: '1', item: convert.TestItem.from(stubTest('aa')) }], + [TestDiffOpType.Add, { id: '3', providerId: 'pid', parent: '1', item: convert.TestItem.from(stubTest('ab')) }], + [TestDiffOpType.Add, { id: '4', providerId: 'pid', parent: '0', item: convert.TestItem.from(stubTest('b')) }], + ]); + }); + + test('no-ops if items not changed', () => { + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + single.collectDiff(); + assert.deepStrictEqual(single.collectDiff(), []); + }); + + test('watches property mutations', () => { + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + single.collectDiff(); + tests.children![0].description = 'Hello world'; /* item a */ + single.onItemChange(tests, 'pid'); + assert.deepStrictEqual(single.collectDiff(), [ + [TestDiffOpType.Update, { id: '1', parent: '0', providerId: 'pid', item: convert.TestItem.from({ ...stubTest('a'), description: 'Hello world' }) }], + ]); + + single.onItemChange(tests, 'pid'); + assert.deepStrictEqual(single.collectDiff(), []); + }); + + test('removes children', () => { + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + single.collectDiff(); + tests.children!.splice(0, 1); + single.onItemChange(tests, 'pid'); + + assert.deepStrictEqual(single.collectDiff(), [ + [TestDiffOpType.Remove, '1'], + ]); + assert.deepStrictEqual([...owned.idToInternal.keys()].sort(), ['0', '4']); + assert.strictEqual(single.itemToInternal.size, 2); + }); + + test('adds new children', () => { + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + single.collectDiff(); + const child = stubTest('ac'); + tests.children![0].children!.push(child); + single.onItemChange(tests, 'pid'); + + assert.deepStrictEqual(single.collectDiff(), [ + [TestDiffOpType.Add, { id: '5', providerId: 'pid', parent: '1', item: convert.TestItem.from(child) }], + ]); + assert.deepStrictEqual([...owned.idToInternal.keys()].sort(), ['0', '1', '2', '3', '4', '5']); + assert.strictEqual(single.itemToInternal.size, 6); + }); + }); + + suite('MirroredTestCollection', () => { + test('mirrors creation of the root', () => { + const m = new TestMirroredCollection(); + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + m.apply(single.collectDiff()); + assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual); + assert.strictEqual(m.length, single.itemToInternal.size); + }); + + test('mirrors node deletion', () => { + const m = new TestMirroredCollection(); + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + m.apply(single.collectDiff()); + tests.children!.splice(0, 1); + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual); + assert.strictEqual(m.length, single.itemToInternal.size); + }); + + test('mirrors node addition', () => { + const m = new TestMirroredCollection(); + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + m.apply(single.collectDiff()); + tests.children![0].children!.push(stubTest('ac')); + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual); + assert.strictEqual(m.length, single.itemToInternal.size); + }); + + test('mirrors node update', () => { + const m = new TestMirroredCollection(); + const tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + m.apply(single.collectDiff()); + tests.children![0].description = 'Hello world'; /* item a */ + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual); + }); + }); +}); + +const stubTest = (label: string): TestItem => ({ + label, + location: undefined, + state: new TestState(TestRunState.Unset), + debuggable: true, + runnable: true, + description: '' +}); + +const assertTreesEqual = (a: TestItem, b: TestItem) => { + assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); + + const aChildren = (a.children ?? []).sort(); + const bChildren = (b.children ?? []).sort(); + assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`); + aChildren.forEach((_, i) => assertTreesEqual(aChildren[i], bChildren[i])); +}; + +const stubNestedTests = () => ({ + ...stubTest('root'), + children: [ + { ...stubTest('a'), children: [stubTest('aa'), stubTest('ab')] }, + stubTest('b'), + ] +}); + +class TestOwnedTestCollection extends OwnedTestCollection { + public get idToInternal() { + return this.testIdToInternal; + } + + public createForHierarchy(publishDiff: (diff: TestsDiff) => void = () => undefined) { + return new TestSingleUseCollection(this.testIdToInternal, publishDiff); + } +} + +class TestSingleUseCollection extends SingleUseTestCollection { + private idCounter = 0; + + public get itemToInternal() { + return this.testItemToInternal; + } + + public get currentDiff() { + return this.diff; + } + + protected getId() { + return String(this.idCounter++); + } + + public setDiff(diff: TestsDiff) { + this.diff = diff; + } +} + +class TestMirroredCollection extends MirroredTestCollection { + public get length() { + return this.items.size; + } +} diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index c5dc396505a..a91d88311ed 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -156,6 +156,9 @@ import 'vs/workbench/contrib/performance/browser/performance.contribution'; // Notebook import 'vs/workbench/contrib/notebook/browser/notebook.contribution'; +// Testing +import 'vs/workbench/contrib/testing/browser/testing.contribution'; + // Logs import 'vs/workbench/contrib/logs/common/logs.contribution'; From 4b5dc2fcbc2d6b33064fe36081d485558982d127 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Nov 2020 18:00:31 +0100 Subject: [PATCH 0091/1837] WorkspaceFileEditOptions add maxSize --- src/vs/editor/common/modes.ts | 1 + src/vs/monaco.d.ts | 1 + .../contrib/bulkEdit/browser/bulkFileEdits.ts | 12 ++++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 5a74bd1613e..31e7c8b48da 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1387,6 +1387,7 @@ export interface WorkspaceFileEditOptions { recursive?: boolean; copy?: boolean; folder?: boolean; + maxSize?: number; } export interface WorkspaceFileEdit { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 529e1fe793a..822389c5910 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -6262,6 +6262,7 @@ declare namespace monaco.languages { recursive?: boolean; copy?: boolean; folder?: boolean; + maxSize?: number; } export interface WorkspaceFileEdit { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index b2840faac3c..47cfebcb1bf 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -5,7 +5,7 @@ import { WorkspaceFileEditOptions } from 'vs/editor/common/modes'; -import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; +import { IFileService, FileSystemProviderCapabilities, IFileContent } from 'vs/platform/files/common/files'; import { IProgress } from 'vs/platform/progress/common/progress'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; @@ -163,10 +163,10 @@ class DeleteOperation implements IFileOperation { return new Noop(); } - let contents: VSBuffer | undefined; + let fileContent: IFileContent | undefined; if (!this._undoesCreateOperation && !this.options.folder) { try { - contents = (await this._fileService.readFile(this.oldUri)).value; + fileContent = (await this._fileService.readFile(this.oldUri)); } catch (err) { this._logService.critical(err); } @@ -174,7 +174,11 @@ class DeleteOperation implements IFileOperation { const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }); - return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, { isUndoing: true }, contents); + + if (typeof this.options.maxSize === 'number' && fileContent && (fileContent?.size > this.options.maxSize)) { + return new Noop(); + } + return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, { isUndoing: true }, fileContent?.value); } toString(): string { From 8cf97fefd90b916038b9c178023b4dd04f852b43 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 13:47:37 -0800 Subject: [PATCH 0092/1837] trust notebook prep --- src/vs/vscode.proposed.d.ts | 6 + .../browser/view/renderers/cellRenderer.ts | 3 +- .../browser/view/renderers/cellWidgets.ts | 91 ++++++++++ .../browser/view/renderers/codeCell.ts | 168 +++++++++--------- .../view/renderers/commonViewComponents.ts | 26 --- .../browser/view/renderers/sizeObserver.ts | 78 -------- .../contrib/notebook/common/notebookCommon.ts | 4 +- 7 files changed, 188 insertions(+), 188 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents.ts delete mode 100644 src/vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver.ts diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 1b4dd21140a..ad93c03af92 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1415,6 +1415,12 @@ declare module 'vscode' { * The document's current run state */ runState?: NotebookRunState; + + /** + * Whether the document is trusted, default to true + * When false, insecure outputs like HTML, JavaScript, SVG will not be rendered. + */ + trusted?: boolean; } export interface NotebookDocumentContentOptions { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 1cf9a98feca..eb9c749c863 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -40,9 +40,8 @@ import { CancelCellAction, DeleteCellAction, ExecuteCellAction, INotebookCellAct import { BaseCellRenderTemplate, CellEditState, CodeCellRenderTemplate, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys'; import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; -import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { CellEditorStatusBar, CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell'; -import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents'; import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/dnd'; import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index b2e75e106af..e9948b1da53 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { renderCodicons } from 'vs/base/browser/codicons'; import * as DOM from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; @@ -13,10 +14,15 @@ import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { extUri } from 'vs/base/common/resources'; +import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; +import { IDimension } from 'vs/editor/common/editorCommon'; import { IModeService } from 'vs/editor/common/services/modeService'; import { localize } from 'vs/nls'; +import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { MenuItemAction } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ChangeCellLanguageAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; @@ -24,6 +30,7 @@ import { ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/b import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon'; + const $ = DOM.$; export interface IClickTarget { @@ -253,3 +260,87 @@ export class CellLanguageStatusBarItem extends Disposable { this.labelElement.title = localize('notebook.cell.status.language', "Select Cell Language Mode"); } } + +export class CodiconActionViewItem extends MenuEntryActionViewItem { + constructor( + readonly _action: MenuItemAction, + keybindingService: IKeybindingService, + notificationService: INotificationService, + ) { + super(_action, keybindingService, notificationService); + } + updateLabel(): void { + if (this.options.label && this.label) { + DOM.reset(this.label, ...renderCodicons(this._commandAction.label ?? '')); + } + } +} + +declare const ResizeObserver: any; + +export interface IResizeObserver { + startObserving: () => void; + stopObserving: () => void; + getWidth(): number; + getHeight(): number; + dispose(): void; +} + +export class BrowserResizeObserver extends Disposable implements IResizeObserver { + private readonly referenceDomElement: HTMLElement | null; + + private readonly observer: any; + private width: number; + private height: number; + + constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) { + super(); + + this.referenceDomElement = referenceDomElement; + this.width = -1; + this.height = -1; + + this.observer = new ResizeObserver((entries: any) => { + for (const entry of entries) { + if (entry.target === referenceDomElement && entry.contentRect) { + if (this.width !== entry.contentRect.width || this.height !== entry.contentRect.height) { + this.width = entry.contentRect.width; + this.height = entry.contentRect.height; + DOM.scheduleAtNextAnimationFrame(() => { + changeCallback(); + }); + } + } + } + }); + } + + getWidth(): number { + return this.width; + } + + getHeight(): number { + return this.height; + } + + startObserving(): void { + this.observer.observe(this.referenceDomElement!); + } + + stopObserving(): void { + this.observer.unobserve(this.referenceDomElement!); + } + + dispose(): void { + this.observer.disconnect(); + super.dispose(); + } +} + +export function getResizesObserver(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void): IResizeObserver { + if (ResizeObserver) { + return new BrowserResizeObserver(referenceDomElement, dimension, changeCallback); + } else { + return new ElementSizeObserver(referenceDomElement, dimension, changeCallback); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 4ffd99ae1d9..0aa67f930ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -21,12 +21,11 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { BUILTIN_RENDERER_ID, CellOutputKind, CellUri, IInsetRenderOutput, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, outputHasDynamicHeight, RENDERER_NOT_AVAILABLE, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { BUILTIN_RENDERER_ID, CellOutputKind, CellUri, IInsetRenderOutput, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, NotebookCellOutputsSplice, outputHasDynamicHeight, RENDERER_NOT_AVAILABLE, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { ClickTargetType, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; const OUTPUT_COUNT_LIMIT = 500; interface IMimeTypeRenderer extends IQuickPickItem { @@ -365,76 +364,6 @@ export class CodeCell extends Disposable { } })); - this._register(viewCell.onDidChangeOutputs((splices) => { - if (!splices.length) { - return; - } - - const previousOutputHeight = this.viewCell.layoutInfo.outputTotalHeight; - - if (this.viewCell.outputs.length) { - this.templateData.outputContainer!.style.display = 'block'; - } else { - this.templateData.outputContainer!.style.display = 'none'; - } - - const reversedSplices = splices.reverse(); - - reversedSplices.forEach(splice => { - viewCell.spliceOutputHeights(splice[0], splice[1], splice[2].map(_ => 0)); - }); - - const removedKeys: IProcessedOutput[] = []; - - this.outputEntries.forEach((value, key) => { - if (viewCell.outputs.indexOf(key) < 0) { - // already removed - removedKeys.push(key); - // remove element from DOM - this.templateData?.outputContainer?.removeChild(value.domNode); - this.notebookEditor.removeInset(key); - } - }); - - removedKeys.forEach(key => { - this.outputEntries.get(key)?.dispose(); - this.outputEntries.delete(key); - }); - - let prevElement: HTMLElement | undefined = undefined; - const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); - - outputsToRender.reverse().forEach(output => { - if (this.outputEntries.has(output)) { - // already exist - prevElement = this.outputEntries.get(output)!.domNode; - return; - } - - // newly added element - const currIndex = this.viewCell.outputs.indexOf(output); - this.renderOutput(output, currIndex, prevElement); - prevElement = this.outputEntries.get(output)?.domNode; - }); - - if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { - this.templateData.outputShowMoreContainer.style.display = 'block'; - this.viewCell.updateOutputShowMoreContainerHeight(46); - } else { - this.templateData.outputShowMoreContainer.style.display = 'none'; - } - - const editorHeight = templateData.editor!.getContentHeight(); - viewCell.editorHeight = editorHeight; - - if (previousOutputHeight === 0 || this.viewCell.outputs.length === 0) { - // first execution or removing all outputs - this.relayoutCell(); - } else { - this.relayoutCellDebounced(); - } - })); - this._register(viewCell.onDidChangeLayout(() => { this.outputEntries.forEach((value, key) => { const index = viewCell.outputs.indexOf(key); @@ -446,6 +375,7 @@ export class CodeCell extends Disposable { })); + // Apply decorations this._register(viewCell.onCellDecorationsChanged((e) => { e.added.forEach(options => { if (options.className) { @@ -467,7 +397,6 @@ export class CodeCell extends Disposable { } }); })); - // apply decorations viewCell.getCellDecorations().forEach(options => { if (options.className) { @@ -479,6 +408,7 @@ export class CodeCell extends Disposable { } }); + // Mouse click handlers this._register(templateData.statusBar.onDidClick(e => { if (e.type !== ClickTargetType.ContributedItem) { const target = templateData.editor.getTargetAtClientPoint(e.event.clientX, e.event.clientY - viewCell.getEditorStatusbarHeight()); @@ -497,11 +427,11 @@ export class CodeCell extends Disposable { } })); + // Focus Mode const updateFocusMode = () => viewCell.focusMode = templateData.editor!.hasWidgetFocus() ? CellFocusMode.Editor : CellFocusMode.Container; this._register(templateData.editor!.onDidFocusEditorWidget(() => { updateFocusMode(); })); - this._register(templateData.editor!.onDidBlurEditorWidget(() => { // this is for a special case: // users click the status bar empty space, which we will then focus the editor @@ -514,10 +444,19 @@ export class CodeCell extends Disposable { updateFocusMode(); } })); - updateFocusMode(); - if (viewCell.outputs.length > 0) { + // Render Outputs + this.renderOutputs(editorHeight); + this._register(viewCell.onDidChangeOutputs((splices) => { + this.updateOutputs(splices); + })); + // Need to do this after the intial renderOutput + updateForCollapseState(); + } + + renderOutputs(editorHeight: number) { + if (this.viewCell.outputs.length > 0) { let layoutCache = false; if (this.viewCell.layoutInfo.totalHeight !== 0 && this.viewCell.layoutInfo.editorHeight > editorHeight) { layoutCache = true; @@ -535,7 +474,7 @@ export class CodeCell extends Disposable { this.renderOutput(currOutput, index, undefined); } - viewCell.editorHeight = editorHeight; + this.viewCell.editorHeight = editorHeight; if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { this.templateData.outputShowMoreContainer.style.display = 'block'; this.viewCell.updateOutputShowMoreContainerHeight(46); @@ -548,7 +487,7 @@ export class CodeCell extends Disposable { } } else { // noop - viewCell.editorHeight = editorHeight; + this.viewCell.editorHeight = editorHeight; this.relayoutCell(); this.templateData.outputContainer!.style.display = 'none'; } @@ -561,9 +500,76 @@ export class CodeCell extends Disposable { this.templateData.outputShowMoreContainer.style.display = 'none'; this.viewCell.updateOutputShowMoreContainerHeight(0); } + } - // Need to do this after the intial renderOutput - updateForCollapseState(); + updateOutputs(splices: NotebookCellOutputsSplice[]) { + if (!splices.length) { + return; + } + + const previousOutputHeight = this.viewCell.layoutInfo.outputTotalHeight; + + if (this.viewCell.outputs.length) { + this.templateData.outputContainer!.style.display = 'block'; + } else { + this.templateData.outputContainer!.style.display = 'none'; + } + + const reversedSplices = splices.reverse(); + + reversedSplices.forEach(splice => { + this.viewCell.spliceOutputHeights(splice[0], splice[1], splice[2].map(_ => 0)); + }); + + const removedKeys: IProcessedOutput[] = []; + + this.outputEntries.forEach((value, key) => { + if (this.viewCell.outputs.indexOf(key) < 0) { + // already removed + removedKeys.push(key); + // remove element from DOM + this.templateData?.outputContainer?.removeChild(value.domNode); + this.notebookEditor.removeInset(key); + } + }); + + removedKeys.forEach(key => { + this.outputEntries.get(key)?.dispose(); + this.outputEntries.delete(key); + }); + + let prevElement: HTMLElement | undefined = undefined; + const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + + outputsToRender.reverse().forEach(output => { + if (this.outputEntries.has(output)) { + // already exist + prevElement = this.outputEntries.get(output)!.domNode; + return; + } + + // newly added element + const currIndex = this.viewCell.outputs.indexOf(output); + this.renderOutput(output, currIndex, prevElement); + prevElement = this.outputEntries.get(output)?.domNode; + }); + + if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { + this.templateData.outputShowMoreContainer.style.display = 'block'; + this.viewCell.updateOutputShowMoreContainerHeight(46); + } else { + this.templateData.outputShowMoreContainer.style.display = 'none'; + } + + const editorHeight = this.templateData.editor!.getContentHeight(); + this.viewCell.editorHeight = editorHeight; + + if (previousOutputHeight === 0 || this.viewCell.outputs.length === 0) { + // first execution or removing all outputs + this.relayoutCell(); + } else { + this.relayoutCellDebounced(); + } } generateShowMoreElement(): any { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents.ts deleted file mode 100644 index 4b5002ebc8d..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as DOM from 'vs/base/browser/dom'; -import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { MenuItemAction } from 'vs/platform/actions/common/actions'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { renderCodicons } from 'vs/base/browser/codicons'; - -export class CodiconActionViewItem extends MenuEntryActionViewItem { - constructor( - readonly _action: MenuItemAction, - keybindingService: IKeybindingService, - notificationService: INotificationService, - ) { - super(_action, keybindingService, notificationService); - } - updateLabel(): void { - if (this.options.label && this.label) { - DOM.reset(this.label, ...renderCodicons(this._commandAction.label ?? '')); - } - } -} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver.ts deleted file mode 100644 index d9be462c054..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver.ts +++ /dev/null @@ -1,78 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as DOM from 'vs/base/browser/dom'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IDimension } from 'vs/editor/common/editorCommon'; -import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; - -declare const ResizeObserver: any; - -export interface IResizeObserver { - startObserving: () => void; - stopObserving: () => void; - getWidth(): number; - getHeight(): number; - dispose(): void; -} - -export class BrowserResizeObserver extends Disposable implements IResizeObserver { - private readonly referenceDomElement: HTMLElement | null; - - private readonly observer: any; - private width: number; - private height: number; - - constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) { - super(); - - this.referenceDomElement = referenceDomElement; - this.width = -1; - this.height = -1; - - this.observer = new ResizeObserver((entries: any) => { - for (const entry of entries) { - if (entry.target === referenceDomElement && entry.contentRect) { - if (this.width !== entry.contentRect.width || this.height !== entry.contentRect.height) { - this.width = entry.contentRect.width; - this.height = entry.contentRect.height; - DOM.scheduleAtNextAnimationFrame(() => { - changeCallback(); - }); - } - } - } - }); - } - - getWidth(): number { - return this.width; - } - - getHeight(): number { - return this.height; - } - - startObserving(): void { - this.observer.observe(this.referenceDomElement!); - } - - stopObserving(): void { - this.observer.unobserve(this.referenceDomElement!); - } - - dispose(): void { - this.observer.disconnect(); - super.dispose(); - } -} - -export function getResizesObserver(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void): IResizeObserver { - if (ResizeObserver) { - return new BrowserResizeObserver(referenceDomElement, dimension, changeCallback); - } else { - return new ElementSizeObserver(referenceDomElement, dimension, changeCallback); - } -} diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index f0e6804ea71..4f89dbc2e5c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -73,7 +73,8 @@ export const notebookDocumentMetadataDefaults: Required Date: Thu, 19 Nov 2020 13:50:19 -0800 Subject: [PATCH 0093/1837] merge cell action view --- .../browser/view/renderers/cellActionView.ts | 27 ++++++++++++++++--- .../browser/view/renderers/cellRenderer.ts | 4 +-- .../browser/view/renderers/cellWidgets.ts | 19 ------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts index 2e698f1ed4a..3ded6bb42b2 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts @@ -3,10 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Action, IAction, Separator } from 'vs/base/common/actions'; -import { IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; -import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { renderCodicons } from 'vs/base/browser/codicons'; +import * as DOM from 'vs/base/browser/dom'; import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { INotificationService } from 'vs/platform/notification/common/notification'; export class VerticalSeparator extends Action { static readonly ID = 'vs.actions.verticalSeparator'; @@ -74,3 +79,19 @@ function asDisposable(groups: ReadonlyArray<[string, ReadonlyArray Date: Thu, 19 Nov 2020 13:50:43 -0800 Subject: [PATCH 0094/1837] cellDnd --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 2 +- .../notebook/browser/view/renderers/{dnd.ts => cellDnd.ts} | 0 .../contrib/notebook/browser/view/renderers/cellRenderer.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/vs/workbench/contrib/notebook/browser/view/renderers/{dnd.ts => cellDnd.ts} (100%) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 4c327a9b74f..57e49098cda 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -50,7 +50,7 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys'; import { CodeCellRenderer, ListTopCellToolbar, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer'; -import { CellDragAndDropController } from 'vs/workbench/contrib/notebook/browser/view/renderers/dnd'; +import { CellDragAndDropController } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellDnd'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/dnd.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts similarity index 100% rename from src/vs/workbench/contrib/notebook/browser/view/renderers/dnd.ts rename to src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 370de7d0107..907da4cd74d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -42,7 +42,7 @@ import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/vie import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell'; -import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/dnd'; +import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellDnd'; import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; From efea77ab7c6929581d3fef8719df93fb7fe5305c Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 14:25:52 -0800 Subject: [PATCH 0095/1837] move cell output element to its own module --- .../browser/view/renderers/cellOutput.ts | 237 ++++++++++++++++++ .../browser/view/renderers/codeCell.ts | 230 +---------------- 2 files changed, 241 insertions(+), 226 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts new file mode 100644 index 00000000000..c9d4f7fe76f --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -0,0 +1,237 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as DOM from 'vs/base/browser/dom'; +import * as nls from 'vs/nls'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; +import { ITransformedDisplayOutputDto, IRenderOutput, IProcessedOutput, RENDERER_NOT_AVAILABLE, BUILTIN_RENDERER_ID, RenderOutputType, outputHasDynamicHeight, CellUri, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; + +interface IMimeTypeRenderer extends IQuickPickItem { + index: number; +} + +export class OutputElement extends Disposable { + + // this isn't super proper but I couldn't find a view-model equivalent for output + // and it seems as of today we use the domain model - and pragamtically enrich it + // with UX properties + private pickedMimeTypes = new WeakMap(); + + readonly resizeListener = new DisposableStore(); + domNode!: HTMLElement; + renderResult?: IRenderOutput; + + constructor( + private notebookEditor: INotebookEditor, + private notebookService: INotebookService, + private quickInputService: IQuickInputService, + private viewCell: CodeCellViewModel, + private outputContainer: HTMLElement, + readonly output: IProcessedOutput + ) { + super(); + } + + render(index: number, beforeElement?: HTMLElement) { + if (this.viewCell.metadata.outputCollapsed) { + return; + } + + const outputItemDiv = document.createElement('div'); + let result: IRenderOutput | undefined = undefined; + + if (this.output.outputKind === CellOutputKind.Rich) { + const transformedDisplayOutput = this.output as ITransformedDisplayOutputDto; + + const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output); + + const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE), 0); + + if (mimeTypes.length > 1) { + outputItemDiv.style.position = 'relative'; + const mimeTypePicker = DOM.$('.multi-mimetype-output'); + mimeTypePicker.classList.add('codicon', 'codicon-code'); + mimeTypePicker.tabIndex = 0; + mimeTypePicker.title = nls.localize('mimeTypePicker', "Choose a different output mimetype, available mimetypes: {0}", mimeTypes.map(mimeType => mimeType.mimeType).join(', ')); + outputItemDiv.appendChild(mimeTypePicker); + this.resizeListener.add(DOM.addStandardDisposableListener(mimeTypePicker, 'mousedown', async e => { + if (e.leftButton) { + e.preventDefault(); + e.stopPropagation(); + await this.pickActiveMimeTypeRenderer(transformedDisplayOutput); + } + })); + + this.resizeListener.add((DOM.addDisposableListener(mimeTypePicker, DOM.EventType.KEY_DOWN, async e => { + const event = new StandardKeyboardEvent(e); + if ((event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) { + e.preventDefault(); + e.stopPropagation(); + await this.pickActiveMimeTypeRenderer(transformedDisplayOutput); + } + }))); + + } + const pickedMimeTypeRenderer = mimeTypes[pick]; + + const innerContainer = DOM.$('.output-inner-container'); + DOM.append(outputItemDiv, innerContainer); + + + if (pickedMimeTypeRenderer.rendererId !== BUILTIN_RENDERER_ID) { + const renderer = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId); + result = renderer + ? { type: RenderOutputType.Extension, renderer, source: this.output, mimeType: pickedMimeTypeRenderer.mimeType } + : this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); + } else { + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); + } + } else { + // for text and error, there is no mimetype + const innerContainer = DOM.$('.output-inner-container'); + DOM.append(outputItemDiv, innerContainer); + + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.getNotebookUri(),); + } + + this.domNode = outputItemDiv; + this.renderResult = result; + + if (!result) { + this.viewCell.updateOutputHeight(index, 0); + return; + } + + if (beforeElement) { + this.outputContainer.insertBefore(outputItemDiv, beforeElement); + } else { + this.outputContainer.appendChild(outputItemDiv); + } + + if (result.type !== RenderOutputType.None) { + this.viewCell.selfSizeMonitoring = true; + this.notebookEditor.createInset(this.viewCell, result as any, this.viewCell.getOutputOffset(index)); + } else { + outputItemDiv.classList.add('foreground', 'output-element'); + outputItemDiv.style.position = 'absolute'; + } + + if (outputHasDynamicHeight(result)) { + this.viewCell.selfSizeMonitoring = true; + + const clientHeight = outputItemDiv.clientHeight; + const dimension = { + width: this.viewCell.layoutInfo.editorWidth, + height: clientHeight + }; + const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { + if (this.outputContainer && document.body.contains(this.outputContainer!)) { + const height = Math.ceil(elementSizeObserver.getHeight()); + + if (clientHeight === height) { + return; + } + + const currIndex = this.viewCell.outputs.indexOf(this.output); + if (currIndex < 0) { + return; + } + + this.viewCell.updateOutputHeight(currIndex, height); + this.relayoutCell(); + } + }); + elementSizeObserver.startObserving(); + this.resizeListener.add(elementSizeObserver); + this.viewCell.updateOutputHeight(index, clientHeight); + } else if (result.type === RenderOutputType.None) { // no-op if it's a webview + const clientHeight = Math.ceil(outputItemDiv.clientHeight); + this.viewCell.updateOutputHeight(index, clientHeight); + + const top = this.viewCell.getOutputOffsetInContainer(index); + outputItemDiv.style.top = `${top}px`; + } + } + + async pickActiveMimeTypeRenderer(output: ITransformedDisplayOutputDto) { + + const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, output); + const currIndex = this.pickedMimeTypes.get(output) ?? 0; + + // const currIndex = output.pickedMimeTypeIndex; + const items = mimeTypes.map((mimeType, index): IMimeTypeRenderer => ({ + label: mimeType.mimeType, + id: mimeType.mimeType, + index: index, + picked: index === currIndex, + detail: this.generateRendererInfo(mimeType.rendererId), + description: index === currIndex ? nls.localize('curruentActiveMimeType', "Currently Active") : undefined + })); + + const picker = this.quickInputService.createQuickPick(); + picker.items = items; + picker.activeItems = items.filter(item => !!item.picked); + picker.placeholder = nls.localize('promptChooseMimeType.placeHolder', "Select output mimetype to render for current output"); + + const pick = await new Promise(resolve => { + picker.onDidAccept(() => { + resolve(picker.selectedItems.length === 1 ? (picker.selectedItems[0] as IMimeTypeRenderer).index : undefined); + picker.dispose(); + }); + picker.show(); + }); + + if (pick === undefined) { + return; + } + + if (pick !== currIndex) { + // user chooses another mimetype + const index = this.viewCell.outputs.indexOf(output); + const nextElement = this.domNode.nextElementSibling; + this.resizeListener.clear(); + const element = this.domNode; + if (element) { + element.parentElement?.removeChild(element); + this.notebookEditor.removeInset(output); + } + + this.pickedMimeTypes.set(output, pick); + this.render(index, nextElement as HTMLElement); + this.relayoutCell(); + } + } + + private getNotebookUri(): URI | undefined { + return CellUri.parse(this.viewCell.uri)?.notebook; + } + + generateRendererInfo(renderId: string | undefined): string { + if (renderId === undefined || renderId === BUILTIN_RENDERER_ID) { + return nls.localize('builtinRenderInfo', "built-in"); + } + + const renderInfo = this.notebookService.getRendererInfo(renderId); + + if (renderInfo) { + const displayName = renderInfo.displayName !== '' ? renderInfo.displayName : renderInfo.id; + return `${displayName} (${renderInfo.extensionId.value})`; + } + + return nls.localize('builtinRenderInfo', "built-in"); + } + + relayoutCell() { + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 0aa67f930ae..1a86544302c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -4,249 +4,27 @@ *--------------------------------------------------------------------------------------------*/ import * as DOM from 'vs/base/browser/dom'; -import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IMarkdownString } from 'vs/base/common/htmlContent'; -import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { URI } from 'vs/base/common/uri'; import { IDimension } from 'vs/editor/common/editorCommon'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { IModeService } from 'vs/editor/common/services/modeService'; -import * as nls from 'vs/nls'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { BUILTIN_RENDERER_ID, CellOutputKind, CellUri, IInsetRenderOutput, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, NotebookCellOutputsSplice, outputHasDynamicHeight, RENDERER_NOT_AVAILABLE, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellOutputKind, IInsetRenderOutput, IProcessedOutput, NotebookCellOutputsSplice, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ClickTargetType, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { OutputElement } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; const OUTPUT_COUNT_LIMIT = 500; -interface IMimeTypeRenderer extends IQuickPickItem { - index: number; -} - -class OutputElement extends Disposable { - - // this isn't super proper but I couldn't find a view-model equivalent for output - // and it seems as of today we use the domain model - and pragamtically enrich it - // with UX properties - private pickedMimeTypes = new WeakMap(); - - readonly resizeListener = new DisposableStore(); - domNode!: HTMLElement; - renderResult?: IRenderOutput; - - constructor( - private notebookEditor: INotebookEditor, - private notebookService: INotebookService, - private quickInputService: IQuickInputService, - private viewCell: CodeCellViewModel, - private outputContainer: HTMLElement, - readonly output: IProcessedOutput - ) { - super(); - } - - render(index: number, beforeElement?: HTMLElement) { - if (this.viewCell.metadata.outputCollapsed) { - return; - } - - const outputItemDiv = document.createElement('div'); - let result: IRenderOutput | undefined = undefined; - - if (this.output.outputKind === CellOutputKind.Rich) { - const transformedDisplayOutput = this.output as ITransformedDisplayOutputDto; - - const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output); - - const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE), 0); - - if (mimeTypes.length > 1) { - outputItemDiv.style.position = 'relative'; - const mimeTypePicker = DOM.$('.multi-mimetype-output'); - mimeTypePicker.classList.add('codicon', 'codicon-code'); - mimeTypePicker.tabIndex = 0; - mimeTypePicker.title = nls.localize('mimeTypePicker', "Choose a different output mimetype, available mimetypes: {0}", mimeTypes.map(mimeType => mimeType.mimeType).join(', ')); - outputItemDiv.appendChild(mimeTypePicker); - this.resizeListener.add(DOM.addStandardDisposableListener(mimeTypePicker, 'mousedown', async e => { - if (e.leftButton) { - e.preventDefault(); - e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(transformedDisplayOutput); - } - })); - - this.resizeListener.add((DOM.addDisposableListener(mimeTypePicker, DOM.EventType.KEY_DOWN, async e => { - const event = new StandardKeyboardEvent(e); - if ((event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) { - e.preventDefault(); - e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(transformedDisplayOutput); - } - }))); - - } - const pickedMimeTypeRenderer = mimeTypes[pick]; - - const innerContainer = DOM.$('.output-inner-container'); - DOM.append(outputItemDiv, innerContainer); - - - if (pickedMimeTypeRenderer.rendererId !== BUILTIN_RENDERER_ID) { - const renderer = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId); - result = renderer - ? { type: RenderOutputType.Extension, renderer, source: this.output, mimeType: pickedMimeTypeRenderer.mimeType } - : this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); - } else { - result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); - } - } else { - // for text and error, there is no mimetype - const innerContainer = DOM.$('.output-inner-container'); - DOM.append(outputItemDiv, innerContainer); - - result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.getNotebookUri(),); - } - - this.domNode = outputItemDiv; - this.renderResult = result; - - if (!result) { - this.viewCell.updateOutputHeight(index, 0); - return; - } - - if (beforeElement) { - this.outputContainer.insertBefore(outputItemDiv, beforeElement); - } else { - this.outputContainer.appendChild(outputItemDiv); - } - - if (result.type !== RenderOutputType.None) { - this.viewCell.selfSizeMonitoring = true; - this.notebookEditor.createInset(this.viewCell, result as any, this.viewCell.getOutputOffset(index)); - } else { - outputItemDiv.classList.add('foreground', 'output-element'); - outputItemDiv.style.position = 'absolute'; - } - - if (outputHasDynamicHeight(result)) { - this.viewCell.selfSizeMonitoring = true; - - const clientHeight = outputItemDiv.clientHeight; - const dimension = { - width: this.viewCell.layoutInfo.editorWidth, - height: clientHeight - }; - const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { - if (this.outputContainer && document.body.contains(this.outputContainer!)) { - const height = Math.ceil(elementSizeObserver.getHeight()); - - if (clientHeight === height) { - return; - } - - const currIndex = this.viewCell.outputs.indexOf(this.output); - if (currIndex < 0) { - return; - } - - this.viewCell.updateOutputHeight(currIndex, height); - this.relayoutCell(); - } - }); - elementSizeObserver.startObserving(); - this.resizeListener.add(elementSizeObserver); - this.viewCell.updateOutputHeight(index, clientHeight); - } else if (result.type === RenderOutputType.None) { // no-op if it's a webview - const clientHeight = Math.ceil(outputItemDiv.clientHeight); - this.viewCell.updateOutputHeight(index, clientHeight); - - const top = this.viewCell.getOutputOffsetInContainer(index); - outputItemDiv.style.top = `${top}px`; - } - } - - async pickActiveMimeTypeRenderer(output: ITransformedDisplayOutputDto) { - - const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, output); - const currIndex = this.pickedMimeTypes.get(output) ?? 0; - - // const currIndex = output.pickedMimeTypeIndex; - const items = mimeTypes.map((mimeType, index): IMimeTypeRenderer => ({ - label: mimeType.mimeType, - id: mimeType.mimeType, - index: index, - picked: index === currIndex, - detail: this.generateRendererInfo(mimeType.rendererId), - description: index === currIndex ? nls.localize('curruentActiveMimeType', "Currently Active") : undefined - })); - - const picker = this.quickInputService.createQuickPick(); - picker.items = items; - picker.activeItems = items.filter(item => !!item.picked); - picker.placeholder = nls.localize('promptChooseMimeType.placeHolder', "Select output mimetype to render for current output"); - - const pick = await new Promise(resolve => { - picker.onDidAccept(() => { - resolve(picker.selectedItems.length === 1 ? (picker.selectedItems[0] as IMimeTypeRenderer).index : undefined); - picker.dispose(); - }); - picker.show(); - }); - - if (pick === undefined) { - return; - } - - if (pick !== currIndex) { - // user chooses another mimetype - const index = this.viewCell.outputs.indexOf(output); - const nextElement = this.domNode.nextElementSibling; - this.resizeListener.clear(); - const element = this.domNode; - if (element) { - element.parentElement?.removeChild(element); - this.notebookEditor.removeInset(output); - } - - this.pickedMimeTypes.set(output, pick); - this.render(index, nextElement as HTMLElement); - this.relayoutCell(); - } - } - - private getNotebookUri(): URI | undefined { - return CellUri.parse(this.viewCell.uri)?.notebook; - } - - generateRendererInfo(renderId: string | undefined): string { - if (renderId === undefined || renderId === BUILTIN_RENDERER_ID) { - return nls.localize('builtinRenderInfo', "built-in"); - } - - const renderInfo = this.notebookService.getRendererInfo(renderId); - - if (renderInfo) { - const displayName = renderInfo.displayName !== '' ? renderInfo.displayName : renderInfo.id; - return `${displayName} (${renderInfo.extensionId.value})`; - } - - return nls.localize('builtinRenderInfo', "built-in"); - } - - relayoutCell() { - this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); - } -} export class CodeCell extends Disposable { private outputEntries = new Map(); From fc98345ba16151ac839adc2be12d202b908964a9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 14:44:50 -0800 Subject: [PATCH 0096/1837] Extract output container renderer --- .../notebook/browser/diff/cellComponents.ts | 2 +- .../browser/view/renderers/cellOutput.ts | 287 +++++++++++++++++- .../browser/view/renderers/codeCell.ts | 267 +--------------- .../browser/view/renderers/markdownCell.ts | 2 +- 4 files changed, 300 insertions(+), 258 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 0529dcd0915..098838e7112 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -22,12 +22,12 @@ import { hash } from 'vs/base/common/hash'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; -import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; const fixedEditorOptions: IEditorOptions = { padding: { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index c9d4f7fe76f..4e2cc304e32 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -10,11 +10,19 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { ITransformedDisplayOutputDto, IRenderOutput, IProcessedOutput, RENDERER_NOT_AVAILABLE, BUILTIN_RENDERER_ID, RenderOutputType, outputHasDynamicHeight, CellUri, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ITransformedDisplayOutputDto, IRenderOutput, IProcessedOutput, RENDERER_NOT_AVAILABLE, BUILTIN_RENDERER_ID, RenderOutputType, outputHasDynamicHeight, CellUri, CellOutputKind, NotebookCellOutputsSplice, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { format } from 'vs/base/common/jsonFormatter'; +import { applyEdits } from 'vs/base/common/jsonEdit'; + +const OUTPUT_COUNT_LIMIT = 500; interface IMimeTypeRenderer extends IQuickPickItem { index: number; @@ -235,3 +243,278 @@ export class OutputElement extends Disposable { this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); } } + +export class OutputContainer extends Disposable { + private outputEntries = new Map(); + + constructor( + private notebookEditor: INotebookEditor, + private viewCell: CodeCellViewModel, + private templateData: CodeCellRenderTemplate, + @INotebookService private notebookService: INotebookService, + @IQuickInputService private readonly quickInputService: IQuickInputService, + @IOpenerService readonly openerService: IOpenerService, + @ITextFileService readonly textFileService: ITextFileService, + ) { + super(); + + this._register(viewCell.onDidChangeOutputs(splices => { + this._updateOutputs(splices); + })); + + this._register(viewCell.onDidChangeLayout(() => { + this.outputEntries.forEach((value, key) => { + const index = viewCell.outputs.indexOf(key); + if (index >= 0) { + const top = this.viewCell.getOutputOffsetInContainer(index); + value.domNode.style.top = `${top}px`; + } + }); + })); + } + + render(editorHeight: number) { + if (this.viewCell.outputs.length > 0) { + let layoutCache = false; + if (this.viewCell.layoutInfo.totalHeight !== 0 && this.viewCell.layoutInfo.editorHeight > editorHeight) { + layoutCache = true; + this._relayoutCell(); + } + + this.templateData.outputContainer!.style.display = 'block'; + // there are outputs, we need to calcualte their sizes and trigger relayout + // @TODO@rebornix, if there is no resizable output, we should not check their height individually, which hurts the performance + const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + for (let index = 0; index < outputsToRender.length; index++) { + const currOutput = this.viewCell.outputs[index]; + + // always add to the end + this._renderOutput(currOutput, index, undefined); + } + + this.viewCell.editorHeight = editorHeight; + if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { + this.templateData.outputShowMoreContainer.style.display = 'block'; + this.viewCell.updateOutputShowMoreContainerHeight(46); + } + + if (layoutCache) { + this._relayoutCellDebounced(); + } else { + this._relayoutCell(); + } + } else { + // noop + this.viewCell.editorHeight = editorHeight; + this._relayoutCell(); + this.templateData.outputContainer!.style.display = 'none'; + } + + this.templateData.outputShowMoreContainer.innerText = ''; + this.templateData.outputShowMoreContainer.appendChild(this._generateShowMoreElement()); + // this.templateData.outputShowMoreContainer.style.top = `${this.viewCell.layoutInfo.outputShowMoreContainerOffset}px`; + + if (this.viewCell.outputs.length < OUTPUT_COUNT_LIMIT) { + this.templateData.outputShowMoreContainer.style.display = 'none'; + this.viewCell.updateOutputShowMoreContainerHeight(0); + } + } + + viewUpdateShowOutputs(): void { + for (let index = 0; index < this.viewCell.outputs.length; index++) { + const currOutput = this.viewCell.outputs[index]; + + const renderedOutput = this.outputEntries.get(currOutput); + if (renderedOutput && renderedOutput.renderResult) { + if (renderedOutput.renderResult.type !== RenderOutputType.None) { + this.notebookEditor.createInset(this.viewCell, renderedOutput.renderResult as IInsetRenderOutput, this.viewCell.getOutputOffset(index)); + } else { + // Anything else, just update the height + this.viewCell.updateOutputHeight(index, renderedOutput.domNode.clientHeight); + } + } else { + // Wasn't previously rendered, render it now + this._renderOutput(currOutput, index); + } + } + + this._relayoutCell(); + } + + viewUpdateHideOuputs(): void { + for (const e of this.outputEntries.keys()) { + this.notebookEditor.hideInset(e); + } + } + + onCellWidthChange(): void { + this.viewCell.outputs.forEach((o, i) => { + const renderedOutput = this.outputEntries.get(o); + if (renderedOutput && renderedOutput.renderResult && renderedOutput.renderResult.type === RenderOutputType.None && !renderedOutput.renderResult.hasDynamicHeight) { + this.viewCell.updateOutputHeight(i, renderedOutput.domNode.clientHeight); + } + }); + } + + private _updateOutputs(splices: NotebookCellOutputsSplice[]) { + if (!splices.length) { + return; + } + + const previousOutputHeight = this.viewCell.layoutInfo.outputTotalHeight; + + if (this.viewCell.outputs.length) { + this.templateData.outputContainer!.style.display = 'block'; + } else { + this.templateData.outputContainer!.style.display = 'none'; + } + + const reversedSplices = splices.reverse(); + + reversedSplices.forEach(splice => { + this.viewCell.spliceOutputHeights(splice[0], splice[1], splice[2].map(_ => 0)); + }); + + const removedKeys: IProcessedOutput[] = []; + + this.outputEntries.forEach((value, key) => { + if (this.viewCell.outputs.indexOf(key) < 0) { + // already removed + removedKeys.push(key); + // remove element from DOM + this.templateData?.outputContainer?.removeChild(value.domNode); + this.notebookEditor.removeInset(key); + } + }); + + removedKeys.forEach(key => { + this.outputEntries.get(key)?.dispose(); + this.outputEntries.delete(key); + }); + + let prevElement: HTMLElement | undefined = undefined; + const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + + outputsToRender.reverse().forEach(output => { + if (this.outputEntries.has(output)) { + // already exist + prevElement = this.outputEntries.get(output)!.domNode; + return; + } + + // newly added element + const currIndex = this.viewCell.outputs.indexOf(output); + this._renderOutput(output, currIndex, prevElement); + prevElement = this.outputEntries.get(output)?.domNode; + }); + + if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { + this.templateData.outputShowMoreContainer.style.display = 'block'; + this.viewCell.updateOutputShowMoreContainerHeight(46); + } else { + this.templateData.outputShowMoreContainer.style.display = 'none'; + } + + const editorHeight = this.templateData.editor!.getContentHeight(); + this.viewCell.editorHeight = editorHeight; + + if (previousOutputHeight === 0 || this.viewCell.outputs.length === 0) { + // first execution or removing all outputs + this._relayoutCell(); + } else { + this._relayoutCellDebounced(); + } + } + + private _renderOutput(currOutput: IProcessedOutput, index: number, beforeElement?: HTMLElement) { + if (!this.outputEntries.has(currOutput)) { + this.outputEntries.set(currOutput, new OutputElement(this.notebookEditor, this.notebookService, this.quickInputService, this.viewCell, this.templateData.outputContainer, currOutput)); + } + + this.outputEntries.get(currOutput)!.render(index, beforeElement); + } + + private _generateShowMoreElement(): any { + const md: IMarkdownString = { + value: `There are more than ${OUTPUT_COUNT_LIMIT} outputs, [show more ...](command:workbench.action.openLargeOutput)`, + isTrusted: true, + supportThemeIcons: true + }; + + const element = renderMarkdown(md, { + actionHandler: { + callback: (content) => { + if (content === 'command:workbench.action.openLargeOutput') { + const content = JSON.stringify(this.viewCell.outputs.map(output => { + switch (output.outputKind) { + case CellOutputKind.Text: + return { + outputKind: 'text', + text: output.text + }; + case CellOutputKind.Error: + return { + outputKind: 'error', + ename: output.ename, + evalue: output.evalue, + traceback: output.traceback + }; + case CellOutputKind.Rich: + return { + data: output.data, + metadata: output.metadata + }; + } + })); + const edits = format(content, undefined, {}); + const metadataSource = applyEdits(content, edits); + + return this.textFileService.untitled.resolve({ + associatedResource: undefined, + mode: 'json', + initialValue: metadataSource + }).then(model => { + const resource = model.resource; + this.openerService.open(resource); + }); + } + + return; + }, + disposeables: new DisposableStore() + } + }); + + element.classList.add('output-show-more'); + return element; + } + + private _relayoutCell() { + if (this._timer !== null) { + clearTimeout(this._timer); + } + + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); + } + + private _timer: number | null = null; + + private _relayoutCellDebounced() { + if (this._timer !== null) { + clearTimeout(this._timer); + } + + this._timer = setTimeout(() => { + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); + this._timer = null; + }, 200) as unknown as number | null; + } + + dispose() { + this.outputEntries.forEach((value) => { + value.dispose(); + }); + + super.dispose(); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 1a86544302c..394b3bb8ac7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -4,37 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import * as DOM from 'vs/base/browser/dom'; -import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { IMarkdownString } from 'vs/base/common/htmlContent'; -import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; -import { format } from 'vs/base/common/jsonFormatter'; -import { applyEdits } from 'vs/base/common/jsonEdit'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { CellOutputKind, IInsetRenderOutput, IProcessedOutput, NotebookCellOutputsSplice, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; -import { OutputElement } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; +import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; -const OUTPUT_COUNT_LIMIT = 500; export class CodeCell extends Disposable { - private outputEntries = new Map(); + private _outputContainerRenderer: OutputContainer; constructor( private notebookEditor: INotebookEditor, private viewCell: CodeCellViewModel, private templateData: CodeCellRenderTemplate, - @INotebookService private notebookService: INotebookService, - @IQuickInputService private readonly quickInputService: IQuickInputService, + @INotebookService notebookService: INotebookService, + @IQuickInputService quickInputService: IQuickInputService, @IOpenerService readonly openerService: IOpenerService, @ITextFileService readonly textFileService: ITextFileService, @IModeService private readonly _modeService: IModeService @@ -142,17 +136,6 @@ export class CodeCell extends Disposable { } })); - this._register(viewCell.onDidChangeLayout(() => { - this.outputEntries.forEach((value, key) => { - const index = viewCell.outputs.indexOf(key); - if (index >= 0) { - const top = this.viewCell.getOutputOffsetInContainer(index); - value.domNode.style.top = `${top}px`; - } - }); - - })); - // Apply decorations this._register(viewCell.onCellDecorationsChanged((e) => { e.added.forEach(options => { @@ -225,186 +208,12 @@ export class CodeCell extends Disposable { updateFocusMode(); // Render Outputs - this.renderOutputs(editorHeight); - this._register(viewCell.onDidChangeOutputs((splices) => { - this.updateOutputs(splices); - })); + this._outputContainerRenderer = new OutputContainer(notebookEditor, viewCell, templateData, notebookService, quickInputService, openerService, textFileService); + this._outputContainerRenderer.render(editorHeight); // Need to do this after the intial renderOutput updateForCollapseState(); } - renderOutputs(editorHeight: number) { - if (this.viewCell.outputs.length > 0) { - let layoutCache = false; - if (this.viewCell.layoutInfo.totalHeight !== 0 && this.viewCell.layoutInfo.editorHeight > editorHeight) { - layoutCache = true; - this.relayoutCell(); - } - - this.templateData.outputContainer!.style.display = 'block'; - // there are outputs, we need to calcualte their sizes and trigger relayout - // @TODO@rebornix, if there is no resizable output, we should not check their height individually, which hurts the performance - const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); - for (let index = 0; index < outputsToRender.length; index++) { - const currOutput = this.viewCell.outputs[index]; - - // always add to the end - this.renderOutput(currOutput, index, undefined); - } - - this.viewCell.editorHeight = editorHeight; - if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { - this.templateData.outputShowMoreContainer.style.display = 'block'; - this.viewCell.updateOutputShowMoreContainerHeight(46); - } - - if (layoutCache) { - this.relayoutCellDebounced(); - } else { - this.relayoutCell(); - } - } else { - // noop - this.viewCell.editorHeight = editorHeight; - this.relayoutCell(); - this.templateData.outputContainer!.style.display = 'none'; - } - - this.templateData.outputShowMoreContainer.innerText = ''; - this.templateData.outputShowMoreContainer.appendChild(this.generateShowMoreElement()); - // this.templateData.outputShowMoreContainer.style.top = `${this.viewCell.layoutInfo.outputShowMoreContainerOffset}px`; - - if (this.viewCell.outputs.length < OUTPUT_COUNT_LIMIT) { - this.templateData.outputShowMoreContainer.style.display = 'none'; - this.viewCell.updateOutputShowMoreContainerHeight(0); - } - } - - updateOutputs(splices: NotebookCellOutputsSplice[]) { - if (!splices.length) { - return; - } - - const previousOutputHeight = this.viewCell.layoutInfo.outputTotalHeight; - - if (this.viewCell.outputs.length) { - this.templateData.outputContainer!.style.display = 'block'; - } else { - this.templateData.outputContainer!.style.display = 'none'; - } - - const reversedSplices = splices.reverse(); - - reversedSplices.forEach(splice => { - this.viewCell.spliceOutputHeights(splice[0], splice[1], splice[2].map(_ => 0)); - }); - - const removedKeys: IProcessedOutput[] = []; - - this.outputEntries.forEach((value, key) => { - if (this.viewCell.outputs.indexOf(key) < 0) { - // already removed - removedKeys.push(key); - // remove element from DOM - this.templateData?.outputContainer?.removeChild(value.domNode); - this.notebookEditor.removeInset(key); - } - }); - - removedKeys.forEach(key => { - this.outputEntries.get(key)?.dispose(); - this.outputEntries.delete(key); - }); - - let prevElement: HTMLElement | undefined = undefined; - const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); - - outputsToRender.reverse().forEach(output => { - if (this.outputEntries.has(output)) { - // already exist - prevElement = this.outputEntries.get(output)!.domNode; - return; - } - - // newly added element - const currIndex = this.viewCell.outputs.indexOf(output); - this.renderOutput(output, currIndex, prevElement); - prevElement = this.outputEntries.get(output)?.domNode; - }); - - if (this.viewCell.outputs.length > OUTPUT_COUNT_LIMIT) { - this.templateData.outputShowMoreContainer.style.display = 'block'; - this.viewCell.updateOutputShowMoreContainerHeight(46); - } else { - this.templateData.outputShowMoreContainer.style.display = 'none'; - } - - const editorHeight = this.templateData.editor!.getContentHeight(); - this.viewCell.editorHeight = editorHeight; - - if (previousOutputHeight === 0 || this.viewCell.outputs.length === 0) { - // first execution or removing all outputs - this.relayoutCell(); - } else { - this.relayoutCellDebounced(); - } - } - - generateShowMoreElement(): any { - const md: IMarkdownString = { - value: `There are more than ${OUTPUT_COUNT_LIMIT} outputs, [show more ...](command:workbench.action.openLargeOutput)`, - isTrusted: true, - supportThemeIcons: true - }; - - const element = renderMarkdown(md, { - actionHandler: { - callback: (content) => { - if (content === 'command:workbench.action.openLargeOutput') { - const content = JSON.stringify(this.viewCell.outputs.map(output => { - switch (output.outputKind) { - case CellOutputKind.Text: - return { - outputKind: 'text', - text: output.text - }; - case CellOutputKind.Error: - return { - outputKind: 'error', - ename: output.ename, - evalue: output.evalue, - traceback: output.traceback - }; - case CellOutputKind.Rich: - return { - data: output.data, - metadata: output.metadata - }; - } - })); - const edits = format(content, undefined, {}); - const metadataSource = applyEdits(content, edits); - - return this.textFileService.untitled.resolve({ - associatedResource: undefined, - mode: 'json', - initialValue: metadataSource - }).then(model => { - const resource = model.resource; - this.openerService.open(resource); - }); - } - - return; - }, - disposeables: new DisposableStore() - } - }); - - element.classList.add('output-show-more'); - return element; - } - private viewUpdate(): void { if (this.viewCell.metadata?.inputCollapsed && this.viewCell.metadata.outputCollapsed) { this.viewUpdateAllCollapsed(); @@ -417,52 +226,24 @@ export class CodeCell extends Disposable { } } - private viewUpdateShowOutputs(): void { - for (let index = 0; index < this.viewCell.outputs.length; index++) { - const currOutput = this.viewCell.outputs[index]; - - const renderedOutput = this.outputEntries.get(currOutput); - if (renderedOutput && renderedOutput.renderResult) { - if (renderedOutput.renderResult.type !== RenderOutputType.None) { - this.notebookEditor.createInset(this.viewCell, renderedOutput.renderResult as IInsetRenderOutput, this.viewCell.getOutputOffset(index)); - } else { - // Anything else, just update the height - this.viewCell.updateOutputHeight(index, renderedOutput.domNode.clientHeight); - } - } else { - // Wasn't previously rendered, render it now - this.renderOutput(currOutput, index); - } - } - - this.relayoutCell(); - } - private viewUpdateInputCollapsed(): void { DOM.hide(this.templateData.cellContainer); DOM.hide(this.templateData.runButtonContainer); DOM.show(this.templateData.collapsedPart); DOM.show(this.templateData.outputContainer); this.templateData.container.classList.toggle('collapsed', true); - - this.viewUpdateShowOutputs(); + this._outputContainerRenderer.viewUpdateShowOutputs(); this.relayoutCell(); } - private viewUpdateHideOuputs(): void { - for (const e of this.outputEntries.keys()) { - this.notebookEditor.hideInset(e); - } - } - private viewUpdateOutputCollapsed(): void { DOM.show(this.templateData.cellContainer); DOM.show(this.templateData.runButtonContainer); DOM.show(this.templateData.collapsedPart); DOM.hide(this.templateData.outputContainer); - this.viewUpdateHideOuputs(); + this._outputContainerRenderer.viewUpdateHideOuputs(); this.templateData.container.classList.toggle('collapsed', false); this.templateData.container.classList.toggle('output-collapsed', true); @@ -477,11 +258,7 @@ export class CodeCell extends Disposable { DOM.hide(this.templateData.outputContainer); this.templateData.container.classList.toggle('collapsed', true); this.templateData.container.classList.toggle('output-collapsed', true); - - for (const e of this.outputEntries.keys()) { - this.notebookEditor.hideInset(e); - } - + this._outputContainerRenderer.viewUpdateHideOuputs(); this.relayoutCell(); } @@ -492,9 +269,7 @@ export class CodeCell extends Disposable { DOM.show(this.templateData.outputContainer); this.templateData.container.classList.toggle('collapsed', false); this.templateData.container.classList.toggle('output-collapsed', false); - - this.viewUpdateShowOutputs(); - + this._outputContainerRenderer.viewUpdateShowOutputs(); this.relayoutCell(); } @@ -516,12 +291,7 @@ export class CodeCell extends Disposable { ); // for contents for which we don't observe for dynamic height, update them manually - this.viewCell.outputs.forEach((o, i) => { - const renderedOutput = this.outputEntries.get(o); - if (renderedOutput && renderedOutput.renderResult && renderedOutput.renderResult.type === RenderOutputType.None && !renderedOutput.renderResult.hasDynamicHeight) { - this.viewCell.updateOutputHeight(i, renderedOutput.domNode.clientHeight); - } - }); + this._outputContainerRenderer.onCellWidthChange(); } private onCellHeightChange(newHeight: number): void { @@ -536,14 +306,6 @@ export class CodeCell extends Disposable { ); } - private renderOutput(currOutput: IProcessedOutput, index: number, beforeElement?: HTMLElement) { - if (!this.outputEntries.has(currOutput)) { - this.outputEntries.set(currOutput, new OutputElement(this.notebookEditor, this.notebookService, this.quickInputService, this.viewCell, this.templateData.outputContainer, currOutput)); - } - - this.outputEntries.get(currOutput)!.render(index, beforeElement); - } - relayoutCell() { if (this._timer !== null) { clearTimeout(this._timer); @@ -567,10 +329,7 @@ export class CodeCell extends Disposable { dispose() { this.viewCell.detachTextEditor(); - this.outputEntries.forEach((value) => { - value.dispose(); - }); - + this._outputContainerRenderer.dispose(); this.templateData.focusIndicatorLeft!.style.height = 'initial'; super.dispose(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 08be444484a..7c55a34abc2 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -19,7 +19,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; +import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; export class StatefulMarkdownCell extends Disposable { From d23c882470960b73a570243f716f1f193588a82e Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 17:32:49 -0800 Subject: [PATCH 0097/1837] use status bar item for execute cell placeholder --- .../notebook/browser/media/notebook.css | 13 ++----- .../browser/view/renderers/codeCell.ts | 38 ++++++++++++++++++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 464d76584a2..11a3fd0ebdf 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -851,15 +851,10 @@ display: flex; } -/* TODO @misolori localize string */ -.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .cell-statusbar-container .cell-run-status:empty::before { - content: "Ctrl + Enter to run"; - width: auto; - height: 100%; - display: block; - opacity: 0.7; -} - .output-show-more { padding: 8px 0; } + +.cell-contributed-items.cell-contributed-items-left { + margin-left: 4px; +} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 394b3bb8ac7..f6eaf70a467 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -6,7 +6,7 @@ import * as DOM from 'vs/base/browser/dom'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; @@ -18,10 +18,13 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; +import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; +import { CellStatusbarAlignment } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class CodeCell extends Disposable { private _outputContainerRenderer: OutputContainer; + private _activeCellRunPlaceholder: IDisposable | null = null; constructor( private notebookEditor: INotebookEditor, @@ -29,6 +32,7 @@ export class CodeCell extends Disposable { private templateData: CodeCellRenderTemplate, @INotebookService notebookService: INotebookService, @IQuickInputService quickInputService: IQuickInputService, + @INotebookCellStatusBarService readonly notebookCellStatusBarService: INotebookCellStatusBarService, @IOpenerService readonly openerService: IOpenerService, @ITextFileService readonly textFileService: ITextFileService, @IModeService private readonly _modeService: IModeService @@ -212,6 +216,37 @@ export class CodeCell extends Disposable { this._outputContainerRenderer.render(editorHeight); // Need to do this after the intial renderOutput updateForCollapseState(); + + const updatePlaceholder = () => { + if (this.notebookEditor.getActiveCell() === this.viewCell && viewCell.metadata.runState === undefined && viewCell.metadata.lastRunDuration === undefined) { + // active cell and no run status + if (this._activeCellRunPlaceholder === null) { + this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry({ + alignment: CellStatusbarAlignment.LEFT, + priority: -1, + cellResource: viewCell.uri, + command: undefined, + text: 'Ctrl + Enter to run', + tooltip: 'Ctrl + Enter to run', + visible: true, + opacity: '0.7' + }); + } + + return; + } + + this._activeCellRunPlaceholder?.dispose(); + this._activeCellRunPlaceholder = null; + }; + + this._register(this.notebookEditor.onDidChangeActiveCell(() => { + updatePlaceholder(); + })); + + this._register(this.viewCell.model.onDidChangeMetadata(() => { + updatePlaceholder(); + })); } private viewUpdate(): void { @@ -330,6 +365,7 @@ export class CodeCell extends Disposable { dispose() { this.viewCell.detachTextEditor(); this._outputContainerRenderer.dispose(); + this._activeCellRunPlaceholder?.dispose(); this.templateData.focusIndicatorLeft!.style.height = 'initial'; super.dispose(); From 33c058d0422364d693ea7ce588cf87ffe629ebfd Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 17:50:52 -0800 Subject: [PATCH 0098/1837] fix mouse click on text status item --- .../browser/view/renderers/cellWidgets.ts | 20 ++++++++++++++----- .../browser/view/renderers/codeCell.ts | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index 4b0060f20c3..59bea186eb7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -37,7 +37,8 @@ export interface IClickTarget { export const enum ClickTargetType { Container = 0, CellStatus = 1, - ContributedItem = 2 + ContributedTextItem = 2, + ContributedCommandItem = 3 } export class CellEditorStatusBar extends Disposable { @@ -95,10 +96,18 @@ export class CellEditorStatusBar extends Disposable { event: e }); } else { - this._onDidClick.fire({ - type: ClickTargetType.ContributedItem, - event: e - }); + if ((e.target as HTMLElement).classList.contains('cell-status-item-has-command')) { + this._onDidClick.fire({ + type: ClickTargetType.ContributedCommandItem, + event: e + }); + } else { + // text + this._onDidClick.fire({ + type: ClickTargetType.ContributedTextItem, + event: e + }); + } } })); } @@ -222,6 +231,7 @@ export class CellLanguageStatusBarItem extends Disposable { super(); this.labelElement = DOM.append(container, $('.cell-language-picker.cell-status-item')); this.labelElement.tabIndex = 0; + this.labelElement.classList.add('cell-status-item-has-command'); this._register(DOM.addDisposableListener(this.labelElement, DOM.EventType.CLICK, () => { this.run(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index f6eaf70a467..1c2016566ba 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -175,7 +175,7 @@ export class CodeCell extends Disposable { // Mouse click handlers this._register(templateData.statusBar.onDidClick(e => { - if (e.type !== ClickTargetType.ContributedItem) { + if (e.type !== ClickTargetType.ContributedCommandItem) { const target = templateData.editor.getTargetAtClientPoint(e.event.clientX, e.event.clientY - viewCell.getEditorStatusbarHeight()); if (target?.position) { templateData.editor.setPosition(target.position); From 4d4f3660a0adb59e726b9828cee23fce2b0b4db8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 17:53:16 -0800 Subject: [PATCH 0099/1837] opacity for notebook cell status --- .../notebook/browser/view/renderers/cellRenderer.ts | 7 +++++++ .../contrib/notebook/browser/view/renderers/cellWidgets.ts | 4 ++++ src/vs/workbench/contrib/notebook/common/notebookCommon.ts | 1 + 3 files changed, 12 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 907da4cd74d..3164a4d1d09 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -1001,6 +1001,7 @@ export class RunStateRenderer { private pendingNewState: NotebookCellRunState | undefined; constructor(private readonly element: HTMLElement, private readonly runToolbar: ToolBar, private readonly instantiationService: IInstantiationService) { + DOM.hide(element); } clear() { @@ -1038,6 +1039,12 @@ export class RunStateRenderer { } else { this.element.innerText = ''; } + + if (runState === NotebookCellRunState.Idle) { + DOM.hide(this.element); + } else { + this.element.style.display = 'flex'; + } } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index 59bea186eb7..174561c01fb 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -160,6 +160,10 @@ class CellStatusBarItem extends Disposable { super(); new CodiconLabel(this.container).text = this._itemModel.text; + if (this._itemModel.opacity) { + this.container.style.opacity = this._itemModel.opacity; + } + let ariaLabel: string; let role: string | undefined; if (this._itemModel.accessibilityInformation) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 4f89dbc2e5c..58e0f94a031 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -856,6 +856,7 @@ export interface INotebookCellStatusBarEntry { readonly command: string | Command | undefined; readonly accessibilityInformation?: IAccessibilityInformation; readonly visible: boolean; + readonly opacity?: string; } export const DisplayOrderKey = 'notebook.displayOrder'; From 1b3b40265b453b7a40f1569b2d783b4fdfb3eb21 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 18:05:53 -0800 Subject: [PATCH 0100/1837] trusted notebook metadata --- .../notebook/browser/contrib/coreActions.ts | 34 ++++++++++-- .../notebook/browser/notebookBrowser.ts | 1 + .../notebook/browser/notebookEditorWidget.ts | 4 +- .../notebook/browser/notebookServiceImpl.ts | 19 ++++--- .../browser/view/renderers/cellOutput.ts | 54 ++++++++++++++++--- .../browser/view/renderers/cellRenderer.ts | 3 ++ .../browser/view/renderers/cellWidgets.ts | 16 ++++++ .../browser/view/renderers/codeCell.ts | 26 +++++---- .../browser/view/renderers/markdownCell.ts | 32 ++++++++++- .../browser/viewModel/baseCellViewModel.ts | 4 +- .../browser/viewModel/notebookViewModel.ts | 4 ++ .../contrib/notebook/common/notebookCommon.ts | 16 +++++- .../notebook/test/notebookViewModel.test.ts | 6 +-- 13 files changed, 179 insertions(+), 40 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index e742bffc887..145598c4474 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -21,9 +21,9 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NotebookDocumentMetadata, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -37,6 +37,7 @@ const NOTEBOOK_FOCUS_PREVIOUS_EDITOR = 'notebook.focusPreviousEditor'; const NOTEBOOK_FOCUS_NEXT_EDITOR = 'notebook.focusNextEditor'; const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs'; const RENDER_ALL_MARKDOWN_CELLS = 'notebook.renderAllMarkdownCells'; +const TRUST_NOTEBOOK = 'notebook.trust'; // Cell Commands const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove'; @@ -64,7 +65,6 @@ const SPLIT_CELL_COMMAND_ID = 'notebook.cell.split'; const JOIN_CELL_ABOVE_COMMAND_ID = 'notebook.cell.joinAbove'; const JOIN_CELL_BELOW_COMMAND_ID = 'notebook.cell.joinBelow'; -const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; const CANCEL_CELL_COMMAND_ID = 'notebook.cell.cancelExecution'; const EXECUTE_CELL_SELECT_BELOW = 'notebook.cell.executeAndSelectBelow'; const EXECUTE_CELL_INSERT_BELOW = 'notebook.cell.executeAndInsertBelow'; @@ -1824,6 +1824,34 @@ registerAction2(class extends ChangeNotebookCellMetadataAction { } }); +abstract class ChangeNotebookMetadataAction extends NotebookCellAction { + async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { + const textModel = context.notebookEditor.viewModel?.notebookDocument; + if (!textModel) { + return; + } + + textModel.applyEdits(textModel.versionId, [{ editType: CellEditType.DocumentMetadata, metadata: { ...textModel.metadata, ...this.getMetadataDelta() } }], true, undefined, () => undefined, undefined); + } + + abstract getMetadataDelta(): Partial; +} + +registerAction2(class extends ChangeNotebookMetadataAction { + constructor() { + super({ + id: TRUST_NOTEBOOK, + title: localize('notebook.trust', "Trust Notebook"), + }); + } + + getMetadataDelta(): Partial { + return { trusted: true }; + } +}); + + + registerAction2(class extends Action2 { constructor() { super({ diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index d5bac93dd4c..5db3402f081 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -60,6 +60,7 @@ export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebo // Shared commands export const EXPAND_CELL_CONTENT_COMMAND_ID = 'notebook.cell.expandCellContent'; +export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; // Kernels diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 57e49098cda..0e2883e8295 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -873,7 +873,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _updateForMetadata(): void { const notebookMetadata = this.viewModel!.metadata; this._editorEditable?.set(!!notebookMetadata?.editable); - this._editorRunnable?.set(!!notebookMetadata?.runnable); + this._editorRunnable?.set(this.viewModel!.runnable); this._overflowContainer.classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable); this.getDomNode().classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable); @@ -1621,7 +1621,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async executeNotebook(): Promise { - if (!this._notebookViewModel!.metadata.runnable) { + if (!this._notebookViewModel!.runnable) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index dc6bf626860..8179b4ed84d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -28,7 +28,7 @@ import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRe import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -732,10 +732,10 @@ export class NotebookService extends Disposable implements INotebookService, ICu getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[] { // TODO@rebornix no string[] casting - return this._getOrderedMimeTypes(output, textModel.metadata.displayOrder as string[] ?? []); + return this._getOrderedMimeTypes(textModel, output, textModel.metadata.displayOrder as string[] ?? []); } - private _getOrderedMimeTypes(output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] { + private _getOrderedMimeTypes(textModel: NotebookTextModel, output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] { const mimeTypes = Object.keys(output.data); const coreDisplayOrder = this._displayOrder; const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], documentDisplayOrder, coreDisplayOrder?.defaultOrder || []); @@ -751,31 +751,36 @@ export class NotebookService extends Disposable implements INotebookService, ICu orderMimeTypes.push({ mimeType: mimeType, rendererId: handler.id, + isTrusted: textModel.metadata.trusted }); for (let i = 1; i < handlers.length; i++) { orderMimeTypes.push({ mimeType: mimeType, - rendererId: handlers[i].id + rendererId: handlers[i].id, + isTrusted: textModel.metadata.trusted }); } if (mimeTypeSupportedByCore(mimeType)) { orderMimeTypes.push({ mimeType: mimeType, - rendererId: BUILTIN_RENDERER_ID + rendererId: BUILTIN_RENDERER_ID, + isTrusted: mimeTypeIsAlwaysSecure(mimeType) || textModel.metadata.trusted }); } } else { if (mimeTypeSupportedByCore(mimeType)) { orderMimeTypes.push({ mimeType: mimeType, - rendererId: BUILTIN_RENDERER_ID + rendererId: BUILTIN_RENDERER_ID, + isTrusted: mimeTypeIsAlwaysSecure(mimeType) || textModel.metadata.trusted }); } else { orderMimeTypes.push({ mimeType: mimeType, - rendererId: RENDERER_NOT_AVAILABLE + rendererId: RENDERER_NOT_AVAILABLE, + isTrusted: textModel.metadata.trusted }); } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index 4e2cc304e32..fc6f6a9aeec 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -63,7 +63,8 @@ export class OutputElement extends Disposable { const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output); - const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE), 0); + // there is at least one mimetype which is safe and can be rendered by the core + const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE && mimeType.isTrusted), 0); if (mimeTypes.length > 1) { outputItemDiv.style.position = 'relative'; @@ -104,6 +105,8 @@ export class OutputElement extends Disposable { } else { result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); } + + this.pickedMimeTypes.set(this.output, pick); } else { // for text and error, there is no mimetype const innerContainer = DOM.$('.output-inner-container'); @@ -174,10 +177,10 @@ export class OutputElement extends Disposable { async pickActiveMimeTypeRenderer(output: ITransformedDisplayOutputDto) { const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, output); - const currIndex = this.pickedMimeTypes.get(output) ?? 0; + const currIndex = this.pickedMimeTypes.get(output); // const currIndex = output.pickedMimeTypeIndex; - const items = mimeTypes.map((mimeType, index): IMimeTypeRenderer => ({ + const items = mimeTypes.filter(mimeType => mimeType.isTrusted).map((mimeType, index): IMimeTypeRenderer => ({ label: mimeType.mimeType, id: mimeType.mimeType, index: index, @@ -189,7 +192,9 @@ export class OutputElement extends Disposable { const picker = this.quickInputService.createQuickPick(); picker.items = items; picker.activeItems = items.filter(item => !!item.picked); - picker.placeholder = nls.localize('promptChooseMimeType.placeHolder', "Select output mimetype to render for current output"); + picker.placeholder = items.length !== mimeTypes.length + ? nls.localize('promptChooseMimeTypeInSecure.placeHolder', "Select mimetype to render for current output. Rich mimetypes are available only when the notebook is trusted") + : nls.localize('promptChooseMimeType.placeHolder', "Select mimetype to render for current output"); const pick = await new Promise(resolve => { picker.onDidAccept(() => { @@ -284,7 +289,7 @@ export class OutputContainer extends Disposable { this.templateData.outputContainer!.style.display = 'block'; // there are outputs, we need to calcualte their sizes and trigger relayout // @TODO@rebornix, if there is no resizable output, we should not check their height individually, which hurts the performance - const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + const outputsToRender = this._calcuateOutputsToRender(); for (let index = 0; index < outputsToRender.length; index++) { const currOutput = this.viewCell.outputs[index]; @@ -356,6 +361,43 @@ export class OutputContainer extends Disposable { }); } + private _calcuateOutputsToRender() { + const outputs = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + if (!this.notebookEditor.viewModel!.metadata.trusted) { + // not trusted + const secureOutput = outputs.filter(output => { + switch (output.outputKind) { + case CellOutputKind.Text: + return true; + case CellOutputKind.Error: + return true; + case CellOutputKind.Rich: + { + const mimeTypes = []; + for (const property in output.data) { + mimeTypes.push(property); + } + + if (mimeTypes.indexOf('text/plain') >= 0 + || mimeTypes.indexOf('text/markdown') >= 0 + || mimeTypes.indexOf('application/json') >= 0 + || mimeTypes.includes('image/png')) { + return true; + } + + return false; + } + default: + return false; + } + }); + + return secureOutput; + } + + return outputs; + } + private _updateOutputs(splices: NotebookCellOutputsSplice[]) { if (!splices.length) { return; @@ -393,7 +435,7 @@ export class OutputContainer extends Disposable { }); let prevElement: HTMLElement | undefined = undefined; - const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length)); + const outputsToRender = this._calcuateOutputsToRender(); outputsToRender.reverse().forEach(output => { if (this.outputEntries.has(output)) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 3164a4d1d09..f7e1fd60fa9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -414,6 +414,9 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR const betweenCellToolbar = disposables.add(this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService)); const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart)); + DOM.hide(statusBar.durationContainer); + DOM.hide(statusBar.cellRunStatusContainer); + const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService)); const templateData: MarkdownCellRenderTemplate = { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index 174561c01fb..b8c2a1172b9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -23,6 +23,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ChangeCellLanguageAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; import { ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -339,3 +340,18 @@ export function getResizesObserver(referenceDomElement: HTMLElement | null, dime return new ElementSizeObserver(referenceDomElement, dimension, changeCallback); } } + +export function getExecuteCellPlaceholder(viewCell: BaseCellViewModel) { + return { + alignment: CellStatusbarAlignment.LEFT, + priority: -1, + cellResource: viewCell.uri, + command: undefined, + // text: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`, + // tooltip: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`, + text: 'Ctrl + Enter to run', + tooltip: 'Ctrl + Enter to run', + visible: true, + opacity: '0.7' + }; +} diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 1c2016566ba..c1350eeabb0 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -16,10 +16,9 @@ import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workb import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { ClickTargetType, getExecuteCellPlaceholder } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; -import { CellStatusbarAlignment } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class CodeCell extends Disposable { @@ -35,7 +34,9 @@ export class CodeCell extends Disposable { @INotebookCellStatusBarService readonly notebookCellStatusBarService: INotebookCellStatusBarService, @IOpenerService readonly openerService: IOpenerService, @ITextFileService readonly textFileService: ITextFileService, - @IModeService private readonly _modeService: IModeService + @IModeService private readonly _modeService: IModeService, + // @IKeybindingService private readonly _keybindingService: IKeybindingService, + ) { super(); @@ -218,19 +219,14 @@ export class CodeCell extends Disposable { updateForCollapseState(); const updatePlaceholder = () => { - if (this.notebookEditor.getActiveCell() === this.viewCell && viewCell.metadata.runState === undefined && viewCell.metadata.lastRunDuration === undefined) { + if (this.notebookEditor.getActiveCell() === this.viewCell + && viewCell.metadata.runState === undefined + && viewCell.metadata.lastRunDuration === undefined + ) { // active cell and no run status if (this._activeCellRunPlaceholder === null) { - this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry({ - alignment: CellStatusbarAlignment.LEFT, - priority: -1, - cellResource: viewCell.uri, - command: undefined, - text: 'Ctrl + Enter to run', - tooltip: 'Ctrl + Enter to run', - visible: true, - opacity: '0.7' - }); + // const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID); + this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(getExecuteCellPlaceholder(this.viewCell)); } return; @@ -247,6 +243,8 @@ export class CodeCell extends Disposable { this._register(this.viewCell.model.onDidChangeMetadata(() => { updatePlaceholder(); })); + + updatePlaceholder(); } private viewUpdate(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 7c55a34abc2..94d2589aa83 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { renderCodicons } from 'vs/base/browser/codicons'; -import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -19,7 +19,8 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { getExecuteCellPlaceholder, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; export class StatefulMarkdownCell extends Disposable { @@ -29,6 +30,7 @@ export class StatefulMarkdownCell extends Disposable { private localDisposables = new DisposableStore(); private foldingState: CellFoldingState; + private _activeCellRunPlaceholder: IDisposable | null = null; constructor( private readonly notebookEditor: INotebookEditor, @@ -37,6 +39,7 @@ export class StatefulMarkdownCell extends Disposable { private editorOptions: IEditorOptions, private readonly renderedEditors: Map, @IContextKeyService private readonly contextKeyService: IContextKeyService, + @INotebookCellStatusBarService readonly notebookCellStatusBarService: INotebookCellStatusBarService, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); @@ -129,6 +132,31 @@ export class StatefulMarkdownCell extends Disposable { }); this.viewUpdate(); + + const updatePlaceholder = () => { + if (this.notebookEditor.getActiveCell() === this.viewCell) { + // active cell and no run status + if (this._activeCellRunPlaceholder === null) { + // const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID); + this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(getExecuteCellPlaceholder(this.viewCell)); + } + + return; + } + + this._activeCellRunPlaceholder?.dispose(); + this._activeCellRunPlaceholder = null; + }; + + this._register(this.notebookEditor.onDidChangeActiveCell(() => { + updatePlaceholder(); + })); + + this._register(this.viewCell.model.onDidChangeMetadata(() => { + updatePlaceholder(); + })); + + updatePlaceholder(); } private viewUpdate(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 8a8b33bf03c..d49dc929cb0 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -453,8 +453,8 @@ export abstract class BaseCellViewModel extends Disposable { const editable = this.metadata?.editable ?? documentMetadata.cellEditable; - const runnable = this.metadata?.runnable ?? - documentMetadata.cellRunnable; + const runnable = (this.metadata?.runnable ?? + documentMetadata.cellRunnable) && !!documentMetadata.trusted; const hasExecutionOrder = this.metadata?.hasExecutionOrder ?? documentMetadata.cellHasExecutionOrder; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 4ea7ba52c4f..86a16531394 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -180,6 +180,10 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD return this._notebook.metadata; } + get runnable() { + return !!this._notebook.metadata?.runnable && !!this._notebook.metadata?.trusted; + } + private readonly _onDidChangeViewCells = this._register(new Emitter()); get onDidChangeViewCells(): Event { return this._onDidChangeViewCells.event; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 58e0f94a031..dcab1f736e6 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -86,7 +86,7 @@ export interface NotebookDocumentMetadata { displayOrder?: (string | glob.IRelativePattern)[]; custom?: { [key: string]: unknown }; runState?: NotebookRunState; - trusted?: boolean; + trusted: boolean; } export enum NotebookCellRunState { @@ -185,6 +185,7 @@ export enum MimeTypeRendererResolver { export interface IOrderedMimeType { mimeType: string; rendererId: string; + isTrusted: boolean; } export interface ITransformedDisplayOutputDto extends IDisplayOutput { @@ -538,6 +539,19 @@ export namespace CellUri { } } +export function mimeTypeIsAlwaysSecure(mimeType: string) { + if ([ + 'application/json', + 'text/markdown', + 'image/png', + 'text/plain' + ].indexOf(mimeType) > -1) { + return true; + } + + return false; +} + export function mimeTypeSupportedByCore(mimeType: string) { if ([ 'application/json', diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index b8d970e6e7f..1ec883fe144 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -156,7 +156,7 @@ suite('NotebookViewModel', () => { ['var e = 5;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }], ], (editor, viewModel) => { - viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: true, cellEditable: true, cellHasExecutionOrder: true }; + viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: true, cellEditable: true, cellHasExecutionOrder: true, trusted: true }; const defaults = { hasExecutionOrder: true }; @@ -190,7 +190,7 @@ suite('NotebookViewModel', () => { ...defaults }); - viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: true, cellHasExecutionOrder: true }; + viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: true, cellHasExecutionOrder: true, trusted: true }; assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), { editable: true, @@ -222,7 +222,7 @@ suite('NotebookViewModel', () => { ...defaults }); - viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: false, cellHasExecutionOrder: true }; + viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: false, cellHasExecutionOrder: true, trusted: true }; assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), { editable: false, From 6b19da71021fba2b706d9b080124dbea77b212b2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 19 Nov 2020 18:18:10 -0800 Subject: [PATCH 0101/1837] update execution button when trusted notebook metadata changes. --- .../notebook/browser/view/renderers/cellRenderer.ts | 7 ++++++- .../notebook/browser/view/renderers/codeCell.ts | 11 ++++++++++- .../notebook/browser/view/renderers/markdownCell.ts | 13 ++++++++++++- .../contrib/notebook/common/notebookCommon.ts | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index f7e1fd60fa9..62aa3a4f1ab 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -47,7 +47,7 @@ import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, NotebookCellsChangeType, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CodiconActionViewItem, createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView'; const $ = DOM.$; @@ -917,6 +917,11 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.updateForHover(element, templateData); } })); + elementDisposables.add(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { + this.updateForMetadata(element, templateData); + } + })); this.updateForOutputs(element, templateData); elementDisposables.add(element.onDidChangeOutputs(_e => this.updateForOutputs(element, templateData))); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index c1350eeabb0..0cab0c01d0e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -19,6 +19,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { ClickTargetType, getExecuteCellPlaceholder } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; +import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class CodeCell extends Disposable { @@ -219,7 +220,9 @@ export class CodeCell extends Disposable { updateForCollapseState(); const updatePlaceholder = () => { - if (this.notebookEditor.getActiveCell() === this.viewCell + if (this.notebookEditor.viewModel + && this.notebookEditor.getActiveCell() === this.viewCell + && viewCell.getEvaluatedMetadata(this.notebookEditor.viewModel.metadata).runnable && viewCell.metadata.runState === undefined && viewCell.metadata.lastRunDuration === undefined ) { @@ -244,6 +247,12 @@ export class CodeCell extends Disposable { updatePlaceholder(); })); + this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { + updatePlaceholder(); + } + })); + updatePlaceholder(); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 94d2589aa83..bbdf6f99ec0 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -21,6 +21,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { getExecuteCellPlaceholder, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; +import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class StatefulMarkdownCell extends Disposable { @@ -134,7 +135,11 @@ export class StatefulMarkdownCell extends Disposable { this.viewUpdate(); const updatePlaceholder = () => { - if (this.notebookEditor.getActiveCell() === this.viewCell) { + if ( + this.notebookEditor.viewModel + && this.notebookEditor.getActiveCell() === this.viewCell + && !!this.notebookEditor.viewModel.metadata.trusted + ) { // active cell and no run status if (this._activeCellRunPlaceholder === null) { // const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID); @@ -156,6 +161,12 @@ export class StatefulMarkdownCell extends Disposable { updatePlaceholder(); })); + this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { + updatePlaceholder(); + } + })); + updatePlaceholder(); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index dcab1f736e6..34a2c09409e 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -74,7 +74,7 @@ export const notebookDocumentMetadataDefaults: Required Date: Thu, 19 Nov 2020 18:24:50 -0800 Subject: [PATCH 0102/1837] add trusted status bar item. --- .../notebook/browser/contrib/coreActions.ts | 7 ++--- .../notebook/browser/notebookBrowser.ts | 1 + .../browser/view/renderers/codeCell.ts | 28 +++++++++++++++++-- .../contrib/notebook/common/notebookCommon.ts | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 145598c4474..bb6d9527324 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -21,7 +21,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED, TRUST_NOTEBOOK_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NotebookDocumentMetadata, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -37,7 +37,6 @@ const NOTEBOOK_FOCUS_PREVIOUS_EDITOR = 'notebook.focusPreviousEditor'; const NOTEBOOK_FOCUS_NEXT_EDITOR = 'notebook.focusNextEditor'; const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs'; const RENDER_ALL_MARKDOWN_CELLS = 'notebook.renderAllMarkdownCells'; -const TRUST_NOTEBOOK = 'notebook.trust'; // Cell Commands const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove'; @@ -1840,8 +1839,8 @@ abstract class ChangeNotebookMetadataAction extends NotebookCellAction { registerAction2(class extends ChangeNotebookMetadataAction { constructor() { super({ - id: TRUST_NOTEBOOK, - title: localize('notebook.trust', "Trust Notebook"), + id: TRUST_NOTEBOOK_COMMAND_ID, + title: localize('notebook.trust', "Trust Current Notebook Document"), }); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 5db3402f081..ad349b19313 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -61,6 +61,7 @@ export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebo // Shared commands export const EXPAND_CELL_CONTENT_COMMAND_ID = 'notebook.cell.expandCellContent'; export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; +export const TRUST_NOTEBOOK_COMMAND_ID = 'notebook.trust'; // Kernels diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 0cab0c01d0e..ed55e72dcd5 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -12,19 +12,20 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor, TRUST_NOTEBOOK_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ClickTargetType, getExecuteCellPlaceholder } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; -import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellStatusbarAlignment, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class CodeCell extends Disposable { private _outputContainerRenderer: OutputContainer; private _activeCellRunPlaceholder: IDisposable | null = null; + private _untrustedStatusItem: IDisposable | null = null; constructor( private notebookEditor: INotebookEditor, @@ -247,13 +248,35 @@ export class CodeCell extends Disposable { updatePlaceholder(); })); + const updateUntrustedStatus = () => { + if (this.notebookEditor.viewModel + && this.notebookEditor.viewModel.metadata.trusted) { + this._untrustedStatusItem?.dispose(); + this._untrustedStatusItem = null; + } else { + if (this._untrustedStatusItem === null) { + this._untrustedStatusItem = this.notebookCellStatusBarService.addEntry({ + alignment: CellStatusbarAlignment.LEFT, + priority: -1, + cellResource: viewCell.uri, + command: TRUST_NOTEBOOK_COMMAND_ID, + text: 'Untrusted', + tooltip: 'Untrusted notebook', + visible: true, + }); + } + } + }; + this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { updatePlaceholder(); + updateUntrustedStatus(); } })); updatePlaceholder(); + updateUntrustedStatus(); } private viewUpdate(): void { @@ -373,6 +396,7 @@ export class CodeCell extends Disposable { this.viewCell.detachTextEditor(); this._outputContainerRenderer.dispose(); this._activeCellRunPlaceholder?.dispose(); + this._untrustedStatusItem?.dispose(); this.templateData.focusIndicatorLeft!.style.height = 'initial'; super.dispose(); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 34a2c09409e..dcab1f736e6 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -74,7 +74,7 @@ export const notebookDocumentMetadataDefaults: Required Date: Fri, 20 Nov 2020 09:38:08 -0800 Subject: [PATCH 0103/1837] give the option completely to notebook extension for now. --- .../notebook/browser/contrib/coreActions.ts | 47 +++++++------------ .../notebook/browser/notebookBrowser.ts | 1 - .../browser/view/renderers/codeCell.ts | 46 +++++++++--------- .../common/model/notebookTextModel.ts | 13 ++++- 4 files changed, 51 insertions(+), 56 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index bb6d9527324..8b680f19324 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -6,7 +6,7 @@ import * as glob from 'vs/base/common/glob'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -21,9 +21,9 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED, TRUST_NOTEBOOK_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NotebookDocumentMetadata, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -1823,34 +1823,6 @@ registerAction2(class extends ChangeNotebookCellMetadataAction { } }); -abstract class ChangeNotebookMetadataAction extends NotebookCellAction { - async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - const textModel = context.notebookEditor.viewModel?.notebookDocument; - if (!textModel) { - return; - } - - textModel.applyEdits(textModel.versionId, [{ editType: CellEditType.DocumentMetadata, metadata: { ...textModel.metadata, ...this.getMetadataDelta() } }], true, undefined, () => undefined, undefined); - } - - abstract getMetadataDelta(): Partial; -} - -registerAction2(class extends ChangeNotebookMetadataAction { - constructor() { - super({ - id: TRUST_NOTEBOOK_COMMAND_ID, - title: localize('notebook.trust', "Trust Current Notebook Document"), - }); - } - - getMetadataDelta(): Partial { - return { trusted: true }; - } -}); - - - registerAction2(class extends Action2 { constructor() { super({ @@ -1894,6 +1866,19 @@ registerAction2(class extends Action2 { } }); +// Revisit once we have a story for trusted workspace +CommandsRegistry.registerCommand('notebook.trust', (accessor, args) => { + const uri = URI.revive(args as UriComponents); + const notebookService = accessor.get(INotebookService); + + + const document = notebookService.listNotebookDocuments().find(document => document.uri.toString() === uri.toString()); + + if (document) { + document.applyEdits(document.versionId, [{ editType: CellEditType.DocumentMetadata, metadata: { ...document.metadata, ...{ trusted: true } } }], true, undefined, () => undefined, undefined, false); + } +}); + CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor, args): { viewType: string; displayName: string; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index ad349b19313..5db3402f081 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -61,7 +61,6 @@ export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebo // Shared commands export const EXPAND_CELL_CONTENT_COMMAND_ID = 'notebook.cell.expandCellContent'; export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; -export const TRUST_NOTEBOOK_COMMAND_ID = 'notebook.trust'; // Kernels diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index ed55e72dcd5..d876198e3fe 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -12,14 +12,14 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor, TRUST_NOTEBOOK_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ClickTargetType, getExecuteCellPlaceholder } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; -import { CellStatusbarAlignment, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class CodeCell extends Disposable { @@ -248,35 +248,35 @@ export class CodeCell extends Disposable { updatePlaceholder(); })); - const updateUntrustedStatus = () => { - if (this.notebookEditor.viewModel - && this.notebookEditor.viewModel.metadata.trusted) { - this._untrustedStatusItem?.dispose(); - this._untrustedStatusItem = null; - } else { - if (this._untrustedStatusItem === null) { - this._untrustedStatusItem = this.notebookCellStatusBarService.addEntry({ - alignment: CellStatusbarAlignment.LEFT, - priority: -1, - cellResource: viewCell.uri, - command: TRUST_NOTEBOOK_COMMAND_ID, - text: 'Untrusted', - tooltip: 'Untrusted notebook', - visible: true, - }); - } - } - }; + // const updateUntrustedStatus = () => { + // if (this.notebookEditor.viewModel + // && this.notebookEditor.viewModel.metadata.trusted) { + // this._untrustedStatusItem?.dispose(); + // this._untrustedStatusItem = null; + // } else { + // if (this._untrustedStatusItem === null) { + // this._untrustedStatusItem = this.notebookCellStatusBarService.addEntry({ + // alignment: CellStatusbarAlignment.LEFT, + // priority: -1, + // cellResource: viewCell.uri, + // command: TRUST_NOTEBOOK_COMMAND_ID, + // text: 'Untrusted', + // tooltip: 'Untrusted notebook', + // visible: true, + // }); + // } + // } + // }; this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { updatePlaceholder(); - updateUntrustedStatus(); + // updateUntrustedStatus(); } })); updatePlaceholder(); - updateUntrustedStatus(); + // updateUntrustedStatus(); } private viewUpdate(): void { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index f31aa89c278..f932f185e02 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -483,6 +483,17 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } + private _isDocumentMetadataChangeTransient(a: NotebookDocumentMetadata, b: NotebookDocumentMetadata) { + const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]); + for (let key of keys) { + if (key !== 'trusted') { + return true; + } + } + + return false; + } + private _updateNotebookMetadata(metadata: NotebookDocumentMetadata, computeUndoRedo: boolean) { const oldMetadata = this.metadata; this.metadata = metadata; @@ -504,7 +515,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }(), undefined, undefined); } - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, metadata: this.metadata, transient: false }, true); + this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, metadata: this.metadata, transient: this._isDocumentMetadataChangeTransient(oldMetadata, metadata) }, true); } private _insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean, endSelections?: number[]): void { From b2b3b015d5375c64a3b6f4d148a02c3280f0769c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 19:39:08 +0100 Subject: [PATCH 0104/1837] Sort line decorations --- .../common/viewLayout/lineDecorations.ts | 18 ++---------------- .../common/viewLayout/viewLineRenderer.ts | 2 +- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index 9578b66e4da..bd72baa148c 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -34,22 +34,8 @@ export class LineDecoration { if (aLen !== bLen) { return false; } - if (aLen === 0) { - return true; - } - if (aLen === 1) { - return LineDecoration._equals(a[0], b[0]); - } - const bSeen: (undefined | true)[] = new Array(bLen); - for (let i = 0; i < aLen; ++i) { - let j = 0; - for (; j < bLen; ++j) { - if (bSeen[j] !== true && LineDecoration._equals(a[i], b[j])) { - bSeen[j] = true; - break; - } - } - if (j === bLen) { + for (let i = 0; i < aLen; i++) { + if (!LineDecoration._equals(a[i], b[i])) { return false; } } diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index 1b75f0f7c3c..49b43c10eca 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -127,7 +127,7 @@ export class RenderLineInput { this.containsRTL = containsRTL; this.fauxIndentLength = fauxIndentLength; this.lineTokens = lineTokens; - this.lineDecorations = lineDecorations; + this.lineDecorations = lineDecorations.sort(LineDecoration.compare); this.tabSize = tabSize; this.startVisibleColumn = startVisibleColumn; this.spaceWidth = spaceWidth; From a0b7c2310f4f77b801d185a65f3488953c80508b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Nov 2020 19:50:31 +0100 Subject: [PATCH 0105/1837] support dropdown actions in notifications --- src/vs/base/browser/ui/button/button.css | 15 +- src/vs/base/browser/ui/button/button.ts | 156 +++++++++++++----- src/vs/base/browser/ui/dialog/dialog.ts | 19 ++- src/vs/base/common/actions.ts | 11 ++ .../standalone/browser/simpleServices.ts | 4 +- .../common/abstractKeybindingService.test.ts | 4 +- .../notification/common/notification.ts | 17 +- .../test/common/testNotificationService.ts | 4 +- .../notifications/media/notificationsList.css | 13 +- .../notifications/notificationsViewer.ts | 44 +++-- .../experimentalPrompts.test.ts | 6 +- ...ensionRecommendationNotificationService.ts | 75 +++++---- .../extensionRecommendationsService.test.ts | 4 +- .../common/notificationService.ts | 4 +- .../api/extHostMessagerService.test.ts | 6 +- 15 files changed, 257 insertions(+), 125 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.css b/src/vs/base/browser/ui/button/button.css index 6d682352484..3e1e0815554 100644 --- a/src/vs/base/browser/ui/button/button.css +++ b/src/vs/base/browser/ui/button/button.css @@ -10,11 +10,14 @@ padding: 4px; text-align: center; cursor: pointer; - outline-offset: 2px !important; justify-content: center; align-items: center; } +.monaco-button { + outline-offset: 2px !important; +} + .monaco-text-button:hover { text-decoration: none !important; } @@ -24,7 +27,15 @@ cursor: default; } -.monaco-button > .codicon { +.monaco-text-button > .codicon { margin: 0 0.2em; color: inherit !important; } + +.monaco-button-dropdown { + display: flex; +} + +.monaco-button-dropdown > .monaco-dropdown-button { + margin-left: 1px; +} diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index a3ca3ac973d..6b24fbbbf38 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -9,10 +9,12 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { Event as BaseEvent, Emitter } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch'; import { renderCodicons } from 'vs/base/browser/codicons'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; +import { DropdownMenu, IDropdownMenuOptions } from 'vs/base/browser/ui/dropdown/dropdown'; +import { IMenuOptions } from 'vs/base/browser/ui/menu/menu'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; @@ -36,7 +38,18 @@ const defaultOptions: IButtonStyles = { buttonForeground: Color.white }; -export class Button extends Disposable { +export interface IButton extends IDisposable { + readonly element: HTMLElement; + readonly onDidClick: BaseEvent; + label: string; + icon: string; + enabled: boolean; + style(styles: IButtonStyles): void; + focus(): void; + hasFocus(): boolean; +} + +export class Button extends Disposable implements IButton { private _element: HTMLElement; private options: IButtonOptions; @@ -189,7 +202,7 @@ export class Button extends Disposable { } set icon(iconClassName: string) { - this._element.classList.add(iconClassName); + this._element.classList.add(...iconClassName.split(' ')); } set enabled(value: boolean) { @@ -217,47 +230,116 @@ export class Button extends Disposable { } } -export class ButtonGroup extends Disposable { - private _buttons: Button[] = []; +export interface IButtonWithDropdownOptions extends IButtonOptions { + readonly dropdownMenuOptions: IDropdownMenuOptions & IMenuOptions; +} - constructor(container: HTMLElement, count: number, options?: IButtonOptions) { +export class ButtonWithDropdown extends Disposable implements IButton { + + private readonly button: Button; + private readonly dropdownButton: Button; + + readonly element: HTMLElement; + readonly onDidClick: BaseEvent; + + constructor(container: HTMLElement, options: IButtonWithDropdownOptions) { super(); - this.create(container, count, options); + this.element = document.createElement('div'); + this.element.classList.add('monaco-button-dropdown'); + container.appendChild(this.element); + + this.button = this._register(new Button(this.element, options)); + this.onDidClick = this.button.onDidClick; + + this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportCodicons: true })); + this.dropdownButton.element.classList.add('monaco-dropdown-button'); + this.dropdownButton.icon = 'codicon codicon-chevron-down'; + const dropdownMenu = this._register(new DropdownMenu(this.dropdownButton.element, options.dropdownMenuOptions)); + this._register(dropdownMenu.onDidChangeVisibility(visible => this.dropdownButton.element.setAttribute('aria-expanded', `${visible}`))); + this._register(this.dropdownButton.onDidClick(() => dropdownMenu.show())); } - get buttons(): Button[] { + set label(value: string) { + this.button.label = value; + } + + set icon(iconClassName: string) { + this.button.icon = iconClassName; + } + + set enabled(enabled: boolean) { + this.button.enabled = enabled; + this.dropdownButton.enabled = enabled; + } + + get enabled(): boolean { + return this.button.enabled; + } + + style(styles: IButtonStyles): void { + this.button.style(styles); + this.dropdownButton.style(styles); + } + + focus(): void { + this.button.focus(); + } + + hasFocus(): boolean { + return this.button.hasFocus() || this.dropdownButton.hasFocus(); + } +} + +export class ButtonBar extends Disposable { + + private _buttons: IButton[] = []; + + constructor(private readonly container: HTMLElement) { + super(); + } + + get buttons(): IButton[] { return this._buttons; } - private create(container: HTMLElement, count: number, options?: IButtonOptions): void { - for (let index = 0; index < count; index++) { - const button = this._register(new Button(container, options)); - this._buttons.push(button); - - // Implement keyboard access in buttons if there are multiple - if (count > 1) { - this._register(addDisposableListener(button.element, EventType.KEY_DOWN, e => { - const event = new StandardKeyboardEvent(e); - let eventHandled = true; - - // Next / Previous Button - let buttonIndexToFocus: number | undefined; - if (event.equals(KeyCode.LeftArrow)) { - buttonIndexToFocus = index > 0 ? index - 1 : this._buttons.length - 1; - } else if (event.equals(KeyCode.RightArrow)) { - buttonIndexToFocus = index === this._buttons.length - 1 ? 0 : index + 1; - } else { - eventHandled = false; - } - - if (eventHandled && typeof buttonIndexToFocus === 'number') { - this._buttons[buttonIndexToFocus].focus(); - EventHelper.stop(e, true); - } - - })); - } - } + addButton(options?: IButtonOptions): IButton { + const button = this._register(new Button(this.container, options)); + this.pushButton(button); + return button; } + + addButtonWithDropdown(options: IButtonWithDropdownOptions): IButton { + const button = this._register(new ButtonWithDropdown(this.container, options)); + this.pushButton(button); + return button; + } + + private pushButton(button: IButton): void { + this._buttons.push(button); + + const index = this._buttons.length - 1; + this._register(addDisposableListener(button.element, EventType.KEY_DOWN, e => { + const event = new StandardKeyboardEvent(e); + let eventHandled = true; + + // Next / Previous Button + let buttonIndexToFocus: number | undefined; + if (event.equals(KeyCode.LeftArrow)) { + buttonIndexToFocus = index > 0 ? index - 1 : this._buttons.length - 1; + } else if (event.equals(KeyCode.RightArrow)) { + buttonIndexToFocus = index === this._buttons.length - 1 ? 0 : index + 1; + } else { + eventHandled = false; + } + + if (eventHandled && typeof buttonIndexToFocus === 'number') { + this._buttons[buttonIndexToFocus].focus(); + EventHelper.stop(e, true); + } + + })); + + } + } diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index 097e879e30d..21d3092acd1 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -11,7 +11,7 @@ import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Color } from 'vs/base/common/color'; -import { ButtonGroup, IButtonStyles } from 'vs/base/browser/ui/button/button'; +import { ButtonBar, IButtonStyles } from 'vs/base/browser/ui/button/button'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { Action } from 'vs/base/common/actions'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; @@ -74,7 +74,7 @@ export class Dialog extends Disposable { private readonly iconElement: HTMLElement; private readonly checkbox: SimpleCheckbox | undefined; private readonly toolbarContainer: HTMLElement; - private buttonGroup: ButtonGroup | undefined; + private buttonBar: ButtonBar | undefined; private styles: IDialogStyles | undefined; private focusToReturn: HTMLElement | undefined; private readonly inputs: InputBox[]; @@ -173,11 +173,12 @@ export class Dialog extends Disposable { return new Promise((resolve) => { clearNode(this.buttonsContainer); - const buttonGroup = this.buttonGroup = this._register(new ButtonGroup(this.buttonsContainer, this.buttons.length, { title: true })); + const buttonBar = this.buttonBar = this._register(new ButtonBar(this.buttonsContainer)); const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId); // Handle button clicks - buttonGroup.buttons.forEach((button, index) => { + buttonMap.forEach((entry, index) => { + const button = this._register(buttonBar.addButton({ title: true })); button.label = mnemonicButtonLabel(buttonMap[index].label, true); this._register(button.onDidClick(e => { @@ -237,8 +238,8 @@ export class Dialog extends Disposable { } } - if (this.buttonGroup) { - for (const button of this.buttonGroup.buttons) { + if (this.buttonBar) { + for (const button of this.buttonBar.buttons) { focusableElements.push(button); if (button.hasFocus()) { focusedIndex = focusableElements.length - 1; @@ -349,7 +350,7 @@ export class Dialog extends Disposable { } else { buttonMap.forEach((value, index) => { if (value.index === 0) { - buttonGroup.buttons[index].focus(); + buttonBar.buttons[index].focus(); } }); } @@ -371,8 +372,8 @@ export class Dialog extends Disposable { this.element.style.backgroundColor = bgColor?.toString() ?? ''; this.element.style.border = border; - if (this.buttonGroup) { - this.buttonGroup.buttons.forEach(button => button.style(style)); + if (this.buttonBar) { + this.buttonBar.buttons.forEach(button => button.style(style)); } if (this.checkbox) { diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index b0badf977b3..8be6f19aff5 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -235,6 +235,17 @@ export class Separator extends Action { } } +export class ActionWithMenuAction extends Action { + + get actions(): IAction[] { + return this._actions; + } + + constructor(id: string, private _actions: IAction[], label?: string, cssClass?: string, enabled?: boolean, actionCallback?: (event?: any) => Promise) { + super(id, label, cssClass, enabled, actionCallback); + } +} + export class SubmenuAction extends Action { get actions(): IAction[] { diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index ba51dfd9e51..3a0a30b1317 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -36,7 +36,7 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent } from 'vs/platform/label/common/label'; -import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationHandle, INotificationService, IPromptChoice, NoOpNotification, IStatusMessageOptions, NotificationsFilter, INotificationProperties } from 'vs/platform/notification/common/notification'; import { IProgressRunner, IEditorProgressService } from 'vs/platform/progress/common/progress'; import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -250,7 +250,7 @@ export class SimpleNotificationService implements INotificationService { return SimpleNotificationService.NO_OP; } - public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { return SimpleNotificationService.NO_OP; } diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index cbbb5434457..f6dd5bf4a06 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -13,7 +13,7 @@ import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; -import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationService, IPromptChoice, INotificationProperties, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { Disposable } from 'vs/base/common/lifecycle'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -155,7 +155,7 @@ suite('AbstractKeybindingService', () => { showMessageCalls.push({ sev: Severity.Error, message }); return new NoOpNotification(); }, - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties) { throw new Error('not implemented'); }, status(message: string, options?: IStatusMessageOptions) { diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index cc3cb107774..acbbb55a3ca 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -35,6 +35,12 @@ export interface INotificationProperties { * such as future requests will not cause the notification to show again. */ readonly neverShowAgain?: INeverShowAgainOptions; + + /** + * Will be called if the user closed the notification without picking + * any of the provided choices. + */ + onCancel?: () => void; } export enum NeverShowAgainScope { @@ -234,15 +240,6 @@ export interface IPromptChoice { run: () => void; } -export interface IPromptOptions extends INotificationProperties { - - /** - * Will be called if the user closed the notification without picking - * any of the provided choices. - */ - onCancel?: () => void; -} - export interface IStatusMessageOptions { /** @@ -327,7 +324,7 @@ export interface INotificationService { * * @returns a handle on the notification to e.g. hide it or update message, buttons, etc. */ - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle; + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle; /** * Shows a status message in the status area with the provided text. diff --git a/src/vs/platform/notification/test/common/testNotificationService.ts b/src/vs/platform/notification/test/common/testNotificationService.ts index 82d9960eaeb..c41a2e67025 100644 --- a/src/vs/platform/notification/test/common/testNotificationService.ts +++ b/src/vs/platform/notification/test/common/testNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, INotificationProperties, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; export class TestNotificationService implements INotificationService { @@ -28,7 +28,7 @@ export class TestNotificationService implements INotificationService { return TestNotificationService.NO_OP; } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { return TestNotificationService.NO_OP; } diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css index c6be6928d49..dc1fb11e68c 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css @@ -105,18 +105,23 @@ overflow: hidden; } -.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-button { +.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container > .monaco-button-dropdown, +.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container > .monaco-button { + margin: 4px 5px; /* allows button focus outline to be visible */ +} + +.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-text-button { width: fit-content; width: -moz-fit-content; padding: 5px 10px; - margin: 4px 5px; /* allows button focus outline to be visible */ + display: inline-block; /* to enable ellipsis in text overflow */ font-size: 12px; overflow: hidden; text-overflow: ellipsis; } -.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-text-button { - display: inline-block; /* to enable ellipsis in text overflow */ +.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-dropdown-button { + padding: 5px } /** Notification: Progress */ diff --git a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts index a78fd31991a..98de6406d7f 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts @@ -8,11 +8,11 @@ import { clearNode, addDisposableListener, EventType, EventHelper, $ } from 'vs/ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { ButtonGroup } from 'vs/base/browser/ui/button/button'; +import { ButtonBar } from 'vs/base/browser/ui/button/button'; import { attachButtonStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IAction, IActionRunner } from 'vs/base/common/actions'; +import { ActionRunner, ActionWithMenuAction, IAction, IActionRunner } from 'vs/base/common/actions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { dispose, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -285,7 +285,8 @@ export class NotificationTemplateRenderer extends Disposable { @IOpenerService private readonly openerService: IOpenerService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IThemeService private readonly themeService: IThemeService, - @IKeybindingService private readonly keybindingService: IKeybindingService + @IKeybindingService private readonly keybindingService: IKeybindingService, + @IContextMenuService private readonly contextMenuService: IContextMenuService, ) { super(); @@ -441,27 +442,40 @@ export class NotificationTemplateRenderer extends Disposable { const primaryActions = notification.actions ? notification.actions.primary : undefined; if (notification.expanded && isNonEmptyArray(primaryActions)) { - const buttonGroup = new ButtonGroup(this.template.buttonsContainer, primaryActions.length, { title: true /* assign titles to buttons in case they overflow */ }); - buttonGroup.buttons.forEach((button, index) => { - const action = primaryActions[index]; - button.label = action.label; - - this.inputDisposables.add(button.onDidClick(e => { - EventHelper.stop(e, true); - + const that = this; + const actionRunner: IActionRunner = new class extends ActionRunner { + protected async runAction(action: IAction): Promise { // Run action - this.actionRunner.run(action, notification); + that.actionRunner.run(action, notification); // Hide notification (unless explicitly prevented) if (!(action instanceof ChoiceAction) || !action.keepOpen) { notification.close(); } + } + }(); + const buttonToolbar = this.inputDisposables.add(new ButtonBar(this.template.buttonsContainer)); + for (const action of primaryActions) { + const buttonOptions = { title: true, /* assign titles to buttons in case they overflow */ }; + const button = this.inputDisposables.add( + action instanceof ActionWithMenuAction + ? buttonToolbar.addButtonWithDropdown({ + ...buttonOptions, + dropdownMenuOptions: { + contextMenuProvider: this.contextMenuService, + actions: action.actions, + actionRunner + } + }) + : buttonToolbar.addButton(buttonOptions)); + button.label = action.label; + this.inputDisposables.add(button.onDidClick(e => { + EventHelper.stop(e, true); + actionRunner.run(action); })); this.inputDisposables.add(attachButtonStyler(button, this.themeService)); - }); - - this.inputDisposables.add(buttonGroup); + } } } diff --git a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts index 584f71b2491..54ef9377778 100644 --- a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts +++ b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Emitter } from 'vs/base/common/event'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotificationService, IPromptChoice, IPromptOptions, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, INotificationProperties, Severity } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -121,7 +121,7 @@ suite('Experimental Prompts', () => { const stub = instantiationService.stub(ICommandService, 'executeCommand', () => undefined); instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], options: IPromptOptions) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options: INotificationProperties) => { c[0].run(); return undefined!; } @@ -159,7 +159,7 @@ suite('Experimental Prompts', () => { }; instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], options: IPromptOptions) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options: INotificationProperties) => { assert.equal(b, promptText); assert.equal(c.length, 2); options.onCancel!(); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts index dca92acdb04..87b425c726f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IAction } from 'vs/base/common/actions'; +import { Action, ActionWithMenuAction, IAction } from 'vs/base/common/actions'; import { distinct } from 'vs/base/common/arrays'; import { CancelablePromise, createCancelablePromise, raceCancellablePromises, raceCancellation, timeout } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -15,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IExtensionRecommendationNotificationService, RecommendationsNotificationResult, RecommendationSource } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; -import { INotificationHandle, INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; @@ -59,13 +59,23 @@ class RecommendationsNotification { constructor( private readonly severity: Severity, private readonly message: string, - private readonly choices: IPromptChoice[], + private readonly primary: IAction[], + private readonly secondary: IAction[], private readonly notificationService: INotificationService ) { } show(): void { if (!this.notificationHandle) { - this.updateNotificationHandle(this.notificationService.prompt(this.severity, this.message, this.choices, { sticky: true, onCancel: () => this.cancelled = true })); + this.updateNotificationHandle(this.notificationService.notify({ + message: this.message, + severity: this.severity, + actions: { + primary: this.primary, + secondary: this.secondary, + }, + sticky: true, + onCancel: () => this.cancelled = true + })); } } @@ -74,7 +84,17 @@ class RecommendationsNotification { this.onDidCloseDisposable.clear(); this.notificationHandle.close(); this.cancelled = false; - this.updateNotificationHandle(this.notificationService.prompt(this.severity, this.message, this.choices, { silent: true, sticky: false, onCancel: () => this.cancelled = true })); + this.updateNotificationHandle(this.notificationService.notify({ + message: this.message, + severity: this.severity, + actions: { + primary: this.primary, + secondary: this.secondary, + }, + silent: true, + sticky: false, + onCancel: () => this.cancelled = true + })); } } @@ -241,7 +261,8 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec { onDidInstallRecommendedExtensions, onDidShowRecommendedExtensions, onDidCancelRecommendedExtensions, onDidNeverShowRecommendedExtensionsAgain }: RecommendationsNotificationActions): CancelablePromise { return createCancelablePromise(async token => { let accepted = false; - const choices: IPromptChoice[] = []; + const primary: IAction[] = []; + const secondary: IAction[] = []; const installExtensions = async (isMachineScoped?: boolean) => { this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); onDidInstallRecommendedExtensions(extensions); @@ -250,34 +271,24 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec this.extensionManagementService.installExtensions(extensions.map(e => e.gallery!), { isMachineScoped }) ]); }; - choices.push({ - label: localize('install', "Install"), - run: () => installExtensions() - }); + if (this.userDataAutoSyncEnablementService.isEnabled() && this.userDataSyncResourceEnablementService.isResourceEnabled(SyncResource.Extensions)) { - choices.push({ - label: localize('install and do no sync', "Install (Do not sync)"), - run: () => installExtensions(true) - }); + primary.push(new ActionWithMenuAction('install', [ + new Action('install and do no sync', localize('install and do no sync', "Install (Do not sync)"), undefined, true, () => installExtensions(true)) + ], localize('install', "Install"), undefined, true, () => installExtensions())); + } else { + primary.push(new Action('install', localize('install', "Install"), undefined, true, () => installExtensions())); } - choices.push(...[{ - label: localize('show recommendations', "Show Recommendations"), - run: async () => { - onDidShowRecommendedExtensions(extensions); - for (const extension of extensions) { - this.extensionsWorkbenchService.open(extension, { pinned: true }); - } - this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); + primary.push(new Action('show recommendations', localize('show recommendations', "Show Recommendations"), undefined, true, async () => { + onDidShowRecommendedExtensions(extensions); + for (const extension of extensions) { + this.extensionsWorkbenchService.open(extension, { pinned: true }); } - }, { - label: choiceNever, - isSecondary: true, - run: () => { - onDidNeverShowRecommendedExtensionsAgain(extensions); - } - }]); + this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); + })); + secondary.push(new Action('donotshow', choiceNever, undefined, true, async () => onDidNeverShowRecommendedExtensionsAgain(extensions))); try { - accepted = await this.doShowRecommendationsNotification(Severity.Info, message, choices, source, token); + accepted = await this.doShowRecommendationsNotification(Severity.Info, message, primary, secondary, source, token); } catch (error) { if (!isPromiseCanceledError(error)) { throw error; @@ -319,11 +330,11 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec * => If it is not exe based and has higher or same priority as current, hide the current notification after showing it for 3s. * => Otherwise wait until the current notification is hidden. */ - private async doShowRecommendationsNotification(severity: Severity, message: string, choices: IPromptChoice[], source: RecommendationSource, token: CancellationToken): Promise { + private async doShowRecommendationsNotification(severity: Severity, message: string, primary: IAction[], secondary: IAction[], source: RecommendationSource, token: CancellationToken): Promise { const disposables = new DisposableStore(); try { this.recommendationSources.push(source); - const recommendationsNotification = new RecommendationsNotification(severity, message, choices, this.notificationService); + const recommendationsNotification = new RecommendationsNotification(severity, message, primary, secondary, this.notificationService); Event.once(Event.filter(recommendationsNotification.onDidChangeVisibility, e => !e))(() => this.showNextNotification()); if (this.visibleNotification) { const index = this.pendingNotificaitons.length; diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts index ed8a92a9831..caf1d102987 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts @@ -38,7 +38,7 @@ import { IURLService } from 'vs/platform/url/common/url'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity, IPromptChoice, INotificationProperties } from 'vs/platform/notification/common/notification'; import { NativeURLService } from 'vs/platform/url/common/urlService'; import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService'; import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test'; @@ -262,7 +262,7 @@ suite('ExtensionRecommendationsService Test', () => { prompted = false; class TestNotificationService2 extends TestNotificationService { - public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties) { prompted = true; promptedEmitter.fire(); return super.prompt(severity, message, choices, options); diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index 70b48e53088..ca8bc01d8b0 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, INotificationProperties, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; @@ -110,7 +110,7 @@ export class NotificationService extends Disposable implements INotificationServ return handle; } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { const toDispose = new DisposableStore(); // Handle neverShowAgain option accordingly diff --git a/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts b/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts index 50f8ae572ed..2d690e270d1 100644 --- a/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts +++ b/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMessageService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, INotificationProperties, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { mock } from 'vs/base/test/common/mock'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; @@ -54,7 +54,7 @@ const emptyNotificationService = new class implements INotificationService { error(...args: any[]): never { throw new Error('not implemented'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { throw new Error('not implemented'); } status(message: string | Error, options?: IStatusMessageOptions): IDisposable { @@ -85,7 +85,7 @@ class EmptyNotificationService implements INotificationService { error(message: any): void { throw new Error('Method not implemented.'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { throw new Error('Method not implemented'); } status(message: string, options?: IStatusMessageOptions): IDisposable { From 0ffe32409d150a134c73cc42e16f220a8a6575e7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 21:38:10 +0100 Subject: [PATCH 0106/1837] Don't show complete command arguments in the native tooltips --- src/vs/editor/contrib/links/links.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 7f7e37de319..04e8b8aa037 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -47,7 +47,17 @@ function getHoverMessage(link: Link, useMetaKey: boolean): MarkdownString { : nls.localize('links.navigate.kb.alt', "alt + click"); if (link.url) { - const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()} "${label}") (${kb})`); + let nativeLabel = ''; + if (/^command:/i.test(link.url.toString())) { + // Don't show complete command arguments in the native tooltip + const match = link.url.toString().match(/^command:([^?#]+)/); + if (match) { + const commandId = match[1]; + const nativeLabelText = nls.localize('tooltip.explanation', "Execute command {0}", commandId); + nativeLabel = ` "${nativeLabelText}"`; + } + } + const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()}${nativeLabel}) (${kb})`); return hoverMessage; } else { return new MarkdownString().appendText(`${label} (${kb})`); From 7265dfb6d79356a5242c190d3d05fb6d583d2dc4 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 20 Nov 2020 13:03:32 -0800 Subject: [PATCH 0107/1837] testing: smarter change event --- src/vs/vscode.proposed.d.ts | 25 +- src/vs/workbench/api/common/extHostTesting.ts | 193 ++++++++++++++-- .../contrib/testing/common/testCollection.ts | 58 +++-- .../test/browser/api/extHostTesting.test.ts | 218 ++++++++++++------ 4 files changed, 392 insertions(+), 102 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index ad93c03af92..5a2f6c75413 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2200,7 +2200,7 @@ declare module 'vscode' { * null if a top-level test was added or removed. When fired, the consumer * should check the test item and all its children for changes. */ - readonly onDidChangeTest: Event; + readonly onDidChangeTest: Event; /** * An event the fires when all test providers have signalled that the tests @@ -2219,6 +2219,29 @@ declare module 'vscode' { dispose(): void; } + export interface TestChangeEvent { + /** + * List of all tests that are newly added. + */ + readonly added: ReadonlyArray; + + /** + * List of existing tests that have updated. + */ + readonly updated: ReadonlyArray; + + /** + * List of existing tests that have been removed. + */ + readonly removed: ReadonlyArray; + + /** + * Highest node in the test tree under which changes were made. This can + * be easily plugged into events like the TreeDataProvider update event. + */ + readonly commonChangeAncestor: TestItem | null; + } + /** * Tree of tests returned from the provide methods in the {@link TestProvider}. */ diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index 270f66a8847..dd4af111c9a 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -19,7 +19,7 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; import { Disposable } from 'vs/workbench/api/common/extHostTypes'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; -import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import type * as vscode from 'vscode'; const getTestSubscriptionKey = (resource: ExtHostTestingResource, uri: URI) => `${resource}:${uri.toString()}`; @@ -378,27 +378,160 @@ export class SingleUseTestCollection implements IDisposable { */ interface MirroredCollectionTestItem extends IncrementalTestCollectionItem { revived: vscode.TestItem; + depth: number; wrapped?: vscode.TestItem; } +class MirroredChangeCollector extends IncrementalChangeCollector { + private readonly added = new Set(); + private readonly updated = new Set(); + private readonly removed = new Set(); + + private readonly alreadyRemoved = new Set(); + + public get isEmpty() { + return this.added.size === 0 && this.removed.size === 0 && this.updated.size === 0; + } + + constructor(private readonly collection: MirroredTestCollection, private readonly emitter: Emitter) { + super(); + } + + /** + * @override + */ + public add(node: MirroredCollectionTestItem): void { + this.added.add(node); + } + + /** + * @override + */ + public update(node: MirroredCollectionTestItem): void { + Object.assign(node.revived, TestItem.to(node.item)); + if (!this.added.has(node)) { + this.updated.add(node); + } + } + + /** + * @override + */ + public remove(node: MirroredCollectionTestItem): void { + if (this.added.has(node)) { + this.added.delete(node); + return; + } + + this.updated.delete(node); + + if (node.parent && this.alreadyRemoved.has(node.parent)) { + this.alreadyRemoved.add(node.id); + return; + } + + this.removed.add(node); + } + + /** + * @override + */ + public getChangeEvent(): vscode.TestChangeEvent { + const { collection, added, updated, removed } = this; + return { + get added() { return [...added].map(collection.getPublicTestItem, collection); }, + get updated() { return [...updated].map(collection.getPublicTestItem, collection); }, + get removed() { return [...removed].map(collection.getPublicTestItem, collection); }, + get commonChangeAncestor() { + let ancestorPath: MirroredCollectionTestItem[] | undefined; + const buildAncestorPath = (node: MirroredCollectionTestItem | undefined) => { + if (!node) { + return undefined; + } + + // add the node and all its parents to the list of ancestors. If + // the node is detached, do not return a path (its parent will + // also have been passed to remove() and be present) + const path: MirroredCollectionTestItem[] = new Array(node.depth + 1); + for (let i = node.depth; i >= 0; i--) { + if (!node) { + return undefined; // detached child + } + + path[node.depth] = node; + node = node.parent ? collection.getMirroredTestDataById(node.parent) : undefined; + } + + return path; + }; + + const addAncestorPath = (node: MirroredCollectionTestItem) => { + // fast path: if the common ancestor is already the root, no more work to do + if (ancestorPath && ancestorPath.length === 0) { + return; + } + + const thisPath = buildAncestorPath(node); + if (!thisPath) { + return; + } + + if (!ancestorPath) { + ancestorPath = thisPath; + return; + } + + // removes node from the path to the ancestor that don't match + // the corresponding node in *this* path. + for (let i = ancestorPath.length - 1; i >= 0; i--) { + if (ancestorPath[i] !== thisPath[i]) { + ancestorPath.pop(); + } + } + }; + + const addParentAncestor = (node: MirroredCollectionTestItem) => { + if (ancestorPath && ancestorPath.length === 0) { + // no-op + } else if (node.parent === null) { + ancestorPath = []; + } else { + const parent = collection.getMirroredTestDataById(node.parent); + if (parent) { + addAncestorPath(parent); + } + } + }; + + for (const node of added) { addParentAncestor(node); } + for (const node of updated) { addAncestorPath(node); } + for (const node of removed) { addParentAncestor(node); } + + const ancestor = ancestorPath && ancestorPath[ancestorPath.length - 1]; + return ancestor ? collection.getPublicTestItem(ancestor) : null; + }, + }; + } + + public complete() { + if (!this.isEmpty) { + this.emitter.fire(this.getChangeEvent()); + } + } +} + /** * Maintains tests in this extension host sent from the main thread. * @private */ export class MirroredTestCollection extends AbstractIncrementalTestCollection { - private changeEmitter = new Emitter(); + private changeEmitter = new Emitter(); /** * Change emitter that fires with the same sematics as `TestObserver.onDidChangeTests`. */ public readonly onDidChangeTests = this.changeEmitter.event; - /** - * Mapping of mirrored test items to their underlying ID. Given here to avoid - * exposing them to extensions. - */ - protected readonly mirroredTestIds = new WeakMap(); - /** * Gets a list of root test items. */ @@ -412,49 +545,67 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection): vscode.TestItem[] { return itemIds.map(itemId => { const item = this.items.get(itemId); - return item && this.createCollectionItemWrapper(item); + return item && this.getPublicTestItem(item); }).filter(isDefined); } + /** + * + * If the test ID exists, returns its underlying ID. + */ + public getMirroredTestDataById(itemId: string) { + return this.items.get(itemId); + } + /** * If the test item is a mirrored test item, returns its underlying ID. */ public getMirroredTestDataByReference(item: vscode.TestItem) { - const itemId = this.mirroredTestIds.get(item); - return itemId ? this.items.get(itemId) : undefined; + const id = getMirroredItemId(item); + return id ? this.items.get(id) : undefined; } /** * @override */ - protected createItem(item: InternalTestItem): MirroredCollectionTestItem { - return { ...item, revived: TestItem.to(item.item), children: new Set() }; + protected createItem(item: InternalTestItem, parent?: MirroredCollectionTestItem): MirroredCollectionTestItem { + return { ...item, revived: TestItem.to(item.item), depth: parent ? parent.depth + 1 : 0, children: new Set() }; } /** * @override */ - protected onChange(item: MirroredCollectionTestItem | null) { - if (item) { - Object.assign(item.revived, TestItem.to(item.item)); - } - - this.changeEmitter.fire(item ? this.createCollectionItemWrapper(item) : null); + protected createChangeCollector() { + return new MirroredChangeCollector(this, this.changeEmitter); } - private createCollectionItemWrapper(item: MirroredCollectionTestItem): vscode.TestItem { + /** + * Gets the public test item instance for the given mirrored record. + */ + public getPublicTestItem(item: MirroredCollectionTestItem): vscode.TestItem { if (!item.wrapped) { item.wrapped = createMirroredTestItem(item, this); - this.mirroredTestIds.set(item.wrapped, item.id); } return item.wrapped; } } +const getMirroredItemId = (item: vscode.TestItem) => { + return (item as any)[MirroredItemId] as string | undefined; +}; + +const MirroredItemId = Symbol('MirroredItemId'); + const createMirroredTestItem = (internal: MirroredCollectionTestItem, collection: MirroredTestCollection): vscode.TestItem => { const obj = {}; + Object.defineProperty(obj, MirroredItemId, { + enumerable: false, + configurable: false, + value: internal.id, + }); + Object.defineProperty(obj, 'children', { enumerable: true, configurable: false, diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index 398294aaec3..ab76dab7311 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -108,6 +108,33 @@ export interface IncrementalTestCollectionItem extends InternalTestItem { children: Set; } +/** + * The IncrementalChangeCollector is used in the IncrementalTestCollection + * and called with diff changes as they're applied. This is used in the + * ext host to create a cohesive change event from a diff. + */ +export class IncrementalChangeCollector { + /** + * A node was added. + */ + public add(node: T): void { } + + /** + * A node in the collection was updated. + */ + public update(node: T): void { } + + /** + * A node was removed. + */ + public remove(node: T): void { } + + /** + * Called when the diff has been applied. + */ + public complete(): void { } +} + /** * Maintains tests in this extension host sent from the main thread. */ @@ -126,19 +153,23 @@ export abstract class AbstractIncrementalTestCollection(); } /** * Creates a new item for the collection from the internal test item. */ - protected abstract createItem(internal: InternalTestItem): T; + protected abstract createItem(internal: InternalTestItem, parent?: T): T; } diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts index 2c784c043d8..3e9732a0fcd 100644 --- a/src/vs/workbench/test/browser/api/extHostTesting.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -8,7 +8,81 @@ import { MirroredTestCollection, OwnedTestCollection, SingleUseTestCollection } import * as convert from 'vs/workbench/api/common/extHostTypeConverters'; import { TestRunState, TestState } from 'vs/workbench/api/common/extHostTypes'; import { TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; -import { TestItem } from 'vscode'; +import { TestChangeEvent, TestItem } from 'vscode'; + +const stubTest = (label: string): TestItem => ({ + label, + location: undefined, + state: new TestState(TestRunState.Unset), + debuggable: true, + runnable: true, + description: '' +}); + +const assertTreesEqual = (a: Readonly, b: Readonly) => { + assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); + + const aChildren = (a.children ?? []).sort(); + const bChildren = (b.children ?? []).sort(); + assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`); + aChildren.forEach((_, i) => assertTreesEqual(aChildren[i], bChildren[i])); +}; + +const assertTreeListEqual = (a: ReadonlyArray>, b: ReadonlyArray>) => { + assert.strictEqual(a.length, b.length, `expected a.length == n.length`); + a.forEach((_, i) => assertTreesEqual(a[i], b[i])); +}; + +const stubNestedTests = () => ({ + ...stubTest('root'), + children: [ + { ...stubTest('a'), children: [stubTest('aa'), stubTest('ab')] }, + stubTest('b'), + ] +}); + +class TestOwnedTestCollection extends OwnedTestCollection { + public get idToInternal() { + return this.testIdToInternal; + } + + public createForHierarchy(publishDiff: (diff: TestsDiff) => void = () => undefined) { + return new TestSingleUseCollection(this.testIdToInternal, publishDiff); + } +} + +class TestSingleUseCollection extends SingleUseTestCollection { + private idCounter = 0; + + public get itemToInternal() { + return this.testItemToInternal; + } + + public get currentDiff() { + return this.diff; + } + + protected getId() { + return String(this.idCounter++); + } + + public setDiff(diff: TestsDiff) { + this.diff = diff; + } +} + +class TestMirroredCollection extends MirroredTestCollection { + public changeEvent!: TestChangeEvent; + + constructor() { + super(); + this.onDidChangeTests(evt => this.changeEvent = evt); + } + + public get length() { + return this.items.size; + } +} suite('ExtHost Testing', () => { let single: TestSingleUseCollection; @@ -88,8 +162,10 @@ suite('ExtHost Testing', () => { }); suite('MirroredTestCollection', () => { + let m: TestMirroredCollection; + setup(() => m = new TestMirroredCollection()); + test('mirrors creation of the root', () => { - const m = new TestMirroredCollection(); const tests = stubNestedTests(); single.addRoot(tests, 'pid'); m.apply(single.collectDiff()); @@ -98,7 +174,6 @@ suite('ExtHost Testing', () => { }); test('mirrors node deletion', () => { - const m = new TestMirroredCollection(); const tests = stubNestedTests(); single.addRoot(tests, 'pid'); m.apply(single.collectDiff()); @@ -111,7 +186,6 @@ suite('ExtHost Testing', () => { }); test('mirrors node addition', () => { - const m = new TestMirroredCollection(); const tests = stubNestedTests(); single.addRoot(tests, 'pid'); m.apply(single.collectDiff()); @@ -124,7 +198,6 @@ suite('ExtHost Testing', () => { }); test('mirrors node update', () => { - const m = new TestMirroredCollection(); const tests = stubNestedTests(); single.addRoot(tests, 'pid'); m.apply(single.collectDiff()); @@ -134,67 +207,78 @@ suite('ExtHost Testing', () => { assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual); }); + + suite('MirroredChangeCollector', () => { + let tests = stubNestedTests(); + setup(() => { + tests = stubNestedTests(); + single.addRoot(tests, 'pid'); + m.apply(single.collectDiff()); + }); + + test('creates change for root', () => { + assert.deepStrictEqual(m.changeEvent.commonChangeAncestor, null); + assertTreeListEqual(m.changeEvent.added, [ + tests, + tests.children[0], + tests.children![0].children![0], + tests.children![0].children![1], + tests.children[1], + ]); + assertTreeListEqual(m.changeEvent.removed, []); + assertTreeListEqual(m.changeEvent.updated, []); + }); + + test('creates change for delete', () => { + const rm = tests.children.shift()!; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assertTreesEqual(m.changeEvent.commonChangeAncestor!, tests); + assertTreeListEqual(m.changeEvent.added, []); + assertTreeListEqual(m.changeEvent.removed, [ + { ...rm, children: [] }, + { ...rm.children![0], children: [] }, + { ...rm.children![1], children: [] }, + ]); + assertTreeListEqual(m.changeEvent.updated, []); + }); + + test('creates change for update', () => { + tests.children[0].label = 'updated!'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'updated!'); + assertTreeListEqual(m.changeEvent.added, []); + assertTreeListEqual(m.changeEvent.removed, []); + assertTreeListEqual(m.changeEvent.updated, [tests.children[0]]); + }); + + test('is a no-op if a node is added and removed', () => { + const nested = stubNestedTests(); + tests.children.push(nested); + single.onItemChange(tests, 'pid'); + tests.children.pop(); + single.onItemChange(tests, 'pid'); + const previousEvent = m.changeEvent; + m.apply(single.collectDiff()); + assert.strictEqual(m.changeEvent, previousEvent); + }); + + test('is a single-op if a node is added and changed', () => { + const child = stubTest('c'); + tests.children.push(child); + single.onItemChange(tests, 'pid'); + child.label = 'd'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); + assertTreeListEqual(m.changeEvent.added, [child]); + assertTreeListEqual(m.changeEvent.removed, []); + assertTreeListEqual(m.changeEvent.updated, []); + }); + }); }); }); - -const stubTest = (label: string): TestItem => ({ - label, - location: undefined, - state: new TestState(TestRunState.Unset), - debuggable: true, - runnable: true, - description: '' -}); - -const assertTreesEqual = (a: TestItem, b: TestItem) => { - assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); - - const aChildren = (a.children ?? []).sort(); - const bChildren = (b.children ?? []).sort(); - assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`); - aChildren.forEach((_, i) => assertTreesEqual(aChildren[i], bChildren[i])); -}; - -const stubNestedTests = () => ({ - ...stubTest('root'), - children: [ - { ...stubTest('a'), children: [stubTest('aa'), stubTest('ab')] }, - stubTest('b'), - ] -}); - -class TestOwnedTestCollection extends OwnedTestCollection { - public get idToInternal() { - return this.testIdToInternal; - } - - public createForHierarchy(publishDiff: (diff: TestsDiff) => void = () => undefined) { - return new TestSingleUseCollection(this.testIdToInternal, publishDiff); - } -} - -class TestSingleUseCollection extends SingleUseTestCollection { - private idCounter = 0; - - public get itemToInternal() { - return this.testItemToInternal; - } - - public get currentDiff() { - return this.diff; - } - - protected getId() { - return String(this.idCounter++); - } - - public setDiff(diff: TestsDiff) { - this.diff = diff; - } -} - -class TestMirroredCollection extends MirroredTestCollection { - public get length() { - return this.items.size; - } -} From c9d89dd5ce2a41e12c2c3d25df03db0216c96058 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Nov 2020 23:21:19 +0100 Subject: [PATCH 0108/1837] `editor.atomicSoftTabs` can be a simple editor option --- .../editor/browser/controller/mouseTarget.ts | 18 +- .../common/config/commonEditorConfig.ts | 5 - src/vs/editor/common/config/editorOptions.ts | 11 +- .../editor/common/controller/cursorCommon.ts | 2 +- .../common/controller/cursorMoveOperations.ts | 1 - src/vs/editor/common/model.ts | 7 - src/vs/editor/common/model/textModel.ts | 5 - src/vs/editor/common/model/textModelEvents.ts | 1 - .../common/services/modelServiceImpl.ts | 10 - .../common/standalone/standaloneEnums.ts | 223 ++++++++-------- .../browser/standaloneCodeEditor.ts | 5 - src/vs/editor/test/common/editorTestUtils.ts | 2 - src/vs/monaco.d.ts | 237 +++++++++--------- src/vs/vscode.d.ts | 6 - .../workbench/api/browser/mainThreadEditor.ts | 5 - .../workbench/api/common/extHost.protocol.ts | 2 - .../workbench/api/common/extHostTextEditor.ts | 20 +- .../browser/api/extHostTextEditor.test.ts | 39 +-- 18 files changed, 253 insertions(+), 346 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index c117e309eab..e38edef2ece 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -240,6 +240,7 @@ export class HitTestContext { public readonly layoutInfo: EditorLayoutInfo; public readonly viewDomNode: HTMLElement; public readonly lineHeight: number; + public readonly atomicSoftTabs: boolean; public readonly typicalHalfwidthCharacterWidth: number; public readonly lastRenderData: PointerHandlerLastRenderData; @@ -252,6 +253,7 @@ export class HitTestContext { this.layoutInfo = options.get(EditorOption.layoutInfo); this.viewDomNode = viewHelper.viewDomNode; this.lineHeight = options.get(EditorOption.lineHeight); + this.atomicSoftTabs = options.get(EditorOption.atomicSoftTabs); this.typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth; this.lastRenderData = lastRenderData; this._context = context; @@ -1012,14 +1014,12 @@ export class MouseTargetFactory { } private static _snapToSoftTabBoundary(position: Position, viewModel: IViewModel): Position { - if (viewModel.getTextModelOptions().atomicSoftTabs) { - const minColumn = viewModel.getLineMinColumn(position.lineNumber); - const lineContent = viewModel.getLineContent(position.lineNumber); - const { tabSize } = viewModel.getTextModelOptions(); - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); - if (newPosition !== -1) { - return new Position(position.lineNumber, newPosition + minColumn); - } + const minColumn = viewModel.getLineMinColumn(position.lineNumber); + const lineContent = viewModel.getLineContent(position.lineNumber); + const { tabSize } = viewModel.getTextModelOptions(); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); + if (newPosition !== -1) { + return new Position(position.lineNumber, newPosition + minColumn); } return position; } @@ -1056,7 +1056,7 @@ export class MouseTargetFactory { }; } // Snap to the nearest soft tab boundary if atomic soft tabs are enabled. - if (result.position !== null && ctx.model.getTextModelOptions().atomicSoftTabs) { + if (result.position !== null && ctx.atomicSoftTabs) { result.position = this._snapToSoftTabBoundary(result.position, ctx.model); } return result; diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index b2cc94f4d57..bf1d608fc14 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -482,11 +482,6 @@ const editorConfiguration: IConfigurationNode = { default: EDITOR_MODEL_DEFAULTS.insertSpaces, markdownDescription: nls.localize('insertSpaces', "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.") }, - 'editor.atomicSoftTabs': { - type: 'boolean', - default: EDITOR_MODEL_DEFAULTS.atomicSoftTabs, - markdownDescription: nls.localize('atomicSoftTabs', "Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. This means selection will snap to indentation boundaries.") - }, 'editor.detectIndentation': { type: 'boolean', default: EDITOR_MODEL_DEFAULTS.detectIndentation, diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 9de6bc5fd83..d314ae046a3 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -420,6 +420,11 @@ export interface IEditorOptions { * Defaults to advanced. */ autoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full'; + /** + * Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. + * This means selection will snap to indentation boundaries. + */ + atomicSoftTabs?: boolean; /** * Enable format on type. * Defaults to false. @@ -3604,7 +3609,6 @@ export const EDITOR_MODEL_DEFAULTS = { tabSize: 4, indentSize: 4, insertSpaces: true, - atomicSoftTabs: false, detectIndentation: true, trimAutoWhitespace: true, largeFileOptimizations: true @@ -3632,6 +3636,7 @@ export const enum EditorOption { autoIndent, automaticLayout, autoSurround, + atomicSoftTabs, codeLens, codeLensFontFamily, codeLensFontSize, @@ -3860,6 +3865,10 @@ export const EditorOptions = { description: nls.localize('autoSurround', "Controls whether the editor should automatically surround selections when typing quotes or brackets.") } )), + atomicSoftTabs: register(new EditorBooleanOption( + EditorOption.atomicSoftTabs, 'atomicSoftTabs', false, + { description: nls.localize('atomicSoftTabs', "Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. This means selection will snap to indentation boundaries.") } + )), codeLens: register(new EditorBooleanOption( EditorOption.codeLens, 'codeLens', true, { description: nls.localize('codeLens', "Controls whether the editor shows CodeLens.") } diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index c7062a7ff3e..4dbc566441f 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -114,7 +114,7 @@ export class CursorConfiguration { this.tabSize = modelOptions.tabSize; this.indentSize = modelOptions.indentSize; this.insertSpaces = modelOptions.insertSpaces; - this.atomicSoftTabs = modelOptions.atomicSoftTabs; + this.atomicSoftTabs = options.get(EditorOption.atomicSoftTabs); this.lineHeight = options.get(EditorOption.lineHeight); this.pageSize = Math.max(1, Math.floor(layoutInfo.height / this.lineHeight) - 2); this.useTabStops = options.get(EditorOption.useTabStops); diff --git a/src/vs/editor/common/controller/cursorMoveOperations.ts b/src/vs/editor/common/controller/cursorMoveOperations.ts index 84fe061d5a0..6d1ed292cd4 100644 --- a/src/vs/editor/common/controller/cursorMoveOperations.ts +++ b/src/vs/editor/common/controller/cursorMoveOperations.ts @@ -10,7 +10,6 @@ import * as strings from 'vs/base/common/strings'; import { Constants } from 'vs/base/common/uint'; import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations'; - export class CursorPosition { _cursorPositionBrand: void; diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index ef428f2baac..98ce23d7b0e 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -400,7 +400,6 @@ export class TextModelResolvedOptions { readonly tabSize: number; readonly indentSize: number; readonly insertSpaces: boolean; - readonly atomicSoftTabs: boolean; readonly defaultEOL: DefaultEndOfLine; readonly trimAutoWhitespace: boolean; @@ -411,14 +410,12 @@ export class TextModelResolvedOptions { tabSize: number; indentSize: number; insertSpaces: boolean; - atomicSoftTabs: boolean; defaultEOL: DefaultEndOfLine; trimAutoWhitespace: boolean; }) { this.tabSize = Math.max(1, src.tabSize | 0); this.indentSize = src.tabSize | 0; this.insertSpaces = Boolean(src.insertSpaces); - this.atomicSoftTabs = Boolean(src.atomicSoftTabs); this.defaultEOL = src.defaultEOL | 0; this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace); } @@ -431,7 +428,6 @@ export class TextModelResolvedOptions { this.tabSize === other.tabSize && this.indentSize === other.indentSize && this.insertSpaces === other.insertSpaces - && this.atomicSoftTabs === other.atomicSoftTabs && this.defaultEOL === other.defaultEOL && this.trimAutoWhitespace === other.trimAutoWhitespace ); @@ -445,7 +441,6 @@ export class TextModelResolvedOptions { tabSize: this.tabSize !== newOpts.tabSize, indentSize: this.indentSize !== newOpts.indentSize, insertSpaces: this.insertSpaces !== newOpts.insertSpaces, - atomicSoftTabs: this.atomicSoftTabs !== newOpts.atomicSoftTabs, trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace, }; } @@ -458,7 +453,6 @@ export interface ITextModelCreationOptions { tabSize: number; indentSize: number; insertSpaces: boolean; - atomicSoftTabs: boolean; detectIndentation: boolean; trimAutoWhitespace: boolean; defaultEOL: DefaultEndOfLine; @@ -470,7 +464,6 @@ export interface ITextModelUpdateOptions { tabSize?: number; indentSize?: number; insertSpaces?: boolean; - atomicSoftTabs?: boolean; trimAutoWhitespace?: boolean; } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 27999ee0bba..7c8ca731d0f 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -197,7 +197,6 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: EDITOR_MODEL_DEFAULTS.tabSize, indentSize: EDITOR_MODEL_DEFAULTS.indentSize, insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces, - atomicSoftTabs: EDITOR_MODEL_DEFAULTS.atomicSoftTabs, detectIndentation: false, defaultEOL: model.DefaultEndOfLine.LF, trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace, @@ -211,7 +210,6 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: guessedIndentation.tabSize, indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize insertSpaces: guessedIndentation.insertSpaces, - atomicSoftTabs: options.atomicSoftTabs, trimAutoWhitespace: options.trimAutoWhitespace, defaultEOL: options.defaultEOL }); @@ -221,7 +219,6 @@ export class TextModel extends Disposable implements model.ITextModel { tabSize: options.tabSize, indentSize: options.indentSize, insertSpaces: options.insertSpaces, - atomicSoftTabs: options.atomicSoftTabs, trimAutoWhitespace: options.trimAutoWhitespace, defaultEOL: options.defaultEOL }); @@ -622,14 +619,12 @@ export class TextModel extends Disposable implements model.ITextModel { let tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize; let indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize; let insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces; - let atomicSoftTabs = (typeof _newOpts.atomicSoftTabs !== 'undefined') ? _newOpts.atomicSoftTabs : this._options.atomicSoftTabs; let trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace; let newOpts = new model.TextModelResolvedOptions({ tabSize: tabSize, indentSize: indentSize, insertSpaces: insertSpaces, - atomicSoftTabs: atomicSoftTabs, defaultEOL: this._options.defaultEOL, trimAutoWhitespace: trimAutoWhitespace }); diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index 477c0b60433..6511d02173f 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -104,7 +104,6 @@ export interface IModelOptionsChangedEvent { readonly tabSize: boolean; readonly indentSize: boolean; readonly insertSpaces: boolean; - readonly atomicSoftTabs: boolean; readonly trimAutoWhitespace: boolean; } diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index a4c297d58cc..7836fa5de72 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -100,7 +100,6 @@ interface IRawEditorConfig { tabSize?: any; indentSize?: any; insertSpaces?: any; - atomicSoftTabs?: any; detectIndentation?: any; trimAutoWhitespace?: any; creationOptions?: any; @@ -214,11 +213,6 @@ export class ModelServiceImpl extends Disposable implements IModelService { insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces)); } - let atomicSoftTabs = EDITOR_MODEL_DEFAULTS.atomicSoftTabs; - if (config.editor && typeof config.editor.atomicSoftTabs !== 'undefined') { - atomicSoftTabs = (config.editor.atomicSoftTabs === 'false' ? false : Boolean(config.editor.atomicSoftTabs)); - } - let newDefaultEOL = DEFAULT_EOL; const eol = config.eol; if (eol === '\r\n') { @@ -247,7 +241,6 @@ export class ModelServiceImpl extends Disposable implements IModelService { tabSize: tabSize, indentSize: indentSize, insertSpaces: insertSpaces, - atomicSoftTabs: atomicSoftTabs, detectIndentation: detectIndentation, defaultEOL: newDefaultEOL, trimAutoWhitespace: trimAutoWhitespace, @@ -310,7 +303,6 @@ export class ModelServiceImpl extends Disposable implements IModelService { if (currentOptions && (currentOptions.detectIndentation === newOptions.detectIndentation) && (currentOptions.insertSpaces === newOptions.insertSpaces) - && (currentOptions.atomicSoftTabs === newOptions.atomicSoftTabs) && (currentOptions.tabSize === newOptions.tabSize) && (currentOptions.indentSize === newOptions.indentSize) && (currentOptions.trimAutoWhitespace === newOptions.trimAutoWhitespace) @@ -322,13 +314,11 @@ export class ModelServiceImpl extends Disposable implements IModelService { if (newOptions.detectIndentation) { model.detectIndentation(newOptions.insertSpaces, newOptions.tabSize); model.updateOptions({ - atomicSoftTabs: newOptions.atomicSoftTabs, trimAutoWhitespace: newOptions.trimAutoWhitespace }); } else { model.updateOptions({ insertSpaces: newOptions.insertSpaces, - atomicSoftTabs: newOptions.atomicSoftTabs, tabSize: newOptions.tabSize, indentSize: newOptions.indentSize, trimAutoWhitespace: newOptions.trimAutoWhitespace diff --git a/src/vs/editor/common/standalone/standaloneEnums.ts b/src/vs/editor/common/standalone/standaloneEnums.ts index c8a841bd212..7558e45806a 100644 --- a/src/vs/editor/common/standalone/standaloneEnums.ts +++ b/src/vs/editor/common/standalone/standaloneEnums.ts @@ -178,117 +178,118 @@ export enum EditorOption { autoIndent = 8, automaticLayout = 9, autoSurround = 10, - codeLens = 11, - codeLensFontFamily = 12, - codeLensFontSize = 13, - colorDecorators = 14, - columnSelection = 15, - comments = 16, - contextmenu = 17, - copyWithSyntaxHighlighting = 18, - cursorBlinking = 19, - cursorSmoothCaretAnimation = 20, - cursorStyle = 21, - cursorSurroundingLines = 22, - cursorSurroundingLinesStyle = 23, - cursorWidth = 24, - disableLayerHinting = 25, - disableMonospaceOptimizations = 26, - dragAndDrop = 27, - emptySelectionClipboard = 28, - extraEditorClassName = 29, - fastScrollSensitivity = 30, - find = 31, - fixedOverflowWidgets = 32, - folding = 33, - foldingStrategy = 34, - foldingHighlight = 35, - unfoldOnClickAfterEndOfLine = 36, - fontFamily = 37, - fontInfo = 38, - fontLigatures = 39, - fontSize = 40, - fontWeight = 41, - formatOnPaste = 42, - formatOnType = 43, - glyphMargin = 44, - gotoLocation = 45, - hideCursorInOverviewRuler = 46, - highlightActiveIndentGuide = 47, - hover = 48, - inDiffEditor = 49, - letterSpacing = 50, - lightbulb = 51, - lineDecorationsWidth = 52, - lineHeight = 53, - lineNumbers = 54, - lineNumbersMinChars = 55, - links = 56, - matchBrackets = 57, - minimap = 58, - mouseStyle = 59, - mouseWheelScrollSensitivity = 60, - mouseWheelZoom = 61, - multiCursorMergeOverlapping = 62, - multiCursorModifier = 63, - multiCursorPaste = 64, - occurrencesHighlight = 65, - overviewRulerBorder = 66, - overviewRulerLanes = 67, - padding = 68, - parameterHints = 69, - peekWidgetDefaultFocus = 70, - definitionLinkOpensInPeek = 71, - quickSuggestions = 72, - quickSuggestionsDelay = 73, - readOnly = 74, - renameOnType = 75, - renderControlCharacters = 76, - renderIndentGuides = 77, - renderFinalNewline = 78, - renderLineHighlight = 79, - renderLineHighlightOnlyWhenFocus = 80, - renderValidationDecorations = 81, - renderWhitespace = 82, - revealHorizontalRightPadding = 83, - roundedSelection = 84, - rulers = 85, - scrollbar = 86, - scrollBeyondLastColumn = 87, - scrollBeyondLastLine = 88, - scrollPredominantAxis = 89, - selectionClipboard = 90, - selectionHighlight = 91, - selectOnLineNumbers = 92, - showFoldingControls = 93, - showUnused = 94, - snippetSuggestions = 95, - smartSelect = 96, - smoothScrolling = 97, - stopRenderingLineAfter = 98, - suggest = 99, - suggestFontSize = 100, - suggestLineHeight = 101, - suggestOnTriggerCharacters = 102, - suggestSelection = 103, - tabCompletion = 104, - tabIndex = 105, - unusualLineTerminators = 106, - useTabStops = 107, - wordSeparators = 108, - wordWrap = 109, - wordWrapBreakAfterCharacters = 110, - wordWrapBreakBeforeCharacters = 111, - wordWrapColumn = 112, - wordWrapMinified = 113, - wrappingIndent = 114, - wrappingStrategy = 115, - showDeprecated = 116, - editorClassName = 117, - pixelRatio = 118, - tabFocusMode = 119, - layoutInfo = 120, - wrappingInfo = 121 + atomicSoftTabs = 11, + codeLens = 12, + codeLensFontFamily = 13, + codeLensFontSize = 14, + colorDecorators = 15, + columnSelection = 16, + comments = 17, + contextmenu = 18, + copyWithSyntaxHighlighting = 19, + cursorBlinking = 20, + cursorSmoothCaretAnimation = 21, + cursorStyle = 22, + cursorSurroundingLines = 23, + cursorSurroundingLinesStyle = 24, + cursorWidth = 25, + disableLayerHinting = 26, + disableMonospaceOptimizations = 27, + dragAndDrop = 28, + emptySelectionClipboard = 29, + extraEditorClassName = 30, + fastScrollSensitivity = 31, + find = 32, + fixedOverflowWidgets = 33, + folding = 34, + foldingStrategy = 35, + foldingHighlight = 36, + unfoldOnClickAfterEndOfLine = 37, + fontFamily = 38, + fontInfo = 39, + fontLigatures = 40, + fontSize = 41, + fontWeight = 42, + formatOnPaste = 43, + formatOnType = 44, + glyphMargin = 45, + gotoLocation = 46, + hideCursorInOverviewRuler = 47, + highlightActiveIndentGuide = 48, + hover = 49, + inDiffEditor = 50, + letterSpacing = 51, + lightbulb = 52, + lineDecorationsWidth = 53, + lineHeight = 54, + lineNumbers = 55, + lineNumbersMinChars = 56, + links = 57, + matchBrackets = 58, + minimap = 59, + mouseStyle = 60, + mouseWheelScrollSensitivity = 61, + mouseWheelZoom = 62, + multiCursorMergeOverlapping = 63, + multiCursorModifier = 64, + multiCursorPaste = 65, + occurrencesHighlight = 66, + overviewRulerBorder = 67, + overviewRulerLanes = 68, + padding = 69, + parameterHints = 70, + peekWidgetDefaultFocus = 71, + definitionLinkOpensInPeek = 72, + quickSuggestions = 73, + quickSuggestionsDelay = 74, + readOnly = 75, + renameOnType = 76, + renderControlCharacters = 77, + renderIndentGuides = 78, + renderFinalNewline = 79, + renderLineHighlight = 80, + renderLineHighlightOnlyWhenFocus = 81, + renderValidationDecorations = 82, + renderWhitespace = 83, + revealHorizontalRightPadding = 84, + roundedSelection = 85, + rulers = 86, + scrollbar = 87, + scrollBeyondLastColumn = 88, + scrollBeyondLastLine = 89, + scrollPredominantAxis = 90, + selectionClipboard = 91, + selectionHighlight = 92, + selectOnLineNumbers = 93, + showFoldingControls = 94, + showUnused = 95, + snippetSuggestions = 96, + smartSelect = 97, + smoothScrolling = 98, + stopRenderingLineAfter = 99, + suggest = 100, + suggestFontSize = 101, + suggestLineHeight = 102, + suggestOnTriggerCharacters = 103, + suggestSelection = 104, + tabCompletion = 105, + tabIndex = 106, + unusualLineTerminators = 107, + useTabStops = 108, + wordSeparators = 109, + wordWrap = 110, + wordWrapBreakAfterCharacters = 111, + wordWrapBreakBeforeCharacters = 112, + wordWrapColumn = 113, + wordWrapMinified = 114, + wrappingIndent = 115, + wrappingStrategy = 116, + showDeprecated = 117, + editorClassName = 118, + pixelRatio = 119, + tabFocusMode = 120, + layoutInfo = 121, + wrappingInfo = 122 } /** diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index b3921e14842..9344ee801c6 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -93,11 +93,6 @@ export interface IGlobalEditorOptions { * Defaults to true. */ insertSpaces?: boolean; - /** - * Treat soft tabs like hard tabs. - * Defaults to false. - */ - atomicSoftTabs?: boolean; /** * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Defaults to true. diff --git a/src/vs/editor/test/common/editorTestUtils.ts b/src/vs/editor/test/common/editorTestUtils.ts index b3adbf3320f..8298cf24b81 100644 --- a/src/vs/editor/test/common/editorTestUtils.ts +++ b/src/vs/editor/test/common/editorTestUtils.ts @@ -21,7 +21,6 @@ export interface IRelaxedTextModelCreationOptions { tabSize?: number; indentSize?: number; insertSpaces?: boolean; - atomicSoftTabs?: boolean; detectIndentation?: boolean; trimAutoWhitespace?: boolean; defaultEOL?: DefaultEndOfLine; @@ -34,7 +33,6 @@ export function createTextModel(text: string, _options: IRelaxedTextModelCreatio tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize), indentSize: (typeof _options.indentSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.indentSize : _options.indentSize), insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces), - atomicSoftTabs: (typeof _options.atomicSoftTabs === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.atomicSoftTabs : _options.atomicSoftTabs), detectIndentation: (typeof _options.detectIndentation === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.detectIndentation : _options.detectIndentation), trimAutoWhitespace: (typeof _options.trimAutoWhitespace === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.trimAutoWhitespace : _options.trimAutoWhitespace), defaultEOL: (typeof _options.defaultEOL === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL : _options.defaultEOL), diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 4e4e1acfd78..fdba8442cc4 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1095,11 +1095,6 @@ declare namespace monaco.editor { * Defaults to true. */ insertSpaces?: boolean; - /** - * Treat soft tabs like hard tabs. - * Defaults to false. - */ - atomicSoftTabs?: boolean; /** * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Defaults to true. @@ -1584,7 +1579,6 @@ declare namespace monaco.editor { readonly tabSize: number; readonly indentSize: number; readonly insertSpaces: boolean; - readonly atomicSoftTabs: boolean; readonly defaultEOL: DefaultEndOfLine; readonly trimAutoWhitespace: boolean; } @@ -1593,7 +1587,6 @@ declare namespace monaco.editor { tabSize?: number; indentSize?: number; insertSpaces?: boolean; - atomicSoftTabs?: boolean; trimAutoWhitespace?: boolean; } @@ -2467,7 +2460,6 @@ declare namespace monaco.editor { readonly tabSize: boolean; readonly indentSize: boolean; readonly insertSpaces: boolean; - readonly atomicSoftTabs: boolean; readonly trimAutoWhitespace: boolean; } @@ -2975,6 +2967,11 @@ declare namespace monaco.editor { * Defaults to advanced. */ autoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full'; + /** + * Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. + * This means selection will snap to indentation boundaries. + */ + atomicSoftTabs?: boolean; /** * Enable format on type. * Defaults to false. @@ -3906,117 +3903,118 @@ declare namespace monaco.editor { autoIndent = 8, automaticLayout = 9, autoSurround = 10, - codeLens = 11, - codeLensFontFamily = 12, - codeLensFontSize = 13, - colorDecorators = 14, - columnSelection = 15, - comments = 16, - contextmenu = 17, - copyWithSyntaxHighlighting = 18, - cursorBlinking = 19, - cursorSmoothCaretAnimation = 20, - cursorStyle = 21, - cursorSurroundingLines = 22, - cursorSurroundingLinesStyle = 23, - cursorWidth = 24, - disableLayerHinting = 25, - disableMonospaceOptimizations = 26, - dragAndDrop = 27, - emptySelectionClipboard = 28, - extraEditorClassName = 29, - fastScrollSensitivity = 30, - find = 31, - fixedOverflowWidgets = 32, - folding = 33, - foldingStrategy = 34, - foldingHighlight = 35, - unfoldOnClickAfterEndOfLine = 36, - fontFamily = 37, - fontInfo = 38, - fontLigatures = 39, - fontSize = 40, - fontWeight = 41, - formatOnPaste = 42, - formatOnType = 43, - glyphMargin = 44, - gotoLocation = 45, - hideCursorInOverviewRuler = 46, - highlightActiveIndentGuide = 47, - hover = 48, - inDiffEditor = 49, - letterSpacing = 50, - lightbulb = 51, - lineDecorationsWidth = 52, - lineHeight = 53, - lineNumbers = 54, - lineNumbersMinChars = 55, - links = 56, - matchBrackets = 57, - minimap = 58, - mouseStyle = 59, - mouseWheelScrollSensitivity = 60, - mouseWheelZoom = 61, - multiCursorMergeOverlapping = 62, - multiCursorModifier = 63, - multiCursorPaste = 64, - occurrencesHighlight = 65, - overviewRulerBorder = 66, - overviewRulerLanes = 67, - padding = 68, - parameterHints = 69, - peekWidgetDefaultFocus = 70, - definitionLinkOpensInPeek = 71, - quickSuggestions = 72, - quickSuggestionsDelay = 73, - readOnly = 74, - renameOnType = 75, - renderControlCharacters = 76, - renderIndentGuides = 77, - renderFinalNewline = 78, - renderLineHighlight = 79, - renderLineHighlightOnlyWhenFocus = 80, - renderValidationDecorations = 81, - renderWhitespace = 82, - revealHorizontalRightPadding = 83, - roundedSelection = 84, - rulers = 85, - scrollbar = 86, - scrollBeyondLastColumn = 87, - scrollBeyondLastLine = 88, - scrollPredominantAxis = 89, - selectionClipboard = 90, - selectionHighlight = 91, - selectOnLineNumbers = 92, - showFoldingControls = 93, - showUnused = 94, - snippetSuggestions = 95, - smartSelect = 96, - smoothScrolling = 97, - stopRenderingLineAfter = 98, - suggest = 99, - suggestFontSize = 100, - suggestLineHeight = 101, - suggestOnTriggerCharacters = 102, - suggestSelection = 103, - tabCompletion = 104, - tabIndex = 105, - unusualLineTerminators = 106, - useTabStops = 107, - wordSeparators = 108, - wordWrap = 109, - wordWrapBreakAfterCharacters = 110, - wordWrapBreakBeforeCharacters = 111, - wordWrapColumn = 112, - wordWrapMinified = 113, - wrappingIndent = 114, - wrappingStrategy = 115, - showDeprecated = 116, - editorClassName = 117, - pixelRatio = 118, - tabFocusMode = 119, - layoutInfo = 120, - wrappingInfo = 121 + atomicSoftTabs = 11, + codeLens = 12, + codeLensFontFamily = 13, + codeLensFontSize = 14, + colorDecorators = 15, + columnSelection = 16, + comments = 17, + contextmenu = 18, + copyWithSyntaxHighlighting = 19, + cursorBlinking = 20, + cursorSmoothCaretAnimation = 21, + cursorStyle = 22, + cursorSurroundingLines = 23, + cursorSurroundingLinesStyle = 24, + cursorWidth = 25, + disableLayerHinting = 26, + disableMonospaceOptimizations = 27, + dragAndDrop = 28, + emptySelectionClipboard = 29, + extraEditorClassName = 30, + fastScrollSensitivity = 31, + find = 32, + fixedOverflowWidgets = 33, + folding = 34, + foldingStrategy = 35, + foldingHighlight = 36, + unfoldOnClickAfterEndOfLine = 37, + fontFamily = 38, + fontInfo = 39, + fontLigatures = 40, + fontSize = 41, + fontWeight = 42, + formatOnPaste = 43, + formatOnType = 44, + glyphMargin = 45, + gotoLocation = 46, + hideCursorInOverviewRuler = 47, + highlightActiveIndentGuide = 48, + hover = 49, + inDiffEditor = 50, + letterSpacing = 51, + lightbulb = 52, + lineDecorationsWidth = 53, + lineHeight = 54, + lineNumbers = 55, + lineNumbersMinChars = 56, + links = 57, + matchBrackets = 58, + minimap = 59, + mouseStyle = 60, + mouseWheelScrollSensitivity = 61, + mouseWheelZoom = 62, + multiCursorMergeOverlapping = 63, + multiCursorModifier = 64, + multiCursorPaste = 65, + occurrencesHighlight = 66, + overviewRulerBorder = 67, + overviewRulerLanes = 68, + padding = 69, + parameterHints = 70, + peekWidgetDefaultFocus = 71, + definitionLinkOpensInPeek = 72, + quickSuggestions = 73, + quickSuggestionsDelay = 74, + readOnly = 75, + renameOnType = 76, + renderControlCharacters = 77, + renderIndentGuides = 78, + renderFinalNewline = 79, + renderLineHighlight = 80, + renderLineHighlightOnlyWhenFocus = 81, + renderValidationDecorations = 82, + renderWhitespace = 83, + revealHorizontalRightPadding = 84, + roundedSelection = 85, + rulers = 86, + scrollbar = 87, + scrollBeyondLastColumn = 88, + scrollBeyondLastLine = 89, + scrollPredominantAxis = 90, + selectionClipboard = 91, + selectionHighlight = 92, + selectOnLineNumbers = 93, + showFoldingControls = 94, + showUnused = 95, + snippetSuggestions = 96, + smartSelect = 97, + smoothScrolling = 98, + stopRenderingLineAfter = 99, + suggest = 100, + suggestFontSize = 101, + suggestLineHeight = 102, + suggestOnTriggerCharacters = 103, + suggestSelection = 104, + tabCompletion = 105, + tabIndex = 106, + unusualLineTerminators = 107, + useTabStops = 108, + wordSeparators = 109, + wordWrap = 110, + wordWrapBreakAfterCharacters = 111, + wordWrapBreakBeforeCharacters = 112, + wordWrapColumn = 113, + wordWrapMinified = 114, + wrappingIndent = 115, + wrappingStrategy = 116, + showDeprecated = 117, + editorClassName = 118, + pixelRatio = 119, + tabFocusMode = 120, + layoutInfo = 121, + wrappingInfo = 122 } export const EditorOptions: { acceptSuggestionOnCommitCharacter: IEditorOption; @@ -4030,6 +4028,7 @@ declare namespace monaco.editor { autoIndent: IEditorOption; automaticLayout: IEditorOption; autoSurround: IEditorOption; + atomicSoftTabs: IEditorOption; codeLens: IEditorOption; codeLensFontFamily: IEditorOption; codeLensFontSize: IEditorOption; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 91883be46bb..117744ceb92 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -655,12 +655,6 @@ declare module 'vscode' { */ insertSpaces?: boolean | string; - /** - * When navigating treat soft tabs like hard tabs. This means you can't position - * the cursor in the middle of an indentation, even if it is made of space. - */ - atomicSoftTabs?: boolean; - /** * The rendering style of the cursor in this editor. * When getting a text editor's options, this property will always be present. diff --git a/src/vs/workbench/api/browser/mainThreadEditor.ts b/src/vs/workbench/api/browser/mainThreadEditor.ts index dfd926d2113..f805b7f9cbe 100644 --- a/src/vs/workbench/api/browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/browser/mainThreadEditor.ts @@ -80,7 +80,6 @@ export class MainThreadTextEditorProperties { insertSpaces: modelOptions.insertSpaces, tabSize: modelOptions.tabSize, indentSize: modelOptions.indentSize, - atomicSoftTabs: modelOptions.atomicSoftTabs, cursorStyle: cursorStyle, lineNumbers: lineNumbers }; @@ -149,7 +148,6 @@ export class MainThreadTextEditorProperties { a.tabSize === b.tabSize && a.indentSize === b.indentSize && a.insertSpaces === b.insertSpaces - && a.atomicSoftTabs === b.atomicSoftTabs && a.cursorStyle === b.cursorStyle && a.lineNumbers === b.lineNumbers ); @@ -376,9 +374,6 @@ export class MainThreadTextEditor { if (typeof newConfiguration.insertSpaces !== 'undefined') { newOpts.insertSpaces = newConfiguration.insertSpaces; } - if (typeof newConfiguration.atomicSoftTabs !== 'undefined') { - newOpts.atomicSoftTabs = newConfiguration.atomicSoftTabs; - } if (typeof newConfiguration.tabSize !== 'undefined') { newOpts.tabSize = newConfiguration.tabSize; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 704fdee51df..6ca43431728 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -234,7 +234,6 @@ export interface ITextEditorConfigurationUpdate { tabSize?: number | 'auto'; indentSize?: number | 'tabSize'; insertSpaces?: boolean | 'auto'; - atomicSoftTabs?: boolean; cursorStyle?: TextEditorCursorStyle; lineNumbers?: RenderLineNumbersType; } @@ -243,7 +242,6 @@ export interface IResolvedTextEditorConfiguration { tabSize: number; indentSize: number; insertSpaces: boolean; - atomicSoftTabs: boolean; cursorStyle: TextEditorCursorStyle; lineNumbers: RenderLineNumbersType; } diff --git a/src/vs/workbench/api/common/extHostTextEditor.ts b/src/vs/workbench/api/common/extHostTextEditor.ts index fe713225d9c..635a5c6c253 100644 --- a/src/vs/workbench/api/common/extHostTextEditor.ts +++ b/src/vs/workbench/api/common/extHostTextEditor.ts @@ -143,7 +143,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { private _tabSize!: number; private _indentSize!: number; private _insertSpaces!: boolean; - private _atomicSoftTabs!: boolean; private _cursorStyle!: TextEditorCursorStyle; private _lineNumbers!: TextEditorLineNumbersStyle; @@ -158,7 +157,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { this._tabSize = source.tabSize; this._indentSize = source.indentSize; this._insertSpaces = source.insertSpaces; - this._atomicSoftTabs = source.atomicSoftTabs; this._cursorStyle = source.cursorStyle; this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers); } @@ -271,23 +269,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { })); } - public get atomicSoftTabs(): boolean { - return this._atomicSoftTabs; - } - - public set atomicSoftTabs(value: boolean) { - const atomicSoftTabs = value; - if (this._atomicSoftTabs === atomicSoftTabs) { - // nothing to do - return; - } - // reflect the new atomicSoftTabs value immediately - this._atomicSoftTabs = atomicSoftTabs; - this._warnOnError(this._proxy.$trySetOptions(this._id, { - atomicSoftTabs - })); - } - public get cursorStyle(): TextEditorCursorStyle { return this._cursorStyle; } @@ -678,3 +659,4 @@ export class ExtHostTextEditor implements vscode.TextEditor { }); } } + diff --git a/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts b/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts index 97a1164075d..931313c55e9 100644 --- a/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTextEditor.test.ts @@ -20,7 +20,7 @@ suite('ExtHostTextEditor', () => { ], '\n', 1, 'text', false); setup(() => { - editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); + editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); }); test('disposed editor', () => { @@ -47,7 +47,7 @@ suite('ExtHostTextEditor', () => { applyCount += 1; return Promise.resolve(true); } - }, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); + }, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); await editor.edit(edit => { }); assert.equal(applyCount, 0); @@ -91,7 +91,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }, new NullLogService()); @@ -107,7 +106,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: opts.tabSize, indentSize: opts.indentSize, insertSpaces: opts.insertSpaces, - atomicSoftTabs: opts.atomicSoftTabs, cursorStyle: opts.cursorStyle, lineNumbers: opts.lineNumbers }; @@ -120,7 +118,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -133,7 +130,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 1, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -146,7 +142,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 2, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -159,7 +154,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 2, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -172,7 +166,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -185,7 +178,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -198,7 +190,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -211,7 +202,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -224,7 +214,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -237,7 +226,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -250,7 +238,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 1, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -263,7 +250,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 2, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -276,7 +262,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 2, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -289,7 +274,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -302,7 +286,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -315,7 +298,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -328,7 +310,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -341,7 +322,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -354,7 +334,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -367,7 +346,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -380,7 +358,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -393,7 +370,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -406,7 +382,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -419,7 +394,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -432,7 +406,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -445,7 +418,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Block, lineNumbers: RenderLineNumbersType.On }); @@ -458,7 +430,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -471,7 +442,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.Off }); @@ -482,7 +452,6 @@ suite('ExtHostTextEditorOptions', () => { opts.assign({ tabSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: TextEditorLineNumbersStyle.On }); @@ -490,7 +459,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -506,7 +474,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: true, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -522,7 +489,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 3, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Line, lineNumbers: RenderLineNumbersType.On }); @@ -538,7 +504,6 @@ suite('ExtHostTextEditorOptions', () => { tabSize: 4, indentSize: 4, insertSpaces: false, - atomicSoftTabs: false, cursorStyle: TextEditorCursorStyle.Block, lineNumbers: RenderLineNumbersType.Relative }); From 93e7dda5a17d1f646be52a8a427bd193506b59c5 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Nov 2020 14:33:18 -0800 Subject: [PATCH 0109/1837] Error if a new ScopedContextKeyService conflicts with an existing ScopedContextKeyService (#110363) `ScopedContextKeyService` stores values using a dom attribute. This means that if you create two ScopedContextKeyService instances on a node, the second instance will end up effecting the first. This seems unexpected to me and cause a lot of confusion while working on c8877809c95b7eba887ec4269ce99de94fdb14c7. The specific bug I hit: - Create scoped service A - Create scoped service B on the same element - Dispose of scoped service A - This also ends up clearing the context storage value for scoped service B This PR makes creating a scoped context key service on a dom node that already has a scoped context key service an error --- src/vs/platform/contextkey/browser/contextKeyService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 20e6021ff6d..7c24fe8647d 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -416,6 +416,9 @@ class ScopedContextKeyService extends AbstractContextKeyService { if (domNode) { this._domNode = domNode; + if (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) { + throw new Error('Element already has context attribute'); + } this._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId)); } } From 3880463037f648a4a3ec727b01ef46c9de2e6f28 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Nov 2020 15:10:41 -0800 Subject: [PATCH 0110/1837] Temporarily only warn on duplicate scoped context The error seems to be hit with the current notebook tests --- src/vs/platform/contextkey/browser/contextKeyService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 7c24fe8647d..21320c0d6b8 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -417,7 +417,7 @@ class ScopedContextKeyService extends AbstractContextKeyService { if (domNode) { this._domNode = domNode; if (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) { - throw new Error('Element already has context attribute'); + console.error('Element already has context attribute'); } this._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId)); } From 06be9f4029eaa33d4d4867f85dd9dadc63423c68 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 20 Nov 2020 15:14:17 -0800 Subject: [PATCH 0111/1837] testing: tests and speed improvements --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHostTesting.ts | 72 ++++++++++++------- src/vs/workbench/api/common/extHostTypes.ts | 11 +++ .../test/browser/api/extHostTesting.test.ts | 30 +++++++- 4 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5a2f6c75413..c595e1876e8 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2359,7 +2359,7 @@ declare module 'vscode' { runnable?: boolean; /** - * Whether this test item can be debugged. + * Whether this test item can be debugged. Defaults to `false` if not provided. */ debuggable?: boolean; diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index dd4af111c9a..02fc32cbffb 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -17,7 +17,7 @@ import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTes import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; -import { Disposable } from 'vs/workbench/api/common/extHostTypes'; +import { Disposable, RequiredTestItem } from 'vs/workbench/api/common/extHostTypes'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import type * as vscode from 'vscode'; @@ -178,7 +178,7 @@ export class ExtHostTesting implements ExtHostTestingShape { } } -const keyMap: { [K in keyof Omit, 'children'>]: null } = { +const keyMap: { [K in keyof Omit]: null } = { label: null, location: null, state: null, @@ -215,6 +215,9 @@ export interface OwnedCollectionTestItem extends InternalTestItem { previousEquals: (v: vscode.TestItem) => boolean; } +/** + * @private + */ export class OwnedTestCollection { protected readonly testIdToInternal = new Map(); @@ -542,11 +545,16 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection): vscode.TestItem[] { - return itemIds.map(itemId => { + public getAllAsTestItem(itemIds: Iterable): vscode.TestItem[] { + let output: vscode.TestItem[] = []; + for (const itemId of itemIds) { const item = this.items.get(itemId); - return item && this.getPublicTestItem(item); - }).filter(isDefined); + if (item) { + output.push(this.getPublicTestItem(item)); + } + } + + return output; } /** @@ -584,7 +592,7 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection { const MirroredItemId = Symbol('MirroredItemId'); -const createMirroredTestItem = (internal: MirroredCollectionTestItem, collection: MirroredTestCollection): vscode.TestItem => { - const obj = {}; +class ExtHostTestItem implements vscode.TestItem, RequiredTestItem { + readonly #internal: MirroredCollectionTestItem; + readonly #collection: MirroredTestCollection; - Object.defineProperty(obj, MirroredItemId, { - enumerable: false, - configurable: false, - value: internal.id, - }); + public get label() { return this.#internal.revived.label; } + public get description() { return this.#internal.revived.description; } + public get state() { return this.#internal.revived.state; } + public get location() { return this.#internal.revived.location; } + public get runnable() { return this.#internal.revived.runnable ?? true; } + public get debuggable() { return this.#internal.revived.debuggable ?? false; } + public get children() { + return this.#collection.getAllAsTestItem(this.#internal.children); + } - Object.defineProperty(obj, 'children', { - enumerable: true, - configurable: false, - get: () => collection.getAllAsTestItem([...internal.children]) - }); + get [MirroredItemId]() { return this.#internal.id; } - simpleProps.forEach(prop => Object.defineProperty(obj, prop, { - enumerable: true, - configurable: false, - get: () => internal.revived[prop], - })); + constructor(internal: MirroredCollectionTestItem, collection: MirroredTestCollection) { + this.#internal = internal; + this.#collection = collection; + } - return obj as any; -}; + public toJSON() { + const serialized: RequiredTestItem = { + label: this.label, + description: this.description, + state: this.state, + location: this.location, + runnable: this.runnable, + debuggable: this.debuggable, + children: this.children.map(c => (c as ExtHostTestItem).toJSON()), + }; + + return serialized; + } +} interface IObserverData { observers: number; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 1013635962d..8788574ca1b 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2940,4 +2940,15 @@ export class TestState { } } +type AllowedUndefined = 'description' | 'location'; + +/** + * Test item without any optional properties. Only some properties are + * permitted to be undefined, but they must still exist. + */ +export type RequiredTestItem = { + [K in keyof Required]: K extends AllowedUndefined ? vscode.TestItem[K] : Required[K] +}; + + //#endregion diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts index 3e9732a0fcd..9ed0f4b2557 100644 --- a/src/vs/workbench/test/browser/api/extHostTesting.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -19,8 +19,16 @@ const stubTest = (label: string): TestItem => ({ description: '' }); +const simplify = (item: TestItem) => { + if ('toJSON' in item) { + item = (item as any).toJSON(); + } + + return { ...item, children: undefined }; +}; + const assertTreesEqual = (a: Readonly, b: Readonly) => { - assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); + assert.deepStrictEqual(simplify(a), simplify(b)); const aChildren = (a.children ?? []).sort(); const bChildren = (b.children ?? []).sort(); @@ -274,11 +282,29 @@ suite('ExtHost Testing', () => { single.onItemChange(tests, 'pid'); m.apply(single.collectDiff()); - assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); assertTreeListEqual(m.changeEvent.added, [child]); assertTreeListEqual(m.changeEvent.removed, []); assertTreeListEqual(m.changeEvent.updated, []); }); + + test('gets the common ancestor (1)', () => { + tests.children![0].children![0].label = 'za'; + tests.children![0].children![1].label = 'zb'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'a'); + }); + + test('gets the common ancestor (2)', () => { + tests.children![0].children![0].label = 'za'; + tests.children![1].label = 'ab'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); + }); }); }); }); From 9195c9ab14ddc6e5aa85f357978fb792725e6d10 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 20 Nov 2020 15:28:18 -0800 Subject: [PATCH 0112/1837] Expose TS server tracing (#110534) * Add typescript.tsserver.enableTracing setting * Document typescript.tsserver.enableTracing setting --- .../typescript-language-features/package.json | 6 +++++ .../package.nls.json | 1 + .../src/tsServer/spawner.ts | 22 ++++++++++++++++--- .../src/utils/configuration.ts | 6 +++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 2f53537dfe9..b7f499afb86 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -197,6 +197,12 @@ "description": "%typescript.implementationsCodeLens.enabled%", "scope": "window" }, + "typescript.tsserver.enableTracing": { + "type": "boolean", + "default": false, + "description": "%typescript.tsserver.enableTracing%", + "scope": "window" + }, "typescript.tsserver.log": { "type": "string", "enum": [ diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index 5ddd514e16b..4283596c2ff 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -8,6 +8,7 @@ "typescript.tsdk.desc": "Specifies the folder path to the tsserver and lib*.d.ts files under a TypeScript install to use for IntelliSense, for example: `./node_modules/typescript/lib`.\n\n- When specified as a user setting, the TypeScript version from `typescript.tsdk` automatically replaces the built-in TypeScript version.\n- When specified as a workspace setting, `typescript.tsdk` allows you to switch to use that workspace version of TypeScript for IntelliSense with the `TypeScript: Select TypeScript version` command.\n\nSee the [TypeScript documentation](https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-newer-typescript-versions) for more detail about managing TypeScript versions.", "typescript.disableAutomaticTypeAcquisition": "Disables automatic type acquisition. Automatic type acquisition fetches `@types` packages from npm to improve IntelliSense for external libraries.", "typescript.enablePromptUseWorkspaceTsdk": "Enables prompting of users to use the TypeScript version configured in the workspace for Intellisense.", + "typescript.tsserver.enableTracing": "Enables tracing TS server performance to a directory. These trace files can be used to diagnose TS Server performance issues. The log may contain file paths, source code, and other potentially sensitive information from your project.", "typescript.tsserver.log": "Enables logging of the TS server to a file. This log can be used to diagnose TS Server issues. The log may contain file paths, source code, and other potentially sensitive information from your project.", "typescript.tsserver.pluginPaths": "Additional paths to discover TypeScript Language Service plugins.", "typescript.tsserver.pluginPaths.item": "Either an absolute or relative path. Relative path will be resolved against workspace folder(s).", diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts index a3ad0abb1c7..58fd431edc7 100644 --- a/extensions/typescript-language-features/src/tsServer/spawner.ts +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -128,7 +128,7 @@ export class TypeScriptServerSpawner { const apiVersion = version.apiVersion || API.defaultVersion; const canceller = cancellerFactory.create(kind, this._tracer); - const { args, tsServerLogFile } = this.getTsServerArgs(kind, configuration, version, apiVersion, pluginManager, canceller.cancellationPipeName); + const { args, tsServerLogFile, tsServerTraceDirectory } = this.getTsServerArgs(kind, configuration, version, apiVersion, pluginManager, canceller.cancellationPipeName); if (TypeScriptServerSpawner.isLoggingEnabled(configuration)) { if (tsServerLogFile) { @@ -138,6 +138,14 @@ export class TypeScriptServerSpawner { } } + if (configuration.enableTsServerTracing) { + if (tsServerTraceDirectory) { + this._logger.info(`<${kind}> Trace directory: ${tsServerTraceDirectory}`); + } else { + this._logger.error(`<${kind}> Could not create trace directory`); + } + } + this._logger.info(`<${kind}> Forking...`); const process = this._factory.fork(version.tsServerPath, args, kind, configuration, this._versionManager); this._logger.info(`<${kind}> Starting...`); @@ -173,9 +181,10 @@ export class TypeScriptServerSpawner { apiVersion: API, pluginManager: PluginManager, cancellationPipeName: string | undefined, - ): { args: string[], tsServerLogFile: string | undefined } { + ): { args: string[], tsServerLogFile: string | undefined, tsServerTraceDirectory: string | undefined } { const args: string[] = []; let tsServerLogFile: string | undefined; + let tsServerTraceDirectory: string | undefined; if (kind === TsServerProcessKind.Syntax) { if (apiVersion.gte(API.v401)) { @@ -216,6 +225,13 @@ export class TypeScriptServerSpawner { } } + if (configuration.enableTsServerTracing && !isWeb()) { + tsServerTraceDirectory = this._logDirectoryProvider.getNewLogDirectory(); + if (tsServerTraceDirectory) { + args.push('--traceDirectory', tsServerTraceDirectory); + } + } + if (!isWeb()) { const pluginPaths = this._pluginPathsProvider.getPluginPaths(); @@ -251,7 +267,7 @@ export class TypeScriptServerSpawner { args.push('--validateDefaultNpmLocation'); } - return { args, tsServerLogFile }; + return { args, tsServerLogFile, tsServerTraceDirectory }; } private static isLoggingEnabled(configuration: TypeScriptServiceConfiguration) { diff --git a/extensions/typescript-language-features/src/utils/configuration.ts b/extensions/typescript-language-features/src/utils/configuration.ts index 9cf827fb5d5..529ba2f3f8f 100644 --- a/extensions/typescript-language-features/src/utils/configuration.ts +++ b/extensions/typescript-language-features/src/utils/configuration.ts @@ -102,6 +102,7 @@ export class TypeScriptServiceConfiguration { public readonly enablePromptUseWorkspaceTsdk: boolean; public readonly watchOptions: protocol.WatchOptions | undefined; public readonly includePackageJsonAutoImports: 'auto' | 'on' | 'off' | undefined; + public readonly enableTsServerTracing: boolean; public static loadFromWorkspace(): TypeScriptServiceConfiguration { return new TypeScriptServiceConfiguration(); @@ -124,6 +125,7 @@ export class TypeScriptServiceConfiguration { this.enablePromptUseWorkspaceTsdk = TypeScriptServiceConfiguration.readEnablePromptUseWorkspaceTsdk(configuration); this.watchOptions = TypeScriptServiceConfiguration.readWatchOptions(configuration); this.includePackageJsonAutoImports = TypeScriptServiceConfiguration.readIncludePackageJsonAutoImports(configuration); + this.enableTsServerTracing = TypeScriptServiceConfiguration.readEnableTsServerTracing(configuration); } public isEqualTo(other: TypeScriptServiceConfiguration): boolean { @@ -210,4 +212,8 @@ export class TypeScriptServiceConfiguration { private static readEnablePromptUseWorkspaceTsdk(configuration: vscode.WorkspaceConfiguration): boolean { return configuration.get('typescript.enablePromptUseWorkspaceTsdk', false); } + + private static readEnableTsServerTracing(configuration: vscode.WorkspaceConfiguration): boolean { + return configuration.get('typescript.tsserver.enableTracing', false); + } } From 2b75c3d5ac346411233565881a696155257c51c7 Mon Sep 17 00:00:00 2001 From: BTNDev <52890714+BTNDev@users.noreply.github.com> Date: Sat, 21 Nov 2020 00:37:46 +0100 Subject: [PATCH 0113/1837] updated javascript for in snippet (#111062) Updated javascript for in snippet to use Object.hasOwnProperty insted of object.hasOwnProperty because of this vulnerability: https://eslint.org/docs/rules/no-prototype-builtins --- extensions/javascript/snippets/javascript.code-snippets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/javascript/snippets/javascript.code-snippets b/extensions/javascript/snippets/javascript.code-snippets index b005c80c844..a48a64c2813 100644 --- a/extensions/javascript/snippets/javascript.code-snippets +++ b/extensions/javascript/snippets/javascript.code-snippets @@ -35,7 +35,7 @@ "prefix": "forin", "body": [ "for (const ${1:key} in ${2:object}) {", - "\tif (${2:object}.hasOwnProperty(${1:key})) {", + "\tif (Object.hasOwnProperty.call(${2:object}, ${1:key})) {", "\t\tconst ${3:element} = ${2:object}[${1:key}];", "\t\t$0", "\t}", From f1cfe2d3a6392ccd2fae26a19d33da417ab8fd49 Mon Sep 17 00:00:00 2001 From: turara Date: Sat, 21 Nov 2020 08:58:23 +0900 Subject: [PATCH 0114/1837] Update CodeActionOnSaveParticipant (#108193) * Update CodeActionOnSaveParticipant Add filtering CodeActionKind.SourceFixAll derivatives for codeActionsOnSave * Add CodeActionOnSaveParticipant#createCodeActionsOnSave method to remove subsets. Fixes #106924. --- .../codeEditor/browser/saveParticipants.ts | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts index f2770354531..d540af4e095 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts @@ -287,8 +287,7 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant { ? setting : Object.keys(setting).filter(x => setting[x]); - const codeActionsOnSave = settingItems - .map(x => new CodeActionKind(x)); + const codeActionsOnSave = this.createCodeActionsOnSave(settingItems); if (!Array.isArray(setting)) { codeActionsOnSave.sort((a, b) => { @@ -319,6 +318,28 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant { await this.applyOnSaveActions(textEditorModel, codeActionsOnSave, excludedActions, progress, token); } + private createCodeActionsOnSave(settingItems: string[]): CodeActionKind[] { + const actionSeeds = new Set(); + + // Remove subsets + const len = settingItems.length; + outer: for (let i = 0; i < len; i++) { + const s1 = settingItems[i]; + for (let j = 0; j < len; j++) { + if (j === i) { + continue; + } + const s2 = settingItems[j]; + if (s1.startsWith(s2) && s1.length > s2.length) { + continue outer; + } + } + actionSeeds.add(s1); + } + + return Array.from(actionSeeds).map(x => new CodeActionKind(x)); + } + private async applyOnSaveActions(model: ITextModel, codeActionsOnSave: readonly CodeActionKind[], excludes: readonly CodeActionKind[], progress: IProgress, token: CancellationToken): Promise { const getActionProgress = new class implements IProgress { From 45ec698b128e4bc3892856549d5ee8b573544d06 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Nov 2020 01:01:56 +0100 Subject: [PATCH 0115/1837] Avoid walking whitespace twice when going left & small stylistic changes --- .../editor/browser/controller/mouseTarget.ts | 4 +- .../controller/cursorAtomicMoveOperations.ts | 151 +++++++++--------- .../common/controller/cursorMoveOperations.ts | 48 ++---- .../cursorAtomicMoveOperations.test.ts | 44 +++-- 4 files changed, 130 insertions(+), 117 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index e38edef2ece..b60883dc082 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -1050,13 +1050,13 @@ export class MouseTargetFactory { } else if ((document.body).createTextRange) { result = this._doHitTestWithMoveToPoint(ctx, request.pos.toClientCoordinates()); } else { - return { + result = { position: null, hitTarget: null }; } // Snap to the nearest soft tab boundary if atomic soft tabs are enabled. - if (result.position !== null && ctx.atomicSoftTabs) { + if (result.position && ctx.atomicSoftTabs) { result.position = this._snapToSoftTabBoundary(result.position, ctx.model); } return result; diff --git a/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts b/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts index 3884bbfd628..4b3a235278f 100644 --- a/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts +++ b/src/vs/editor/common/controller/cursorAtomicMoveOperations.ts @@ -6,21 +6,31 @@ import { CharCode } from 'vs/base/common/charCode'; import { CursorColumns } from 'vs/editor/common/controller/cursorCommon'; -export enum Direction { +export const enum Direction { Left, Right, Nearest, } export class AtomicTabMoveOperations { - // Get the visible column at the position. If we get to a non-whitespace character first - // or past the end of string then return -1. Note `position` and the return - // value are 0-based. - public static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number) { + /** + * Get the visible column at the position. If we get to a non-whitespace character first + * or past the end of string then return -1. + * + * **Note** `position` and the return value are 0-based. + */ + public static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number): [number, number, number] { + const lineLength = lineContent.length; let visibleColumn = 0; - for (let i = 0; i < lineContent.length; ++i) { + let prevTabStopPosition = -1; + let prevTabStopVisibleColumn = -1; + for (let i = 0; i < lineLength; i++) { if (i === position) { - return visibleColumn; + return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn]; + } + if (visibleColumn % tabSize === 0) { + prevTabStopPosition = i; + prevTabStopVisibleColumn = visibleColumn; } const chCode = lineContent.charCodeAt(i); switch (chCode) { @@ -32,26 +42,30 @@ export class AtomicTabMoveOperations { visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); break; default: - return -1; + return [-1, -1, -1]; } } - if (position === lineContent.length) { - return visibleColumn; + if (position === lineLength) { + return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn]; } - return -1; + return [-1, -1, -1]; } - // Return the position that should result from a move left, right or to the - // nearest tab, if atomic tabs are enabled. Left and right are used for the - // arrow key movements, nearest is used for mouse selection. It returns - // -1 if atomic tabs are not relevant and you should fall back to normal - // behaviour. - // - // Note, `position` and the return value are 0-based. + /** + * Return the position that should result from a move left, right or to the + * nearest tab, if atomic tabs are enabled. Left and right are used for the + * arrow key movements, nearest is used for mouse selection. It returns + * -1 if atomic tabs are not relevant and you should fall back to normal + * behaviour. + * + * **Note**: `position` and the return value are 0-based. + */ public static atomicPosition(lineContent: string, position: number, tabSize: number, direction: Direction): number { + const lineLength = lineContent.length; + // Get the 0-based visible column corresponding to the position, or return // -1 if it is not in the initial whitespace. - let visibleColumn = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize); + const [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn] = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize); if (visibleColumn === -1) { return -1; @@ -78,77 +92,68 @@ export class AtomicTabMoveOperations { break; } - // The code below won't work if visibleColumn is zero and left is true because - // it takes the mod of a negative number, which behaves oddly. In that case - // we already know what to return. - if (left && visibleColumn === 0) { + // If going left, we can just use the info about the last tab stop position and + // last tab stop visible column that we computed in the first walk over the whitespace. + if (left) { + if (prevTabStopPosition === -1) { + return -1; + } + // If the direction is left, we need to keep scanning right to ensure + // that targetVisibleColumn + tabSize is before non-whitespace. + // This is so that when we press left at the end of a partial + // indentation it only goes one character. For example ' foo' with + // tabSize 4, should jump from position 6 to position 5, not 4. + let currentVisibleColumn = prevTabStopVisibleColumn; + for (let i = prevTabStopPosition; i < lineLength; ++i) { + if (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) { + // It is a full indentation. + return prevTabStopPosition; + } + + const chCode = lineContent.charCodeAt(i); + switch (chCode) { + case CharCode.Space: + currentVisibleColumn += 1; + break; + case CharCode.Tab: + currentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize); + break; + default: + return -1; + } + } + if (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) { + return prevTabStopPosition; + } + // It must have been a partial indentation. return -1; } - const tmp = visibleColumn + (left ? -1 : tabSize); - const targetVisibleColumn = tmp - tmp % tabSize; + // We are going right. + const targetVisibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); - // Find the target visible column. If going right we can just continue from - // where whitespaceVisibleColumn got to. If going left it's easiest to start - // from the beginning because the width of tab characters depend on the - // characters to their left. E.g. ' \t' is one tabSize, but so is '\t'. - if (left) { - visibleColumn = 0; - } - for (let i = (left ? 0 : position); i < lineContent.length; ++i) { - if (visibleColumn === targetVisibleColumn) { - // This is the position we want to get to, but we have one more case - // to handle if going left. - if (left) { - // If the direction is left, we need to keep scanning right to ensure - // that targetVisibleColumn + tabSize is before non-whitespace. - // This is so that when we press left at the end of a partial - // indentation it only goes one character. For example ' foo' with - // tabSize 4, should jump from position 6 to position 5, not 4. - for (let k = i; k < lineContent.length; ++k) { - if (visibleColumn === targetVisibleColumn + tabSize) { - // It is a full indentation. - return i; - } - - const chCode = lineContent.charCodeAt(k); - switch (chCode) { - case CharCode.Space: - visibleColumn += 1; - break; - case CharCode.Tab: - visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); - break; - default: - return -1; - } - } - if (visibleColumn === targetVisibleColumn + tabSize) { - return i; - } - // It must have been a partial indentation. - return -1; - } else { - // If going right then we must have been in a complete indentation. - return i; - } + // We can just continue from where whitespaceVisibleColumn got to. + let currentVisibleColumn = visibleColumn; + for (let i = position; i < lineLength; i++) { + if (currentVisibleColumn === targetVisibleColumn) { + return i; } const chCode = lineContent.charCodeAt(i); switch (chCode) { case CharCode.Space: - visibleColumn += 1; + currentVisibleColumn += 1; break; case CharCode.Tab: - visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize); + currentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize); break; default: return -1; } } // This condition handles when the target column is at the end of the line. - if (visibleColumn === targetVisibleColumn) { - return lineContent.length; + if (currentVisibleColumn === targetVisibleColumn) { + return lineLength; } return -1; } diff --git a/src/vs/editor/common/controller/cursorMoveOperations.ts b/src/vs/editor/common/controller/cursorMoveOperations.ts index 6d1ed292cd4..a654865f471 100644 --- a/src/vs/editor/common/controller/cursorMoveOperations.ts +++ b/src/vs/editor/common/controller/cursorMoveOperations.ts @@ -30,33 +30,25 @@ export class MoveOperations { if (column > model.getLineMinColumn(lineNumber)) { column = column - strings.prevCharLength(model.getLineContent(lineNumber), column - 1); } else if (lineNumber > 1) { - lineNumber -= 1; + lineNumber = lineNumber - 1; column = model.getLineMaxColumn(lineNumber); } return new Position(lineNumber, column); } - public static leftPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position { + public static leftPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position { const minColumn = model.getLineMinColumn(lineNumber); - if (column > minColumn) { - const lineContent = model.getLineContent(lineNumber); - - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left); - if (newPosition !== -1) { - column = minColumn + newPosition; - } else { - column -= strings.prevCharLength(model.getLineContent(lineNumber), column - 1); - } - } else if (lineNumber > 1) { - lineNumber -= 1; - column = model.getLineMaxColumn(lineNumber); + const lineContent = model.getLineContent(lineNumber); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left); + if (newPosition === -1) { + return this.leftPosition(model, lineNumber, column); } - return new Position(lineNumber, column); + return new Position(lineNumber, minColumn + newPosition); } public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { const pos = config.atomicSoftTabs - ? MoveOperations.leftPositionatomicSoftTabs(model, lineNumber, column, config.tabSize) + ? MoveOperations.leftPositionAtomicSoftTabs(model, lineNumber, column, config.tabSize) : MoveOperations.leftPosition(model, lineNumber, column); return new CursorPosition(pos.lineNumber, pos.column, 0); } @@ -82,33 +74,25 @@ export class MoveOperations { if (column < model.getLineMaxColumn(lineNumber)) { column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1); } else if (lineNumber < model.getLineCount()) { - lineNumber += 1; + lineNumber = lineNumber + 1; column = model.getLineMinColumn(lineNumber); } return new Position(lineNumber, column); } - public static rightPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position { + public static rightPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position { const minColumn = model.getLineMinColumn(lineNumber); - if (column < model.getLineMaxColumn(lineNumber)) { - const lineContent = model.getLineContent(lineNumber); - - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right); - if (newPosition !== -1) { - column = minColumn + newPosition; - } else { - column += strings.nextCharLength(model.getLineContent(lineNumber), column - 1); - } - } else if (lineNumber < model.getLineCount()) { - lineNumber += 1; - column = minColumn; + const lineContent = model.getLineContent(lineNumber); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right); + if (newPosition === -1) { + return this.rightPosition(model, lineNumber, column); } - return new Position(lineNumber, column); + return new Position(lineNumber, minColumn + newPosition); } public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { const pos = config.atomicSoftTabs - ? MoveOperations.rightPositionatomicSoftTabs(model, lineNumber, column, config.tabSize, config.indentSize) + ? MoveOperations.rightPositionAtomicSoftTabs(model, lineNumber, column, config.tabSize, config.indentSize) : MoveOperations.rightPosition(model, lineNumber, column); return new CursorPosition(pos.lineNumber, pos.column, 0); } diff --git a/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts b/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts index b037e530cf3..e9c60b6e3be 100644 --- a/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts +++ b/src/vs/editor/test/common/controller/cursorAtomicMoveOperations.test.ts @@ -13,48 +13,72 @@ suite('Cursor move command test', () => { { lineContent: ' ', tabSize: 4, - expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, -1], + expectedPrevTabStopPosition: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1], + expectedVisibleColumn: [0, 1, 2, 3, 4, 5, 6, 7, 8, -1], }, { lineContent: ' ', tabSize: 4, - expected: [0, 1, 2, -1], + expectedPrevTabStopPosition: [-1, 0, 0, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, 0, -1], + expectedVisibleColumn: [0, 1, 2, -1], }, { lineContent: '\t', tabSize: 4, - expected: [0, 4, -1], + expectedPrevTabStopPosition: [-1, 0, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, -1], + expectedVisibleColumn: [0, 4, -1], }, { lineContent: '\t ', tabSize: 4, - expected: [0, 4, 5, -1], + expectedPrevTabStopPosition: [-1, 0, 1, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, 4, -1], + expectedVisibleColumn: [0, 4, 5, -1], }, { lineContent: ' \t\t ', tabSize: 4, - expected: [0, 1, 4, 8, 9, -1], + expectedPrevTabStopPosition: [-1, 0, 0, 2, 3, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, 0, 4, 8, -1], + expectedVisibleColumn: [0, 1, 4, 8, 9, -1], }, { lineContent: ' \tA', tabSize: 4, - expected: [0, 1, 4, -1, -1], + expectedPrevTabStopPosition: [-1, 0, 0, -1, -1], + expectedPrevTabStopVisibleColumn: [-1, 0, 0, -1, -1], + expectedVisibleColumn: [0, 1, 4, -1, -1], }, { lineContent: 'A', tabSize: 4, - expected: [0, -1, -1], + expectedPrevTabStopPosition: [-1, -1, -1], + expectedPrevTabStopVisibleColumn: [-1, -1, -1], + expectedVisibleColumn: [0, -1, -1], }, { lineContent: '', tabSize: 4, - expected: [0, -1], + expectedPrevTabStopPosition: [-1, -1], + expectedPrevTabStopVisibleColumn: [-1, -1], + expectedVisibleColumn: [0, -1], }, ]; for (const testCase of testCases) { - const actual = testCase.expected.map((_, i) => AtomicTabMoveOperations.whitespaceVisibleColumn(testCase.lineContent, i, testCase.tabSize)); - assert.deepStrictEqual(actual, testCase.expected); + const maxPosition = testCase.expectedVisibleColumn.length; + for (let position = 0; position < maxPosition; position++) { + const actual = AtomicTabMoveOperations.whitespaceVisibleColumn(testCase.lineContent, position, testCase.tabSize); + const expected = [ + testCase.expectedPrevTabStopPosition[position], + testCase.expectedPrevTabStopVisibleColumn[position], + testCase.expectedVisibleColumn[position] + ]; + assert.deepStrictEqual(actual, expected); + } } }); From a194746aa349333c66cd045058e88f492d3b70c8 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 20 Nov 2020 16:06:55 -0800 Subject: [PATCH 0116/1837] auto attach: allow temporarily disabling Fixes https://github.com/microsoft/vscode/issues/111021 --- extensions/debug-auto-launch/src/extension.ts | 109 ++++++++++++------ 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/extensions/debug-auto-launch/src/extension.ts b/extensions/debug-auto-launch/src/extension.ts index 5ae907a9dbe..440b3296e57 100644 --- a/extensions/debug-auto-launch/src/extension.ts +++ b/extensions/debug-auto-launch/src/extension.ts @@ -9,9 +9,13 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -const TEXT_ALWAYS = localize('status.text.auto.attach.always', 'Auto Attach: Always'); -const TEXT_SMART = localize('status.text.auto.attach.smart', 'Auto Attach: Smart'); -const TEXT_WITH_FLAG = localize('status.text.auto.attach.withFlag', 'Auto Attach: With Flag'); +const TEXT_STATUSBAR_LABEL = { + [State.Disabled]: localize('status.text.auto.attach.disabled', 'Auto Attach: Disabled'), + [State.Always]: localize('status.text.auto.attach.always', 'Auto Attach: Always'), + [State.Smart]: localize('status.text.auto.attach.smart', 'Auto Attach: Smart'), + [State.OnlyWithFlag]: localize('status.text.auto.attach.withFlag', 'Auto Attach: With Flag'), +}; + const TEXT_STATE_LABEL = { [State.Disabled]: localize('debug.javascript.autoAttach.disabled.label', 'Disabled'), [State.Always]: localize('debug.javascript.autoAttach.always.label', 'Always'), @@ -41,6 +45,9 @@ const TEXT_STATE_DESCRIPTION = { }; const TEXT_TOGGLE_WORKSPACE = localize('scope.workspace', 'Toggle auto attach in this workspace'); const TEXT_TOGGLE_GLOBAL = localize('scope.global', 'Toggle auto attach on this machine'); +const TEXT_TEMP_DISABLE = localize('tempDisable.disable', 'Temporarily disable auto attach in this session'); +const TEXT_TEMP_ENABLE = localize('tempDisable.enable', 'Re-enable auto attach'); +const TEXT_TEMP_DISABLE_LABEL = localize('tempDisable.suffix', 'Auto Attach: Disabled'); const TOGGLE_COMMAND = 'extension.node-debug.toggleAutoAttach'; const STORAGE_IPC = 'jsDebugIpcState'; @@ -65,12 +72,13 @@ const enum State { let currentState: Promise<{ context: vscode.ExtensionContext; state: State | null }>; let statusItem: vscode.StatusBarItem | undefined; // and there is no status bar item let server: Promise | undefined; // auto attach server +let isTemporarilyDisabled = false; // whether the auto attach server is disabled temporarily, reset whenever the state changes export function activate(context: vscode.ExtensionContext): void { currentState = Promise.resolve({ context, state: null }); context.subscriptions.push( - vscode.commands.registerCommand(TOGGLE_COMMAND, toggleAutoAttachSetting), + vscode.commands.registerCommand(TOGGLE_COMMAND, toggleAutoAttachSetting.bind(null, context)), ); context.subscriptions.push( @@ -108,24 +116,36 @@ function getDefaultScope(info: ReturnType { +async function toggleAutoAttachSetting(context: vscode.ExtensionContext, scope?: vscode.ConfigurationTarget): Promise { const section = vscode.workspace.getConfiguration(SETTING_SECTION); scope = scope || getDefaultScope(section.inspect(SETTING_STATE)); const isGlobalScope = scope === vscode.ConfigurationTarget.Global; - const quickPick = vscode.window.createQuickPick(); + const quickPick = vscode.window.createQuickPick(); const current = readCurrentState(); - quickPick.items = [State.Always, State.Smart, State.OnlyWithFlag, State.Disabled].map(state => ({ + const items: PickItem[] = [State.Always, State.Smart, State.OnlyWithFlag, State.Disabled].map(state => ({ state, label: TEXT_STATE_LABEL[state], description: TEXT_STATE_DESCRIPTION[state], alwaysShow: true, })); - quickPick.activeItems = quickPick.items.filter(i => i.state === current); + if (current !== State.Disabled) { + items.unshift({ + setTempDisabled: !isTemporarilyDisabled, + label: isTemporarilyDisabled ? TEXT_TEMP_ENABLE : TEXT_TEMP_DISABLE, + alwaysShow: true, + }); + } + + quickPick.items = items; + quickPick.activeItems = isTemporarilyDisabled + ? [items[0]] + : quickPick.items.filter(i => 'state' in i && i.state === current); quickPick.title = isGlobalScope ? TEXT_TOGGLE_GLOBAL : TEXT_TOGGLE_WORKSPACE; quickPick.buttons = [ { @@ -155,12 +175,23 @@ async function toggleAutoAttachSetting(scope?: vscode.ConfigurationTarget): Prom } if ('scope' in result) { - return await toggleAutoAttachSetting(result.scope); + return await toggleAutoAttachSetting(context, result.scope); } if ('state' in result) { section.update(SETTING_STATE, result.state, scope); } + + if ('setTempDisabled' in result) { + updateStatusBar(context, current, true); + isTemporarilyDisabled = result.setTempDisabled; + if (result.setTempDisabled) { + await destroyAttachServer(); + } else { + await createAttachServer(context); // unsets temp disabled var internally + } + updateStatusBar(context, current, false); + } } function readCurrentState(): State { @@ -168,26 +199,6 @@ function readCurrentState(): State { return section.get(SETTING_STATE) ?? State.Disabled; } -/** - * Makes sure the status bar exists and is visible. - */ -function ensureStatusBarExists(context: vscode.ExtensionContext) { - if (!statusItem) { - statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); - statusItem.command = TOGGLE_COMMAND; - statusItem.tooltip = localize( - 'status.tooltip.auto.attach', - 'Automatically attach to node.js processes in debug mode', - ); - statusItem.show(); - context.subscriptions.push(statusItem); - } else { - statusItem.show(); - } - - return statusItem; -} - async function clearJsDebugAttachState(context: vscode.ExtensionContext) { await context.workspaceState.update(STORAGE_IPC, undefined); await vscode.commands.executeCommand('extension.js-debug.clearAutoAttachVariables'); @@ -275,28 +286,46 @@ interface CachedIpcState { const transitions: { [S in State]: (context: vscode.ExtensionContext) => Promise } = { async [State.Disabled](context) { await clearJsDebugAttachState(context); - statusItem?.hide(); }, async [State.OnlyWithFlag](context) { await createAttachServer(context); - const statusItem = ensureStatusBarExists(context); - statusItem.text = TEXT_WITH_FLAG; }, async [State.Smart](context) { await createAttachServer(context); - const statusItem = ensureStatusBarExists(context); - statusItem.text = TEXT_SMART; }, async [State.Always](context) { await createAttachServer(context); - const statusItem = ensureStatusBarExists(context); - statusItem.text = TEXT_ALWAYS; }, }; +/** + * Ensures the status bar text reflects the current state. + */ +function updateStatusBar(context: vscode.ExtensionContext, state: State, busy = false) { + if (state === State.Disabled && !busy) { + statusItem?.hide(); + return; + } + + if (!statusItem) { + statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + statusItem.command = TOGGLE_COMMAND; + statusItem.tooltip = localize( + 'status.tooltip.auto.attach', + 'Automatically attach to node.js processes in debug mode', + ); + context.subscriptions.push(statusItem); + } + + let text = busy ? '$(loading) ' : ''; + text += isTemporarilyDisabled ? TEXT_TEMP_DISABLE_LABEL : TEXT_STATUSBAR_LABEL[state]; + statusItem.text = text; + statusItem.show(); +} + /** * Updates the auto attach feature based on the user or workspace setting */ @@ -306,7 +335,13 @@ function updateAutoAttach(newState: State) { return { context, state: oldState }; } + if (oldState !== null) { + updateStatusBar(context, oldState, true); + } + await transitions[newState](context); + isTemporarilyDisabled = false; + updateStatusBar(context, newState, false); return { context, state: newState }; }); } From 88856f1a1c8f90bcc12171d1af920d74bb59b625 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Nov 2020 16:07:39 -0800 Subject: [PATCH 0117/1837] Simplify changes from #108193 --- .../codeEditor/browser/saveParticipants.ts | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts index d540af4e095..76ffc0b6094 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts @@ -318,26 +318,13 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant { await this.applyOnSaveActions(textEditorModel, codeActionsOnSave, excludedActions, progress, token); } - private createCodeActionsOnSave(settingItems: string[]): CodeActionKind[] { - const actionSeeds = new Set(); + private createCodeActionsOnSave(settingItems: readonly string[]): CodeActionKind[] { + const kinds = settingItems.map(x => new CodeActionKind(x)); // Remove subsets - const len = settingItems.length; - outer: for (let i = 0; i < len; i++) { - const s1 = settingItems[i]; - for (let j = 0; j < len; j++) { - if (j === i) { - continue; - } - const s2 = settingItems[j]; - if (s1.startsWith(s2) && s1.length > s2.length) { - continue outer; - } - } - actionSeeds.add(s1); - } - - return Array.from(actionSeeds).map(x => new CodeActionKind(x)); + return kinds.filter(kind => { + return kinds.every(otherKind => otherKind.equals(kind) || !otherKind.contains(kind)); + }); } private async applyOnSaveActions(model: ITextModel, codeActionsOnSave: readonly CodeActionKind[], excludes: readonly CodeActionKind[], progress: IProgress, token: CancellationToken): Promise { From eae037b391a5ff707a0a2a7759d8597435d2c092 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Sun, 22 Nov 2020 10:52:27 +0800 Subject: [PATCH 0118/1837] Fixed Hover style incorrect when writing javascript in HTML --- .../server/src/modes/javascriptMode.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/html-language-features/server/src/modes/javascriptMode.ts b/extensions/html-language-features/server/src/modes/javascriptMode.ts index 086b8a906b8..1fc33faedec 100644 --- a/extensions/html-language-features/server/src/modes/javascriptMode.ts +++ b/extensions/html-language-features/server/src/modes/javascriptMode.ts @@ -6,7 +6,7 @@ import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache'; import { SymbolInformation, SymbolKind, CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation, - Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover, MarkedString, + Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover, DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions, FoldingRange, FoldingRangeKind, SelectionRange, LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext } from './languageModes'; @@ -142,10 +142,10 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache Date: Sun, 22 Nov 2020 09:44:22 +0100 Subject: [PATCH 0119/1837] env - tweak shell resolve experience on startup --- .../parts/sandbox/electron-browser/preload.js | 36 +++++------ .../parts/sandbox/electron-sandbox/globals.ts | 10 +++- src/vs/code/electron-main/app.ts | 59 +++++++++---------- src/vs/code/electron-main/window.ts | 2 +- src/vs/code/node/shellEnv.ts | 12 +++- .../electron-main/windowsMainService.ts | 3 +- .../browser/parts/editor/textDiffEditor.ts | 2 +- .../browser/parts/editor/textEditor.ts | 1 + src/vs/workbench/electron-sandbox/window.ts | 20 ++++--- .../services/timer/browser/timerService.ts | 2 +- 10 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index 702a28ea652..3ee0b2ca853 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -108,18 +108,13 @@ get type() { return 'renderer'; }, get execPath() { return process.execPath; }, - _resolveEnv: undefined, resolveEnv: /** * @param userEnv {{[key: string]: string}} * @returns {Promise} */ function (userEnv) { - if (!this._resolveEnv) { - this._resolveEnv = resolveEnv(userEnv); - } - - return this._resolveEnv; + return resolveEnv(userEnv); }, getProcessMemoryInfo: @@ -194,6 +189,9 @@ return true; } + /** @type {Promise | undefined} */ + let resolvedEnv = undefined; + /** * If VSCode is not run from a terminal, we should resolve additional * shell specific environment from the OS shell to ensure we are seeing @@ -204,23 +202,27 @@ * @returns {Promise} */ function resolveEnv(userEnv) { + if (!resolvedEnv) { - // Apply `userEnv` directly - Object.assign(process.env, userEnv); + // Apply `userEnv` directly + Object.assign(process.env, userEnv); - // Resolve `shellEnv` from the main side - return new Promise(function (resolve) { - ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { + // Resolve `shellEnv` from the main side + resolvedEnv = new Promise(function (resolve) { + ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { - // Assign all keys of the shell environment to our process environment - // But make sure that the user environment wins in the end - Object.assign(process.env, shellEnv, userEnv); + // Assign all keys of the shell environment to our process environment + // But make sure that the user environment wins in the end + Object.assign(process.env, shellEnv, userEnv); - resolve(); + resolve(); + }); + + ipcRenderer.send('vscode:fetchShellEnv'); }); + } - ipcRenderer.send('vscode:fetchShellEnv'); - }); + return resolvedEnv; } //#endregion diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 1116cf2135f..69f3a2a8637 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -35,9 +35,10 @@ export interface ISandboxNodeProcess extends INodeProcess { readonly execPath: string; /** - * Resolve the true process environment to use. There are different layers of environment - * that will apply: - * - `process.env`: this is the actual environment of the process + * Resolve the true process environment to use and apply it to `process.env`. + * + * There are different layers of environment that will apply: + * - `process.env`: this is the actual environment of the process before this method * - `shellEnv` : if the program was not started from a terminal, we resolve all shell * variables to get the same experience as if the program was started from * a terminal (Linux, macOS) @@ -45,6 +46,9 @@ export interface ISandboxNodeProcess extends INodeProcess { * from a terminal and changed certain variables * * The order of overwrites is `process.env` < `shellEnv` < `userEnv`. + * + * It is critical that every process awaits this method early on startup to get the right + * set of environment in `process.env`. */ resolveEnv(userEnv: IProcessEnvironment): Promise; diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 597c45bad02..5f91f3fd6d7 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -83,7 +83,6 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService'; import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; -import { toErrorMessage } from 'vs/base/common/errorMessage'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; @@ -272,45 +271,45 @@ export class CodeApplication extends Disposable { let replied = false; function acceptShellEnv(env: NodeJS.ProcessEnv): void { - clearTimeout(shellEnvTimeoutWarningHandle); + clearTimeout(shellEnvSlowWarningHandle); + clearTimeout(shellEnvTimeoutErrorHandle); if (!replied) { - webContents.send('vscode:acceptShellEnv', env); replied = true; + + if (!webContents.isDestroyed()) { + webContents.send('vscode:acceptShellEnv', env); + } } } - const shellEnvTimeoutWarningHandle = setTimeout(function () { - window?.sendWhenReady('vscode:showShellEnvTimeoutWarning'); // notify inside window if we have one + // Handle slow shell environment resolve calls: + // - a warning after 3s but continue to resolve + // - an error after 10s and stop trying to resolve + const shellEnvSlowWarningHandle = setTimeout(() => window?.sendWhenReady('vscode:showShellEnvSlowWarning'), 3000); + const shellEnvTimeoutErrorHandle = setTimeout(function () { + window?.sendWhenReady('vscode:showShellEnvTimeoutError'); acceptShellEnv({}); }, 10000); - try { - - // Prefer to use the args and env from the target window - // when resolving the shell env. It is possible that - // a first window was opened from the UI but a second - // from the CLI and that has implications for wether to - // resolve the shell environment or not. - let args: NativeParsedArgs; - let env: NodeJS.ProcessEnv; - if (window?.config) { - args = window.config; - env = { ...process.env, ...window.config.userEnv }; - } else { - args = this.environmentService.args; - env = process.env; - } - - // Resolve shell env - const shellEnv = await resolveShellEnv(this.logService, args, env); - acceptShellEnv(shellEnv); - } catch (error) { - window?.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); // notify inside window if we have one - acceptShellEnv({}); - - this.logService.error('Error fetching shell env', error); + // Prefer to use the args and env from the target window + // when resolving the shell env. It is possible that + // a first window was opened from the UI but a second + // from the CLI and that has implications for wether to + // resolve the shell environment or not. + let args: NativeParsedArgs; + let env: NodeJS.ProcessEnv; + if (window?.config) { + args = window.config; + env = { ...process.env, ...window.config.userEnv }; + } else { + args = this.environmentService.args; + env = process.env; } + + // Resolve shell env + const shellEnv = await resolveShellEnv(this.logService, args, env); + acceptShellEnv(shellEnv); }); ipc.on('vscode:toggleDevTools', (event: IpcMainEvent) => event.sender.toggleDevTools()); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 6019f2d2062..135f1b70b91 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -685,7 +685,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { // (for https://github.com/microsoft/vscode/issues/108571) const currentUserEnv = (this.currentConfig ?? this.pendingLoadConfig)?.userEnv; if (currentUserEnv && isLaunchedFromCli(currentUserEnv) && !isLaunchedFromCli(config.userEnv)) { - config.userEnv = currentUserEnv; + config.userEnv = { ...currentUserEnv, ...config.userEnv }; // still allow to override certain environment as passed in } // If this is the first time the window is loaded, we associate the paths diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 79ba3d252fe..29ef8c143b3 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -9,6 +9,7 @@ import { isWindows } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; +import { toErrorMessage } from 'vs/base/common/errorMessage'; /** * We need to get the environment from a user's shell. @@ -56,7 +57,7 @@ export async function resolveShellEnv(logService: ILogService, args: NativeParse let unixShellEnvPromise: Promise | undefined = undefined; -function doResolveUnixShellEnv(logService: ILogService): Promise { +async function doResolveUnixShellEnv(logService: ILogService): Promise { const promise = new Promise((resolve, reject) => { const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; logService.trace('getUnixShellEnvironment#runAsNode', runAsNode); @@ -125,6 +126,11 @@ function doResolveUnixShellEnv(logService: ILogService): Promise ({})); + try { + return await promise; + } catch (error) { + logService.error('getUnixShellEnvironment#error', toErrorMessage(error)); + + return {}; // ignore any errors + } } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index cc1d0a1288b..30f5d85c93e 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -7,7 +7,6 @@ import * as fs from 'fs'; import { basename, normalize, join, posix } from 'vs/base/common/path'; import { localize } from 'vs/nls'; import * as arrays from 'vs/base/common/arrays'; -import { mixin } from 'vs/base/common/objects'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; @@ -1369,7 +1368,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow { // Build INativeWindowConfiguration from config and options - const configuration: INativeWindowConfiguration = mixin({}, options.cli); // inherit all properties from CLI + const configuration = { ...options.cli } as INativeWindowConfiguration; configuration.appRoot = this.environmentService.appRoot; configuration.machineId = this.machineId; configuration.nodeCachedDataDir = this.environmentService.nodeCachedDataDir; diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 1b239b03cdd..4557a2c480f 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -246,7 +246,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan diffEditorConfiguration.diffWordWrap = <'off' | 'on' | 'inherit' | undefined>diffEditorConfiguration.wordWrap; delete diffEditorConfiguration.wordWrap; - objects.mixin(editorConfiguration, diffEditorConfiguration); + Object.assign(editorConfiguration, diffEditorConfiguration); } return editorConfiguration; diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index a0416530459..9cae4d21417 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -67,6 +67,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa @IEditorGroupsService protected editorGroupService: IEditorGroupsService ) { super(id, telemetryService, themeService, storageService); + this._instantiationService = instantiationService; this.editorMemento = this.getEditorMemento(editorGroupService, BaseTextEditor.TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100); diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index aabf783b310..cd990d2a6b6 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -32,7 +32,7 @@ import { IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/wo import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity'; import { isWindows, isMacintosh } from 'vs/base/common/platform'; import { IProductService } from 'vs/platform/product/common/productService'; -import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, NeverShowAgainScope, Severity } from 'vs/platform/notification/common/notification'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; @@ -192,15 +192,19 @@ export class NativeWindow extends Disposable { run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667') }]; - ipcRenderer.on('vscode:showShellEnvError', (event: unknown, error: string) => this.notificationService.prompt( - Severity.Error, - nls.localize('shellEnvError', "Unable to resolve your shell environment: {0}", error), - choices + ipcRenderer.on('vscode:showShellEnvSlowWarning', () => this.notificationService.prompt( + Severity.Warning, + nls.localize('shellEnvSlowWarning', "Resolving your shell environment is taking very long. Please review your shell configuration."), + choices, + { + sticky: true, + neverShowAgain: { id: 'ignoreShellEnvSlowWarning', scope: NeverShowAgainScope.GLOBAL } + } )); - ipcRenderer.on('vscode:showShellEnvTimeoutWarning', () => this.notificationService.prompt( - Severity.Warning, - nls.localize('shellEnvTimeoutWarning', "Unable to resolve your shell environment in a reasonable time. Please review your shell configuration."), + ipcRenderer.on('vscode:showShellEnvTimeoutError', () => this.notificationService.prompt( + Severity.Error, + nls.localize('shellEnvTimeoutError', "Unable to resolve your shell environment in a reasonable time. Please review your shell configuration."), choices )); diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index b63386aa9f2..2f146375db0 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -193,7 +193,7 @@ export interface IStartupMetrics { * * Happens in the renderer-process * * Measured with the `willWaitForShellEnv` and `didWaitForShellEnv` performance marks. */ - readonly ellapsedWaitForShellEnv?: number; + readonly ellapsedWaitForShellEnv: number; /** * The time it took to require the workspace storage DB, connect to it From 3182ea7f89a713ee9170563dffc8fa34fe005c6c Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Tue, 17 Nov 2020 21:22:44 +0330 Subject: [PATCH 0120/1837] snake case --- .../linesOperations/linesOperations.ts | 16 ++++ .../test/linesOperations.test.ts | 95 ++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 9c365d50709..9d1b105c357 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -1049,6 +1049,21 @@ export class TitleCaseAction extends AbstractCaseAction { } } +export class SnakeCaseAction extends AbstractCaseAction { + constructor() { + super({ + id: 'editor.action.transformToSnakecase', + label: nls.localize('editor.transformToSnakecase', "Transform to Snake Case"), + alias: 'Transform to Snake Case', + precondition: EditorContextKeys.writable + }); + } + + protected _modifyText(text: string, wordSeparators: string): string { + return text.replace(/(?<=\p{Ll})(\p{Lu})|(? { withTestCodeEditor( [ 'hello world', - 'öçşğü' + 'öçşğü', + 'parseHTMLString', + 'getElementById', + 'insertHTML', + 'PascalCase', + 'CSSSelectorsList', + 'iD', + 'tEST', + 'öçşÖÇŞğüĞÜ', + 'myObject.doSomethingV2();', + 'snake_case', + 'Capital_Snake_Case', + 'kebab-case', + 'Capital-Kebab-Case', + 'Title Case', + 'some text' ], {}, (editor) => { let model = editor.getModel()!; let uppercaseAction = new UpperCaseAction(); let lowercaseAction = new LowerCaseAction(); let titlecaseAction = new TitleCaseAction(); + let snakecaseAction = new SnakeCaseAction(); editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(uppercaseAction, editor); @@ -580,6 +596,81 @@ suite('Editor Contrib - Line Operations', () => { executeAction(titlecaseAction, editor); assert.equal(model.getLineContent(2), 'Öçşğü'); assertSelection(editor, new Selection(2, 1, 2, 6)); + + editor.setSelection(new Selection(3, 1, 3, 16)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(3), 'parse_html_string'); + assertSelection(editor, new Selection(3, 1, 3, 16)); + + editor.setSelection(new Selection(4, 1, 4, 15)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(4), 'get_element_by_id'); + assertSelection(editor, new Selection(4, 1, 4, 15)); + + editor.setSelection(new Selection(5, 1, 5, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(5), 'insert_html'); + assertSelection(editor, new Selection(5, 1, 5, 11)); + + editor.setSelection(new Selection(6, 1, 6, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(6), 'pascal_case'); + assertSelection(editor, new Selection(6, 1, 6, 11)); + + editor.setSelection(new Selection(7, 1, 7, 17)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(7), 'css_selectors_list'); + assertSelection(editor, new Selection(7, 1, 7, 17)); + + editor.setSelection(new Selection(8, 1, 8, 3)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(8), 'i_d'); + assertSelection(editor, new Selection(8, 1, 8, 3)); + + editor.setSelection(new Selection(9, 1, 9, 5)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(9), 't_est'); + assertSelection(editor, new Selection(9, 1, 9, 5)); + + editor.setSelection(new Selection(10, 1, 10, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); + assertSelection(editor, new Selection(10, 1, 10, 11)); + + editor.setSelection(new Selection(11, 1, 11, 26)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); + assertSelection(editor, new Selection(11, 1, 11, 26)); + + editor.setSelection(new Selection(12, 1, 12, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(12), 'snake_case'); + assertSelection(editor, new Selection(12, 1, 12, 11)); + + editor.setSelection(new Selection(13, 1, 13, 19)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(13), 'capital_snake_case'); + assertSelection(editor, new Selection(13, 1, 13, 19)); + + editor.setSelection(new Selection(14, 1, 14, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(14), 'kebab_case'); + assertSelection(editor, new Selection(14, 1, 14, 11)); + + editor.setSelection(new Selection(15, 1, 15, 19)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(15), 'capital_kebab_case'); + assertSelection(editor, new Selection(15, 1, 15, 19)); + + editor.setSelection(new Selection(16, 1, 16, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(16), 'title_case'); + assertSelection(editor, new Selection(16, 1, 16, 11)); + + editor.setSelection(new Selection(17, 1, 17, 10)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(17), 'some_text'); + assertSelection(editor, new Selection(17, 1, 17, 10)); } ); From 43418e212de38a097344769d79b9b8ef4595b2a3 Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Thu, 19 Nov 2020 20:30:00 +0330 Subject: [PATCH 0121/1837] update selection, better multiline support --- .../editor/common/commands/replaceCommand.ts | 45 +++++++++++++++++ .../linesOperations/linesOperations.ts | 45 ++++++++++++++++- .../test/linesOperations.test.ts | 50 +++++++------------ 3 files changed, 107 insertions(+), 33 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index 3e628f2db76..dddf007f0c8 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -142,3 +142,48 @@ export class ReplaceCommandThatPreservesSelection implements ICommand { return helper.getTrackedSelection(this._selectionId!); } } + +export class ReplaceCommandThatModifiesSelection implements ICommand { + + private readonly _range: Range; + private readonly _text: string; + private readonly _initialSelection: Selection; + private readonly _initialText: string; + private readonly _forceMoveMarkers: boolean; + + constructor(editRange: Range, text: string, initialSelection: Selection, initialText: string, forceMoveMarkers: boolean = false) { + this._range = editRange; + this._text = text; + this._initialSelection = initialSelection; + this._initialText = initialText; + this._forceMoveMarkers = forceMoveMarkers; + } + + public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { + builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers); + } + + public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { + let start = 0; + let end = 0; + let modifiedLines = this._text.split('\n'); + let initialLines = this._initialText.split('\n'); + + if (this._initialSelection.selectionStartLineNumber < this._initialSelection.positionLineNumber || + (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && + this._initialSelection.selectionStartColumn < this._initialSelection.positionColumn)) { + start = this._initialSelection.selectionStartColumn; + end = this._initialSelection.positionColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + } else if (this._initialSelection.selectionStartLineNumber > this._initialSelection.positionLineNumber || + (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && + this._initialSelection.selectionStartColumn > this._initialSelection.positionColumn)) { + end = this._initialSelection.positionColumn; + start = this._initialSelection.selectionStartColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + } else { + start = this._initialSelection.selectionStartColumn; + end = this._initialSelection.positionColumn; + } + + return new Selection(this._initialSelection.selectionStartLineNumber, start, this._initialSelection.positionLineNumber, end); + } +} diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 9d1b105c357..6e3765bf9f8 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -8,7 +8,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, IActionOptions, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions'; -import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText } from 'vs/editor/common/commands/replaceCommand'; +import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText, ReplaceCommandThatModifiesSelection } from 'vs/editor/common/commands/replaceCommand'; import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -1059,8 +1059,49 @@ export class SnakeCaseAction extends AbstractCaseAction { }); } + public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { + let selections = editor.getSelections(); + if (selections === null) { + return; + } + + let model = editor.getModel(); + if (model === null) { + return; + } + + let wordSeparators = editor.getOption(EditorOption.wordSeparators); + + let commands: ICommand[] = []; + + for (let i = 0, len = selections.length; i < len; i++) { + let selection = selections[i]; + if (selection.isEmpty()) { + let cursor = selection.getStartPosition(); + const word = editor.getConfiguredWordAtPosition(cursor); + + if (!word) { + continue; + } + + let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + let text = model.getValueInRange(wordRange); + commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), + new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); + + } else { + let text = model.getValueInRange(selection); + commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); + } + } + + editor.pushUndoStop(); + editor.executeCommands(this.id, commands); + editor.pushUndoStop(); + } + protected _modifyText(text: string, wordSeparators: string): string { - return text.replace(/(?<=\p{Ll})(\p{Lu})|(? { 'myObject.doSomethingV2();', 'snake_case', 'Capital_Snake_Case', - 'kebab-case', - 'Capital-Kebab-Case', - 'Title Case', - 'some text' + `function helloWorld() { + return someGlobalObject.printHelloWorld("en", "utf-8"); + } + helloWorld();`.replace(/^\s+/gm, '') ], {}, (editor) => { let model = editor.getModel()!; let uppercaseAction = new UpperCaseAction(); @@ -600,47 +600,47 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(3, 1, 3, 16)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(3), 'parse_html_string'); - assertSelection(editor, new Selection(3, 1, 3, 16)); + assertSelection(editor, new Selection(3, 1, 3, 18)); editor.setSelection(new Selection(4, 1, 4, 15)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(4), 'get_element_by_id'); - assertSelection(editor, new Selection(4, 1, 4, 15)); + assertSelection(editor, new Selection(4, 1, 4, 18)); editor.setSelection(new Selection(5, 1, 5, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(5), 'insert_html'); - assertSelection(editor, new Selection(5, 1, 5, 11)); + assertSelection(editor, new Selection(5, 1, 5, 12)); editor.setSelection(new Selection(6, 1, 6, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(6), 'pascal_case'); - assertSelection(editor, new Selection(6, 1, 6, 11)); + assertSelection(editor, new Selection(6, 1, 6, 12)); editor.setSelection(new Selection(7, 1, 7, 17)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(7), 'css_selectors_list'); - assertSelection(editor, new Selection(7, 1, 7, 17)); + assertSelection(editor, new Selection(7, 1, 7, 19)); editor.setSelection(new Selection(8, 1, 8, 3)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(8), 'i_d'); - assertSelection(editor, new Selection(8, 1, 8, 3)); + assertSelection(editor, new Selection(8, 1, 8, 4)); editor.setSelection(new Selection(9, 1, 9, 5)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(9), 't_est'); - assertSelection(editor, new Selection(9, 1, 9, 5)); + assertSelection(editor, new Selection(9, 1, 9, 6)); editor.setSelection(new Selection(10, 1, 10, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); - assertSelection(editor, new Selection(10, 1, 10, 11)); + assertSelection(editor, new Selection(10, 1, 10, 14)); editor.setSelection(new Selection(11, 1, 11, 26)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); - assertSelection(editor, new Selection(11, 1, 11, 26)); + assertSelection(editor, new Selection(11, 1, 11, 29)); editor.setSelection(new Selection(12, 1, 12, 11)); executeAction(snakecaseAction, editor); @@ -652,25 +652,13 @@ suite('Editor Contrib - Line Operations', () => { assert.equal(model.getLineContent(13), 'capital_snake_case'); assertSelection(editor, new Selection(13, 1, 13, 19)); - editor.setSelection(new Selection(14, 1, 14, 11)); + editor.setSelection(new Selection(14, 1, 17, 14)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(14), 'kebab_case'); - assertSelection(editor, new Selection(14, 1, 14, 11)); - - editor.setSelection(new Selection(15, 1, 15, 19)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(15), 'capital_kebab_case'); - assertSelection(editor, new Selection(15, 1, 15, 19)); - - editor.setSelection(new Selection(16, 1, 16, 11)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(16), 'title_case'); - assertSelection(editor, new Selection(16, 1, 16, 11)); - - editor.setSelection(new Selection(17, 1, 17, 10)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(17), 'some_text'); - assertSelection(editor, new Selection(17, 1, 17, 10)); + assert.equal(model.getValueInRange(new Selection(14, 1, 17, 15)), `function hello_world() { + return some_global_object.print_hello_world("en", "utf-8"); + } + hello_world();`.replace(/^\s+/gm, '')); + assertSelection(editor, new Selection(14, 1, 17, 15)); } ); From 4ae26a156300729ed3f9d23377e5d2aff9dcd982 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Sun, 22 Nov 2020 15:48:33 +0100 Subject: [PATCH 0122/1837] Update milestone --- .vscode/notebooks/endgame.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 0d6e4533429..05b22bdc902 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -14,7 +14,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github\n\n$MILESTONE=milestone:\"October 2020\"\n\n$MINE=assignee:@me", + "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github\n\n$MILESTONE=milestone:\"November 2020\"\n\n$MINE=assignee:@me", "editable": true }, { From fc393cae1bb07c6b49212618871ac4d3101a9534 Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Sun, 22 Nov 2020 18:30:01 +0330 Subject: [PATCH 0123/1837] readability and test improvements --- .../editor/common/commands/replaceCommand.ts | 39 +++++++++++-------- .../linesOperations/linesOperations.ts | 20 +++++----- .../test/linesOperations.test.ts | 8 ++-- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index dddf007f0c8..0d4aa010d60 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -164,26 +164,31 @@ export class ReplaceCommandThatModifiesSelection implements ICommand { } public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { - let start = 0; - let end = 0; - let modifiedLines = this._text.split('\n'); - let initialLines = this._initialText.split('\n'); + let startColumn = 0; + let endColumn = 0; + const modifiedLines = this._text.split('\n'); + const initialLines = this._initialText.split('\n'); + const { + selectionStartLineNumber, + positionLineNumber, + selectionStartColumn, + positionColumn + } = this._initialSelection; - if (this._initialSelection.selectionStartLineNumber < this._initialSelection.positionLineNumber || - (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && - this._initialSelection.selectionStartColumn < this._initialSelection.positionColumn)) { - start = this._initialSelection.selectionStartColumn; - end = this._initialSelection.positionColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); - } else if (this._initialSelection.selectionStartLineNumber > this._initialSelection.positionLineNumber || - (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && - this._initialSelection.selectionStartColumn > this._initialSelection.positionColumn)) { - end = this._initialSelection.positionColumn; - start = this._initialSelection.selectionStartColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + const lastInitialLineLength = initialLines[initialLines.length - 1].length; + const lastModifiedLineLength = modifiedLines[modifiedLines.length - 1].length; + + if (selectionStartLineNumber < positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn < positionColumn)) { + startColumn = selectionStartColumn; + endColumn = positionColumn + (lastModifiedLineLength - lastInitialLineLength); + } else if (selectionStartLineNumber > positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn > positionColumn)) { + endColumn = positionColumn; + startColumn = selectionStartColumn + (lastModifiedLineLength - lastInitialLineLength); } else { - start = this._initialSelection.selectionStartColumn; - end = this._initialSelection.positionColumn; + startColumn = selectionStartColumn; + endColumn = positionColumn; } - return new Selection(this._initialSelection.selectionStartLineNumber, start, this._initialSelection.positionLineNumber, end); + return new Selection(selectionStartLineNumber, startColumn, positionLineNumber, endColumn); } } diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 6e3765bf9f8..48f57a6cff8 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -1060,37 +1060,35 @@ export class SnakeCaseAction extends AbstractCaseAction { } public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - let selections = editor.getSelections(); + const selections = editor.getSelections(); if (selections === null) { return; } - let model = editor.getModel(); + const model = editor.getModel(); if (model === null) { return; } - let wordSeparators = editor.getOption(EditorOption.wordSeparators); + const wordSeparators = editor.getOption(EditorOption.wordSeparators); + const commands: ICommand[] = []; - let commands: ICommand[] = []; - - for (let i = 0, len = selections.length; i < len; i++) { - let selection = selections[i]; + for (const selection of selections) { if (selection.isEmpty()) { - let cursor = selection.getStartPosition(); + const cursor = selection.getStartPosition(); const word = editor.getConfiguredWordAtPosition(cursor); if (!word) { continue; } - let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - let text = model.getValueInRange(wordRange); + const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + const text = model.getValueInRange(wordRange); commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); } else { - let text = model.getValueInRange(selection); + const text = model.getValueInRange(selection); commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); } } diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index 7e977e20559..f7b6b002f42 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -543,7 +543,7 @@ suite('Editor Contrib - Line Operations', () => { 'iD', 'tEST', 'öçşÖÇŞğüĞÜ', - 'myObject.doSomethingV2();', + 'audioConverter.convertM4AToMP3();', 'snake_case', 'Capital_Snake_Case', `function helloWorld() { @@ -637,10 +637,10 @@ suite('Editor Contrib - Line Operations', () => { assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); assertSelection(editor, new Selection(10, 1, 10, 14)); - editor.setSelection(new Selection(11, 1, 11, 26)); + editor.setSelection(new Selection(11, 1, 11, 34)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); - assertSelection(editor, new Selection(11, 1, 11, 29)); + assert.equal(model.getLineContent(11), 'audio_converter.convert_m4a_to_mp3();'); + assertSelection(editor, new Selection(11, 1, 11, 38)); editor.setSelection(new Selection(12, 1, 12, 11)); executeAction(snakecaseAction, editor); From 986e1248f6d8c1aa2a7f57a3fadbb00f94248c2b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Sun, 22 Nov 2020 20:47:56 +0100 Subject: [PATCH 0124/1837] bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e40d6c7161..97c1366c53b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "eec03a44a38591e43680fe058326dbf2d2015518", + "distro": "2c1e3052a2a83d9f37ebad5aaaf49401c19231d9", "author": { "name": "Microsoft Corporation" }, From 6026ab576dc6a4fbb8e255241a364816f42464c5 Mon Sep 17 00:00:00 2001 From: rebornix Date: Sun, 22 Nov 2020 20:02:53 -0800 Subject: [PATCH 0125/1837] fix #109104, #105884. --- .../browser/view/renderers/webviewPreloads.ts | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index c29832730a0..936792e8a50 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -137,14 +137,27 @@ function webviewPreloads() { } if (entry.target.id === id && entry.contentRect) { - vscode.postMessage({ - __vscode_notebook_message: true, - type: 'dimension', - id: id, - data: { - height: entry.contentRect.height + __outputNodePadding__ * 2 - } - }); + if (entry.contentRect.height !== 0) { + entry.target.style.padding = `${__outputNodePadding__}px`; + vscode.postMessage({ + __vscode_notebook_message: true, + type: 'dimension', + id: id, + data: { + height: entry.contentRect.height + __outputNodePadding__ * 2 + } + }); + } else { + entry.target.style.padding = `0px`; + vscode.postMessage({ + __vscode_notebook_message: true, + type: 'dimension', + id: id, + data: { + height: entry.contentRect.height + } + }); + } } } }); @@ -410,7 +423,8 @@ function webviewPreloads() { outputNode.style.top = data.top + 'px'; outputNode.style.left = data.left + 'px'; outputNode.style.width = 'calc(100% - ' + data.left + 'px)'; - outputNode.style.minHeight = '32px'; + // outputNode.style.minHeight = '32px'; + outputNode.style.padding = '0px'; outputNode.id = outputId; addMouseoverListeners(outputNode, outputId); From 1436b523d4aaa773ab246daa68daaa70cef48b1d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 23 Nov 2020 09:41:47 +0100 Subject: [PATCH 0126/1837] [themes] Generate Color Theme From Current Settings doesn't have all colors. Fixes #111147 --- .../contrib/themes/browser/themes.contribution.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 66ac2d3b335..465497930d7 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -302,7 +302,7 @@ class GenerateColorThemeAction extends Action { let theme = this.themeService.getColorTheme(); let colors = Registry.as(ColorRegistryExtensions.ColorContribution).getColors(); let colorIds = colors.map(c => c.id).sort(); - let resultingColors: { [key: string]: string } = {}; + let resultingColors: { [key: string]: string | null } = {}; let inherited: string[] = []; for (let colorId of colorIds) { const color = theme.getColor(colorId, false); @@ -312,12 +312,18 @@ class GenerateColorThemeAction extends Action { inherited.push(colorId); } } + const nullDefaults = []; for (let id of inherited) { const color = theme.getColor(id); if (color) { resultingColors['__' + id] = Color.Format.CSS.formatHexA(color, true); + } else { + nullDefaults.push(id); } } + for (let id of nullDefaults) { + resultingColors['__' + id] = null; + } let contents = JSON.stringify({ '$schema': colorThemeSchemaId, type: theme.type, From d632381e7166bb47a3d732b05ba5c3895047c8af Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 20 Nov 2020 13:18:10 +0100 Subject: [PATCH 0127/1837] Add running process info to tunnels Part of microsoft/vscode-remote-release#4021 --- .../api/browser/mainThreadTunnelService.ts | 4 +- .../contrib/remote/browser/remoteExplorer.ts | 6 +- .../contrib/remote/browser/tunnelView.ts | 28 ++-- .../remote/common/remoteExplorerService.ts | 131 ++++++++++++------ 4 files changed, 101 insertions(+), 68 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index 3b91d45d95a..af625d0871d 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -6,7 +6,7 @@ import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostContext, ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; -import { IRemoteExplorerService, MakeAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, makeAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver'; @@ -64,7 +64,7 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun return { tunnelRemotePort: tunnel.remoteAddress.port, tunnelRemoteHost: tunnel.remoteAddress.host, - localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : MakeAddress(tunnel.localAddress.host, tunnel.localAddress.port), + localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port), tunnelLocalPort: typeof tunnel.localAddress !== 'string' ? tunnel.localAddress.port : undefined, dispose: (silent?: boolean) => { this._proxy.$closeTunnel({ host: tunnel.remoteAddress.host, port: tunnel.remoteAddress.port }, silent); diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 4eb693366fb..3f5b0089072 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Extensions, IViewDescriptorService, IViewsRegistry, IViewsService } from 'vs/workbench/common/views'; -import { IRemoteExplorerService, MakeAddress, mapHasTunnelLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -166,12 +166,12 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon } this.urlFinder = this._register(new UrlFinder(this.terminalService, this.debugService)); this._register(this.urlFinder.onDidMatchLocalUrl(async (localUrl) => { - if (mapHasTunnelLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, localUrl.host, localUrl.port)) { + if (mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, localUrl.host, localUrl.port)) { return; } const forwarded = await this.remoteExplorerService.forward(localUrl); if (forwarded) { - const address = MakeAddress(forwarded.tunnelRemoteHost, forwarded.tunnelRemotePort); + const address = makeAddress(forwarded.tunnelRemoteHost, forwarded.tunnelRemotePort); const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available.", forwarded.tunnelRemotePort); const browserChoice: IPromptChoice = { diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 52018fae5a6..914dc37348c 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -26,7 +26,7 @@ import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { ActionRunner, IAction } from 'vs/base/common/actions'; import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction, ILocalizedString, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel, mapHasTunnelLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, TunnelModel, makeAddress, TunnelType, ITunnelItem, Tunnel, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID, parseAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; @@ -92,7 +92,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { const groups: ITunnelGroup[] = []; this._candidates = new Map(); (await this.model.candidates).forEach(candidate => { - this._candidates.set(MakeAddress(candidate.host, candidate.port), candidate); + this._candidates.set(makeAddress(candidate.host, candidate.port), candidate); }); if ((this.model.forwarded.size > 0) || this.remoteExplorerService.getEditableData(undefined)) { groups.push({ @@ -123,7 +123,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { } private addProcessInfoFromCandidate(tunnelItem: ITunnelItem) { - const key = MakeAddress(tunnelItem.remoteHost, tunnelItem.remotePort); + const key = makeAddress(tunnelItem.remoteHost, tunnelItem.remotePort); if (this._candidates.has(key)) { tunnelItem.description = this._candidates.get(key)!.detail; } @@ -158,8 +158,8 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { get candidates(): TunnelItem[] { const candidates: TunnelItem[] = []; this._candidates.forEach(value => { - if (!mapHasTunnelLocalhostOrAllInterfaces(this.model.forwarded, value.host, value.port) && - !mapHasTunnelLocalhostOrAllInterfaces(this.model.detected, value.host, value.port)) { + if (!mapHasAddressLocalhostOrAllInterfaces(this.model.forwarded, value.host, value.port) && + !mapHasAddressLocalhostOrAllInterfaces(this.model.detected, value.host, value.port)) { candidates.push(new TunnelItem(TunnelType.Candidate, value.host, value.port, undefined, undefined, false, undefined, value.detail)); } }); @@ -387,7 +387,7 @@ interface ITunnelGroup { class TunnelItem implements ITunnelItem { static createFromTunnel(tunnel: Tunnel, type: TunnelType = TunnelType.Forwarded, closeable?: boolean) { - return new TunnelItem(type, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, tunnel.localPort, closeable === undefined ? tunnel.closeable : closeable, tunnel.name, tunnel.description); + return new TunnelItem(type, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, tunnel.localPort, closeable === undefined ? tunnel.closeable : closeable, tunnel.name, tunnel.description ?? tunnel.runningProcess); } constructor( @@ -750,16 +750,8 @@ export namespace ForwardPortAction { export const TREEITEM_LABEL = nls.localize('remote.tunnel.forwardItem', "Forward Port"); const forwardPrompt = nls.localize('remote.tunnel.forwardPrompt', "Port number or address (eg. 3000 or 10.10.10.10:2000)."); - function parseInput(value: string): { host: string, port: number } | undefined { - const matches = value.match(/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\:|localhost:)?([0-9]+)$/); - if (!matches) { - return undefined; - } - return { host: matches[1]?.substring(0, matches[1].length - 1) || 'localhost', port: Number(matches[2]) }; - } - function validateInput(value: string): string | null { - const parsed = parseInput(value); + const parsed = parseAddress(value); if (!parsed) { return invalidPortString; } else if (parsed.port >= maxPortNumber) { @@ -784,7 +776,7 @@ export namespace ForwardPortAction { remoteExplorerService.setEditable(undefined, { onFinish: async (value, success) => { let parsed: { host: string, port: number } | undefined; - if (success && (parsed = parseInput(value))) { + if (success && (parsed = parseAddress(value))) { remoteExplorerService.forward({ host: parsed.host, port: parsed.port }).then(tunnel => error(notificationService, tunnel, parsed!.host, parsed!.port)); } remoteExplorerService.setEditable(undefined, null); @@ -808,7 +800,7 @@ export namespace ForwardPortAction { validateInput: (value) => Promise.resolve(validateInput(value)) }); let parsed: { host: string, port: number } | undefined; - if (value && (parsed = parseInput(value))) { + if (value && (parsed = parseAddress(value))) { remoteExplorerService.forward({ host: parsed.host, port: parsed.port }).then(tunnel => error(notificationService, tunnel, parsed!.host, parsed!.port)); } }; @@ -877,7 +869,7 @@ export namespace OpenPortInBrowserAction { if (arg instanceof TunnelItem) { const model = accessor.get(IRemoteExplorerService).tunnelModel; const openerService = accessor.get(IOpenerService); - const key = MakeAddress(arg.remoteHost, arg.remotePort); + const key = makeAddress(arg.remoteHost, arg.remotePort); return run(model, openerService, key); } }; diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index de784029338..510f0848bc0 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -47,37 +47,47 @@ export interface Tunnel { name?: string; description?: string; closeable?: boolean; + runningProcess: string | undefined; } -export function MakeAddress(host: string, port: number): string { +export function makeAddress(host: string, port: number): string { return host + ':' + port; } -export function mapHasTunnel(map: Map, host: string, port: number): boolean { - if (!isLocalhost(host)) { - return map.has(MakeAddress(host, port)); +export function parseAddress(address: string): { host: string, port: number } | undefined { + const matches = address.match(/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\:|localhost:)?([0-9]+)$/); + if (!matches) { + return undefined; } - - const stringAddress = MakeAddress('localhost', port); - if (map.has(stringAddress)) { - return true; - } - const numberAddress = MakeAddress('127.0.0.1', port); - if (map.has(numberAddress)) { - return true; - } - return false; + return { host: matches[1]?.substring(0, matches[1].length - 1) || 'localhost', port: Number(matches[2]) }; } -export function mapHasTunnelLocalhostOrAllInterfaces(map: Map, host: string, port: number): boolean { - if (!mapHasTunnel(map, host, port)) { - const otherHost = host === '0.0.0.0' ? 'localhost' : (host === 'localhost' ? '0.0.0.0' : undefined); - if (otherHost) { - return mapHasTunnel(map, otherHost, port); - } - return false; +export function mapHasAddress(map: Map, host: string, port: number): T | undefined { + if (!isLocalhost(host)) { + return map.get(makeAddress(host, port)); } - return true; + + const stringAddress = makeAddress('localhost', port); + if (map.has(stringAddress)) { + return map.get(stringAddress); + } + const numberAddress = makeAddress('127.0.0.1', port); + if (map.has(numberAddress)) { + return map.get(numberAddress); + } + return undefined; +} + +export function mapHasAddressLocalhostOrAllInterfaces(map: Map, host: string, port: number): T | undefined { + const originalAddress = mapHasAddress(map, host, port); + if (originalAddress) { + return originalAddress; + } + const otherHost = host === '0.0.0.0' ? 'localhost' : (host === 'localhost' ? '0.0.0.0' : undefined); + if (otherHost) { + return mapHasAddress(map, otherHost, port); + } + return undefined; } export class TunnelModel extends Disposable { @@ -89,7 +99,7 @@ export class TunnelModel extends Disposable { public onClosePort: Event<{ host: string, port: number }> = this._onClosePort.event; private _onPortName: Emitter<{ host: string, port: number }> = new Emitter(); public onPortName: Event<{ host: string, port: number }> = this._onPortName.event; - private _candidates: { host: string, port: number, detail: string }[] = []; + private _candidates: Map; private _onCandidatesChanged: Emitter = new Emitter(); public onCandidatesChanged: Event = this._onCandidatesChanged.event; private _candidateFilter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined; @@ -102,15 +112,17 @@ export class TunnelModel extends Disposable { @IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, ) { super(); + this._candidates = new Map(); this.forwarded = new Map(); this.tunnelService.tunnels.then(tunnels => { tunnels.forEach(tunnel => { if (tunnel.localAddress) { - this.forwarded.set(MakeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort), { + this.forwarded.set(makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort), { remotePort: tunnel.tunnelRemotePort, remoteHost: tunnel.tunnelRemoteHost, localAddress: tunnel.localAddress, - localPort: tunnel.tunnelLocalPort + localPort: tunnel.tunnelLocalPort, + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort)?.detail }); } }); @@ -118,21 +130,22 @@ export class TunnelModel extends Disposable { this.detected = new Map(); this._register(this.tunnelService.onTunnelOpened(tunnel => { - const key = MakeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort); + const key = makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort); if ((!this.forwarded.has(key)) && tunnel.localAddress) { this.forwarded.set(key, { remoteHost: tunnel.tunnelRemoteHost, remotePort: tunnel.tunnelRemotePort, localAddress: tunnel.localAddress, localPort: tunnel.tunnelLocalPort, - closeable: true + closeable: true, + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort)?.detail }); this.storeForwarded(); } this._onForwardPort.fire(this.forwarded.get(key)!); })); this._register(this.tunnelService.onTunnelClosed(address => { - const key = MakeAddress(address.host, address.port); + const key = makeAddress(address.host, address.port); if (this.forwarded.has(key)) { this.forwarded.delete(key); this.storeForwarded(); @@ -159,7 +172,7 @@ export class TunnelModel extends Disposable { } async forward(remote: { host: string, port: number }, local?: number, name?: string): Promise { - const key = MakeAddress(remote.host, remote.port); + const key = makeAddress(remote.host, remote.port); if (!this.forwarded.has(key)) { const authority = this.environmentService.remoteAuthority; const addressProvider: IAddressProvider | undefined = authority ? { @@ -174,7 +187,8 @@ export class TunnelModel extends Disposable { localPort: tunnel.tunnelLocalPort, name: name, closeable: true, - localAddress: tunnel.localAddress + localAddress: tunnel.localAddress, + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, remote.host, remote.port)?.detail }; this.forwarded.set(key, newForward); this._onForwardPort.fire(newForward); @@ -184,7 +198,7 @@ export class TunnelModel extends Disposable { } name(host: string, port: number, name: string) { - const key = MakeAddress(host, port); + const key = makeAddress(host, port); if (this.forwarded.has(key)) { this.forwarded.get(key)!.name = name; this.storeForwarded(); @@ -200,17 +214,18 @@ export class TunnelModel extends Disposable { } address(host: string, port: number): string | undefined { - const key = MakeAddress(host, port); + const key = makeAddress(host, port); return (this.forwarded.get(key) || this.detected.get(key))?.localAddress; } addEnvironmentTunnels(tunnels: TunnelDescription[]): void { tunnels.forEach(tunnel => { - this.detected.set(MakeAddress(tunnel.remoteAddress.host, tunnel.remoteAddress.port), { + this.detected.set(makeAddress(tunnel.remoteAddress.host, tunnel.remoteAddress.port), { remoteHost: tunnel.remoteAddress.host, remotePort: tunnel.remoteAddress.port, - localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : MakeAddress(tunnel.localAddress.host, tunnel.localAddress.port), - closeable: false + localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port), + closeable: false, + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.remoteAddress.host, tunnel.remoteAddress.port)?.detail }); }); this._onForwardPort.fire(); @@ -223,22 +238,48 @@ export class TunnelModel extends Disposable { async setCandidates(candidates: { host: string, port: number, detail: string }[]) { let processedCandidates = candidates; if (this._candidateFilter) { + // When an extension provides a filter, we do the filtering on the extension host before the candidates are set here. + // However, when the filter doesn't come from an extension we filter here. processedCandidates = await this._candidateFilter(candidates); } - this._candidates = processedCandidates.map(value => { - const nullIndex = value.detail.indexOf('\0'); - const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim(); - return { - host: value.host, - port: value.port, - detail - }; - }); + this.updateInResponseToCandidates(processedCandidates); this._onCandidatesChanged.fire(); } + private updateInResponseToCandidates(candidates: { host: string, port: number, detail: string }[]) { + const removedCandidates = this._candidates; + this._candidates = new Map(); + candidates.forEach(value => { + const nullIndex = value.detail.indexOf('\0'); + const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim(); + const addressKey = makeAddress(value.host, value.port); + this._candidates.set(addressKey, { + host: value.host, + port: value.port, + detail + }); + if (removedCandidates.has(addressKey)) { + removedCandidates.delete(addressKey); + } + }); + removedCandidates.forEach((_value, key) => { + const parsedAddress = parseAddress(key); + if (!parsedAddress) { + return; + } + const forwardedValue = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, parsedAddress.host, parsedAddress.port); + if (forwardedValue) { + forwardedValue.runningProcess = undefined; + } + const detectedValue = mapHasAddressLocalhostOrAllInterfaces(this.detected, parsedAddress.host, parsedAddress.port); + if (detectedValue) { + detectedValue.runningProcess = undefined; + } + }); + } + get candidates(): { host: string, port: number, detail: string }[] { - return this._candidates; + return Array.from(this._candidates.values()); } } From ab6878688f13563e4bc132d4b074c73f69046299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Nov 2020 10:53:22 +0100 Subject: [PATCH 0128/1837] fix terrapin usage --- build/azure-pipelines/darwin/product-build-darwin.yml | 2 +- build/azure-pipelines/linux/product-build-linux.yml | 2 +- build/azure-pipelines/product-compile.yml | 2 +- build/azure-pipelines/web/product-build-web.yml | 2 +- build/azure-pipelines/win32/product-build-win32-arm64.yml | 2 +- build/azure-pipelines/win32/product-build-win32.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 7366b36b536..8f13bfb5b9b 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -54,7 +54,7 @@ steps: displayName: Merge distro - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index f206a62d1ac..ebbc419a591 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -53,7 +53,7 @@ steps: displayName: Merge distro - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - script: | diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index d48a75c6799..0f3357ddc83 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -53,7 +53,7 @@ steps: condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 4203d760f51..d7b4ac42485 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -53,7 +53,7 @@ steps: displayName: Merge distro - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages # - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index ffce9961040..c536ed13eeb 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -59,7 +59,7 @@ steps: displayName: Merge distro - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 581c55de5b2..db56dc95451 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -59,7 +59,7 @@ steps: displayName: Merge distro - script: | - npx https://aka.ms/enablesecurefeed + npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 From 3a37613eb5e279cead507b76a846d9dca6422af3 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 10:59:44 +0100 Subject: [PATCH 0129/1837] Automatically forward candidate ports Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/remoteExplorer.ts | 225 ++++++++++++++---- .../contrib/remote/browser/tunnelView.ts | 7 +- .../remote/common/remoteExplorerService.ts | 13 +- 3 files changed, 197 insertions(+), 48 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 3f5b0089072..70e167d1245 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -7,7 +7,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Extensions, IViewDescriptorService, IViewsRegistry, IViewsService } from 'vs/workbench/common/views'; import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; -import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; +import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -15,10 +15,13 @@ import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarA import { UrlFinder } from 'vs/workbench/contrib/remote/browser/urlFinder'; import Severity from 'vs/base/common/severity'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationHandle, INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; +import { OperatingSystem } from 'vs/base/common/platform'; +import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; export const VIEWLET_ID = 'workbench.view.remote'; @@ -117,36 +120,103 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu export class AutomaticPortForwarding extends Disposable implements IWorkbenchContribution { - private contextServiceListener?: IDisposable; - private urlFinder?: UrlFinder; - private static AUTO_FORWARD_SETTING = 'remote.autoForwardPorts'; + static AUTO_FORWARD_SETTING = 'remote.autoForwardPorts'; constructor( - @ITerminalService private readonly terminalService: ITerminalService, - @INotificationService private readonly notificationService: INotificationService, - @IOpenerService private readonly openerService: IOpenerService, - @IViewsService private readonly viewsService: IViewsService, - @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, - @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IDebugService private readonly debugService: IDebugService + @ITerminalService readonly terminalService: ITerminalService, + @INotificationService readonly notificationService: INotificationService, + @IOpenerService readonly openerService: IOpenerService, + @IViewsService readonly viewsService: IViewsService, + @IRemoteExplorerService readonly remoteExplorerService: IRemoteExplorerService, + @IWorkbenchEnvironmentService readonly environmentService: IWorkbenchEnvironmentService, + @IContextKeyService readonly contextKeyService: IContextKeyService, + @IConfigurationService readonly configurationService: IConfigurationService, + @IDebugService readonly debugService: IDebugService, + @IRemoteAgentService readonly remoteAgentService: IRemoteAgentService ) { super(); + if (!this.environmentService.remoteAuthority) { + return; + } + + remoteAgentService.getEnvironment().then(environment => { + if (environment?.os === OperatingSystem.Windows) { + this._register(new WindowsAutomaticPortForwarding(terminalService, notificationService, openerService, + remoteExplorerService, contextKeyService, configurationService, debugService)); + } else if (environment?.os === OperatingSystem.Linux) { + this._register(new LinuxAutomaticPortForwarding(configurationService, remoteExplorerService, notificationService, openerService)); + } + }); + } +} + +class ForwardedPortNotifier extends Disposable { + private lastNotifyTime: Date; + private static COOL_DOWN = 5000; // milliseconds + private lastNotification: INotificationHandle | undefined; + + constructor(private readonly notificationService: INotificationService, + private readonly remoteExplorerService: IRemoteExplorerService, + private readonly openerService: IOpenerService) { + super(); + this.lastNotifyTime = new Date(); + this.lastNotifyTime.setFullYear(this.lastNotifyTime.getFullYear() - 1); + } + + public notify(tunnels: RemoteTunnel[]) { + if (Date.now() - this.lastNotifyTime.getTime() > ForwardedPortNotifier.COOL_DOWN) { + this.showNotification(tunnels); + } + } + + private showNotification(tunnels: RemoteTunnel[]) { + if (tunnels.length === 0) { + return; + } + tunnels = tunnels.sort((a, b) => a.tunnelRemotePort - b.tunnelRemotePort); + const firstTunnel = tunnels.shift()!; + const address = makeAddress(firstTunnel.tunnelRemoteHost, firstTunnel.tunnelRemotePort); + const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available. [See all available ports](command:{1}.focus)", + firstTunnel.tunnelRemotePort, TunnelPanel.ID); + const browserChoice: IPromptChoice = { + label: OpenPortInBrowserAction.LABEL, + run: () => OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, this.openerService, address) + }; + this.lastNotification = this.notificationService.prompt(Severity.Info, message, [browserChoice], { neverShowAgain: { id: 'remote.tunnelsView.autoForwardNeverShow', isSecondary: true } }); + this.lastNotification.onDidClose(() => { + this.lastNotification = undefined; + }); + } +} + +class WindowsAutomaticPortForwarding extends Disposable { + private contextServiceListener?: IDisposable; + private urlFinder?: UrlFinder; + private notifier: ForwardedPortNotifier; + + constructor( + private readonly terminalService: ITerminalService, + readonly notificationService: INotificationService, + readonly openerService: IOpenerService, + private readonly remoteExplorerService: IRemoteExplorerService, + private readonly contextKeyService: IContextKeyService, + private readonly configurationService: IConfigurationService, + private readonly debugService: IDebugService + ) { + super(); + this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); this._register(configurationService.onDidChangeConfiguration((e) => { if (e.affectsConfiguration(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { this.tryStartStopUrlFinder(); } })); - if (this.environmentService.remoteAuthority) { - this.contextServiceListener = this._register(this.contextKeyService.onDidChangeContext(e => { - if (e.affectsSome(new Set(forwardedPortsViewEnabled.keys()))) { - this.tryStartStopUrlFinder(); - } - })); - this.tryStartStopUrlFinder(); - } + this.contextServiceListener = this._register(this.contextKeyService.onDidChangeContext(e => { + if (e.affectsSome(new Set(forwardedPortsViewEnabled.keys()))) { + this.tryStartStopUrlFinder(); + } + })); + this.tryStartStopUrlFinder(); } private tryStartStopUrlFinder() { @@ -171,26 +241,7 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon } const forwarded = await this.remoteExplorerService.forward(localUrl); if (forwarded) { - const address = makeAddress(forwarded.tunnelRemoteHost, forwarded.tunnelRemotePort); - const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available.", - forwarded.tunnelRemotePort); - const browserChoice: IPromptChoice = { - label: OpenPortInBrowserAction.LABEL, - run: () => OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, this.openerService, address) - }; - const showChoice: IPromptChoice = { - label: nls.localize('remote.tunnelsView.showView', "Show Forwarded Ports"), - run: () => { - const remoteAuthority = this.environmentService.remoteAuthority; - const explorerType: string[] | undefined = remoteAuthority ? [remoteAuthority.split('+')[0]] : undefined; - if (explorerType) { - this.remoteExplorerService.targetType = explorerType; - } - this.viewsService.openViewContainer(VIEWLET_ID); - }, - isSecondary: true - }; - this.notificationService.prompt(Severity.Info, message, [browserChoice, showChoice], { neverShowAgain: { id: 'remote.tunnelsView.autoForwardNeverShow', isSecondary: true } }); + this.notifier.notify([forwarded]); } })); } @@ -202,3 +253,93 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon } } } + +class LinuxAutomaticPortForwarding extends Disposable { + private candidateListener: IDisposable | undefined; + private autoForwarded: Set = new Set(); + private notifier: ForwardedPortNotifier; + private initialCandidates: Set = new Set(); + + constructor( + private readonly configurationService: IConfigurationService, + readonly remoteExplorerService: IRemoteExplorerService, + readonly notificationService: INotificationService, + readonly openerService: IOpenerService + ) { + super(); + this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); + this._register(configurationService.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + this.startStopCandidateListener(); + } + })); + + this.startStopCandidateListener(); + } + + private startStopCandidateListener() { + if (this.configurationService.getValue(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + this.startCandidateListener(); + } else { + this.stopCandidateListener(); + } + } + + private stopCandidateListener() { + if (this.candidateListener) { + this.candidateListener.dispose(); + this.candidateListener = undefined; + } + } + + private startCandidateListener() { + if (this.candidateListener) { + // already started + return; + } + + this.candidateListener = this._register(this.remoteExplorerService.tunnelModel.onCandidatesChanged(this.handleCandidateUpdate, this)); + // Capture list of starting candidates so we don't auto forward them later. + this.setInitialCandidates(); + } + + private setInitialCandidates() { + this.remoteExplorerService.tunnelModel.candidates.forEach(async (value) => { + this.initialCandidates.add(makeAddress(value.host, value.port)); + }); + } + + private async forwardCandidates(): Promise { + const allTunnels = (await Promise.all(this.remoteExplorerService.tunnelModel.candidates.map(async (value) => { + const address = makeAddress(value.host, value.port); + if (this.initialCandidates.has(address)) { + return undefined; + } + const forwarded = await this.remoteExplorerService.forward(value); + if (forwarded) { + this.autoForwarded.add(address); + } + return forwarded; + }))).filter(tunnel => !!tunnel); + if (allTunnels.length === 0) { + return undefined; + } + return allTunnels; + } + + private async handleCandidateUpdate(removed: Map) { + removed.forEach((value, key) => { + if (this.autoForwarded.has(key)) { + this.remoteExplorerService.close(value); + this.autoForwarded.delete(key); + } else if (this.initialCandidates.has(key)) { + this.initialCandidates.delete(key); + } + }); + + const tunnels = await this.forwardCandidates(); + if (tunnels) { + this.notifier.notify(tunnels); + } + } +} diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 914dc37348c..61f640248b8 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -866,10 +866,15 @@ export namespace OpenPortInBrowserAction { export function handler(): ICommandHandler { return async (accessor, arg) => { + let key: string | undefined; if (arg instanceof TunnelItem) { + key = makeAddress(arg.remoteHost, arg.remotePort); + } else if (arg.tunnelRemoteHost && arg.tunnelRemotePort) { + key = makeAddress(arg.tunnelRemoteHost, arg.tunnelRemotePort); + } + if (key) { const model = accessor.get(IRemoteExplorerService).tunnelModel; const openerService = accessor.get(IOpenerService); - const key = makeAddress(arg.remoteHost, arg.remotePort); return run(model, openerService, key); } }; diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 510f0848bc0..ade9350f404 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -100,8 +100,9 @@ export class TunnelModel extends Disposable { private _onPortName: Emitter<{ host: string, port: number }> = new Emitter(); public onPortName: Event<{ host: string, port: number }> = this._onPortName.event; private _candidates: Map; - private _onCandidatesChanged: Emitter = new Emitter(); - public onCandidatesChanged: Event = this._onCandidatesChanged.event; + private _onCandidatesChanged: Emitter> = new Emitter(); + // onCandidateChanged returns the removed candidates + public onCandidatesChanged: Event> = this._onCandidatesChanged.event; private _candidateFilter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined; constructor( @@ -242,11 +243,12 @@ export class TunnelModel extends Disposable { // However, when the filter doesn't come from an extension we filter here. processedCandidates = await this._candidateFilter(candidates); } - this.updateInResponseToCandidates(processedCandidates); - this._onCandidatesChanged.fire(); + const removedCandidates = this.updateInResponseToCandidates(processedCandidates); + this._onCandidatesChanged.fire(removedCandidates); } - private updateInResponseToCandidates(candidates: { host: string, port: number, detail: string }[]) { + // Returns removed candidates + private updateInResponseToCandidates(candidates: { host: string, port: number, detail: string }[]): Map { const removedCandidates = this._candidates; this._candidates = new Map(); candidates.forEach(value => { @@ -276,6 +278,7 @@ export class TunnelModel extends Disposable { detectedValue.runningProcess = undefined; } }); + return removedCandidates; } get candidates(): { host: string, port: number, detail: string }[] { From 4b6b2bc6c2525e761d801ae73cfc2e136bbf5798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Nov 2020 11:00:40 +0100 Subject: [PATCH 0130/1837] update cache salt --- build/.cachesalt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/.cachesalt b/build/.cachesalt index 3f2ee542ad5..0e8a2d8b1a6 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-10-05T20:24:23.714Z +2020-11-23T10:00:34.612Z From eaf5eaa29fa55f67d14350d752187231bb959785 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 11:12:33 +0100 Subject: [PATCH 0131/1837] Allow name to be updated on extension forwarded ports Fixes microsoft/vscode-remote-release#4028 --- .../workbench/services/remote/common/remoteExplorerService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index ade9350f404..41eb11dddd8 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -195,6 +195,9 @@ export class TunnelModel extends Disposable { this._onForwardPort.fire(newForward); return tunnel; } + } else { + this.forwarded.get(key)!.name = name; + this._onForwardPort.fire(); } } From ee6e905a8a3062b69a0cd4bb619587bfa285e221 Mon Sep 17 00:00:00 2001 From: Jiaxun Wei Date: Mon, 23 Nov 2020 04:17:56 -0600 Subject: [PATCH 0132/1837] cache OpenURLOptions in ExtensionUrlBootstrapHandler (#110725) --- .../services/extensions/browser/extensionUrlHandler.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index a9370701c61..5ef04b5f571 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -118,7 +118,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { ); const cache = ExtensionUrlBootstrapHandler.cache; - setTimeout(() => cache.forEach(uri => this.handleURL(uri))); + setTimeout(() => cache.forEach(([uri, option]) => this.handleURL(uri, option))); } async handleURL(uri: URI, options?: IOpenURLOptions): Promise { @@ -346,10 +346,10 @@ registerSingleton(IExtensionUrlHandler, ExtensionUrlHandler); */ class ExtensionUrlBootstrapHandler implements IWorkbenchContribution, IURLHandler { - private static _cache: URI[] = []; + private static _cache: [URI, IOpenURLOptions | undefined][] = []; private static disposable: IDisposable; - static get cache(): URI[] { + static get cache(): [URI, IOpenURLOptions | undefined][] { ExtensionUrlBootstrapHandler.disposable.dispose(); const result = ExtensionUrlBootstrapHandler._cache; @@ -361,12 +361,12 @@ class ExtensionUrlBootstrapHandler implements IWorkbenchContribution, IURLHandle ExtensionUrlBootstrapHandler.disposable = urlService.registerHandler(this); } - async handleURL(uri: URI): Promise { + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { if (!isExtensionId(uri.authority)) { return false; } - ExtensionUrlBootstrapHandler._cache.push(uri); + ExtensionUrlBootstrapHandler._cache.push([uri, options]); return true; } } From 07d680b7c871293d7b574f64285280b4fdd19b46 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 23 Nov 2020 11:41:06 +0100 Subject: [PATCH 0133/1837] semantic highligting: deprecate member, add method. Fixes microsoft/language-server-protocol#1087 --- .../server/src/modes/javascriptSemanticTokens.ts | 8 ++++---- .../server/src/test/semanticTokens.test.ts | 10 +++++----- .../src/languageFeatures/semanticTokens.ts | 2 +- .../theme/common/tokenClassificationRegistry.ts | 3 ++- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts index 2f91c3d1486..f560559727a 100644 --- a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts +++ b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts @@ -99,7 +99,7 @@ function classifySymbol(symbol: ts.Symbol) { } export const enum TokenType { - class, enum, interface, namespace, typeParameter, type, parameter, variable, property, function, member, _ + class, enum, interface, namespace, typeParameter, type, parameter, variable, property, function, method, _ } export const enum TokenModifier { @@ -117,7 +117,7 @@ tokenTypes[TokenType.parameter] = 'parameter'; tokenTypes[TokenType.variable] = 'variable'; tokenTypes[TokenType.property] = 'property'; tokenTypes[TokenType.function] = 'function'; -tokenTypes[TokenType.member] = 'member'; +tokenTypes[TokenType.method] = 'method'; const tokenModifiers: string[] = []; tokenModifiers[TokenModifier.async] = 'async'; @@ -133,9 +133,9 @@ const tokenFromDeclarationMapping: { [name: string]: TokenType } = { [ts.SyntaxKind.EnumDeclaration]: TokenType.enum, [ts.SyntaxKind.EnumMember]: TokenType.property, [ts.SyntaxKind.ClassDeclaration]: TokenType.class, - [ts.SyntaxKind.MethodDeclaration]: TokenType.member, + [ts.SyntaxKind.MethodDeclaration]: TokenType.method, [ts.SyntaxKind.FunctionDeclaration]: TokenType.function, - [ts.SyntaxKind.MethodSignature]: TokenType.member, + [ts.SyntaxKind.MethodSignature]: TokenType.method, [ts.SyntaxKind.GetAccessor]: TokenType.property, [ts.SyntaxKind.PropertySignature]: TokenType.property, [ts.SyntaxKind.InterfaceDeclaration]: TokenType.interface, diff --git a/extensions/html-language-features/server/src/test/semanticTokens.test.ts b/extensions/html-language-features/server/src/test/semanticTokens.test.ts index 6d815748e5e..61fc1d5441e 100644 --- a/extensions/html-language-features/server/src/test/semanticTokens.test.ts +++ b/extensions/html-language-features/server/src/test/semanticTokens.test.ts @@ -87,8 +87,8 @@ suite('HTML Semantic Tokens', () => { ]; await assertTokens(input, [ t(3, 11, 3, 'function.declaration'), t(3, 15, 2, 'parameter.declaration'), - t(4, 11, 3, 'function'), t(4, 15, 4, 'interface'), t(4, 20, 3, 'member'), t(4, 24, 2, 'parameter'), - t(6, 6, 6, 'variable'), t(6, 13, 8, 'property'), t(6, 24, 5, 'member'), t(6, 35, 7, 'member'), t(6, 43, 1, 'parameter.declaration'), t(6, 48, 3, 'function'), t(6, 52, 1, 'parameter') + t(4, 11, 3, 'function'), t(4, 15, 4, 'interface'), t(4, 20, 3, 'method'), t(4, 24, 2, 'parameter'), + t(6, 6, 6, 'variable'), t(6, 13, 8, 'property'), t(6, 24, 5, 'method'), t(6, 35, 7, 'method'), t(6, 43, 1, 'parameter.declaration'), t(6, 48, 3, 'function'), t(6, 52, 1, 'parameter') ]); }); @@ -157,7 +157,7 @@ suite('HTML Semantic Tokens', () => { t(3, 8, 1, 'variable.declaration.readonly'), t(4, 8, 1, 'class.declaration'), t(4, 28, 1, 'property.declaration.static.readonly'), t(4, 42, 3, 'property.declaration.static'), t(4, 47, 3, 'interface'), t(5, 13, 1, 'enum.declaration'), t(5, 17, 1, 'property.declaration.readonly'), t(5, 24, 1, 'property.declaration.readonly'), t(5, 28, 1, 'property.readonly'), - t(6, 2, 7, 'variable'), t(6, 10, 3, 'member'), t(6, 14, 1, 'variable.readonly'), t(6, 18, 1, 'class'), t(6, 20, 1, 'property.static.readonly'), t(6, 24, 1, 'class'), t(6, 26, 3, 'property.static'), t(6, 30, 6, 'property.readonly'), + t(6, 2, 7, 'variable'), t(6, 10, 3, 'method'), t(6, 14, 1, 'variable.readonly'), t(6, 18, 1, 'class'), t(6, 20, 1, 'property.static.readonly'), t(6, 24, 1, 'class'), t(6, 26, 3, 'property.static'), t(6, 30, 6, 'property.readonly'), ]); }); @@ -197,7 +197,7 @@ suite('HTML Semantic Tokens', () => { ]; await assertTokens(input, [ t(3, 11, 1, 'function.declaration'), t(3, 13, 1, 'typeParameter.declaration'), t(3, 16, 2, 'parameter.declaration'), t(3, 20, 1, 'typeParameter'), t(3, 24, 1, 'typeParameter'), t(3, 39, 2, 'parameter'), - t(6, 2, 6, 'variable'), t(6, 9, 5, 'member') + t(6, 2, 6, 'variable'), t(6, 9, 5, 'method') ]); }); @@ -215,7 +215,7 @@ suite('HTML Semantic Tokens', () => { /*9*/'', ]; await assertTokens(input, [ - t(3, 2, 6, 'variable'), t(3, 9, 5, 'member') + t(3, 2, 6, 'variable'), t(3, 9, 5, 'method') ], [Range.create(Position.create(2, 0), Position.create(4, 0))]); await assertTokens(input, [ diff --git a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts index 202ed4d4ae1..16f78dbe486 100644 --- a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts +++ b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts @@ -174,7 +174,7 @@ tokenTypes[TokenType.variable] = 'variable'; tokenTypes[TokenType.enumMember] = 'enumMember'; tokenTypes[TokenType.property] = 'property'; tokenTypes[TokenType.function] = 'function'; -tokenTypes[TokenType.member] = 'member'; +tokenTypes[TokenType.member] = 'method'; const tokenModifiers: string[] = []; tokenModifiers[TokenModifier.async] = 'async'; diff --git a/src/vs/platform/theme/common/tokenClassificationRegistry.ts b/src/vs/platform/theme/common/tokenClassificationRegistry.ts index faceac2c61e..cf7a8df0f65 100644 --- a/src/vs/platform/theme/common/tokenClassificationRegistry.ts +++ b/src/vs/platform/theme/common/tokenClassificationRegistry.ts @@ -522,7 +522,8 @@ function createDefaultTokenClassificationRegistry(): TokenClassificationRegistry registerTokenType('typeParameter', nls.localize('typeParameter', "Style for type parameters."), [['entity.name.type.parameter']]); registerTokenType('function', nls.localize('function', "Style for functions"), [['entity.name.function'], ['support.function']]); - registerTokenType('member', nls.localize('member', "Style for member"), [['entity.name.function.member'], ['support.function']]); + registerTokenType('member', nls.localize('member', "Style for member functions"), [], 'method', 'Deprecated use `method` instead'); + registerTokenType('method', nls.localize('method', "Style for method (member functions)"), [['entity.name.function.member'], ['support.function']]); registerTokenType('macro', nls.localize('macro', "Style for macros."), [['entity.name.function.preprocessor']]); registerTokenType('variable', nls.localize('variable', "Style for variables."), [['variable.other.readwrite'], ['entity.name.variable']]); From 93f8adf26366a9a5fd7c6494bd62dfb79aff3ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Nov 2020 11:50:16 +0100 Subject: [PATCH 0134/1837] :lipstick: --- extensions/git/package.json | 2 +- .../browser/parts/views/viewPaneContainer.ts | 23 +++++++------------ src/vs/workbench/common/views.ts | 6 +---- .../contrib/debug/browser/welcomeView.ts | 1 - .../common/viewsWelcomeContribution.ts | 5 ++-- 5 files changed, 12 insertions(+), 25 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index fbd4fa421ee..bea5f96a67d 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2276,7 +2276,7 @@ { "view": "scm", "contents": "%view.workbench.scm.workspace%", - "when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0", + "when": "config.git.enabled && workbenchState == workspace && workspaceFolderCount != 0", "enablement": "git.state == initialized", "group": "5_scm@1" }, diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index f91487fcba4..92a6459dab8 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -556,8 +556,7 @@ export abstract class ViewPane extends Pane implements IView { this.bodyContainer.classList.add('welcome'); this.viewWelcomeContainer.innerText = ''; - for (const { content, preconditions } of contents) { - let buttonIndex = 0; + for (const { content, precondition } of contents) { const lines = content.split('\n'); for (let line of lines) { @@ -580,21 +579,15 @@ export abstract class ViewPane extends Pane implements IView { disposables.add(button); disposables.add(attachButtonStyler(button, this.themeService)); - if (preconditions) { - const precondition = preconditions[buttonIndex]; + if (precondition) { + const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); + updateEnablement(); - if (precondition) { - const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); - updateEnablement(); - - const keys = new Set(); - precondition.keys().forEach(key => keys.add(key)); - const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); - onDidChangeContext(updateEnablement, null, disposables); - } + const keys = new Set(); + precondition.keys().forEach(key => keys.add(key)); + const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); + onDidChangeContext(updateEnablement, null, disposables); } - - buttonIndex++; } else { const p = append(this.viewWelcomeContainer, $('p')); diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 95d534a587e..9205a76de48 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -294,11 +294,7 @@ export interface IViewContentDescriptor { readonly when?: ContextKeyExpression | 'default'; readonly group?: string; readonly order?: number; - - /** - * ordered preconditions for each button in the content - */ - readonly preconditions?: (ContextKeyExpression | undefined)[]; + readonly precondition?: ContextKeyExpression | undefined; } export interface IViewsRegistry { diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index 497a58b24af..c88b28e8b6f 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -117,7 +117,6 @@ let debugKeybindingLabel = ''; viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { content: localize({ key: 'runAndDebugAction', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] }, "[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID), - preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR], when: CONTEXT_DEBUGGERS_AVAILABLE, group: ViewContentGroups.Debug }); diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index 0863bedb546..ff54b32e0e8 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -36,12 +36,11 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo for (const welcome of contribution.value) { const id = ViewIdentifierMap[welcome.view] ?? welcome.view; const { group, order } = parseGroupAndOrder(welcome, contribution); - const enablement = ContextKeyExpr.deserialize(welcome.enablement); + const precondition = ContextKeyExpr.deserialize(welcome.enablement); const disposable = viewsRegistry.registerViewWelcomeContent(id, { content: welcome.contents, when: ContextKeyExpr.deserialize(welcome.when), - // supply the enablement clause for each line in case the line defines a button - preconditions: welcome.contents.split('\n').map((_) => enablement), + precondition, group, order }); From 93534b15da4566208a25e7cce32a9f5146c6f096 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 23 Nov 2020 12:12:07 +0100 Subject: [PATCH 0135/1837] fixes #104793 --- .../contrib/files/browser/views/explorerViewer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index f4bbf4725f1..de32dad57e7 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -871,7 +871,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Native DND if (isNative) { - if (!containsDragType(originalEvent, DataTransfers.FILES, CodeDataTransfers.FILES)) { + if (!containsDragType(originalEvent, DataTransfers.FILES, CodeDataTransfers.FILES, DataTransfers.RESOURCES)) { return false; } } @@ -975,7 +975,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // The only custom data transfer we set from the explorer is a file transfer // to be able to DND between multiple code file explorers across windows - const fileResources = items.filter(s => !s.isDirectory && s.resource.scheme === Schemas.file).map(r => r.resource.fsPath); + const fileResources = items.filter(s => s.resource.scheme === Schemas.file).map(r => r.resource.fsPath); if (fileResources.length) { originalEvent.dataTransfer.setData(CodeDataTransfers.FILES, JSON.stringify(fileResources)); } @@ -1278,9 +1278,9 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Pass focus to window this.hostService.focus(); - // Handle folders by adding to workspace if we are in workspace context + // Handle folders by adding to workspace if we are in workspace context and if dropped on top const folders = result.filter(r => r.success && r.stat && r.stat.isDirectory).map(result => ({ uri: result.stat!.resource })); - if (folders.length > 0) { + if (folders.length > 0 && target.isRoot) { const buttons = [ folders.length > 1 ? localize('copyFolders', "&&Copy Folders") : localize('copyFolder', "&&Copy Folder"), localize('cancel', "Cancel") From 951509368c133f357eb3762284298371845c02c3 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 12:18:16 +0100 Subject: [PATCH 0136/1837] Add terminal hack for task line data back in Fixes #105159 --- .../contrib/tasks/browser/terminalTaskSystem.ts | 9 ++++++--- .../workbench/contrib/tasks/common/problemCollectors.ts | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 7e5a1114930..4a4becc173e 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -858,7 +858,6 @@ export class TerminalTaskSystem implements ITaskSystem { }); promise = new Promise((resolve, reject) => { const onExit = terminal!.onExit((exitCode) => { - onData.dispose(); onExit.dispose(); let key = task.getMapKey(); this.removeFromActiveTasks(task); @@ -889,8 +888,12 @@ export class TerminalTaskSystem implements ITaskSystem { // There is nothing else to do here. } } - startStopProblemMatcher.done(); - startStopProblemMatcher.dispose(); + // Hack to work around #92868 until terminal is fixed. + setTimeout(() => { + onData.dispose(); + startStopProblemMatcher.done(); + startStopProblemMatcher.dispose(); + }, 100); if (!processStartedSignaled && terminal) { this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessStarted, task, terminal.processId!)); processStartedSignaled = true; diff --git a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts index 46574e02250..7af3764cad6 100644 --- a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts @@ -14,6 +14,7 @@ import { ILineMatcher, createLineMatcher, ProblemMatcher, ProblemMatch, ApplyToK import { IMarkerService, IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { generateUuid } from 'vs/base/common/uuid'; import { IFileService } from 'vs/platform/files/common/files'; +import { isWindows } from 'vs/base/common/platform'; export const enum ProblemCollectorEventKind { BackgroundProcessingBegins = 'backgroundProcessingBegins', @@ -282,7 +283,7 @@ export abstract class AbstractProblemCollector implements IDisposable { let existingMarker; if (!markersPerResource.has(key)) { markersPerResource.set(key, marker); - } else if (((existingMarker = markersPerResource.get(key)) !== undefined) && existingMarker.message.length < marker.message.length) { + } else if (((existingMarker = markersPerResource.get(key)) !== undefined) && (existingMarker.message.length < marker.message.length) && isWindows) { // Most likely https://github.com/microsoft/vscode/issues/77475 // Heuristic dictates that when the key is the same and message is smaller, we have hit this limitation. markersPerResource.set(key, marker); @@ -311,7 +312,7 @@ export abstract class AbstractProblemCollector implements IDisposable { this.deliverMarkersPerOwnerAndResourceResolved(owner, resource, markersPerResource, deliveredMarkersPerOwner); } - private deliverMarkersPerOwnerAndResourceResolved(owner: string, resource: string, markers: Map, reported: Map): void { + private deliverMarkersPerOwnerAndResourceResolved(owner: string, resource: string, markers: Map, reported: Map): Promise { if (markers.size !== reported.get(resource)) { let toSet: IMarkerData[] = []; markers.forEach(value => toSet.push(value)); From 9a07d50f52bf43d80b4901aaf7e81b59b86a8ef3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Nov 2020 21:35:15 +0100 Subject: [PATCH 0137/1837] Delegate to the command service as a fallback (microsoft/monaco-editor#2195) --- src/vs/editor/browser/widget/codeEditorWidget.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index beb7331a138..e39d4773399 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -1027,6 +1027,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE if (this._triggerEditorCommand(source, handlerId, payload)) { return; } + + this._commandService.executeCommand(handlerId, payload); } private _startComposition(): void { From e9fc5e147df0821f4e3f458e3170f8cad9b6ccfa Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Nov 2020 22:41:03 +0100 Subject: [PATCH 0138/1837] Fixes microsoft/monaco-editor#2192 --- src/vs/editor/browser/controller/mouseTarget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index b60883dc082..f09d41eb809 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -1073,7 +1073,7 @@ export function shadowCaretRangeFromPoint(shadowRoot: ShadowRoot, x: number, y: // Get the last child of the element until its firstChild is a text node // This assumes that the pointer is on the right of the line, out of the tokens // and that we want to get the offset of the last token of the line - while (el && el.firstChild && el.firstChild.nodeType !== el.firstChild.TEXT_NODE) { + while (el && el.firstChild && el.firstChild.nodeType !== el.firstChild.TEXT_NODE && el.lastChild && el.lastChild.firstChild) { el = el.lastChild; } From f19b19018c05ff24e4e9ecd01db04fc6055d4e39 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 14:57:49 +0100 Subject: [PATCH 0139/1837] Automatic port forwarding polish Part of microsoft/vscode-remote-release#4021 --- .../remote/common/remoteExplorerService.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 41eb11dddd8..9d9bb61126d 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -93,6 +93,7 @@ export function mapHasAddressLocalhostOrAllInterfaces(map: Map, ho export class TunnelModel extends Disposable { readonly forwarded: Map; readonly detected: Map; + private remoteTunnels: Map; private _onForwardPort: Emitter = new Emitter(); public onForwardPort: Event = this._onForwardPort.event; private _onClosePort: Emitter<{ host: string, port: number }> = new Emitter(); @@ -115,16 +116,19 @@ export class TunnelModel extends Disposable { super(); this._candidates = new Map(); this.forwarded = new Map(); + this.remoteTunnels = new Map(); this.tunnelService.tunnels.then(tunnels => { tunnels.forEach(tunnel => { if (tunnel.localAddress) { - this.forwarded.set(makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort), { + const key = makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort); + this.forwarded.set(key, { remotePort: tunnel.tunnelRemotePort, remoteHost: tunnel.tunnelRemoteHost, localAddress: tunnel.localAddress, localPort: tunnel.tunnelLocalPort, runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort)?.detail }); + this.remoteTunnels.set(key, tunnel); } }); }); @@ -143,6 +147,7 @@ export class TunnelModel extends Disposable { }); this.storeForwarded(); } + this.remoteTunnels.set(key, tunnel); this._onForwardPort.fire(this.forwarded.get(key)!); })); this._register(this.tunnelService.onTunnelClosed(address => { @@ -173,8 +178,8 @@ export class TunnelModel extends Disposable { } async forward(remote: { host: string, port: number }, local?: number, name?: string): Promise { - const key = makeAddress(remote.host, remote.port); - if (!this.forwarded.has(key)) { + const existingTunnel = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, remote.host, remote.port); + if (!existingTunnel) { const authority = this.environmentService.remoteAuthority; const addressProvider: IAddressProvider | undefined = authority ? { getAddress: async () => { return (await this.remoteAuthorityResolverService.resolveAuthority(authority)).authority; } @@ -191,13 +196,16 @@ export class TunnelModel extends Disposable { localAddress: tunnel.localAddress, runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, remote.host, remote.port)?.detail }; + const key = makeAddress(remote.host, remote.port); this.forwarded.set(key, newForward); + this.remoteTunnels.set(key, tunnel); this._onForwardPort.fire(newForward); return tunnel; } } else { - this.forwarded.get(key)!.name = name; + existingTunnel.name = name; this._onForwardPort.fire(); + return mapHasAddressLocalhostOrAllInterfaces(this.remoteTunnels, remote.host, remote.port); } } @@ -266,6 +274,10 @@ export class TunnelModel extends Disposable { if (removedCandidates.has(addressKey)) { removedCandidates.delete(addressKey); } + const forwardedValue = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, value.host, value.port); + if (forwardedValue) { + forwardedValue.runningProcess = value.detail; + } }); removedCandidates.forEach((_value, key) => { const parsedAddress = parseAddress(key); From 4e1eff7083ddd34a141d21c775f74e405338e56b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Nov 2020 15:00:32 +0100 Subject: [PATCH 0140/1837] web - turn the home indicator into a menu --- src/vs/platform/actions/common/actions.ts | 2 +- .../api/common/menusExtensionPoint.ts | 14 +- .../browser/actions/navigationActions.ts | 31 +- .../parts/activitybar/activitybarActions.ts | 387 ++++++++---------- .../parts/activitybar/activitybarPart.ts | 54 +-- .../browser/parts/titlebar/menubarControl.ts | 20 +- 6 files changed, 210 insertions(+), 298 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index aa382fdd58d..c06a3511b3a 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -95,7 +95,7 @@ export class MenuId { static readonly MenubarSwitchGroupMenu = new MenuId('MenubarSwitchGroupMenu'); static readonly MenubarTerminalMenu = new MenuId('MenubarTerminalMenu'); static readonly MenubarViewMenu = new MenuId('MenubarViewMenu'); - static readonly MenubarWebNavigationMenu = new MenuId('MenubarWebNavigationMenu'); + static readonly MenubarHomeMenu = new MenuId('MenubarHomeMenu'); static readonly OpenEditorsContext = new MenuId('OpenEditorsContext'); static readonly ProblemsPanelContext = new MenuId('ProblemsPanelContext'); static readonly SCMChangeContext = new MenuId('SCMChangeContext'); diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index 21af049d770..32027cbe252 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -73,19 +73,19 @@ const apiMenus: IAPIMenu[] = [ id: MenuId.DebugToolBar, description: localize('menus.debugToolBar', "The debug toolbar menu") }, - { - key: 'menuBar/webNavigation', - id: MenuId.MenubarWebNavigationMenu, - description: localize('menus.webNavigation', "The top level navigational menu (web only)"), - proposed: true, - supportsSubmenus: false - }, { key: 'menuBar/file', id: MenuId.MenubarFileMenu, description: localize('menus.file', "The top level file menu"), proposed: true }, + { + key: 'menuBar/home', + id: MenuId.MenubarHomeMenu, + description: localize('menus.home', "The home indicator context menu (web only)"), + proposed: true, + supportsSubmenus: false + }, { key: 'scm/title', id: MenuId.SCMTitle, diff --git a/src/vs/workbench/browser/actions/navigationActions.ts b/src/vs/workbench/browser/actions/navigationActions.ts index 7344a3a29b3..5833c3291dc 100644 --- a/src/vs/workbench/browser/actions/navigationActions.ts +++ b/src/vs/workbench/browser/actions/navigationActions.ts @@ -12,13 +12,10 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { IPanel } from 'vs/workbench/common/panel'; -import { Action2, MenuId, registerAction2, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions, CATEGORIES } from 'vs/workbench/common/actions'; import { Direction } from 'vs/base/browser/ui/grid/grid'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { isAncestor } from 'vs/base/browser/dom'; @@ -275,29 +272,6 @@ export class FocusPreviousPart extends Action { } } -class GoHomeContributor implements IWorkbenchContribution { - - constructor( - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService - ) { - const homeIndicator = environmentService.options?.homeIndicator; - if (homeIndicator) { - registerAction2(class extends Action2 { - constructor() { - super({ - id: `workbench.actions.goHome`, - title: nls.localize('goHome', "Go Home"), - menu: { id: MenuId.MenubarWebNavigationMenu } - }); - } - async run(): Promise { - window.location.href = homeIndicator.href; - } - }); - } - } -} - // --- Actions Registration const actionsRegistry = Registry.as(Extensions.WorkbenchActions); @@ -308,6 +282,3 @@ actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateLeftAc actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateRightAction, undefined), 'View: Navigate to the View on the Right', CATEGORIES.View.value); actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusNextPart, { primary: KeyCode.F6 }), 'View: Focus Next Part', CATEGORIES.View.value); actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPreviousPart, { primary: KeyMod.Shift | KeyCode.F6 }), 'View: Focus Previous Part', CATEGORIES.View.value); - -const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); -workbenchRegistry.registerWorkbenchContribution(GoHomeContributor, LifecyclePhase.Ready); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 3e47bb6a681..4e53f75857b 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -10,15 +10,14 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { dispose } from 'vs/base/common/lifecycle'; -import { SyncActionDescriptor, IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IMenuService, MenuId, IMenu, registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions'; -import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; +import { CATEGORIES } from 'vs/workbench/common/actions'; import { IActivity } from 'vs/workbench/common/activity'; import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; @@ -26,44 +25,31 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { Codicon } from 'vs/base/common/codicons'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; import { AuthenticationSession } from 'vs/editor/common/modes'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IProductService } from 'vs/platform/product/common/productService'; import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { getTitleBarStyle } from 'vs/platform/windows/common/windows'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; export class ViewContainerActivityAction extends ActivityAction { private static readonly preventDoubleClickDelay = 300; - private readonly viewletService: IViewletService; - private readonly layoutService: IWorkbenchLayoutService; - private readonly telemetryService: ITelemetryService; - private readonly configurationService: IConfigurationService; - - private lastRun: number; + private lastRun = 0; constructor( activity: IActivity, - @IViewletService viewletService: IViewletService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @ITelemetryService telemetryService: ITelemetryService, - @IConfigurationService configurationService: IConfigurationService + @IViewletService private readonly viewletService: IViewletService, + @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, + @ITelemetryService private readonly telemetryService: ITelemetryService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(activity); - - this.lastRun = 0; - this.viewletService = viewletService; - this.layoutService = layoutService; - this.telemetryService = telemetryService; - this.configurationService = configurationService; } updateActivity(activity: IActivity): void { @@ -105,6 +91,7 @@ export class ViewContainerActivityAction extends ActivityAction { this.logAction('show'); await this.viewletService.openViewlet(this.activity.id, true); + return this.activate(); } @@ -117,21 +104,18 @@ export class ViewContainerActivityAction extends ActivityAction { } } -export const ACCOUNTS_VISIBILITY_PREFERENCE_KEY = 'workbench.activity.showAccounts'; +class MenuActivityActionViewItem extends ActivityActionViewItem { -export class AccountsActionViewItem extends ActivityActionViewItem { constructor( + private readonly menuId: MenuId, action: ActivityAction, colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IMenuService protected menuService: IMenuService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IAuthenticationService private readonly authenticationService: IAuthenticationService, - @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IStorageService private readonly storageService: IStorageService, - @IProductService private readonly productService: IProductService, - @IConfigurationService private readonly configurationService: IConfigurationService, + @IMenuService protected readonly menuService: IMenuService, + @IContextMenuService protected readonly contextMenuService: IContextMenuService, + @IContextKeyService protected readonly contextKeyService: IContextKeyService, + @IConfigurationService protected readonly configurationService: IConfigurationService, + @IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService ) { super(action, { draggable: false, colors, icon: true }, themeService); } @@ -161,12 +145,103 @@ export class AccountsActionViewItem extends ActivityActionViewItem { })); } - private async getActions(accountsMenu: IMenu) { + protected async showContextMenu(e?: MouseEvent): Promise { + const disposables = new DisposableStore(); + + const menu = disposables.add(this.menuService.createMenu(this.menuId, this.contextKeyService)); + const actions = await this.resolveActions(menu, disposables); + + const isUsingCustomMenu = isWeb || (getTitleBarStyle(this.configurationService, this.environmentService) !== 'native' && !isMacintosh); // see #40262 + const position = this.configurationService.getValue('workbench.sideBar.location'); + + this.contextMenuService.showContextMenu({ + getAnchor: () => isUsingCustomMenu ? this.container : e || this.container, + anchorAlignment: isUsingCustomMenu ? (position === 'left' ? AnchorAlignment.RIGHT : AnchorAlignment.LEFT) : undefined, + anchorAxisAlignment: isUsingCustomMenu ? AnchorAxisAlignment.HORIZONTAL : AnchorAxisAlignment.VERTICAL, + getActions: () => actions, + onHide: () => disposables.dispose() + }); + } + + protected async resolveActions(menu: IMenu, disposables: DisposableStore): Promise { + const actions: IAction[] = []; + + disposables.add(createAndFillInActionBarActions(menu, undefined, { primary: [], secondary: actions })); + + return actions; + } +} + +export class HomeActivityActionViewItem extends MenuActivityActionViewItem { + + static readonly HOME_BAR_VISIBILITY_PREFERENCE = 'workbench.activity.showHomeIndicator'; + + constructor( + private readonly goHomeHref: string, + action: ActivityAction, + colors: (theme: IColorTheme) => ICompositeBarColors, + @IThemeService themeService: IThemeService, + @IMenuService menuService: IMenuService, + @IContextMenuService contextMenuService: IContextMenuService, + @IContextKeyService contextKeyService: IContextKeyService, + @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IStorageService private readonly storageService: IStorageService + ) { + super(MenuId.MenubarHomeMenu, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); + } + + protected async resolveActions(homeMenu: IMenu, disposables: DisposableStore): Promise { + const actions = []; + + // Go Home + actions.push(disposables.add(new Action('goHome', nls.localize('goHome', "Go Home"), undefined, true, async () => window.location.href = this.goHomeHref))); + actions.push(disposables.add(new Separator())); + + // Contributed + const contributedActions = await super.resolveActions(homeMenu, disposables); + actions.push(...contributedActions); + + // Hide + if (contributedActions.length > 0) { + actions.push(disposables.add(new Separator())); + } + actions.push(disposables.add(new Action('hide', nls.localize('hide', "Hide"), undefined, true, async () => { + this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, false, StorageScope.GLOBAL, StorageTarget.USER); + }))); + + return actions; + } +} + +export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { + + static readonly ACCOUNTS_VISIBILITY_PREFERENCE_KEY = 'workbench.activity.showAccounts'; + + constructor( + action: ActivityAction, + colors: (theme: IColorTheme) => ICompositeBarColors, + @IThemeService themeService: IThemeService, + @IContextMenuService contextMenuService: IContextMenuService, + @IMenuService menuService: IMenuService, + @IContextKeyService contextKeyService: IContextKeyService, + @IAuthenticationService private readonly authenticationService: IAuthenticationService, + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IStorageService private readonly storageService: IStorageService, + @IProductService private readonly productService: IProductService, + @IConfigurationService configurationService: IConfigurationService, + ) { + super(MenuId.AccountsContext, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); + } + + protected async resolveActions(accountsMenu: IMenu, disposables: DisposableStore): Promise { + await super.resolveActions(accountsMenu, disposables); + const otherCommands = accountsMenu.getActions(); const providers = this.authenticationService.getProviderIds(); - const allSessions = providers.map(async id => { + const allSessions = providers.map(async providerId => { try { - const sessions = await this.authenticationService.getSessions(id); + const sessions = await this.authenticationService.getSessions(providerId); const groupedSessions: { [label: string]: AuthenticationSession[] } = {}; sessions.forEach(session => { @@ -177,14 +252,9 @@ export class AccountsActionViewItem extends ActivityActionViewItem { } }); - return { - providerId: id, - sessions: groupedSessions - }; + return { providerId, sessions: groupedSessions }; } catch { - return { - providerId: id - }; + return { providerId }; } }); @@ -196,130 +266,67 @@ export class AccountsActionViewItem extends ActivityActionViewItem { if (sessionInfo.sessions) { Object.keys(sessionInfo.sessions).forEach(accountName => { - const hasEmbedderAccountSession = sessionInfo.sessions[accountName].some(session => session.id === (authenticationSession?.id)); - const manageExtensionsAction = new Action(`configureSessions${accountName}`, nls.localize('manageTrustedExtensions', "Manage Trusted Extensions"), '', true, _ => { + const manageExtensionsAction = disposables.add(new Action(`configureSessions${accountName}`, nls.localize('manageTrustedExtensions', "Manage Trusted Extensions"), '', true, () => { return this.authenticationService.manageTrustedExtensionsForAccount(sessionInfo.providerId, accountName); - }); - const signOutAction = new Action('signOut', nls.localize('signOut', "Sign Out"), '', true, _ => { - return this.authenticationService.signOutOfAccount(sessionInfo.providerId, accountName); - }); + })); - const actions = [manageExtensionsAction]; + const signOutAction = disposables.add(new Action('signOut', nls.localize('signOut', "Sign Out"), '', true, () => { + return this.authenticationService.signOutOfAccount(sessionInfo.providerId, accountName); + })); + + const providerSubMenuActions = [manageExtensionsAction]; + + const hasEmbedderAccountSession = sessionInfo.sessions[accountName].some(session => session.id === (authenticationSession?.id)); if (!hasEmbedderAccountSession || authenticationSession?.canSignOut) { - actions.push(signOutAction); + providerSubMenuActions.push(signOutAction); } - const menu = new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, actions); - menus.push(menu); + const providerSubMenu = disposables.add(new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, providerSubMenuActions)); + menus.push(providerSubMenu); }); } else { - const menu = new Action('providerUnavailable', nls.localize('authProviderUnavailable', '{0} is currently unavailable', providerDisplayName)); - menus.push(menu); + const providerUnavailableAction = disposables.add(new Action('providerUnavailable', nls.localize('authProviderUnavailable', '{0} is currently unavailable', providerDisplayName))); + menus.push(providerUnavailableAction); } }); if (menus.length && otherCommands.length) { - menus.push(new Separator()); + menus.push(disposables.add(new Separator())); } otherCommands.forEach((group, i) => { const actions = group[1]; menus = menus.concat(actions); if (i !== otherCommands.length - 1) { - menus.push(new Separator()); + menus.push(disposables.add(new Separator())); } }); if (menus.length) { - menus.push(new Separator()); + menus.push(disposables.add(new Separator())); } - menus.push(new Action('hide', nls.localize('hide', "Hide"), undefined, true, _ => { - this.storageService.store(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); - return Promise.resolve(); - })); + menus.push(disposables.add(new Action('hide', nls.localize('hide', "Hide"), undefined, true, async () => { + this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + }))); return menus; } - - private async showContextMenu(e?: MouseEvent): Promise { - const accountsActions: IAction[] = []; - const accountsMenu = this.menuService.createMenu(MenuId.AccountsContext, this.contextKeyService); - const actionsDisposable = createAndFillInActionBarActions(accountsMenu, undefined, { primary: [], secondary: accountsActions }); - const customMenus = isWeb || (getTitleBarStyle(this.configurationService, this.environmentService) !== 'native' && !isMacintosh); // see #40262 - const position = this.configurationService.getValue('workbench.sideBar.location'); - - const actions = await this.getActions(accountsMenu); - this.contextMenuService.showContextMenu({ - getAnchor: () => customMenus ? this.container : e || this.container, - anchorAlignment: customMenus ? (position === 'left' ? AnchorAlignment.RIGHT : AnchorAlignment.LEFT) : undefined, - anchorAxisAlignment: customMenus ? AnchorAxisAlignment.HORIZONTAL : AnchorAxisAlignment.VERTICAL, - getActions: () => actions, - onHide: () => { - accountsMenu.dispose(); - dispose(actionsDisposable); - } - }); - } } -export class GlobalActivityActionViewItem extends ActivityActionViewItem { +export class GlobalActivityActionViewItem extends MenuActivityActionViewItem { constructor( action: ActivityAction, colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, - @IMenuService private readonly menuService: IMenuService, - @IContextMenuService protected readonly contextMenuService: IContextMenuService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IEnvironmentService private readonly environmentService: IEnvironmentService + @IMenuService menuService: IMenuService, + @IContextMenuService contextMenuService: IContextMenuService, + @IContextKeyService contextKeyService: IContextKeyService, + @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService ) { - super(action, { draggable: false, colors, icon: true }, themeService); - } - - render(container: HTMLElement): void { - super.render(container); - - // Context menus are triggered on mouse down so that an item can be picked - // and executed with releasing the mouse over it - - this._register(DOM.addDisposableListener(this.container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { - DOM.EventHelper.stop(e, true); - this.showContextMenu(e); - })); - - this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { - let event = new StandardKeyboardEvent(e); - if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { - DOM.EventHelper.stop(e, true); - this.showContextMenu(); - } - })); - - this._register(DOM.addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => { - DOM.EventHelper.stop(e, true); - this.showContextMenu(); - })); - } - - private showContextMenu(e?: MouseEvent): void { - const globalActivityActions: IAction[] = []; - const globalActivityMenu = this.menuService.createMenu(MenuId.GlobalActivity, this.contextKeyService); - const actionsDisposable = createAndFillInActionBarActions(globalActivityMenu, undefined, { primary: [], secondary: globalActivityActions }); - const customMenus = isWeb || (getTitleBarStyle(this.configurationService, this.environmentService) !== 'native' && !isMacintosh); // see #40262 - const position = this.configurationService.getValue('workbench.sideBar.location'); - - this.contextMenuService.showContextMenu({ - getAnchor: () => customMenus ? this.container : e || this.container, - anchorAlignment: customMenus ? (position === 'left' ? AnchorAlignment.RIGHT : AnchorAlignment.LEFT) : undefined, - anchorAxisAlignment: customMenus ? AnchorAxisAlignment.HORIZONTAL : AnchorAxisAlignment.VERTICAL, - getActions: () => globalActivityActions, - onHide: () => { - globalActivityMenu.dispose(); - dispose(actionsDisposable); - } - }); + super(MenuId.GlobalActivity, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } } @@ -336,106 +343,62 @@ export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinne } } -class SwitchSideBarViewAction extends Action { +class SwitchSideBarViewAction extends Action2 { constructor( - id: string, - name: string, - @IViewletService private readonly viewletService: IViewletService, - @IActivityBarService private readonly activityBarService: IActivityBarService + desc: Readonly, + private readonly offset: number ) { - super(id, name); + super(desc); } - async run(offset: number): Promise { - const visibleViewletIds = this.activityBarService.getVisibleViewContainerIds(); + async run(accessor: ServicesAccessor): Promise { + const activityBarService = accessor.get(IActivityBarService); + const viewletService = accessor.get(IViewletService); - const activeViewlet = this.viewletService.getActiveViewlet(); + const visibleViewletIds = activityBarService.getVisibleViewContainerIds(); + + const activeViewlet = viewletService.getActiveViewlet(); if (!activeViewlet) { return; } let targetViewletId: string | undefined; for (let i = 0; i < visibleViewletIds.length; i++) { if (visibleViewletIds[i] === activeViewlet.getId()) { - targetViewletId = visibleViewletIds[(i + visibleViewletIds.length + offset) % visibleViewletIds.length]; + targetViewletId = visibleViewletIds[(i + visibleViewletIds.length + this.offset) % visibleViewletIds.length]; break; } } - await this.viewletService.openViewlet(targetViewletId, true); + await viewletService.openViewlet(targetViewletId, true); } } -export class PreviousSideBarViewAction extends SwitchSideBarViewAction { - - static readonly ID = 'workbench.action.previousSideBarView'; - static readonly LABEL = nls.localize('previousSideBarView', 'Previous Side Bar View'); - - constructor( - id: string, - name: string, - @IViewletService viewletService: IViewletService, - @IActivityBarService activityBarService: IActivityBarService - ) { - super(id, name, viewletService, activityBarService); - } - - run(): Promise { - return super.run(-1); - } -} - -export class NextSideBarViewAction extends SwitchSideBarViewAction { - - static readonly ID = 'workbench.action.nextSideBarView'; - static readonly LABEL = nls.localize('nextSideBarView', 'Next Side Bar View'); - - constructor( - id: string, - name: string, - @IViewletService viewletService: IViewletService, - @IActivityBarService activityBarService: IActivityBarService - ) { - super(id, name, viewletService, activityBarService); - } - - run(): Promise { - return super.run(1); - } -} - -export class HomeAction extends Action { - - constructor( - private readonly href: string, - name: string, - icon: Codicon - ) { - super('workbench.action.home', name, icon.classNames); - } - - async run(event: MouseEvent): Promise { - let openInNewWindow = false; - if (isMacintosh) { - openInNewWindow = event.metaKey; - } else { - openInNewWindow = event.ctrlKey; - } - - if (openInNewWindow) { - DOM.windowOpenNoOpener(this.href); - } else { - window.location.href = this.href; +registerAction2( + class PreviousSideBarViewAction extends SwitchSideBarViewAction { + constructor() { + super({ + id: 'workbench.action.previousSideBarView', + title: { value: nls.localize('previousSideBarView', "Previous Side Bar View"), original: 'Previous Side Bar View' }, + category: CATEGORIES.View, + f1: true + }, -1); } } -} +); -export class HomeActionViewItem extends ActionViewItem { - - constructor(action: IAction) { - super(undefined, action, { icon: true, label: false, useEventAsContext: true }); +registerAction2( + class NextSideBarViewAction extends SwitchSideBarViewAction { + constructor() { + super({ + id: 'workbench.action.nextSideBarView', + title: { value: nls.localize('nextSideBarView', "Next Side Bar View"), original: 'Next Side Bar View' }, + category: CATEGORIES.View, + f1: true + }, 1); + } } -} +); registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { const activityBarBackgroundColor = theme.getColor(ACTIVITY_BAR_BACKGROUND); @@ -547,7 +510,3 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = } } }); - -const registry = Registry.as(ActionExtensions.WorkbenchActions); -registry.registerWorkbenchAction(SyncActionDescriptor.from(PreviousSideBarViewAction), 'View: Previous Side Bar View', CATEGORIES.View.value); -registry.registerWorkbenchAction(SyncActionDescriptor.from(NextSideBarViewAction), 'View: Next Side Bar View', CATEGORIES.View.value); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index c7286d2c661..f33ef3ff9f9 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { GLOBAL_ACTIVITY_ID, IActivity, ACCOUNTS_ACTIVITY_ID } from 'vs/workbench/common/activity'; import { Part } from 'vs/workbench/browser/part'; -import { GlobalActivityActionViewItem, ViewContainerActivityAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewContainerActivityAction, AccountsActionViewItem, HomeAction, HomeActionViewItem, ACCOUNTS_VISIBILITY_PREFERENCE_KEY } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { GlobalActivityActionViewItem, ViewContainerActivityAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewContainerActivityAction, AccountsActivityActionViewItem, HomeActivityActionViewItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -72,11 +72,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { declare readonly _serviceBrand: undefined; - private static readonly ACTION_HEIGHT = 48; - static readonly PINNED_VIEW_CONTAINERS = 'workbench.activity.pinnedViewlets2'; + private static readonly PINNED_VIEW_CONTAINERS = 'workbench.activity.pinnedViewlets2'; private static readonly PLACEHOLDER_VIEW_CONTAINERS = 'workbench.activity.placeholderViewlets'; - private static readonly HOME_BAR_VISIBILITY_PREFERENCE = 'workbench.activity.showHomeIndicator'; + private static readonly ACTION_HEIGHT = 48; private static readonly ACCOUNTS_ACTION_INDEX = 0; + //#region IView readonly minimumWidth: number = 48; @@ -436,7 +436,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { codicon = Codicon.code; } - this.createHomeBar(homeIndicator.href, homeIndicator.title, codicon); + this.createHomeBar(homeIndicator.href, codicon); this.onDidChangeHomeBarVisibility(); } @@ -450,7 +450,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Global action bar this.globalActivitiesContainer = document.createElement('div'); - this.globalActivitiesContainer.classList.add('global-activity'); this.content.appendChild(this.globalActivitiesContainer); this.createGlobalActivityActionBar(this.globalActivitiesContainer); @@ -522,23 +521,19 @@ export class ActivitybarPart extends Part implements IActivityBarService { } })); } - - - } - private createHomeBar(href: string, title: string, icon: Codicon): void { + private createHomeBar(href: string, icon: Codicon): void { this.homeBarContainer = document.createElement('div'); this.homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home")); this.homeBarContainer.setAttribute('role', 'toolbar'); this.homeBarContainer.classList.add('home-bar'); this.homeBar = this._register(new ActionBar(this.homeBarContainer, { + actionViewItemProvider: action => this.instantiationService.createInstance(HomeActivityActionViewItem, href, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)), orientation: ActionsOrientation.VERTICAL, - animated: false, ariaLabel: nls.localize('home', "Home"), - actionViewItemProvider: action => new HomeActionViewItem(action), - allowContextMenu: true, + animated: false, preventLoopNavigation: true, ignoreOrientationForPreviousAndNextKey: true })); @@ -546,7 +541,12 @@ export class ActivitybarPart extends Part implements IActivityBarService { const homeBarIconBadge = document.createElement('div'); homeBarIconBadge.classList.add('home-bar-icon-badge'); this.homeBarContainer.appendChild(homeBarIconBadge); - this.homeBar.push(this._register(this.instantiationService.createInstance(HomeAction, href, title, icon))); + + this.homeBar.push(this._register(new ActivityAction({ + id: 'workbench.actions.home', + name: nls.localize('home', "Home"), + cssClass: icon.classNames + }))); const content = assertIsDefined(this.content); content.prepend(this.homeBarContainer); @@ -585,7 +585,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } if (action.id === 'workbench.actions.accounts') { - return this.instantiationService.createInstance(AccountsActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); + return this.instantiationService.createInstance(AccountsActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); } throw new Error(`No view item for action '${action.id}'`); @@ -597,18 +597,18 @@ export class ActivitybarPart extends Part implements IActivityBarService { ignoreOrientationForPreviousAndNextKey: true })); - this.globalActivityAction = new ActivityAction({ + this.globalActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.manage', name: nls.localize('manage', "Manage"), cssClass: Codicon.settingsGear.classNames - }); + })); if (this.accountsVisibilityPreference) { - this.accountsActivityAction = new ActivityAction({ + this.accountsActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.accounts', name: nls.localize('accounts', "Accounts"), cssClass: Codicon.account.classNames - }); + })); this.globalActivityActionBar.push(this.accountsActivityAction, { index: ActivitybarPart.ACCOUNTS_ACTION_INDEX }); } @@ -622,11 +622,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.globalActivityActionBar.pull(ActivitybarPart.ACCOUNTS_ACTION_INDEX); this.accountsActivityAction = undefined; } else { - this.accountsActivityAction = new ActivityAction({ + this.accountsActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.accounts', name: nls.localize('accounts', "Accounts"), cssClass: Codicon.account.classNames - }); + })); this.globalActivityActionBar.push(this.accountsActivityAction, { index: ActivitybarPart.ACCOUNTS_ACTION_INDEX }); } } @@ -864,11 +864,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.compositeBar.setCompositeBarItems(newCompositeItems); } - if (e.key === ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE && e.scope === StorageScope.GLOBAL) { + if (e.key === HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE && e.scope === StorageScope.GLOBAL) { this.onDidChangeHomeBarVisibility(); } - if (e.key === ACCOUNTS_VISIBILITY_PREFERENCE_KEY && e.scope === StorageScope.GLOBAL) { + if (e.key === AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY && e.scope === StorageScope.GLOBAL) { this.toggleAccountsActivity(); } } @@ -1001,19 +1001,19 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private get homeBarVisibilityPreference(): boolean { - return this.storageService.getBoolean(ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE, StorageScope.GLOBAL, true); + return this.storageService.getBoolean(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, StorageScope.GLOBAL, true); } private set homeBarVisibilityPreference(value: boolean) { - this.storageService.store(ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE, value, StorageScope.GLOBAL, StorageTarget.USER); + this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, value, StorageScope.GLOBAL, StorageTarget.USER); } private get accountsVisibilityPreference(): boolean { - return this.storageService.getBoolean(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, StorageScope.GLOBAL, true); + return this.storageService.getBoolean(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, StorageScope.GLOBAL, true); } private set accountsVisibilityPreference(value: boolean) { - this.storageService.store(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, value, StorageScope.GLOBAL, StorageTarget.USER); + this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, value, StorageScope.GLOBAL, StorageTarget.USER); } private migrateFromOldCachedViewContainersValue(): void { diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 6b539f6d0a5..6bb23035468 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -660,25 +660,7 @@ export class CustomMenubarControl extends MenubarControl { visibility: this.currentMenubarVisibility, getKeybinding: (action) => this.keybindingService.lookupKeybinding(action.id), alwaysOnMnemonics: this.alwaysOnMnemonics, - compactMode: this.currentCompactMenuMode, - getCompactMenuActions: () => { - if (!isWeb) { - return []; // only for web - } - - const webNavigationActions: IAction[] = []; - const webNavigationMenu = this.menuService.createMenu(MenuId.MenubarWebNavigationMenu, this.contextKeyService); - for (const groups of webNavigationMenu.getActions()) { - const [, actions] = groups; - for (const action of actions) { - action.label = mnemonicMenuLabel(this.calculateActionLabel(action)); - webNavigationActions.push(action); - } - } - webNavigationMenu.dispose(); - - return webNavigationActions; - } + compactMode: this.currentCompactMenuMode }; } From 21a42246d32e2072e736acc5e227fa30b518d328 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Nov 2020 15:00:38 +0100 Subject: [PATCH 0141/1837] fix compile --- src/vs/workbench/contrib/tasks/common/problemCollectors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts index 7af3764cad6..5e6c6f746fb 100644 --- a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts @@ -312,7 +312,7 @@ export abstract class AbstractProblemCollector implements IDisposable { this.deliverMarkersPerOwnerAndResourceResolved(owner, resource, markersPerResource, deliveredMarkersPerOwner); } - private deliverMarkersPerOwnerAndResourceResolved(owner: string, resource: string, markers: Map, reported: Map): Promise { + private deliverMarkersPerOwnerAndResourceResolved(owner: string, resource: string, markers: Map, reported: Map): void { if (markers.size !== reported.get(resource)) { let toSet: IMarkerData[] = []; markers.forEach(value => toSet.push(value)); From ea989da383e8bcaf17afb73123e7fbfd50b1ef6f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 15:36:06 +0100 Subject: [PATCH 0142/1837] Feedback from resolveTreeItem API proposal review Part of #100741 --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHostTreeViews.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index c595e1876e8..7de4a986580 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1028,7 +1028,7 @@ declare module 'vscode' { * @param element * @param item Undefined properties of `item` should be set then `item` should be returned. */ - resolveTreeItem?(element: T, item: TreeItem2): TreeItem2 | Thenable; + resolveTreeItem?(item: TreeItem2, element: T): ProviderResult; } export class TreeItem2 extends TreeItem { diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index dfbc29ebbdc..af3a31890f2 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -379,7 +379,7 @@ class ExtHostTreeView extends Disposable { if (element) { const node = this.nodes.get(element); if (node) { - const resolve = await this.dataProvider.resolveTreeItem(element, node.extensionItem); + const resolve = await this.dataProvider.resolveTreeItem(node.extensionItem, element) ?? node.extensionItem; // Resolvable elements. Currently only tooltip. node.item.tooltip = this.getTooltip(resolve.tooltip); return node.item; From a85b3391ef3c7c4193eeff38ea6b5587874a775f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Nov 2020 15:57:13 +0100 Subject: [PATCH 0143/1837] Consider to remove migrateFromOldCachedViewContainersValue (fix #109726) --- .../parts/activitybar/activitybarPart.ts | 171 ++++++++++-------- 1 file changed, 92 insertions(+), 79 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index f33ef3ff9f9..b4be48be029 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -25,7 +25,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions'; import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation, IViewsService } from 'vs/workbench/common/views'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; +import { assertIsDefined } from 'vs/base/common/types'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Schemas } from 'vs/base/common/network'; @@ -44,26 +44,26 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { CATEGORIES } from 'vs/workbench/common/actions'; interface IPlaceholderViewContainer { - id: string; - name?: string; - iconUrl?: UriComponents; - themeIcon?: ThemeIcon; - views?: { when?: string }[]; + readonly id: string; + readonly name?: string; + readonly iconUrl?: UriComponents; + readonly themeIcon?: ThemeIcon; + readonly views?: { when?: string }[]; } interface IPinnedViewContainer { - id: string; - pinned: boolean; - order?: number; - visible: boolean; + readonly id: string; + readonly pinned: boolean; + readonly order?: number; + readonly visible: boolean; } interface ICachedViewContainer { - id: string; + readonly id: string; name?: string; icon?: URI | ThemeIcon; - pinned: boolean; - order?: number; + readonly pinned: boolean; + readonly order?: number; visible: boolean; views?: { when?: string }[]; } @@ -99,17 +99,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { private globalActivityAction: ActivityAction | undefined; private globalActivityActionBar: ActionBar | undefined; - private readonly globalActivity: ICompositeActivity[] = []; private globalActivitiesContainer: HTMLElement | undefined; + private readonly globalActivity: ICompositeActivity[] = []; private accountsActivityAction: ActivityAction | undefined; - private accountsActivity: ICompositeActivity[] = []; + private readonly accountsActivity: ICompositeActivity[] = []; private readonly compositeActions = new Map(); private readonly viewContainerDisposables = new Map(); - private readonly keyboardNavigationDisposables = new DisposableStore(); + private readonly keyboardNavigationDisposables = this._register(new DisposableStore()); private readonly location = ViewContainerLocation.Sidebar; @@ -127,19 +127,33 @@ export class ActivitybarPart extends Part implements IActivityBarService { ) { super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService); - this.migrateFromOldCachedViewContainersValue(); - for (const cachedViewContainer of this.cachedViewContainers) { - if (environmentService.remoteAuthority // In remote window, hide activity bar entries until registered. - || this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) + if ( + environmentService.remoteAuthority || // In remote window, hide activity bar entries until registered + this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) ) { cachedViewContainer.visible = false; } } + this.compositeBar = this.createCompositeBar(); + + this.onDidRegisterViewContainers(this.getViewContainers()); + + this.registerListeners(); + } + + private createCompositeBar() { const cachedItems = this.cachedViewContainers - .map(v => ({ id: v.id, name: v.name, visible: v.visible, order: v.order, pinned: v.pinned })); - this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, cachedItems, { + .map(container => ({ + id: container.id, + name: container.name, + visible: container.visible, + order: container.order, + pinned: container.pinned + })); + + return this._register(this.instantiationService.createInstance(CompositeBar, cachedItems, { icon: true, orientation: ActionsOrientation.VERTICAL, preventLoopNavigation: true, @@ -148,8 +162,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction, getOnCompositeClickAction: (compositeId: string) => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)), getContextMenuActions: () => { - const menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService); const actions = []; + + // Home if (this.homeBarContainer) { actions.push(new Action( 'toggleHomeBarAction', @@ -160,22 +175,26 @@ export class ActivitybarPart extends Part implements IActivityBarService { )); } + // Menu + const menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService); if (menuBarVisibility === 'compact' || (menuBarVisibility === 'hidden' && isWeb)) { actions.push(this.instantiationService.createInstance(ToggleMenuBarAction, ToggleMenuBarAction.ID, menuBarVisibility === 'compact' ? nls.localize('hideMenu', "Hide Menu") : nls.localize('showMenu', "Show Menu"))); } - const toggleAccountsVisibilityAction = new Action( + // Accounts + actions.push(new Action( 'toggleAccountsVisibility', this.accountsVisibilityPreference ? nls.localize('hideAccounts', "Hide Accounts") : nls.localize('showAccounts', "Show Accounts"), undefined, true, async () => { this.accountsVisibilityPreference = !this.accountsVisibilityPreference; } - ); - - actions.push(toggleAccountsVisibilityAction); + )); actions.push(new Separator()); + // Toggle Sidebar actions.push(this.instantiationService.createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService))); + + // Toggle Activity Bar actions.push(new Action( ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"), @@ -198,19 +217,12 @@ export class ActivitybarPart extends Part implements IActivityBarService { colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme), overflowActionSize: ActivitybarPart.ACTION_HEIGHT })); - - this.onDidRegisterViewContainers(this.getViewContainers()); - this.registerListeners(); - } - - focusActivityBar(): void { - this.compositeBar.focus(); } private getContextMenuActionsForComposite(compositeId: string): Action[] { - const viewContainer = this.viewDescriptorService.getViewContainerById(compositeId)!; - const actions = []; + + const viewContainer = this.viewDescriptorService.getViewContainerById(compositeId)!; const defaultLocation = this.viewDescriptorService.getDefaultViewContainerLocation(viewContainer)!; if (defaultLocation !== this.viewDescriptorService.getViewContainerLocation(viewContainer)) { actions.push(new Action('resetLocationAction', nls.localize('resetLocation', "Reset Location"), undefined, true, async () => { @@ -271,6 +283,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (from === this.location) { this.onDidDeregisterViewContainer(container); } + if (to === this.location) { this.onDidRegisterViewContainers([container]); } @@ -300,6 +313,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private onDidViewContainerVisible(id: string): void { const viewContainer = this.getViewContainer(id); if (viewContainer) { + // Update the composite bar by adding this.compositeBar.addComposite(viewContainer); this.compositeBar.activateComposite(viewContainer.id); @@ -307,7 +321,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (viewContainer.hideIfEmpty) { const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer); if (viewContainerModel.activeViewDescriptors.length === 0) { - this.hideComposite(viewContainer.id); // Update the composite bar by hiding + // Update the composite bar by hiding + this.hideComposite(viewContainer.id); } } } @@ -333,6 +348,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (typeof priority !== 'number') { priority = 0; } + const activity: ICompositeActivity = { badge, clazz, priority }; const activityCache = activityId === GLOBAL_ACTIVITY_ID ? this.globalActivity : this.accountsActivity; @@ -381,16 +397,18 @@ export class ActivitybarPart extends Part implements IActivityBarService { private getCumulativeNumberBadge(activityCache: ICompositeActivity[], priority: number): NumberBadge { const numberActivities = activityCache.filter(activity => activity.badge instanceof NumberBadge && activity.priority === priority); - let number = numberActivities.reduce((result, activity) => { return result + (activity.badge).number; }, 0); - let descriptorFn = (): string => { + const number = numberActivities.reduce((result, activity) => { return result + (activity.badge).number; }, 0); + const descriptorFn = (): string => { return numberActivities.reduce((result, activity, index) => { result = result + (activity.badge).getDescription(); if (index < numberActivities.length - 1) { - result = result + '\n'; + result = `${result}\n`; } + return result; }, ''); }; + return new NumberBadge(number, descriptorFn); } @@ -454,6 +472,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.createGlobalActivityActionBar(this.globalActivitiesContainer); + // Keyboard Navigation this.registerKeyboardNavigationListeners(); return this.content; @@ -552,31 +571,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { content.prepend(this.homeBarContainer); } - updateStyles(): void { - super.updateStyles(); - - const container = assertIsDefined(this.getContainer()); - const background = this.getColor(ACTIVITY_BAR_BACKGROUND) || ''; - container.style.backgroundColor = background; - - const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || ''; - container.classList.toggle('bordered', !!borderColor); - container.style.borderColor = borderColor ? borderColor : ''; - } - - private getActivitybarItemColors(theme: IColorTheme): ICompositeBarColors { - return { - activeForegroundColor: theme.getColor(ACTIVITY_BAR_FOREGROUND), - inactiveForegroundColor: theme.getColor(ACTIVITY_BAR_INACTIVE_FOREGROUND), - activeBorderColor: theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER), - activeBackground: theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND), - badgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND), - badgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND), - dragAndDropBorder: theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BORDER), - activeBackgroundColor: undefined, inactiveBackgroundColor: undefined, activeBorderBottomColor: undefined, - }; - } - private createGlobalActivityActionBar(container: HTMLElement): void { this.globalActivityActionBar = this._register(new ActionBar(container, { actionViewItemProvider: action => { @@ -733,6 +727,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } else if (ThemeIcon.isThemeIcon(icon)) { cssClass = ThemeIcon.asClassName(icon); } + return { id, name, cssClass, iconUrl, keybindingId }; } @@ -804,6 +799,35 @@ export class ActivitybarPart extends Part implements IActivityBarService { .map(v => v.id); } + focusActivityBar(): void { + this.compositeBar.focus(); + } + + updateStyles(): void { + super.updateStyles(); + + const container = assertIsDefined(this.getContainer()); + const background = this.getColor(ACTIVITY_BAR_BACKGROUND) || ''; + container.style.backgroundColor = background; + + const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || ''; + container.classList.toggle('bordered', !!borderColor); + container.style.borderColor = borderColor ? borderColor : ''; + } + + private getActivitybarItemColors(theme: IColorTheme): ICompositeBarColors { + return { + activeForegroundColor: theme.getColor(ACTIVITY_BAR_FOREGROUND), + inactiveForegroundColor: theme.getColor(ACTIVITY_BAR_INACTIVE_FOREGROUND), + activeBorderColor: theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER), + activeBackground: theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND), + badgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND), + badgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND), + dragAndDropBorder: theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BORDER), + activeBackgroundColor: undefined, inactiveBackgroundColor: undefined, activeBorderBottomColor: undefined, + }; + } + layout(width: number, height: number): void { if (!this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) { return; @@ -828,6 +852,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private getViewContainer(id: string): ViewContainer | undefined { const viewContainer = this.viewDescriptorService.getViewContainerById(id); + return viewContainer && this.viewDescriptorService.getViewContainerLocation(viewContainer) === this.location ? viewContainer : undefined; } @@ -917,6 +942,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } } } + return this._cachedViewContainers; } @@ -927,6 +953,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { visible, order }))); + this.setPlaceholderViewContainers(cachedViewContainers.map(({ id, icon, name, views }) => ({ id, iconUrl: URI.isUri(icon) ? icon : undefined, @@ -1016,20 +1043,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, value, StorageScope.GLOBAL, StorageTarget.USER); } - private migrateFromOldCachedViewContainersValue(): void { - const value = this.storageService.get('workbench.activity.pinnedViewlets', StorageScope.GLOBAL); - if (value !== undefined) { - const storedStates: Array = JSON.parse(value); - const cachedViewContainers = storedStates.map(c => { - const serialized: ICachedViewContainer = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: undefined, visible: true, name: undefined, icon: undefined, views: undefined } : c; - serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible; - return serialized; - }); - this.storeCachedViewContainersState(cachedViewContainers); - this.storageService.remove('workbench.activity.pinnedViewlets', StorageScope.GLOBAL); - } - } - toJSON(): object { return { type: Parts.ACTIVITYBAR_PART From 5e82d27fa7a02da6ebeaf59a81b20868067dc9b0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 23 Nov 2020 16:02:54 +0100 Subject: [PATCH 0144/1837] support menu with prompt choices --- .../notification/common/notification.ts | 15 +++- .../notifications/notificationsViewer.ts | 6 +- src/vs/workbench/common/notifications.ts | 8 +- ...ensionRecommendationNotificationService.ts | 77 ++++++++----------- 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index acbbb55a3ca..c567c3de2de 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -240,6 +240,19 @@ export interface IPromptChoice { run: () => void; } +export interface IPromptChoiceWithMenu extends IPromptChoice { + + /** + * Additional choices those will be shown in the dropdown menu for this choice. + */ + readonly menu: IPromptChoice[]; + + /** + * Menu is not supported on secondary choices + */ + readonly isSecondary: undefined; +} + export interface IStatusMessageOptions { /** @@ -324,7 +337,7 @@ export interface INotificationService { * * @returns a handle on the notification to e.g. hide it or update message, buttons, etc. */ - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle; + prompt(severity: Severity, message: string, choices: (IPromptChoice | IPromptChoiceWithMenu)[], options?: INotificationProperties): INotificationHandle; /** * Shows a status message in the status area with the provided text. diff --git a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts index 98de6406d7f..21e87488da1 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts @@ -457,13 +457,15 @@ export class NotificationTemplateRenderer extends Disposable { const buttonToolbar = this.inputDisposables.add(new ButtonBar(this.template.buttonsContainer)); for (const action of primaryActions) { const buttonOptions = { title: true, /* assign titles to buttons in case they overflow */ }; + const dropdownActions = action instanceof ChoiceAction ? action.menu + : action instanceof ActionWithMenuAction ? action.actions : undefined; const button = this.inputDisposables.add( - action instanceof ActionWithMenuAction + dropdownActions ? buttonToolbar.addButtonWithDropdown({ ...buttonOptions, dropdownMenuOptions: { contextMenuProvider: this.contextMenuService, - actions: action.actions, + actions: dropdownActions, actionRunner } }) diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index b9fb58ac44c..e7df7148660 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter, INotificationProgressProperties } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter, INotificationProgressProperties, IPromptChoiceWithMenu } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -695,6 +695,7 @@ export class ChoiceAction extends Action { readonly onDidRun = this._onDidRun.event; private readonly _keepOpen: boolean; + private readonly _menu: ChoiceAction[] | undefined; constructor(id: string, choice: IPromptChoice) { super(id, choice.label, undefined, true, async () => { @@ -707,6 +708,11 @@ export class ChoiceAction extends Action { }); this._keepOpen = !!choice.keepOpen; + this._menu = !choice.isSecondary && (choice).menu ? (choice).menu.map((c, index) => new ChoiceAction(`${id}.${index}`, c)) : undefined; + } + + get menu(): ChoiceAction[] | undefined { + return this._menu; } get keepOpen(): boolean { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts index 87b425c726f..ab902f413c8 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Action, ActionWithMenuAction, IAction } from 'vs/base/common/actions'; +import { IAction } from 'vs/base/common/actions'; import { distinct } from 'vs/base/common/arrays'; import { CancelablePromise, createCancelablePromise, raceCancellablePromises, raceCancellation, timeout } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -15,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IExtensionRecommendationNotificationService, RecommendationsNotificationResult, RecommendationSource } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; -import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationHandle, INotificationService, IPromptChoice, IPromptChoiceWithMenu, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; @@ -59,23 +59,13 @@ class RecommendationsNotification { constructor( private readonly severity: Severity, private readonly message: string, - private readonly primary: IAction[], - private readonly secondary: IAction[], + private readonly choices: IPromptChoice[], private readonly notificationService: INotificationService ) { } show(): void { if (!this.notificationHandle) { - this.updateNotificationHandle(this.notificationService.notify({ - message: this.message, - severity: this.severity, - actions: { - primary: this.primary, - secondary: this.secondary, - }, - sticky: true, - onCancel: () => this.cancelled = true - })); + this.updateNotificationHandle(this.notificationService.prompt(this.severity, this.message, this.choices, { sticky: true, onCancel: () => this.cancelled = true })); } } @@ -84,17 +74,7 @@ class RecommendationsNotification { this.onDidCloseDisposable.clear(); this.notificationHandle.close(); this.cancelled = false; - this.updateNotificationHandle(this.notificationService.notify({ - message: this.message, - severity: this.severity, - actions: { - primary: this.primary, - secondary: this.secondary, - }, - silent: true, - sticky: false, - onCancel: () => this.cancelled = true - })); + this.updateNotificationHandle(this.notificationService.prompt(this.severity, this.message, this.choices, { silent: true, sticky: false, onCancel: () => this.cancelled = true })); } } @@ -261,8 +241,7 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec { onDidInstallRecommendedExtensions, onDidShowRecommendedExtensions, onDidCancelRecommendedExtensions, onDidNeverShowRecommendedExtensionsAgain }: RecommendationsNotificationActions): CancelablePromise { return createCancelablePromise(async token => { let accepted = false; - const primary: IAction[] = []; - const secondary: IAction[] = []; + const choices: (IPromptChoice | IPromptChoiceWithMenu)[] = []; const installExtensions = async (isMachineScoped?: boolean) => { this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); onDidInstallRecommendedExtensions(extensions); @@ -271,24 +250,32 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec this.extensionManagementService.installExtensions(extensions.map(e => e.gallery!), { isMachineScoped }) ]); }; - - if (this.userDataAutoSyncEnablementService.isEnabled() && this.userDataSyncResourceEnablementService.isResourceEnabled(SyncResource.Extensions)) { - primary.push(new ActionWithMenuAction('install', [ - new Action('install and do no sync', localize('install and do no sync', "Install (Do not sync)"), undefined, true, () => installExtensions(true)) - ], localize('install', "Install"), undefined, true, () => installExtensions())); - } else { - primary.push(new Action('install', localize('install', "Install"), undefined, true, () => installExtensions())); - } - primary.push(new Action('show recommendations', localize('show recommendations', "Show Recommendations"), undefined, true, async () => { - onDidShowRecommendedExtensions(extensions); - for (const extension of extensions) { - this.extensionsWorkbenchService.open(extension, { pinned: true }); + choices.push({ + label: localize('install', "Install"), + run: () => installExtensions(), + menu: this.userDataAutoSyncEnablementService.isEnabled() && this.userDataSyncResourceEnablementService.isResourceEnabled(SyncResource.Extensions) ? [{ + label: localize('install and do no sync', "Install (Do not sync)"), + run: () => installExtensions(true) + }] : undefined, + }); + choices.push(...[{ + label: localize('show recommendations', "Show Recommendations"), + run: async () => { + onDidShowRecommendedExtensions(extensions); + for (const extension of extensions) { + this.extensionsWorkbenchService.open(extension, { pinned: true }); + } + this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); } - this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); - })); - secondary.push(new Action('donotshow', choiceNever, undefined, true, async () => onDidNeverShowRecommendedExtensionsAgain(extensions))); + }, { + label: choiceNever, + isSecondary: true, + run: () => { + onDidNeverShowRecommendedExtensionsAgain(extensions); + } + }]); try { - accepted = await this.doShowRecommendationsNotification(Severity.Info, message, primary, secondary, source, token); + accepted = await this.doShowRecommendationsNotification(Severity.Info, message, choices, source, token); } catch (error) { if (!isPromiseCanceledError(error)) { throw error; @@ -330,11 +317,11 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec * => If it is not exe based and has higher or same priority as current, hide the current notification after showing it for 3s. * => Otherwise wait until the current notification is hidden. */ - private async doShowRecommendationsNotification(severity: Severity, message: string, primary: IAction[], secondary: IAction[], source: RecommendationSource, token: CancellationToken): Promise { + private async doShowRecommendationsNotification(severity: Severity, message: string, choices: IPromptChoice[], source: RecommendationSource, token: CancellationToken): Promise { const disposables = new DisposableStore(); try { this.recommendationSources.push(source); - const recommendationsNotification = new RecommendationsNotification(severity, message, primary, secondary, this.notificationService); + const recommendationsNotification = new RecommendationsNotification(severity, message, choices, this.notificationService); Event.once(Event.filter(recommendationsNotification.onDidChangeVisibility, e => !e))(() => this.showNextNotification()); if (this.visibleNotification) { const index = this.pendingNotificaitons.length; From a2ca2bbb1ced161cf48a6dd2d2e67b9327c00bb1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 23 Nov 2020 16:09:03 +0100 Subject: [PATCH 0145/1837] revert onCancel --- .../notification/common/notification.ts | 17 ++++++++++------- .../experimentalPrompts.test.ts | 4 ++-- .../notification/common/notificationService.ts | 4 ++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index c567c3de2de..487ed4484b6 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -35,12 +35,6 @@ export interface INotificationProperties { * such as future requests will not cause the notification to show again. */ readonly neverShowAgain?: INeverShowAgainOptions; - - /** - * Will be called if the user closed the notification without picking - * any of the provided choices. - */ - onCancel?: () => void; } export enum NeverShowAgainScope { @@ -253,6 +247,15 @@ export interface IPromptChoiceWithMenu extends IPromptChoice { readonly isSecondary: undefined; } +export interface IPromptOptions extends INotificationProperties { + + /** + * Will be called if the user closed the notification without picking + * any of the provided choices. + */ + onCancel?: () => void; +} + export interface IStatusMessageOptions { /** @@ -337,7 +340,7 @@ export interface INotificationService { * * @returns a handle on the notification to e.g. hide it or update message, buttons, etc. */ - prompt(severity: Severity, message: string, choices: (IPromptChoice | IPromptChoiceWithMenu)[], options?: INotificationProperties): INotificationHandle; + prompt(severity: Severity, message: string, choices: (IPromptChoice | IPromptChoiceWithMenu)[], options?: IPromptOptions): INotificationHandle; /** * Shows a status message in the status area with the provided text. diff --git a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts index 54ef9377778..f2b4d57f7c3 100644 --- a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts +++ b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Emitter } from 'vs/base/common/event'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotificationService, IPromptChoice, INotificationProperties, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, INotificationProperties, Severity, IPromptOptions } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -159,7 +159,7 @@ suite('Experimental Prompts', () => { }; instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], options: INotificationProperties) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options: IPromptOptions) => { assert.equal(b, promptText); assert.equal(c.length, 2); options.onCancel!(); diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index ca8bc01d8b0..d118dd1590d 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, INotificationProperties, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter, IPromptOptions } from 'vs/platform/notification/common/notification'; import { NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; @@ -110,7 +110,7 @@ export class NotificationService extends Disposable implements INotificationServ return handle; } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { const toDispose = new DisposableStore(); // Handle neverShowAgain option accordingly From 535943628c397f47f60a171af1efaf370d2752de Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 23 Nov 2020 16:13:31 +0100 Subject: [PATCH 0146/1837] revert --- src/vs/editor/standalone/browser/simpleServices.ts | 4 ++-- .../test/common/abstractKeybindingService.test.ts | 4 ++-- .../notification/test/common/testNotificationService.ts | 4 ++-- .../test/electron-browser/experimentalPrompts.test.ts | 4 ++-- .../extensionRecommendationsService.test.ts | 4 ++-- .../services/notification/common/notificationService.ts | 2 +- .../test/browser/api/extHostMessagerService.test.ts | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 3a0a30b1317..ba51dfd9e51 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -36,7 +36,7 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent } from 'vs/platform/label/common/label'; -import { INotification, INotificationHandle, INotificationService, IPromptChoice, NoOpNotification, IStatusMessageOptions, NotificationsFilter, INotificationProperties } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { IProgressRunner, IEditorProgressService } from 'vs/platform/progress/common/progress'; import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -250,7 +250,7 @@ export class SimpleNotificationService implements INotificationService { return SimpleNotificationService.NO_OP; } - public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { return SimpleNotificationService.NO_OP; } diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index f6dd5bf4a06..cbbb5434457 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -13,7 +13,7 @@ import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; -import { INotification, INotificationService, IPromptChoice, INotificationProperties, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { Disposable } from 'vs/base/common/lifecycle'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -155,7 +155,7 @@ suite('AbstractKeybindingService', () => { showMessageCalls.push({ sev: Severity.Error, message }); return new NoOpNotification(); }, - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties) { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { throw new Error('not implemented'); }, status(message: string, options?: IStatusMessageOptions) { diff --git a/src/vs/platform/notification/test/common/testNotificationService.ts b/src/vs/platform/notification/test/common/testNotificationService.ts index c41a2e67025..82d9960eaeb 100644 --- a/src/vs/platform/notification/test/common/testNotificationService.ts +++ b/src/vs/platform/notification/test/common/testNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, INotificationProperties, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; export class TestNotificationService implements INotificationService { @@ -28,7 +28,7 @@ export class TestNotificationService implements INotificationService { return TestNotificationService.NO_OP; } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { return TestNotificationService.NO_OP; } diff --git a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts index f2b4d57f7c3..584f71b2491 100644 --- a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts +++ b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentalPrompts.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Emitter } from 'vs/base/common/event'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotificationService, IPromptChoice, INotificationProperties, Severity, IPromptOptions } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, IPromptOptions, Severity } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -121,7 +121,7 @@ suite('Experimental Prompts', () => { const stub = instantiationService.stub(ICommandService, 'executeCommand', () => undefined); instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], options: INotificationProperties) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options: IPromptOptions) => { c[0].run(); return undefined!; } diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts index caf1d102987..ed8a92a9831 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts @@ -38,7 +38,7 @@ import { IURLService } from 'vs/platform/url/common/url'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotificationService, Severity, IPromptChoice, INotificationProperties } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; import { NativeURLService } from 'vs/platform/url/common/urlService'; import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService'; import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test'; @@ -262,7 +262,7 @@ suite('ExtensionRecommendationsService Test', () => { prompted = false; class TestNotificationService2 extends TestNotificationService { - public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties) { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { prompted = true; promptedEmitter.fire(); return super.prompt(severity, message, choices, options); diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index d118dd1590d..70b48e53088 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter, IPromptOptions } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; diff --git a/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts b/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts index 2d690e270d1..50f8ae572ed 100644 --- a/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts +++ b/src/vs/workbench/test/browser/api/extHostMessagerService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMessageService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, INotificationProperties, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { mock } from 'vs/base/test/common/mock'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; @@ -54,7 +54,7 @@ const emptyNotificationService = new class implements INotificationService { error(...args: any[]): never { throw new Error('not implemented'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { throw new Error('not implemented'); } status(message: string | Error, options?: IStatusMessageOptions): IDisposable { @@ -85,7 +85,7 @@ class EmptyNotificationService implements INotificationService { error(message: any): void { throw new Error('Method not implemented.'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: INotificationProperties): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { throw new Error('Method not implemented'); } status(message: string, options?: IStatusMessageOptions): IDisposable { From 0223a22d873a5318724ee77e5d6bce09a097e5ff Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 23 Nov 2020 16:34:57 +0100 Subject: [PATCH 0147/1837] externalize debug icons --- src/vs/base/common/codicons.ts | 9 ++- .../browser/breakpointEditorContribution.ts | 38 ++++++------ .../contrib/debug/browser/breakpointsView.ts | 40 +++++++------ .../browser/callStackEditorContribution.ts | 5 +- .../contrib/debug/browser/callStackView.ts | 23 ++++---- .../debug/browser/debug.contribution.ts | 40 ++++++------- .../debug/browser/debugActionViewItems.ts | 3 +- .../contrib/debug/browser/debugActions.ts | 15 ++--- .../browser/debugConfigurationManager.ts | 3 +- .../contrib/debug/browser/debugIcons.ts | 58 +++++++++++++++++++ .../contrib/debug/browser/debugQuickAccess.ts | 3 +- .../contrib/debug/browser/debugToolBar.ts | 23 ++++---- .../contrib/debug/browser/debugViewlet.ts | 3 +- .../contrib/debug/browser/exceptionWidget.ts | 3 +- .../workbench/contrib/debug/browser/repl.ts | 5 +- .../contrib/debug/browser/replViewer.ts | 3 +- .../contrib/debug/browser/variablesView.ts | 3 +- .../debug/browser/watchExpressionsView.ts | 3 +- .../debug/test/browser/breakpoints.test.ts | 46 +++++++-------- .../debug/test/browser/callStack.test.ts | 7 ++- 20 files changed, 206 insertions(+), 127 deletions(-) diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 3c4fffd3b5c..ccfa3022fbf 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -18,9 +18,12 @@ class Registry implements IIconRegistry { private readonly _onDidRegister = new Emitter(); public add(icon: Codicon) { - if (!this._icons.has(icon.id)) { + const existing = this._icons.get(icon.id); + if (!existing) { this._icons.set(icon.id, icon); this._onDidRegister.fire(icon); + } else if (icon.description) { + existing.description = icon.description; } else { console.error(`Duplicate registration of codicon ${icon.id}`); } @@ -44,7 +47,7 @@ const _registry = new Registry(); export const iconRegistry: IIconRegistry = _registry; export function registerIcon(id: string, def: Codicon, description?: string) { - return new Codicon(id, def); + return new Codicon(id, def, description); } export class Codicon { @@ -55,6 +58,8 @@ export class Codicon { // classNamesArray is useful for migrating to ES6 classlist public get classNamesArray() { return ['codicon', 'codicon-' + this.id]; } public get cssSelector() { return '.codicon.codicon-' + this.id; } + + public get classNameIdentifier() { return 'codicon-' + this.id; } } interface IconDefinition { diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 883f7e94e5b..e18f751b30f 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -22,7 +22,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { BreakpointWidget } from 'vs/workbench/contrib/debug/browser/breakpointWidget'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { MarkdownString } from 'vs/base/common/htmlContent'; -import { getBreakpointMessageAndClassName } from 'vs/workbench/contrib/debug/browser/breakpointsView'; +import { getBreakpointMessageAndIcon } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { generateUuid } from 'vs/base/common/uuid'; import { memoize } from 'vs/base/common/decorators'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; @@ -35,6 +35,7 @@ import { isSafari } from 'vs/base/browser/browser'; import { registerThemingParticipant, themeColorFromId } from 'vs/platform/theme/common/themeService'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; const $ = dom.$; @@ -46,7 +47,7 @@ interface IBreakpointDecoration { } const breakpointHelperDecoration: IModelDecorationOptions = { - glyphMarginClassName: 'codicon-debug-hint', + glyphMarginClassName: icons.debugBreakpointHint.classNames, stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }; @@ -72,7 +73,7 @@ export function createBreakpointDecorations(model: ITextModel, breakpoints: Read } function getBreakpointDecorationOptions(model: ITextModel, breakpoint: IBreakpoint, state: State, breakpointsActivated: boolean, showBreakpointsInOverviewRuler: boolean): IModelDecorationOptions { - const { className, message } = getBreakpointMessageAndClassName(state, breakpointsActivated, breakpoint, undefined); + const { icon, message } = getBreakpointMessageAndIcon(state, breakpointsActivated, breakpoint, undefined); let glyphMarginHoverMessage: MarkdownString | undefined; if (message) { @@ -94,7 +95,7 @@ function getBreakpointDecorationOptions(model: ITextModel, breakpoint: IBreakpoi const renderInline = breakpoint.column && (breakpoint.column > model.getLineFirstNonWhitespaceColumn(breakpoint.lineNumber)); return { - glyphMarginClassName: `${className}`, + glyphMarginClassName: icon.classNames, glyphMarginHoverMessage, stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, beforeContentClassName: renderInline ? `debug-breakpoint-placeholder` : undefined, @@ -453,9 +454,9 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi // Candidate decoration has a breakpoint attached when a breakpoint is already at that location and we did not yet set a decoration there // In practice this happens for the first breakpoint that was set on a line // We could have also rendered this first decoration as part of desiredBreakpointDecorations however at that moment we have no location information - const cssClass = candidate.breakpoint ? getBreakpointMessageAndClassName(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).className : 'codicon-debug-breakpoint-disabled'; + const icon = candidate.breakpoint ? getBreakpointMessageAndIcon(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).icon : icons.debugBreakpointDisabled; const contextMenuActions = () => this.getContextMenuActions(candidate.breakpoint ? [candidate.breakpoint] : [], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn); - const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, cssClass, candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions); + const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, icon.classNames, candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions); return { decorationId, @@ -575,9 +576,8 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable { private create(cssClass: string | null | undefined): void { this.domNode = $('.inline-breakpoint-widget'); - this.domNode.classList.add('codicon'); if (cssClass) { - this.domNode.classList.add(cssClass); + this.domNode.classList.add(...cssClass.split(' ')); } this.toDispose.push(dom.addDisposableListener(this.domNode, dom.EventType.CLICK, async e => { if (this.breakpoint) { @@ -645,15 +645,15 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointColor = theme.getColor(debugIconBreakpointForeground); if (debugIconBreakpointColor) { collector.addRule(` - .monaco-workbench .codicon-debug-breakpoint, - .monaco-workbench .codicon-debug-breakpoint-conditional, - .monaco-workbench .codicon-debug-breakpoint-log, - .monaco-workbench .codicon-debug-breakpoint-function, - .monaco-workbench .codicon-debug-breakpoint-data, - .monaco-workbench .codicon-debug-breakpoint-unsupported, - .monaco-workbench .codicon-debug-hint:not([class*='codicon-debug-breakpoint']):not([class*='codicon-debug-stackframe']), - .monaco-workbench .codicon-debug-breakpoint.codicon-debug-stackframe-focused::after, - .monaco-workbench .codicon-debug-breakpoint.codicon-debug-stackframe::after { + .monaco-workbench ${icons.debugBreakpoint.cssSelector}, + .monaco-workbench ${icons.debugBreakpointConditional.cssSelector}, + .monaco-workbench ${icons.debugBreakpointLog.cssSelector}, + .monaco-workbench ${icons.debugBreakpointFunction.cssSelector}, + .monaco-workbench ${icons.debugBreakpointData.cssSelector}, + .monaco-workbench ${icons.debugBreakpointUnsupported.cssSelector}, + .monaco-workbench ${icons.debugBreakpointHint.cssSelector}:not([class*='${icons.debugBreakpoint.classNameIdentifier}']):not([class*='${icons.debugStackframe.classNameIdentifier}']), + .monaco-workbench ${icons.debugBreakpoint.cssSelector}${icons.debugStackframeFocused.cssSelector}::after, + .monaco-workbench ${icons.debugBreakpoint.cssSelector}${icons.debugStackframe.cssSelector}::after { color: ${debugIconBreakpointColor} !important; } `); @@ -680,7 +680,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointCurrentStackframeForegroundColor = theme.getColor(debugIconBreakpointCurrentStackframeForeground); if (debugIconBreakpointCurrentStackframeForegroundColor) { collector.addRule(` - .monaco-workbench .codicon-debug-stackframe, + .monaco-workbench ${icons.debugStackframe.cssSelector}, .monaco-editor .debug-top-stack-frame-column::before { color: ${debugIconBreakpointCurrentStackframeForegroundColor} !important; } @@ -690,7 +690,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeForeground); if (debugIconBreakpointStackframeFocusedColor) { collector.addRule(` - .monaco-workbench .codicon-debug-stackframe-focused { + .monaco-workbench ${icons.debugStackframeFocused.cssSelector} { color: ${debugIconBreakpointStackframeFocusedColor} !important; } `); diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index b5ad993aedc..8a449d87fde 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -37,6 +37,8 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { Codicon } from 'vs/base/common/codicons'; const $ = dom.$; @@ -379,8 +381,8 @@ class BreakpointsRenderer implements IListRenderer this.tree, true, 'explorer-action codicon-collapse-all')]; + return [new CollapseAction(() => this.tree, true, 'explorer-action ' + icons.debugCollapseAll.classNames)]; } return []; @@ -501,7 +502,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer { + const action = new Action('debug.callStack.restartFrame', nls.localize('restartFrame', "Restart Frame"), icons.debugRestartFrame.classNames, true, async () => { try { await stackFrame.restart(); } catch (e) { @@ -994,7 +995,7 @@ class StopAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STOP_ID}`, STOP_LABEL, 'debug-action codicon-debug-stop'); + super(`action.${STOP_ID}`, STOP_LABEL, 'debug-action ' + icons.debugStop.classNames); } public run(): Promise { @@ -1008,7 +1009,7 @@ class DisconnectAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${DISCONNECT_ID}`, DISCONNECT_LABEL, 'debug-action codicon-debug-disconnect'); + super(`action.${DISCONNECT_ID}`, DISCONNECT_LABEL, 'debug-action ' + icons.debugDisconnect.classNames); } public run(): Promise { @@ -1022,7 +1023,7 @@ class RestartAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${RESTART_SESSION_ID}`, RESTART_LABEL, 'debug-action codicon-debug-restart'); + super(`action.${RESTART_SESSION_ID}`, RESTART_LABEL, 'debug-action ' + icons.debugRestart.classNames); } public run(): Promise { @@ -1036,7 +1037,7 @@ class StepOverAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_OVER_ID}`, STEP_OVER_LABEL, 'debug-action codicon-debug-step-over', thread.stopped); + super(`action.${STEP_OVER_ID}`, STEP_OVER_LABEL, 'debug-action ' + icons.debugStepOver.classNames, thread.stopped); } public run(): Promise { @@ -1050,7 +1051,7 @@ class StepIntoAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_INTO_ID}`, STEP_INTO_LABEL, 'debug-action codicon-debug-step-into', thread.stopped); + super(`action.${STEP_INTO_ID}`, STEP_INTO_LABEL, 'debug-action ' + icons.debugStepInto.classNames, thread.stopped); } public run(): Promise { @@ -1064,7 +1065,7 @@ class StepOutAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_OUT_ID}`, STEP_OUT_LABEL, 'debug-action codicon-debug-step-out', thread.stopped); + super(`action.${STEP_OUT_ID}`, STEP_OUT_LABEL, 'debug-action ' + icons.debugStepOut.classNames, thread.stopped); } public run(): Promise { @@ -1078,7 +1079,7 @@ class PauseAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${PAUSE_ID}`, PAUSE_LABEL, 'debug-action codicon-debug-pause', !thread.stopped); + super(`action.${PAUSE_ID}`, PAUSE_LABEL, 'debug-action ' + icons.debugPause.classNames, !thread.stopped); } public run(): Promise { @@ -1092,7 +1093,7 @@ class ContinueAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${CONTINUE_ID}`, CONTINUE_LABEL, 'debug-action codicon-debug-continue', thread.stopped); + super(`action.${CONTINUE_ID}`, CONTINUE_LABEL, 'debug-action ' + icons.debugContinue.classNames, thread.stopped); } public run(): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index fff513dedcb..d7178990077 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -52,7 +52,7 @@ import { DebugTitleContribution } from 'vs/workbench/contrib/debug/browser/debug import { registerColors } from 'vs/workbench/contrib/debug/browser/debugColors'; import { DebugEditorContribution } from 'vs/workbench/contrib/debug/browser/debugEditorContribution'; import { FileAccess } from 'vs/base/common/network'; -import { breakpointsViewIcon, callStackViewIcon, debugConsoleViewIcon, loadedScriptsViewIcon, runViewIcon, variablesViewIcon, watchViewIcon } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); const debugCategory = nls.localize('debugCategory', "Debug"); @@ -153,16 +153,16 @@ function registerCommandsAndActions(): void { }); }; - registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, { id: 'codicon/debug-continue' }, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, { id: 'codicon/debug-pause' }, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); - registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, { id: 'codicon/debug-stop' }, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); - registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, { id: 'codicon/debug-disconnect' }, CONTEXT_FOCUSED_SESSION_IS_ATTACH); - registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, { id: 'codicon/debug-step-over' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, { id: 'codicon/debug-step-into' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, { id: 'codicon/debug-step-out' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, { id: 'codicon/debug-restart' }); - registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, { id: 'codicon/debug-step-back' }, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, { id: 'codicon/debug-reverse-continue' }, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, ThemeIcon.fromCodicon(icons.debugContinue), CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, ThemeIcon.fromCodicon(icons.debugPause), CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); + registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, ThemeIcon.fromCodicon(icons.debugStop), CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); + registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, ThemeIcon.fromCodicon(icons.debugDisconnect), CONTEXT_FOCUSED_SESSION_IS_ATTACH); + registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, ThemeIcon.fromCodicon(icons.debugStepOver), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, ThemeIcon.fromCodicon(icons.debugStepInto), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, ThemeIcon.fromCodicon(icons.debugStepOut), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, ThemeIcon.fromCodicon(icons.debugRestart)); + registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, ThemeIcon.fromCodicon(icons.debugStepBack), CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, ThemeIcon.fromCodicon(icons.debugReverseContinue), CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); // Debug callstack context menu const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, order: number, when?: ContextKeyExpression, precondition?: ContextKeyExpression, group = 'navigation') => { @@ -460,7 +460,7 @@ function registerDebugPanel(): void { const VIEW_CONTAINER: ViewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: DEBUG_PANEL_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - icon: ThemeIcon.fromCodicon(debugConsoleViewIcon), + icon: ThemeIcon.fromCodicon(icons.debugConsoleViewIcon), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: DEBUG_PANEL_ID, focusCommand: { id: OpenDebugConsoleAction.ID }, @@ -471,7 +471,7 @@ function registerDebugPanel(): void { Registry.as(ViewExtensions.ViewsRegistry).registerViews([{ id: REPL_VIEW_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - containerIcon: ThemeIcon.fromCodicon(debugConsoleViewIcon), + containerIcon: ThemeIcon.fromCodicon(icons.debugConsoleViewIcon), canToggleVisibility: false, canMoveView: true, when: CONTEXT_DEBUGGERS_AVAILABLE, @@ -487,7 +487,7 @@ function registerDebugView(): void { id: VIEWLET_ID, name: nls.localize('run', "Run"), ctorDescriptor: new SyncDescriptor(DebugViewPaneContainer), - icon: ThemeIcon.fromCodicon(runViewIcon), + icon: ThemeIcon.fromCodicon(icons.runViewIcon), alwaysUseContainerInfo: true, order: 2 }, ViewContainerLocation.Sidebar); @@ -495,12 +495,12 @@ function registerDebugView(): void { // Register default debug views const viewsRegistry = Registry.as(ViewExtensions.ViewsRegistry); - viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: ThemeIcon.fromCodicon(variablesViewIcon), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: ThemeIcon.fromCodicon(watchViewIcon), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: ThemeIcon.fromCodicon(callStackViewIcon), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: ThemeIcon.fromCodicon(breakpointsViewIcon), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); - viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: ThemeIcon.fromCodicon(runViewIcon), ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); - viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: ThemeIcon.fromCodicon(loadedScriptsViewIcon), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: ThemeIcon.fromCodicon(icons.variablesViewIcon), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: ThemeIcon.fromCodicon(icons.watchViewIcon), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: ThemeIcon.fromCodicon(icons.callStackViewIcon), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: ThemeIcon.fromCodicon(icons.breakpointsViewIcon), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: ThemeIcon.fromCodicon(icons.runViewIcon), ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); + viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: ThemeIcon.fromCodicon(icons.loadedScriptsViewIcon), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); } function registerConfiguration(): void { diff --git a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts index 24a6695f824..8e2acc29b6d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts @@ -20,6 +20,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ADD_CONFIGURATION_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { debugStart } from 'vs/workbench/contrib/debug/browser/debugIcons'; const $ = dom.$; @@ -68,7 +69,7 @@ export class StartDebugActionViewItem implements IActionViewItem { render(container: HTMLElement): void { this.container = container; container.classList.add('start-debug-action-item'); - this.start = dom.append(container, $('.codicon.codicon-debug-start')); + this.start = dom.append(container, $(debugStart.cssSelector)); this.start.title = this.action.label; this.start.setAttribute('role', 'button'); this.start.tabIndex = 0; diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 98e516afd78..6d3eb9c3a56 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -14,6 +14,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { deepClone } from 'vs/base/common/objects'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; export abstract class AbstractDebugAction extends Action { @@ -64,7 +65,7 @@ export class ConfigureAction extends AbstractDebugAction { @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IQuickInputService private readonly quickInputService: IQuickInputService ) { - super(id, label, 'debug-action codicon codicon-gear', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.debugConfigure.classNames, debugService, keybindingService); this._register(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass())); this.updateClass(); } @@ -79,7 +80,7 @@ export class ConfigureAction extends AbstractDebugAction { private updateClass(): void { const configurationManager = this.debugService.getConfigurationManager(); - this.class = configurationManager.selectedConfiguration.name ? 'debug-action codicon codicon-gear' : 'debug-action codicon codicon-gear notification'; + this.class = configurationManager.selectedConfiguration.name ? 'debug-action' + icons.debugConfigure.classNames : 'debug-action ' + icons.debugConfigure.classNames + ' notification'; } async run(): Promise { @@ -210,7 +211,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { static readonly LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action codicon-close-all', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.breakpointsRemoveAll.classNames, debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } @@ -268,7 +269,7 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { static readonly DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action codicon-activate-breakpoints', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.breakpointsActivate.classNames, debugService, keybindingService); this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => { @@ -311,7 +312,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { static readonly LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action codicon-add', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.watchExpressionsAddFuncBreakpoint.classNames, debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } @@ -330,7 +331,7 @@ export class AddWatchExpressionAction extends AbstractDebugAction { static readonly LABEL = nls.localize('addWatchExpression', "Add Expression"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action codicon-add', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.watchExpressionsAdd.classNames, debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); this._register(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement())); } @@ -350,7 +351,7 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { static readonly LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action codicon-close-all', debugService, keybindingService); + super(id, label, 'debug-action ' + icons.watchExpressionsRemoveAll.classNames, debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); } diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index 09186a3bbdf..ba5b86f55e4 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -37,6 +37,7 @@ import { getVisibleAndSorted } from 'vs/workbench/contrib/debug/common/debugUtil import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager'; +import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons'; const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); jsonRegistry.registerSchema(launchSchemaId, launchSchema); @@ -225,7 +226,7 @@ export class ConfigurationManager implements IConfigurationManager { description: launch.name, config, buttons: [{ - iconClass: 'codicon-gear', + iconClass: debugConfigure.classNames, tooltip: nls.localize('editLaunchConfig', "Edit Debug Configuration in launch.json") }], launch diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts index 4c5923d9694..fdf87e6edd9 100644 --- a/src/vs/workbench/contrib/debug/browser/debugIcons.ts +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -13,3 +13,61 @@ export const watchViewIcon = registerIcon('watch-view-icon', Codicon.debugAlt, l export const callStackViewIcon = registerIcon('callstack-view-icon', Codicon.debugAlt, localize('callStackViewIcon', 'View icon of the call stack view.')); export const breakpointsViewIcon = registerIcon('breakpoints-view-icon', Codicon.debugAlt, localize('breakpointsViewIcon', 'View icon of the breakpoints view.')); export const loadedScriptsViewIcon = registerIcon('loaded-scripts-view-icon', Codicon.debugAlt, localize('loadedScriptsViewIcon', 'View icon of the loaded scripts view.')); + +export const debugBreakpoint = registerIcon('debug-breakpoint', Codicon.debugBreakpoint, localize('debugBreakpoint', 'Icon for breakpoints.')); +export const debugBreakpointDisabled = registerIcon('debug-breakpoint-disabled', Codicon.debugBreakpointDisabled, localize('debugBreakpointDisabled', 'Icon for disabled breakpoints.')); +export const debugBreakpointUnverified = registerIcon('debug-breakpoint-unverified', Codicon.debugBreakpointUnverified, localize('debugBreakpointUnverified', 'Icon for unverified breakpoints.')); +export const debugBreakpointHint = registerIcon('debug-hint', Codicon.debugHint, localize('debugBreakpointHint', 'Icon for breakpoint hints.')); +export const debugBreakpointFunction = registerIcon('debug-breakpoint-function', Codicon.debugBreakpointFunction, localize('debugBreakpointFunction', 'Icon for function breakpoints.')); +export const debugBreakpointFunctionUnverified = registerIcon('debug-breakpoint-function-unverified', Codicon.debugBreakpointFunctionUnverified, localize('debugBreakpointFunctionUnverified', 'Icon for unverified function breakpoints.')); +export const debugBreakpointFunctionDisabled = registerIcon('debug-breakpoint-function-disabled', Codicon.debugBreakpointFunctionDisabled, localize('debugBreakpointFunctionDisabled', 'Icon for disabled function breakpoints.')); + +export const debugBreakpointUnsupported = registerIcon('debug-breakpoint-unsupported', Codicon.debugBreakpointUnsupported, localize('debugBreakpointUnsupported', 'Icon for unsupported breakpoints.')); + +export const debugBreakpointConditionalUnverified = registerIcon('debug-breakpoint-conditional-unverified', Codicon.debugBreakpointConditionalUnverified, localize('debugBreakpointConditionalUnverified', 'Icon for unverified conditional breakpoints.')); +export const debugBreakpointConditional = registerIcon('debug-breakpoint-conditional', Codicon.debugBreakpointConditional, localize('debugBreakpointConditional', 'Icon for conditional breakpoints.')); +export const debugBreakpointConditionalDisabled = registerIcon('debug-breakpoint-conditional-disabled', Codicon.debugBreakpointConditionalDisabled, localize('debugBreakpointConditionalDisabled', 'Icon for disabled conditional breakpoints.')); +export const debugBreakpointDataUnverified = registerIcon('debug-breakpoint-data-unverified', Codicon.debugBreakpointDataUnverified, localize('debugBreakpointDataUnverified', 'Icon for unverified data breakpoints.')); +export const debugBreakpointData = registerIcon('debug-breakpoint-data', Codicon.debugBreakpointData, localize('debugBreakpointData', 'Icon for data breakpoints.')); +export const debugBreakpointDataDisabled = registerIcon('debug-breakpoint-data-disabled', Codicon.debugBreakpointDataDisabled, localize('debugBreakpointDataDisabled', 'Icon for disabled data breakpoints.')); +export const debugBreakpointLogUnverified = registerIcon('debug-breakpoint-log-unverified', Codicon.debugBreakpointLogUnverified, localize('debugBreakpointLogUnverified', 'Icon for unverified log breakpoints.')); +export const debugBreakpointLog = registerIcon('debug-breakpoint-log', Codicon.debugBreakpointLog, localize('debugBreakpointLog', 'Icon for log breakpoints.')); +export const debugBreakpointLogDisabled = registerIcon('debug-breakpoint-log-disabled', Codicon.debugBreakpointLogDisabled, localize('debugBreakpointLogDisabled', 'Icon for disabled log breakpoint.')); + +export const debugStackframeActive = registerIcon('debug-stackframe-active', Codicon.debugStackframeActive, localize('debugStackframeActive', 'Icon for an active stackframe.')); +export const debugStackframeDot = registerIcon('debug-stackframe-dot', Codicon.debugStackframeDot, localize('debugStackframeDot', 'Icon for a stackframe dot.')); +export const debugStackframe = registerIcon('debug-stackframe', Codicon.debugStackframe, localize('debugStackframe', 'Icon for a stackframe.')); +export const debugStackframeFocused = registerIcon('debug-stackframe-focused', Codicon.debugStackframeFocused, localize('debugStackframeFocused', 'Icon for a focused stackframe.')); + +export const debugGripper = registerIcon('debug-gripper', Codicon.gripper, localize('debugGripper', 'Icon for the debug bar gripper.')); + +export const debugRestartFrame = registerIcon('debug-restart-frame', Codicon.debugRestartFrame, localize('debugRestartFrame', 'Icon for the debug restart frame action.')); + +export const debugStop = registerIcon('debug-stop', Codicon.debugStop, localize('debugStop', 'Icon for the debug stop action.')); +export const debugDisconnect = registerIcon('debug-disconnect', Codicon.debugDisconnect, localize('debugDisconnect', 'Icon for the debug disconnect action.')); +export const debugRestart = registerIcon('debug-restart', Codicon.debugRestart, localize('debugRestart', 'Icon for the debug restart action.')); +export const debugStepOver = registerIcon('debug-step-over', Codicon.debugStepOver, localize('debugStepOver', 'Icon for the debug step over action.')); +export const debugStepInto = registerIcon('debug-step-into', Codicon.debugStepInto, localize('debugStepInto', 'Icon for the debug step into action.')); +export const debugStepOut = registerIcon('debug-step-out', Codicon.debugStepOut, localize('debugStepOut', 'Icon for the debug step out action.')); +export const debugStepBack = registerIcon('debug-step-back', Codicon.debugStepBack, localize('debugStepBack', 'Icon for the debug step back action.')); +export const debugPause = registerIcon('debug-pause', Codicon.debugPause, localize('debugPause', 'Icon for the debug pause action.')); +export const debugContinue = registerIcon('debug-continue', Codicon.debugContinue, localize('debugContinue', 'Icon for the debug continue action.')); +export const debugReverseContinue = registerIcon('debug-reverse-continue', Codicon.debugReverseContinue, localize('debugReverseContinue', 'Icon for the debug reverse continue action.')); + +export const debugStart = registerIcon('debug-start', Codicon.debugStart, localize('debugStart', 'Icon for the debug start action.')); +export const debugConfigure = registerIcon('debug-configure', Codicon.gear, localize('debugConfigure', 'Icon for the debug configure action.')); +export const debugConsole = registerIcon('debug-console', Codicon.gear, localize('debugConsole', 'Icon for the debug console open action.')); + +export const debugCollapseAll = registerIcon('debug-collapse-all', Codicon.collapseAll, localize('debugCollapseAll', 'Icon for the collapse all action in the debug views.')); +export const callstackViewSession = registerIcon('callstack-view-session', Codicon.bug, localize('callstackViewSession', 'Icon for the session icon in the call stack view.')); +export const debugConsoleClearAll = registerIcon('debug-console-clear-all', Codicon.clearAll, localize('debugConsoleClearAll', 'Icon for the clear all action in the debug console.')); +export const watchExpressionsRemoveAll = registerIcon('watch-expressions-remove-all', Codicon.closeAll, localize('watchExpressionsRemoveAll', 'Icon for the remove all action in the watch view.')); +export const watchExpressionsAdd = registerIcon('watch-expressions-add', Codicon.add, localize('watchExpressionsAdd', 'Icon for the add action in the watch view.')); +export const watchExpressionsAddFuncBreakpoint = registerIcon('watch-expressions-add-function-breakpoint', Codicon.add, localize('watchExpressionsAddFuncBreakpoint', 'Icon for the add function breakpoint action in the watch view.')); + +export const breakpointsRemoveAll = registerIcon('breakpoints-remove-all', Codicon.closeAll, localize('breakpointsRemoveAll', 'Icon for the remove all action in the breakpoints view.')); +export const breakpointsActivate = registerIcon('breakpoints-activate', Codicon.activateBreakpoints, localize('breakpointsActivate', 'Icon for the activatel action in the breakpoints view.')); + +export const debugConsoleEvaluationInput = registerIcon('debug-console-evaluation-input', Codicon.arrowSmallRight, localize('debugConsoleEvaluationInput', 'Icon for the debug evaluation input marker.')); +export const debugConsoleEvaluationPrompt = registerIcon('debug-console-evaluation-prompt', Codicon.chevronRight, localize('debugConsoleEvaluationPrompt', 'Icon for the debug evaluation prompt.')); +export const debugExceptionWidgetClose = registerIcon('debug-exception-widget-close', Codicon.close, localize('debugExceptionWidgetClose', 'Icon for the close action of the debug exception widget.')); diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts index cbcef52120d..1ab4d8e9b99 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts @@ -13,6 +13,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { matchesFuzzy } from 'vs/base/common/filters'; import { withNullAsUndefined } from 'vs/base/common/types'; import { ADD_CONFIGURATION_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons'; export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { @@ -55,7 +56,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 57c52f1f424..539e95ceb4f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -29,6 +29,7 @@ import { IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from ' import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -64,7 +65,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { this.$el = dom.$('div.debug-toolbar'); this.$el.style.top = `${layoutService.offset?.top ?? 0}px`; - this.dragArea = dom.append(this.$el, dom.$('div.drag-area.codicon.codicon-gripper')); + this.dragArea = dom.append(this.$el, dom.$('div.drag-area' + icons.debugGripper.cssSelector)); const actionBarContainer = dom.append(this.$el, dom.$('div.action-bar-container')); this.debugToolBarMenu = menuService.createMenu(MenuId.DebugToolBar, contextKeyService); @@ -351,51 +352,51 @@ registerThemingParticipant((theme, collector) => { const debugIconStartColor = theme.getColor(debugIconStartForeground); if (debugIconStartColor) { - collector.addRule(`.monaco-workbench .codicon-debug-start { color: ${debugIconStartColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStart.cssSelector} { color: ${debugIconStartColor} !important; }`); } const debugIconPauseColor = theme.getColor(debugIconPauseForeground); if (debugIconPauseColor) { - collector.addRule(`.monaco-workbench .codicon-debug-pause { color: ${debugIconPauseColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugPause.cssSelector} { color: ${debugIconPauseColor} !important; }`); } const debugIconStopColor = theme.getColor(debugIconStopForeground); if (debugIconStopColor) { - collector.addRule(`.monaco-workbench .codicon-debug-stop, .monaco-workbench .debug-view-content .codicon-record { color: ${debugIconStopColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStop.cssSelector} { color: ${debugIconStopColor} !important; }`); } const debugIconDisconnectColor = theme.getColor(debugIconDisconnectForeground); if (debugIconDisconnectColor) { - collector.addRule(`.monaco-workbench .debug-view-content .codicon-debug-disconnect, .monaco-workbench .debug-toolbar .codicon-debug-disconnect { color: ${debugIconDisconnectColor} !important; }`); + collector.addRule(`.monaco-workbench .debug-view-content ${icons.debugDisconnect.cssSelector}, .monaco-workbench .debug-toolbar ${icons.debugDisconnect.cssSelector}, { color: ${debugIconDisconnectColor} !important; }`); } const debugIconRestartColor = theme.getColor(debugIconRestartForeground); if (debugIconRestartColor) { - collector.addRule(`.monaco-workbench .codicon-debug-restart, .monaco-workbench .codicon-debug-restart-frame { color: ${debugIconRestartColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugRestart.cssSelector},, .monaco-workbench ${icons.debugRestartFrame.cssSelector}, { color: ${debugIconRestartColor} !important; }`); } const debugIconStepOverColor = theme.getColor(debugIconStepOverForeground); if (debugIconStepOverColor) { - collector.addRule(`.monaco-workbench .codicon-debug-step-over { color: ${debugIconStepOverColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepOver.cssSelector}, { color: ${debugIconStepOverColor} !important; }`); } const debugIconStepIntoColor = theme.getColor(debugIconStepIntoForeground); if (debugIconStepIntoColor) { - collector.addRule(`.monaco-workbench .codicon-debug-step-into { color: ${debugIconStepIntoColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepInto.cssSelector}, { color: ${debugIconStepIntoColor} !important; }`); } const debugIconStepOutColor = theme.getColor(debugIconStepOutForeground); if (debugIconStepOutColor) { - collector.addRule(`.monaco-workbench .codicon-debug-step-out { color: ${debugIconStepOutColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepOut.cssSelector}, { color: ${debugIconStepOutColor} !important; }`); } const debugIconContinueColor = theme.getColor(debugIconContinueForeground); if (debugIconContinueColor) { - collector.addRule(`.monaco-workbench .codicon-debug-continue,.monaco-workbench .codicon-debug-reverse-continue { color: ${debugIconContinueColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugContinue.cssSelector},,.monaco-workbench ${icons.debugReverseContinue.cssSelector}, { color: ${debugIconContinueColor} !important; }`); } const debugIconStepBackColor = theme.getColor(debugIconStepBackForeground); if (debugIconStepBackColor) { - collector.addRule(`.monaco-workbench .codicon-debug-step-back { color: ${debugIconStepBackColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepBack.cssSelector}, { color: ${debugIconStepBackColor} !important; }`); } }); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index f13479c4ec5..3182a136f9e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -33,6 +33,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { debugConsole } from 'vs/workbench/contrib/debug/browser/debugIcons'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -247,7 +248,7 @@ export class OpenDebugConsoleAction extends ToggleViewAction { @IContextKeyService contextKeyService: IContextKeyService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, 'codicon-debug-console'); + super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, debugConsole.classNames); } } diff --git a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts index 7cc8ad9d5b8..0fc8890c1f8 100644 --- a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts @@ -18,6 +18,7 @@ import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { Action } from 'vs/base/common/actions'; +import { debugExceptionWidgetClose } from 'vs/workbench/contrib/debug/browser/debugIcons'; const $ = dom.$; // theming @@ -79,7 +80,7 @@ export class ExceptionWidget extends ZoneWidget { let ariaLabel = label.textContent; const actionBar = new ActionBar(actions); - actionBar.push(new Action('editor.closeExceptionWidget', nls.localize('close', "Close"), 'codicon codicon-close', true, async () => { + actionBar.push(new Action('editor.closeExceptionWidget', nls.localize('close', "Close"), debugExceptionWidgetClose.classNames, true, async () => { const contribution = this.editor.getContribution(EDITOR_CONTRIBUTION_ID); contribution.closeExceptionWidget(); }), { label: false, icon: true }); diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index ab5592633ae..88a38e6ce16 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -59,6 +59,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { EDITOR_FONT_DEFAULTS, EditorOption } from 'vs/editor/common/config/editorOptions'; import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor'; import { ReplFilter, ReplFilterState, ReplFilterActionViewItem } from 'vs/workbench/contrib/debug/browser/replFilter'; +import { debugConsoleClearAll, debugConsoleEvaluationPrompt } from 'vs/workbench/contrib/debug/browser/debugIcons'; const $ = dom.$; @@ -595,7 +596,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { private createReplInput(container: HTMLElement): void { this.replInputContainer = dom.append(container, $('.repl-input-wrapper')); - dom.append(this.replInputContainer, $('.repl-input-chevron.codicon.codicon-chevron-right')); + dom.append(this.replInputContainer, $('.repl-input-chevron' + debugConsoleEvaluationPrompt.cssSelector)); const { scopedContextKeyService, historyNavigationEnablement } = createAndBindHistoryNavigationWidgetScopedContextKeyService(this.contextKeyService, { target: this.replInputContainer, historyNavigator: this }); this.historyNavigationEnablement = historyNavigationEnablement; @@ -856,7 +857,7 @@ export class ClearReplAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'debug-action codicon-clear-all'); + super(id, label, 'debug-action ' + debugConsoleClearAll.classNames); } async run(): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts index 861eb4ff6db..07302918462 100644 --- a/src/vs/workbench/contrib/debug/browser/replViewer.ts +++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts @@ -25,6 +25,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { localize } from 'vs/nls'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; +import { debugConsoleEvaluationInput } from 'vs/workbench/contrib/debug/browser/debugIcons'; const $ = dom.$; @@ -67,7 +68,7 @@ export class ReplEvaluationInputsRenderer implements ITreeRenderer this.tree, true, 'explorer-action codicon-collapse-all')]; + return [new CollapseAction(() => this.tree, true, 'explorer-action ' + debugCollapseAll.classNames)]; } layoutBody(width: number, height: number): void { diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index ac56c479111..65806b518a2 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -32,6 +32,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { debugCollapseAll } from 'vs/workbench/contrib/debug/browser/debugIcons'; const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024; let ignoreViewUpdates = false; @@ -160,7 +161,7 @@ export class WatchExpressionsView extends ViewPane { getActions(): IAction[] { return [ new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService), - new CollapseAction(() => this.tree, true, 'explorer-action codicon-collapse-all'), + new CollapseAction(() => this.tree, true, 'explorer-action ' + debugCollapseAll.classNames), new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService) ]; } diff --git a/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts b/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts index aece705d654..675fc6aa136 100644 --- a/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { URI as uri } from 'vs/base/common/uri'; import { DebugModel, Breakpoint } from 'vs/workbench/contrib/debug/common/debugModel'; -import { getExpandedBodySize, getBreakpointMessageAndClassName } from 'vs/workbench/contrib/debug/browser/breakpointsView'; +import { getExpandedBodySize, getBreakpointMessageAndIcon } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { dispose } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; import { IBreakpointData, IBreakpointUpdateData, State } from 'vs/workbench/contrib/debug/common/debug'; @@ -258,40 +258,40 @@ suite('Debug - Breakpoints', () => { ]); const breakpoints = model.getBreakpoints(); - let result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[0]); + let result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[0]); assert.equal(result.message, 'Expression: x > 5'); - assert.equal(result.className, 'codicon-debug-breakpoint-conditional'); + assert.equal(result.icon.id, 'debug-breakpoint-conditional'); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[1]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[1]); assert.equal(result.message, 'Disabled Breakpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint-disabled'); + assert.equal(result.icon.id, 'debug-breakpoint-disabled'); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[2]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[2]); assert.equal(result.message, 'Log Message: hello'); - assert.equal(result.className, 'codicon-debug-breakpoint-log'); + assert.equal(result.icon.id, 'debug-breakpoint-log'); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[3]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[3]); assert.equal(result.message, 'Hit Count: 12'); - assert.equal(result.className, 'codicon-debug-breakpoint-conditional'); + assert.equal(result.icon.id, 'debug-breakpoint-conditional'); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[4]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[4]); assert.equal(result.message, 'Breakpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint'); + assert.equal(result.icon.id, 'debug-breakpoint'); - result = getBreakpointMessageAndClassName(State.Stopped, false, breakpoints[2]); + result = getBreakpointMessageAndIcon(State.Stopped, false, breakpoints[2]); assert.equal(result.message, 'Disabled Logpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint-log-disabled'); + assert.equal(result.icon.id, 'debug-breakpoint-log-disabled'); model.addDataBreakpoint('label', 'id', true, ['read']); const dataBreakpoints = model.getDataBreakpoints(); - result = getBreakpointMessageAndClassName(State.Stopped, true, dataBreakpoints[0]); + result = getBreakpointMessageAndIcon(State.Stopped, true, dataBreakpoints[0]); assert.equal(result.message, 'Data Breakpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint-data'); + assert.equal(result.icon.id, 'debug-breakpoint-data'); const functionBreakpoint = model.addFunctionBreakpoint('foo', '1'); - result = getBreakpointMessageAndClassName(State.Stopped, true, functionBreakpoint); + result = getBreakpointMessageAndIcon(State.Stopped, true, functionBreakpoint); assert.equal(result.message, 'Function Breakpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint-function'); + assert.equal(result.icon.id, 'debug-breakpoint-function'); const data = new Map(); data.set(breakpoints[0].getId(), { verified: false, line: 10 }); @@ -300,17 +300,17 @@ suite('Debug - Breakpoints', () => { data.set(functionBreakpoint.getId(), { verified: true }); model.setBreakpointSessionData('mocksessionid', { supportsFunctionBreakpoints: false, supportsDataBreakpoints: true, supportsLogPoints: true }, data); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[0]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[0]); assert.equal(result.message, 'Unverified Breakpoint'); - assert.equal(result.className, 'codicon-debug-breakpoint-unverified'); + assert.equal(result.icon.id, 'debug-breakpoint-unverified'); - result = getBreakpointMessageAndClassName(State.Stopped, true, functionBreakpoint); + result = getBreakpointMessageAndIcon(State.Stopped, true, functionBreakpoint); assert.equal(result.message, 'Function breakpoints not supported by this debug type'); - assert.equal(result.className, 'codicon-debug-breakpoint-function-unverified'); + assert.equal(result.icon.id, 'debug-breakpoint-function-unverified'); - result = getBreakpointMessageAndClassName(State.Stopped, true, breakpoints[2]); + result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[2]); assert.equal(result.message, 'Log Message: hello, world'); - assert.equal(result.className, 'codicon-debug-breakpoint-log'); + assert.equal(result.icon.id, 'debug-breakpoint-log'); }); test('decorations', () => { diff --git a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts index ba1d0fa311d..4ccc9771607 100644 --- a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts @@ -17,6 +17,7 @@ import { Constants } from 'vs/base/common/uint'; import { getContext, getContextForContributedActions, getSpecificSourceName } from 'vs/workbench/contrib/debug/browser/callStackView'; import { getStackFrameThreadAndSessionToFocus } from 'vs/workbench/contrib/debug/browser/debugService'; import { generateUuid } from 'vs/base/common/uuid'; +import { debugStackframe, debugStackframeFocused } from 'vs/workbench/contrib/debug/browser/debugIcons'; export function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession { return new DebugSession(generateUuid(), { resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, { @@ -308,7 +309,7 @@ suite('Debug - CallStack', () => { let decorations = createDecorationsForStackFrame(firstStackFrame, firstStackFrame.range, true); assert.equal(decorations.length, 2); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, 'codicon-debug-stackframe'); + assert.equal(decorations[0].options.glyphMarginClassName, debugStackframe.classNames); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-top-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); @@ -316,7 +317,7 @@ suite('Debug - CallStack', () => { decorations = createDecorationsForStackFrame(secondStackFrame, firstStackFrame.range, true); assert.equal(decorations.length, 2); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, 'codicon-debug-stackframe-focused'); + assert.equal(decorations[0].options.glyphMarginClassName, debugStackframeFocused.classNames); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-focused-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); @@ -324,7 +325,7 @@ suite('Debug - CallStack', () => { decorations = createDecorationsForStackFrame(firstStackFrame, new Range(1, 5, 1, 6), true); assert.equal(decorations.length, 3); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, 'codicon-debug-stackframe'); + assert.equal(decorations[0].options.glyphMarginClassName, debugStackframe.classNames); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-top-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); From ef5a9128764592ed0031c413512b82d863ebc631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Nov 2020 16:51:41 +0100 Subject: [PATCH 0148/1837] fixes #109097 --- src/vs/workbench/contrib/update/browser/update.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index 5dae03bdd5e..3ee18c956dd 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -263,6 +263,10 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu } private onError(error: string): void { + if (/The request timed out|The network connection was lost/i.test(error)) { + return; + } + error = error.replace(/See https:\/\/github\.com\/Squirrel\/Squirrel\.Mac\/issues\/182 for more information/, 'See [this link](https://github.com/microsoft/vscode/issues/7426#issuecomment-425093469) for more information'); this.notificationService.notify({ From 34b0cedeb74beb80f643b0f8d8a6b0c2dcba9f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Nov 2020 16:54:17 +0100 Subject: [PATCH 0149/1837] fixes #108073 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index b2907e2e71f..b23b1174083 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1063,12 +1063,14 @@ class ViewModel { } focus() { - for (const repository of this.scmViewService.visibleRepositories) { - const widget = this.inputRenderer.getRenderedInputWidget(repository.input); + if (this.tree.getFocus().length === 0) { + for (const repository of this.scmViewService.visibleRepositories) { + const widget = this.inputRenderer.getRenderedInputWidget(repository.input); - if (widget) { - widget.focus(); - return; + if (widget) { + widget.focus(); + return; + } } } From eecbbcd3e340af5a0a361734d379feca8c676669 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Mon, 23 Nov 2020 16:00:30 +0000 Subject: [PATCH 0150/1837] fixes #110720 --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index b4be48be029..937bbd30de5 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -426,6 +426,10 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private installMenubar() { + if (this.menuBar) { + return; // prevent menu bar from installing twice #110720 + } + this.menuBarContainer = document.createElement('div'); this.menuBarContainer.classList.add('menubar'); From 542de8a8d7c498cad8de76e94edb498cf36f3251 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 17:09:00 +0100 Subject: [PATCH 0151/1837] Fix bug where tasks.json tasks aren't resolved --- src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index d66b3b50b7b..35f0c4bde49 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -1703,7 +1703,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return; } - if (contributed.length === 0) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { result.add(key, ...folderTasks.set.tasks); } else { let configurations = folderTasks.configurations; From a7b126700674665253600a922b95dcb89790046f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 23 Nov 2020 18:05:51 +0100 Subject: [PATCH 0152/1837] both custom and native hover showing (#111178) Fixes #111082 --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 0e1ba77f691..b996d599700 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -98,6 +98,8 @@ export class IconLabel extends Disposable { private descriptionNode: FastLabelNode | HighlightedLabel | undefined; private descriptionNodeFactory: () => FastLabelNode | HighlightedLabel; + private labelContainer: HTMLElement; + private hoverDelegate: IHoverDelegate | undefined = undefined; private readonly customHovers: Map = new Map(); @@ -106,10 +108,10 @@ export class IconLabel extends Disposable { this.domNode = this._register(new FastLabelNode(dom.append(container, dom.$('.monaco-icon-label')))); - const labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container')); + this.labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container')); - const nameContainer = dom.append(labelContainer, dom.$('span.monaco-icon-name-container')); - this.descriptionContainer = this._register(new FastLabelNode(dom.append(labelContainer, dom.$('span.monaco-icon-description-container')))); + const nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container')); + this.descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container')))); if (options?.supportHighlights) { this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportCodicons); @@ -149,7 +151,7 @@ export class IconLabel extends Disposable { } this.domNode.className = classes.join(' '); - this.setupHover(this.domNode.element, options?.title); + this.setupHover(this.labelContainer, options?.title); this.nameNode.setLabel(label, options); From 40a902c9cfa9ed79c6255aace8d6d818477a0f91 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 22 Nov 2020 13:52:38 -0800 Subject: [PATCH 0153/1837] Multiline markdownEnumDescription should not break split json settings editor Fix #110840 --- .../services/preferences/common/preferencesModels.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index f4bd140d3b8..50611fa179d 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -996,7 +996,9 @@ class SettingsContentBuilder { `${displayEnum}: ${fixSettingLink(desc)}` : displayEnum; - this._contentByLines.push(`${indent}// - ${line}`); + const lines = line.split(/\n/g); + lines[0] = ' - ' + lines[0]; + this._contentByLines.push(...lines.map(l => `${indent}// ${l}`)); setting.descriptionRanges.push({ startLineNumber: this.lineCountWithOffset, startColumn: this.lastLine.indexOf(line) + 1, endLineNumber: this.lineCountWithOffset, endColumn: this.lastLine.length }); }); From 4c55c7264ff66fcd15faecfd1c52016a337efa9e Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Mon, 23 Nov 2020 09:02:15 -0800 Subject: [PATCH 0154/1837] Revert "Fix #58600, Format Emmet package.json (#110891)" This reverts commit ffacef4727ef6896823b895d5684f7e9e3df27fb. --- extensions/emmet/package.json | 891 +++++++++--------- extensions/emmet/package.nls.json | 1 - extensions/emmet/src/emmetCommon.ts | 6 +- .../browser/actions/expandAbbreviation.ts | 43 + .../emmet/browser/emmet.contribution.ts | 4 +- ...ndEmmetAbbreviation.ts => emmetActions.ts} | 64 +- ...breviation.test.ts => emmetAction.test.ts} | 52 +- 7 files changed, 544 insertions(+), 517 deletions(-) create mode 100644 src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts rename src/vs/workbench/contrib/emmet/browser/{expandEmmetAbbreviation.ts => emmetActions.ts} (69%) rename src/vs/workbench/contrib/emmet/test/browser/{expandEmmetAbbreviation.test.ts => emmetAction.test.ts} (57%) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index a0a22505f85..12178fa8b56 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -1,461 +1,446 @@ { - "name": "emmet", - "displayName": "Emmet", - "description": "%description%", - "version": "1.0.0", - "publisher": "vscode", - "license": "MIT", - "engines": { - "vscode": "^1.13.0" - }, - "icon": "images/icon.png", - "categories": [ - "Other" - ], - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-emmet" - }, - "activationEvents": [ - "*", - "onCommand:emmet.expandAbbreviation", - "onLanguage:html", - "onLanguage:css", - "onLanguage:scss", - "onLanguage:less" - ], - "main": "./out/node/emmetNodeMain", - "browser": "./dist/browser/emmetBrowserMain", - "contributes": { - "configuration": { - "type": "object", - "title": "Emmet", - "properties": { - "emmet.showExpandedAbbreviation": { - "type": [ - "string" - ], - "enum": [ - "never", - "always", - "inMarkupAndStylesheetFilesOnly" - ], - "default": "always", - "markdownDescription": "%emmetShowExpandedAbbreviation%" - }, - "emmet.showAbbreviationSuggestions": { - "type": "boolean", - "default": true, - "markdownDescription": "%emmetShowAbbreviationSuggestions%" - }, - "emmet.includeLanguages": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "default": {}, - "markdownDescription": "%emmetIncludeLanguages%" - }, - "emmet.variables": { - "type": "object", - "properties": { - "lang": { - "type": "string", - "default": "en" - }, - "charset": { - "type": "string", - "default": "UTF-8" - } - }, - "default": {}, - "description": "%emmetVariables%" - }, - "emmet.syntaxProfiles": { - "type": "object", - "default": {}, - "description": "%emmetSyntaxProfiles%" - }, - "emmet.excludeLanguages": { - "type": "array", - "default": [ - "markdown" - ], - "description": "%emmetExclude%" - }, - "emmet.extensionsPath": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "%emmetExtensionsPath%" - }, - "emmet.triggerExpansionOnTab": { - "type": "boolean", - "default": false, - "description": "%emmetTriggerExpansionOnTab%" - }, - "emmet.preferences": { - "type": "object", - "default": {}, - "description": "%emmetPreferences%", - "properties": { - "css.intUnit": { - "type": "string", - "default": "px", - "description": "%emmetPreferencesIntUnit%" - }, - "css.floatUnit": { - "type": "string", - "default": "em", - "description": "%emmetPreferencesFloatUnit%" - }, - "css.propertyEnd": { - "type": "string", - "default": ";", - "description": "%emmetPreferencesCssAfter%" - }, - "sass.propertyEnd": { - "type": "string", - "default": "", - "description": "%emmetPreferencesSassAfter%" - }, - "stylus.propertyEnd": { - "type": "string", - "default": "", - "description": "%emmetPreferencesStylusAfter%" - }, - "css.valueSeparator": { - "type": "string", - "default": ": ", - "description": "%emmetPreferencesCssBetween%" - }, - "sass.valueSeparator": { - "type": "string", - "default": ": ", - "description": "%emmetPreferencesSassBetween%" - }, - "stylus.valueSeparator": { - "type": "string", - "default": " ", - "description": "%emmetPreferencesStylusBetween%" - }, - "bem.elementSeparator": { - "type": "string", - "default": "__", - "description": "%emmetPreferencesBemElementSeparator%" - }, - "bem.modifierSeparator": { - "type": "string", - "default": "_", - "description": "%emmetPreferencesBemModifierSeparator%" - }, - "filter.commentBefore": { - "type": "string", - "default": "", - "description": "%emmetPreferencesFilterCommentBefore%" - }, - "filter.commentAfter": { - "type": "string", - "default": "\n", - "description": "%emmetPreferencesFilterCommentAfter%" - }, - "filter.commentTrigger": { - "type": "array", - "default": [ - "id", - "class" - ], - "description": "%emmetPreferencesFilterCommentTrigger%" - }, - "format.noIndentTags": { - "type": "array", - "default": [ - "html" - ], - "description": "%emmetPreferencesFormatNoIndentTags%" - }, - "format.forceIndentationForTags": { - "type": "array", - "default": [ - "body" - ], - "description": "%emmetPreferencesFormatForceIndentTags%" - }, - "profile.allowCompactBoolean": { - "type": "boolean", - "default": false, - "description": "%emmetPreferencesAllowCompactBoolean%" - }, - "css.webkitProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssWebkitProperties%" - }, - "css.mozProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssMozProperties%" - }, - "css.oProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssOProperties%" - }, - "css.msProperties": { - "type": "string", - "default": null, - "markdownDescription": "%emmetPreferencesCssMsProperties%" - }, - "css.fuzzySearchMinScore": { - "type": "number", - "default": 0.3, - "description": "%emmetPreferencesCssFuzzySearchMinScore%" - } - } - }, - "emmet.showSuggestionsAsSnippets": { - "type": "boolean", - "default": false, - "markdownDescription": "%emmetShowSuggestionsAsSnippets%" - }, - "emmet.optimizeStylesheetParsing": { - "type": "boolean", - "default": true, - "markdownDescription": "%emmetOptimizeStylesheetParsing%" - } - } + "name": "emmet", + "displayName": "Emmet", + "description": "%description%", + "version": "1.0.0", + "publisher": "vscode", + "license": "MIT", + "engines": { + "vscode": "^1.13.0" }, - "commands": [ - { - "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation", - "title": "%command.wrapIndividualLinesWithAbbreviation%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.wrapWithAbbreviation", - "title": "%command.wrapWithAbbreviation%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.expandAbbreviation", - "title": "%command.expandAbbreviation%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.removeTag", - "title": "%command.removeTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.updateTag", - "title": "%command.updateTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.matchTag", - "title": "%command.matchTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.balanceIn", - "title": "%command.balanceIn%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.balanceOut", - "title": "%command.balanceOut%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.prevEditPoint", - "title": "%command.prevEditPoint%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.nextEditPoint", - "title": "%command.nextEditPoint%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.mergeLines", - "title": "%command.mergeLines%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.selectPrevItem", - "title": "%command.selectPrevItem%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.selectNextItem", - "title": "%command.selectNextItem%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.splitJoinTag", - "title": "%command.splitJoinTag%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.toggleComment", - "title": "%command.toggleComment%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.evaluateMathExpression", - "title": "%command.evaluateMathExpression%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.updateImageSize", - "title": "%command.updateImageSize%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByOneTenth", - "title": "%command.incrementNumberByOneTenth%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByOne", - "title": "%command.incrementNumberByOne%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.incrementNumberByTen", - "title": "%command.incrementNumberByTen%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByOneTenth", - "title": "%command.decrementNumberByOneTenth%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByOne", - "title": "%command.decrementNumberByOne%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.decrementNumberByTen", - "title": "%command.decrementNumberByTen%", - "category": "Emmet" - }, - { - "command": "editor.emmet.action.reflectCSSValue", - "title": "%command.reflectCSSValue%", - "category": "Emmet" - }, - { - "command": "workbench.action.showEmmetCommands", - "title": "%command.showEmmetCommands%", - "category": "" - } + "icon": "images/icon.png", + "categories": [ + "Other" ], - "keybindings": [ - { - "key": "tab", - "command": "editor.emmet.action.expandAbbreviation", - "when": "config.emmet.triggerExpansionOnTab && editorTextFocus && !editorReadonly && !editorTabMovesFocus" - } + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-emmet" + }, + "activationEvents": [ + "*", + "onCommand:emmet.expandAbbreviation", + "onLanguage:html", + "onLanguage:css", + "onLanguage:scss", + "onLanguage:less" ], - "menus": { - "commandPalette": [ - { - "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation" + "main": "./out/node/emmetNodeMain", + "browser": "./dist/browser/emmetBrowserMain", + "contributes": { + "configuration": { + "type": "object", + "title": "Emmet", + "properties": { + "emmet.showExpandedAbbreviation": { + "type": [ + "string" + ], + "enum": [ + "never", + "always", + "inMarkupAndStylesheetFilesOnly" + ], + "default": "always", + "markdownDescription": "%emmetShowExpandedAbbreviation%" + }, + "emmet.showAbbreviationSuggestions": { + "type": "boolean", + "default": true, + "markdownDescription": "%emmetShowAbbreviationSuggestions%" + }, + "emmet.includeLanguages": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "default": {}, + "markdownDescription": "%emmetIncludeLanguages%" + }, + "emmet.variables": { + "type": "object", + "properties": { + "lang": { + "type": "string", + "default": "en" + }, + "charset": { + "type": "string", + "default": "UTF-8" + } + }, + "default": {}, + "description": "%emmetVariables%" + }, + "emmet.syntaxProfiles": { + "type": "object", + "default": {}, + "description": "%emmetSyntaxProfiles%" + }, + "emmet.excludeLanguages": { + "type": "array", + "default": [ + "markdown" + ], + "description": "%emmetExclude%" + }, + "emmet.extensionsPath": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "%emmetExtensionsPath%" + }, + "emmet.triggerExpansionOnTab": { + "type": "boolean", + "default": false, + "description": "%emmetTriggerExpansionOnTab%" + }, + "emmet.preferences": { + "type": "object", + "default": {}, + "description": "%emmetPreferences%", + "properties": { + "css.intUnit": { + "type": "string", + "default": "px", + "description": "%emmetPreferencesIntUnit%" + }, + "css.floatUnit": { + "type": "string", + "default": "em", + "description": "%emmetPreferencesFloatUnit%" + }, + "css.propertyEnd": { + "type": "string", + "default": ";", + "description": "%emmetPreferencesCssAfter%" + }, + "sass.propertyEnd": { + "type": "string", + "default": "", + "description": "%emmetPreferencesSassAfter%" + }, + "stylus.propertyEnd": { + "type": "string", + "default": "", + "description": "%emmetPreferencesStylusAfter%" + }, + "css.valueSeparator": { + "type": "string", + "default": ": ", + "description": "%emmetPreferencesCssBetween%" + }, + "sass.valueSeparator": { + "type": "string", + "default": ": ", + "description": "%emmetPreferencesSassBetween%" + }, + "stylus.valueSeparator": { + "type": "string", + "default": " ", + "description": "%emmetPreferencesStylusBetween%" + }, + "bem.elementSeparator": { + "type": "string", + "default": "__", + "description": "%emmetPreferencesBemElementSeparator%" + }, + "bem.modifierSeparator": { + "type": "string", + "default": "_", + "description": "%emmetPreferencesBemModifierSeparator%" + }, + "filter.commentBefore": { + "type": "string", + "default": "", + "description": "%emmetPreferencesFilterCommentBefore%" + }, + "filter.commentAfter": { + "type": "string", + "default": "\n", + "description": "%emmetPreferencesFilterCommentAfter%" + }, + "filter.commentTrigger": { + "type": "array", + "default": [ + "id", + "class" + ], + "description": "%emmetPreferencesFilterCommentTrigger%" + }, + "format.noIndentTags": { + "type": "array", + "default": [ + "html" + ], + "description": "%emmetPreferencesFormatNoIndentTags%" + }, + "format.forceIndentationForTags": { + "type": "array", + "default": [ + "body" + ], + "description": "%emmetPreferencesFormatForceIndentTags%" + }, + "profile.allowCompactBoolean": { + "type": "boolean", + "default": false, + "description": "%emmetPreferencesAllowCompactBoolean%" + }, + "css.webkitProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssWebkitProperties%" + }, + "css.mozProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssMozProperties%" + }, + "css.oProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssOProperties%" + }, + "css.msProperties": { + "type": "string", + "default": null, + "markdownDescription": "%emmetPreferencesCssMsProperties%" + }, + "css.fuzzySearchMinScore": { + "type": "number", + "default": 0.3, + "description": "%emmetPreferencesCssFuzzySearchMinScore%" + } + } + }, + "emmet.showSuggestionsAsSnippets": { + "type": "boolean", + "default": false, + "markdownDescription": "%emmetShowSuggestionsAsSnippets%" + }, + "emmet.optimizeStylesheetParsing": { + "type": "boolean", + "default": true, + "markdownDescription": "%emmetOptimizeStylesheetParsing%" + } + } }, - { - "command": "editor.emmet.action.wrapWithAbbreviation" - }, - { - "command": "editor.emmet.action.expandAbbreviation" - }, - { - "command": "editor.emmet.action.removeTag" - }, - { - "command": "editor.emmet.action.updateTag" - }, - { - "command": "editor.emmet.action.matchTag" - }, - { - "command": "editor.emmet.action.balanceIn" - }, - { - "command": "editor.emmet.action.balanceOut" - }, - { - "command": "editor.emmet.action.prevEditPoint" - }, - { - "command": "editor.emmet.action.nextEditPoint" - }, - { - "command": "editor.emmet.action.mergeLines" - }, - { - "command": "editor.emmet.action.selectPrevItem" - }, - { - "command": "editor.emmet.action.selectNextItem" - }, - { - "command": "editor.emmet.action.splitJoinTag" - }, - { - "command": "editor.emmet.action.toggleComment" - }, - { - "command": "editor.emmet.action.evaluateMathExpression" - }, - { - "command": "editor.emmet.action.updateImageSize", - "when": "resourceScheme =~ /^file$/" - }, - { - "command": "editor.emmet.action.incrementNumberByOneTenth" - }, - { - "command": "editor.emmet.action.incrementNumberByOne" - }, - { - "command": "editor.emmet.action.incrementNumberByTen" - }, - { - "command": "editor.emmet.action.decrementNumberByOneTenth" - }, - { - "command": "editor.emmet.action.decrementNumberByOne" - }, - { - "command": "editor.emmet.action.decrementNumberByTen" - }, - { - "command": "editor.emmet.action.reflectCSSValue" + "commands": [ + { + "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation", + "title": "%command.wrapIndividualLinesWithAbbreviation%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.wrapWithAbbreviation", + "title": "%command.wrapWithAbbreviation%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.removeTag", + "title": "%command.removeTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.updateTag", + "title": "%command.updateTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.matchTag", + "title": "%command.matchTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.balanceIn", + "title": "%command.balanceIn%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.balanceOut", + "title": "%command.balanceOut%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.prevEditPoint", + "title": "%command.prevEditPoint%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.nextEditPoint", + "title": "%command.nextEditPoint%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.mergeLines", + "title": "%command.mergeLines%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.selectPrevItem", + "title": "%command.selectPrevItem%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.selectNextItem", + "title": "%command.selectNextItem%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.splitJoinTag", + "title": "%command.splitJoinTag%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.toggleComment", + "title": "%command.toggleComment%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.evaluateMathExpression", + "title": "%command.evaluateMathExpression%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.updateImageSize", + "title": "%command.updateImageSize%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByOneTenth", + "title": "%command.incrementNumberByOneTenth%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByOne", + "title": "%command.incrementNumberByOne%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.incrementNumberByTen", + "title": "%command.incrementNumberByTen%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByOneTenth", + "title": "%command.decrementNumberByOneTenth%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByOne", + "title": "%command.decrementNumberByOne%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.decrementNumberByTen", + "title": "%command.decrementNumberByTen%", + "category": "Emmet" + }, + { + "command": "editor.emmet.action.reflectCSSValue", + "title": "%command.reflectCSSValue%", + "category": "Emmet" + }, + { + "command": "workbench.action.showEmmetCommands", + "title": "%command.showEmmetCommands%", + "category": "" + } + ], + "menus": { + "commandPalette": [ + { + "command": "editor.emmet.action.wrapIndividualLinesWithAbbreviation" + }, + { + "command": "editor.emmet.action.wrapWithAbbreviation" + }, + { + "command": "editor.emmet.action.removeTag" + }, + { + "command": "editor.emmet.action.updateTag" + }, + { + "command": "editor.emmet.action.matchTag" + }, + { + "command": "editor.emmet.action.balanceIn" + }, + { + "command": "editor.emmet.action.balanceOut" + }, + { + "command": "editor.emmet.action.prevEditPoint" + }, + { + "command": "editor.emmet.action.nextEditPoint" + }, + { + "command": "editor.emmet.action.mergeLines" + }, + { + "command": "editor.emmet.action.selectPrevItem" + }, + { + "command": "editor.emmet.action.selectNextItem" + }, + { + "command": "editor.emmet.action.splitJoinTag" + }, + { + "command": "editor.emmet.action.toggleComment" + }, + { + "command": "editor.emmet.action.evaluateMathExpression" + }, + { + "command": "editor.emmet.action.updateImageSize", + "when": "resourceScheme =~ /^file$/" + }, + { + "command": "editor.emmet.action.incrementNumberByOneTenth" + }, + { + "command": "editor.emmet.action.incrementNumberByOne" + }, + { + "command": "editor.emmet.action.incrementNumberByTen" + }, + { + "command": "editor.emmet.action.decrementNumberByOneTenth" + }, + { + "command": "editor.emmet.action.decrementNumberByOne" + }, + { + "command": "editor.emmet.action.decrementNumberByTen" + }, + { + "command": "editor.emmet.action.reflectCSSValue" + } + ] } - ] + }, + "scripts": { + "watch": "gulp watch-extension:emmet", + "compile": "gulp compile-extension:emmet", + "deps": "yarn add vscode-emmet-helper" + }, + "devDependencies": { + "@types/node": "^12.11.7", + "mocha-junit-reporter": "^1.17.0", + "mocha-multi-reporters": "^1.1.7", + "vscode": "1.0.1" + }, + "dependencies": { + "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", + "@emmetio/html-matcher": "^0.3.3", + "@emmetio/math-expression": "^1.0.4", + "image-size": "^0.5.2", + "vscode-emmet-helper": "~2.0.0", + "vscode-html-languageservice": "^3.0.3" } - }, - "scripts": { - "watch": "gulp watch-extension:emmet", - "compile": "gulp compile-extension:emmet", - "deps": "yarn add vscode-emmet-helper" - }, - "devDependencies": { - "@types/node": "^12.11.7", - "mocha-junit-reporter": "^1.17.0", - "mocha-multi-reporters": "^1.1.7", - "vscode": "1.0.1" - }, - "dependencies": { - "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", - "@emmetio/html-matcher": "^0.3.3", - "@emmetio/math-expression": "^1.0.4", - "image-size": "^0.5.2", - "vscode-emmet-helper": "~2.0.0", - "vscode-html-languageservice": "^3.0.3" - } } diff --git a/extensions/emmet/package.nls.json b/extensions/emmet/package.nls.json index 4d4090c2b1f..2a1add8935e 100644 --- a/extensions/emmet/package.nls.json +++ b/extensions/emmet/package.nls.json @@ -2,7 +2,6 @@ "description": "Emmet support for VS Code", "command.wrapWithAbbreviation": "Wrap with Abbreviation", "command.wrapIndividualLinesWithAbbreviation": "Wrap Individual Lines with Abbreviation", - "command.expandAbbreviation": "Expand Abbreviation", "command.removeTag": "Remove Tag", "command.updateTag": "Update Tag", "command.matchTag": "Go to Matching Pair", diff --git a/extensions/emmet/src/emmetCommon.ts b/extensions/emmet/src/emmetCommon.ts index a458433057c..e768b03afd6 100644 --- a/extensions/emmet/src/emmetCommon.ts +++ b/extensions/emmet/src/emmetCommon.ts @@ -31,14 +31,10 @@ export function activateEmmetExtension(context: vscode.ExtensionContext) { wrapIndividualLinesWithAbbreviation(args); })); - context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.expandAbbreviationInternal', (args) => { + context.subscriptions.push(vscode.commands.registerCommand('emmet.expandAbbreviation', (args) => { expandEmmetAbbreviation(args); })); - context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.expandAbbreviation', () => { - vscode.commands.executeCommand('workbench.action.expandEmmetAbbreviation'); - })); - context.subscriptions.push(vscode.commands.registerCommand('editor.emmet.action.removeTag', () => { return removeTag(); })); diff --git a/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts b/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts new file mode 100644 index 00000000000..b6129b8a6ae --- /dev/null +++ b/src/vs/workbench/contrib/emmet/browser/actions/expandAbbreviation.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; +import { EmmetEditorAction } from 'vs/workbench/contrib/emmet/browser/emmetActions'; +import { registerEditorAction } from 'vs/editor/browser/editorExtensions'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { MenuId } from 'vs/platform/actions/common/actions'; + +class ExpandAbbreviationAction extends EmmetEditorAction { + + constructor() { + super({ + id: 'editor.emmet.action.expandAbbreviation', + label: nls.localize('expandAbbreviationAction', "Emmet: Expand Abbreviation"), + alias: 'Emmet: Expand Abbreviation', + precondition: EditorContextKeys.writable, + actionName: 'expand_abbreviation', + kbOpts: { + primary: KeyCode.Tab, + kbExpr: ContextKeyExpr.and( + EditorContextKeys.editorTextFocus, + EditorContextKeys.tabDoesNotMoveFocus, + ContextKeyExpr.has('config.emmet.triggerExpansionOnTab') + ), + weight: KeybindingWeight.EditorContrib + }, + menuOpts: { + menuId: MenuId.MenubarEditMenu, + group: '5_insert', + title: nls.localize({ key: 'miEmmetExpandAbbreviation', comment: ['&& denotes a mnemonic'] }, "Emmet: E&&xpand Abbreviation"), + order: 3 + } + }); + + } +} + +registerEditorAction(ExpandAbbreviationAction); diff --git a/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts b/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts index 8d64955f6de..f29d6b2c022 100644 --- a/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts +++ b/src/vs/workbench/contrib/emmet/browser/emmet.contribution.ts @@ -3,7 +3,5 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { registerEditorCommand } from 'vs/editor/browser/editorExtensions'; -import { expandEmmetAbbreviationCommand } from './expandEmmetAbbreviation'; +import './actions/expandAbbreviation'; -registerEditorCommand(expandEmmetAbbreviationCommand); diff --git a/src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts b/src/vs/workbench/contrib/emmet/browser/emmetActions.ts similarity index 69% rename from src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts rename to src/vs/workbench/contrib/emmet/browser/emmetActions.ts index 008f63c289f..607da869cc3 100644 --- a/src/vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation.ts +++ b/src/vs/workbench/contrib/emmet/browser/emmetActions.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ServicesAccessor, EditorCommand } from 'vs/editor/browser/editorExtensions'; +import { EditorAction, ServicesAccessor, IActionOptions } from 'vs/editor/browser/editorExtensions'; import { grammarsExtPoint, ITMSyntaxExtensionPoint } from 'vs/workbench/services/textMate/common/TMGrammars'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IExtensionService, ExtensionPointContribution } from 'vs/workbench/services/extensions/common/extensions'; @@ -24,6 +24,7 @@ export interface ILanguageIdentifierResolver { } class GrammarContributions implements IGrammarContributions { + private static _grammars: ModeScopeMap = {}; constructor(contributions: ExtensionPointContribution[]) { @@ -47,12 +48,20 @@ class GrammarContributions implements IGrammarContributions { } } -export class ExpandEmmetAbbreviationCommand extends EditorCommand { - constructor() { - super({ id: 'workbench.action.expandEmmetAbbreviation', precondition: undefined }); +export interface IEmmetActionOptions extends IActionOptions { + actionName: string; +} + +export abstract class EmmetEditorAction extends EditorAction { + + protected emmetActionName: string; + + constructor(opts: IEmmetActionOptions) { + super(opts); + this.emmetActionName = opts.actionName; } - private static readonly emmetSupportedModes = ['html', 'xml', 'xsl', 'jsx', 'js', 'pug', 'slim', 'haml', 'css', 'sass', 'scss', 'less', 'sss', 'stylus']; + private static readonly emmetSupportedModes = ['html', 'css', 'xml', 'xsl', 'haml', 'jade', 'jsx', 'slim', 'scss', 'sass', 'less', 'stylus', 'styl', 'svg']; private _lastGrammarContributions: Promise | null = null; private _lastExtensionService: IExtensionService | null = null; @@ -66,21 +75,20 @@ export class ExpandEmmetAbbreviationCommand extends EditorCommand { return this._lastGrammarContributions || Promise.resolve(null); } - public runEditorCommand(accessor: ServicesAccessor | null, editor: ICodeEditor, args: any): void | Promise { - if (!accessor) { - return; - } - + public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise { const extensionService = accessor.get(IExtensionService); const modeService = accessor.get(IModeService); const commandService = accessor.get(ICommandService); return this._withGrammarContributions(extensionService).then((grammarContributions) => { - if (this.id === 'workbench.action.expandEmmetAbbreviation' && grammarContributions) { - return commandService.executeCommand('editor.emmet.action.expandAbbreviationInternal', ExpandEmmetAbbreviationCommand.getLanguage(modeService, editor, grammarContributions)); + + if (this.id === 'editor.emmet.action.expandAbbreviation' && grammarContributions) { + return commandService.executeCommand('emmet.expandAbbreviation', EmmetEditorAction.getLanguage(modeService, editor, grammarContributions)); } + return undefined; }); + } public static getLanguage(languageIdentifierResolver: ILanguageIdentifierResolver, editor: ICodeEditor, grammars: IGrammarContributions) { @@ -96,34 +104,24 @@ export class ExpandEmmetAbbreviationCommand extends EditorCommand { const languageId = model.getLanguageIdAtPosition(position.lineNumber, position.column); const languageIdentifier = languageIdentifierResolver.getLanguageIdentifier(languageId); const language = languageIdentifier ? languageIdentifier.language : ''; - let syntax = language.split('.').pop(); + const syntax = language.split('.').pop(); if (!syntax) { return null; } - // map to something Emmet understands - if (['jsx-tags', 'javascriptreact', 'typescriptreact'].includes(syntax)) { - syntax = 'jsx'; - } - - const getParentMode = (syntax: string): string => { - if (syntax === 'jsx') { - // return otherwise getGrammar gives a string that Emmet doesn't understand - return syntax; - } - - const languageGrammar = grammars.getGrammar(syntax); + let checkParentMode = (): string => { + let languageGrammar = grammars.getGrammar(syntax); if (!languageGrammar) { return syntax; } - const languages = languageGrammar.split('.'); - if (languages.length <= 1) { + let languages = languageGrammar.split('.'); + if (languages.length < 2) { return syntax; } - for (let i = languages.length - 1; i >= 1; i--) { - const language = languages[i]; - if (this.emmetSupportedModes.includes(language)) { + for (let i = 1; i < languages.length; i++) { + const language = languages[languages.length - i]; + if (this.emmetSupportedModes.indexOf(language) !== -1) { return language; } } @@ -132,9 +130,9 @@ export class ExpandEmmetAbbreviationCommand extends EditorCommand { return { language: syntax, - parentMode: getParentMode(syntax) + parentMode: checkParentMode() }; } -} -export const expandEmmetAbbreviationCommand = new ExpandEmmetAbbreviationCommand(); + +} diff --git a/src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts b/src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts similarity index 57% rename from src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts rename to src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts index 885e1a5064e..c56afa2d157 100644 --- a/src/vs/workbench/contrib/emmet/test/browser/expandEmmetAbbreviation.test.ts +++ b/src/vs/workbench/contrib/emmet/test/browser/emmetAction.test.ts @@ -3,11 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IGrammarContributions, ILanguageIdentifierResolver, ExpandEmmetAbbreviationCommand } from 'vs/workbench/contrib/emmet/browser/expandEmmetAbbreviation'; +import { IGrammarContributions, ILanguageIdentifierResolver, EmmetEditorAction } from 'vs/workbench/contrib/emmet/browser/emmetActions'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import * as assert from 'assert'; import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; +// +// To run the emmet tests only change .vscode/launch.json +// { +// "name": "Stacks Tests", +// "type": "node", +// "request": "launch", +// "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", +// "stopOnEntry": false, +// "args": [ +// "--timeout", +// "999999", +// "--colors", +// "-g", +// "Stacks" <<<--- Emmet +// ], +// Select the 'Stacks Tests' launch config and F5 +// + class MockGrammarContributions implements IGrammarContributions { private scopeName: string; @@ -15,14 +33,16 @@ class MockGrammarContributions implements IGrammarContributions { this.scopeName = scopeName; } - public getGrammar(_: string): string { + public getGrammar(mode: string): string { return this.scopeName; } } -suite('Emmet expandAbbreviation command', () => { - test('gets language mode and parent mode for Emmet', () => { +suite('Emmet', () => { + + test('Get language mode and parent mode for emmet', () => { withTestCodeEditor([], {}, (editor) => { + function testIsEnabled(mode: string, scopeName: string, expectedLanguage?: string, expectedParentLanguage?: string) { const languageIdentifier = new LanguageIdentifier(mode, 73); const languageIdentifierResolver: ILanguageIdentifierResolver = { @@ -39,13 +59,13 @@ suite('Emmet expandAbbreviation command', () => { } model.setMode(languageIdentifier); - const langOutput = ExpandEmmetAbbreviationCommand.getLanguage(languageIdentifierResolver, editor, new MockGrammarContributions(scopeName)); + let langOutput = EmmetEditorAction.getLanguage(languageIdentifierResolver, editor, new MockGrammarContributions(scopeName)); if (!langOutput) { assert.fail('langOutput not found'); } - assert.strictEqual(langOutput.language, expectedLanguage); - assert.strictEqual(langOutput.parentMode, expectedParentLanguage); + assert.equal(langOutput.language, expectedLanguage); + assert.equal(langOutput.parentMode, expectedParentLanguage); } // syntaxes mapped using the scope name of the grammar @@ -54,22 +74,10 @@ suite('Emmet expandAbbreviation command', () => { testIsEnabled('nunjucks', 'text.html.nunjucks', 'nunjucks', 'html'); testIsEnabled('laravel-blade', 'text.html.php.laravel-blade', 'laravel-blade', 'html'); - // basic syntaxes - testIsEnabled('html', 'text.html.derivative', 'html', 'html'); - testIsEnabled('css', 'source.css', 'css', 'css'); - testIsEnabled('scss', 'source.css.scss', 'scss', 'scss'); - testIsEnabled('xml', 'text.xml', 'xml', 'xml'); - testIsEnabled('xsl', 'text.xml.xsl', 'xsl', 'xsl'); + // languages that have different Language Id and scopeName + // testIsEnabled('razor', 'text.html.cshtml', 'razor', 'html'); + // testIsEnabled('HTML (Eex)', 'text.html.elixir', 'boo', 'html'); - // syntaxes that combine HTML and TS/JS - // expanding inside of HTML tags within jsx/tsx - testIsEnabled('jsx-tags', 'source.js.jsx', 'jsx', 'jsx'); - // expanding outside of HTML tags within jsx/tsx - testIsEnabled('javascriptreact', 'source.js.jsx', 'jsx', 'jsx'); - testIsEnabled('typescriptreact', 'source.tsx', 'jsx', 'jsx'); - - // syntaxes that combine HTML and some other language - testIsEnabled('razor', 'text.html.cshtml', 'razor', 'html'); }); }); }); From 1732cb9540e041cb3d54cd1432a955f04bf76de3 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 23 Nov 2020 18:23:47 +0100 Subject: [PATCH 0155/1837] DAP: add support for conditional exceptions --- .../contrib/debug/common/debugProtocol.d.ts | 86 +++++++++++-------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts index 0f0374d541b..c6ffbcf5507 100644 --- a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts @@ -16,7 +16,7 @@ declare module DebugProtocol { /** Message type. Values: 'request', 'response', 'event', etc. */ - type: string; + type: 'request' | 'response' | 'event' | string; } /** A client or debug adapter initiated request. */ @@ -56,7 +56,7 @@ declare module DebugProtocol { 'cancelled': request was cancelled. etc. */ - message?: string; + message?: 'cancelled' | string; /** Contains request result if success is true and optional error details if success is false. */ body?: any; } @@ -129,7 +129,7 @@ declare module DebugProtocol { For backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated). Values: 'step', 'breakpoint', 'exception', 'pause', 'entry', 'goto', 'function breakpoint', 'data breakpoint', 'instruction breakpoint', etc. */ - reason: string; + reason: 'step' | 'breakpoint' | 'exception' | 'pause' | 'entry' | 'goto' | 'function breakpoint' | 'data breakpoint' | 'instruction breakpoint' | string; /** The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated. */ description?: string; /** The thread which was stopped. */ @@ -194,7 +194,7 @@ declare module DebugProtocol { /** The reason for the event. Values: 'started', 'exited', etc. */ - reason: string; + reason: 'started' | 'exited' | string; /** The identifier of the thread. */ threadId: number; }; @@ -209,7 +209,7 @@ declare module DebugProtocol { /** The output category. If not specified, 'console' is assumed. Values: 'console', 'stdout', 'stderr', 'telemetry', etc. */ - category?: string; + category?: 'console' | 'stdout' | 'stderr' | 'telemetry' | string; /** The output to report. */ output: string; /** Support for keeping an output log organized by grouping related messages. @@ -221,7 +221,7 @@ declare module DebugProtocol { A non empty 'output' attribute is shown as the unindented end of the group. */ group?: 'start' | 'startCollapsed' | 'end'; - /** If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31 - 1). */ + /** If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31-1). */ variablesReference?: number; /** An optional source location where the output was produced. */ source?: Source; @@ -243,7 +243,7 @@ declare module DebugProtocol { /** The reason for the event. Values: 'changed', 'new', 'removed', etc. */ - reason: string; + reason: 'changed' | 'new' | 'removed' | string; /** The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values. */ breakpoint: Breakpoint; }; @@ -383,7 +383,7 @@ declare module DebugProtocol { export interface InvalidatedEvent extends Event { // event: 'invalidated'; body: { - /** Optional set of logical areas that got invalidated. If this property is missing or empty, a single value 'all' is assumed. */ + /** 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'. */ areas?: InvalidatedAreas[]; /** If specified, the client only needs to refetch data related to this thread. */ threadId?: number; @@ -408,7 +408,7 @@ declare module DebugProtocol { kind?: 'integrated' | 'external'; /** Optional title of the terminal. */ title?: string; - /** Working directory of the command. */ + /** Working directory for the command. For non-empty, valid paths this typically results in execution of a change directory command. */ cwd: string; /** List of arguments. The first argument is the command to run. */ args: string[]; @@ -419,9 +419,9 @@ declare module DebugProtocol { /** Response to 'runInTerminal' request. */ export interface RunInTerminalResponse extends Response { body: { - /** The process ID. The value should be less than or equal to 2147483647 (2^31 - 1). */ + /** The process ID. The value should be less than or equal to 2147483647 (2^31-1). */ processId?: number; - /** The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31 - 1). */ + /** The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31-1). */ shellProcessId?: number; }; } @@ -455,7 +455,7 @@ declare module DebugProtocol { /** Determines in what format paths are specified. The default is 'path', which is the native format. Values: 'path', 'uri', etc. */ - pathFormat?: string; + pathFormat?: 'path' | 'uri' | string; /** Client supports the optional type attribute for variables. */ supportsVariableType?: boolean; /** Client supports the paging of variables. */ @@ -712,8 +712,10 @@ declare module DebugProtocol { /** Arguments for 'setExceptionBreakpoints' request. */ export interface SetExceptionBreakpointsArguments { - /** IDs of checked exception options. The set of IDs is returned via the 'exceptionBreakpointFilters' capability. */ + /** Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. */ 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. */ + filterOptions?: ExceptionFilterOptions[]; /** Configuration options for selected exceptions. The attribute is only honored by a debug adapter if the capability 'supportsExceptionOptions' is true. */ @@ -1125,17 +1127,17 @@ declare module DebugProtocol { /** The type of the new value. Typically shown in the UI when hovering over the value. */ type?: string; /** If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ variablesReference?: number; /** The number of named child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ namedVariables?: number; /** The number of indexed child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ indexedVariables?: number; }; @@ -1275,7 +1277,7 @@ declare module DebugProtocol { The attribute is only honored by a debug adapter if the capability 'supportsClipboardContext' is true. etc. */ - context?: string; + context?: 'watch' | 'repl' | 'hover' | 'clipboard' | string; /** Specifies details on how to format the Evaluate result. The attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true. */ @@ -1294,17 +1296,17 @@ declare module DebugProtocol { /** Properties of a evaluate result that can be used to determine how to render the result in the UI. */ presentationHint?: VariablePresentationHint; /** If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ variablesReference: number; /** The number of named child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ namedVariables?: number; /** The number of indexed child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ indexedVariables?: number; /** Optional memory reference to a location appropriate for this result. @@ -1349,17 +1351,17 @@ declare module DebugProtocol { /** Properties of a value that can be used to determine how to render the result in the UI. */ presentationHint?: VariablePresentationHint; /** If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ variablesReference?: number; /** The number of named child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ namedVariables?: number; /** The number of indexed child variables. The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ indexedVariables?: number; }; @@ -1556,7 +1558,7 @@ declare module DebugProtocol { supportsHitConditionalBreakpoints?: boolean; /** The debug adapter supports a (side effect free) evaluate request for data hovers. */ supportsEvaluateForHovers?: boolean; - /** Available filters or options for the setExceptionBreakpoints request. */ + /** Available exception filter options for the 'setExceptionBreakpoints' request. */ exceptionBreakpointFilters?: ExceptionBreakpointsFilter[]; /** The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests. */ supportsStepBack?: boolean; @@ -1616,16 +1618,20 @@ declare module DebugProtocol { supportsSteppingGranularity?: boolean; /** The debug adapter supports adding breakpoints based on instruction references. */ supportsInstructionBreakpoints?: boolean; + /** The debug adapter supports 'filterOptions' as an argument on the 'setExceptionBreakpoints' request. */ + supportsExceptionFilterOptions?: boolean; } - /** An ExceptionBreakpointsFilter is shown in the UI as an option for configuring how exceptions are dealt with. */ + /** An ExceptionBreakpointsFilter is shown in the UI as an filter option for configuring how exceptions are dealt with. */ export interface ExceptionBreakpointsFilter { - /** The internal ID of the filter. This value is passed to the setExceptionBreakpoints request. */ + /** The internal ID of the filter option. This value is passed to the 'setExceptionBreakpoints' request. */ filter: string; - /** The name of the filter. This will be shown in the UI. */ + /** The name of the filter option. This will be shown in the UI. */ label: string; - /** Initial value of the filter. If not specified a value 'false' is assumed. */ + /** Initial value of the filter option. If not specified a value 'false' is assumed. */ default?: boolean; + /** Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set. */ + supportsCondition?: boolean; } /** A structured message object. Used to return errors from requests. */ @@ -1730,7 +1736,7 @@ declare module DebugProtocol { path?: string; /** If sourceReference > 0 the contents of the source must be retrieved through the SourceRequest (even if a path is specified). A sourceReference is only valid for a session, so it must not be used to persist a source. - The value should be less than or equal to 2147483647 (2^31 - 1). + The value should be less than or equal to 2147483647 (2^31-1). */ sourceReference?: number; /** An optional hint for how to present the source in the UI. @@ -1788,7 +1794,7 @@ declare module DebugProtocol { 'registers': Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request. etc. */ - presentationHint?: string; + presentationHint?: 'arguments' | 'locals' | 'registers' | string; /** The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest. */ variablesReference: number; /** The number of named variables in this scope. @@ -1867,7 +1873,7 @@ declare module DebugProtocol { 'dataBreakpoint': Indicates that a data breakpoint is registered for the object. etc. */ - kind?: string; + kind?: 'property' | 'method' | 'class' | 'data' | 'event' | 'baseClass' | 'innerClass' | 'interface' | 'mostDerivedClass' | 'virtual' | 'dataBreakpoint' | string; /** Set of attributes represented as an array of strings. Before introducing additional values, try to use the listed values. Values: 'static': Indicates that the object is static. @@ -1879,11 +1885,11 @@ declare module DebugProtocol { 'hasSideEffects': Indicates that the evaluation had side effects. etc. */ - attributes?: string[]; + attributes?: ('static' | 'constant' | 'readOnly' | 'rawString' | 'hasObjectId' | 'canHaveObjectId' | 'hasSideEffects' | string)[]; /** Visibility of variable. Before introducing additional values, try to use the listed values. Values: 'public', 'private', 'protected', 'internal', 'final', etc. */ - visibility?: string; + visibility?: 'public' | 'private' | 'protected' | 'internal' | 'final' | string; } /** Properties of a breakpoint location returned from the 'breakpointLocations' request. */ @@ -2108,6 +2114,16 @@ 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 { + /** ID of an exception filter returned by the 'exceptionBreakpointFilters' capability. */ + filterId: string; + /** An optional expression for conditional exceptions. + The exception will break into the debugger if the result of the condition is true. + */ + condition?: string; + } + /** An ExceptionOptions assigns configuration options to a set of exceptions. */ export interface ExceptionOptions { /** A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected. @@ -2179,11 +2195,13 @@ declare module DebugProtocol { } /** Logical areas that can be invalidated by the 'invalidated' event. + Values: 'all': All previously fetched data has become invalid and needs to be refetched. 'stacks': Previously fetched stack related data has become invalid and needs to be refetched. 'threads': Previously fetched thread related data has become invalid and needs to be refetched. 'variables': Previously fetched variable data has become invalid and needs to be refetched. + etc. */ - export type InvalidatedAreas = 'all' | 'stacks' | 'threads' | 'variables'; + export type InvalidatedAreas = 'all' | 'stacks' | 'threads' | 'variables' | string; } From 2a1c8bbaf295cb138df5ad04a2b4e277b6f5a377 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 23 Nov 2020 09:57:15 -0800 Subject: [PATCH 0156/1837] re #108464. --- .../notebook/browser/notebookEditorWidget.ts | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 0e2883e8295..598ea026676 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1354,6 +1354,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return new Promise(resolve => { r = resolve; }); } + private _nearestCodeCellIndex(index: number /* exclusive */, direction: 'above' | 'below') { + const nearest = this._notebookViewModel!.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); + if (nearest > -1) { + return index - nearest - 1; + } else { + const nearestCellTheOtherDirection = this._notebookViewModel!.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); + if (nearestCellTheOtherDirection > -1) { + return index + nearestCellTheOtherDirection; + } + return -1; + } + } + insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction: 'above' | 'below' = 'above', initialText: string = '', ui: boolean = false): CellViewModel | null { if (!this._notebookViewModel!.metadata.editable) { return null; @@ -1361,10 +1374,29 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const index = cell ? this._notebookViewModel!.getCellIndex(cell) : 0; const nextIndex = ui ? this._notebookViewModel!.getNextVisibleCellIndex(index) : index + 1; - const newLanguages = this._notebookViewModel!.resolvedLanguages; - const language = (cell?.cellKind === CellKind.Code && type === CellKind.Code) - ? cell.language - : ((type === CellKind.Code && newLanguages && newLanguages.length) ? newLanguages[0] : 'markdown'); + let language; + if (type === CellKind.Code) { + if (cell?.cellKind === CellKind.Code) { + language = cell.language; + } else if (cell?.cellKind === CellKind.Markdown) { + const nearestCodeCellIndex = this._nearestCodeCellIndex(index, direction); + if (nearestCodeCellIndex > -1) { + language = this._notebookViewModel!.viewCells[nearestCodeCellIndex].language; + } else { + language = this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + } + } else { + if (cell === undefined && direction === 'above') { + // insert cell at the very top + language = this._notebookViewModel!.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + } else { + language = this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + } + } + } else { + language = 'markdown'; + } + const insertIndex = cell ? (direction === 'above' ? index : nextIndex) : index; From 8e76838da587390de109f736f763d3c853871d9a Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 23 Nov 2020 20:14:36 +0100 Subject: [PATCH 0157/1837] Tweaked endgame notebook, added my endgame notebook --- .vscode/notebooks/endgame.github-issues | 134 +++----------- .vscode/notebooks/my-endgame.github-issues | 194 +++++++++++++++++++++ 2 files changed, 219 insertions(+), 109 deletions(-) create mode 100644 .vscode/notebooks/my-endgame.github-issues diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 05b22bdc902..6954317e28d 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -2,43 +2,37 @@ { "kind": 1, "language": "markdown", - "value": "# Endgame", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "## Macros", + "value": "#### Macros", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github\n\n$MILESTONE=milestone:\"November 2020\"\n\n$MINE=assignee:@me", + "value": "$REPOS=repo:microsoft/vscode \n\t repo:microsoft/vscode-internalbacklog\n\t repo:microsoft/vscode-js-debug\n\t repo:microsoft/vscode-remote-release\n\t repo:microsoft/vscode-pull-request-github\n\t repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"", + "editable": false + }, + { + "kind": 1, + "language": "markdown", + "value": "# Preparation", "editable": true }, { "kind": 1, "language": "markdown", - "value": "## Endgame Champion", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### Test Plan Items", + "value": "## Open Issues on the Milestone", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE label:testplan-item is:open", + "value": "$REPOS $MILESTONE is:issue is:open", "editable": true }, { "kind": 1, "language": "markdown", - "value": "### Feature Requests Missing Labels", + "value": "## Feature Requests Missing Labels", "editable": true }, { @@ -50,133 +44,55 @@ { "kind": 1, "language": "markdown", - "value": "### Open Issues on the Milestone", + "value": "# Testing", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Test Plan Items", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -label:testplan-item -label:iteration-plan -label:endgame-plan is:open", + "value": "$REPOS $MILESTONE is:issue is:open label:testplan-item", "editable": true }, { "kind": 1, "language": "markdown", - "value": "## Testing", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### My Assigned Test Plan Items", + "value": "## Verification Needed", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE label:testplan-item is:open", + "value": "$REPOS $MILESTONE is:issue is:closed label:feature-request label:verification-needed", "editable": true }, { "kind": 1, "language": "markdown", - "value": "### My Created Test Plan Items", + "value": "# Verification", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE author:@me label:testplan-item", + "value": "$REPOS $MILESTONE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, { "kind": 1, "language": "markdown", - "value": "## Verification", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### Issues to Verify", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "#### Issues filed by me", + "value": "# Candidates", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE author:@me sort:updated-asc is:closed is:issue label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "#### Issues filed by others", - "editable": true - }, - { - "kind": 2, - "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE -author:@me sort:updated-asc is:closed is:issue label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### Verification Needed", - "editable": true - }, - { - "kind": 2, - "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:closed label:feature-request -label:verification-needed -label:on-testplan -label:verified -label:*duplicate ", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### My Issues Needing Verification", - "editable": true - }, - { - "kind": 2, - "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE sort:updated-desc is:closed is:issue -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found\n", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### My Open Issues", - "editable": true - }, - { - "kind": 2, - "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:open is:issue", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "## Documentation", - "editable": true - }, - { - "kind": 1, - "language": "markdown", - "value": "### Needing Release Notes", - "editable": true - }, - { - "kind": 2, - "language": "github-issues", - "value": "repo:microsoft/vscode $MILESTONE $MINE is:closed label:feature-request -label:on-release-notes", + "value": "$REPOS $MILESTONE label:candidate", "editable": true } ] \ No newline at end of file diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues new file mode 100644 index 00000000000..155f1009909 --- /dev/null +++ b/.vscode/notebooks/my-endgame.github-issues @@ -0,0 +1,194 @@ +[ + { + "kind": 1, + "language": "markdown", + "value": "#### Macros", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS=repo:microsoft/vscode \n\t repo:microsoft/vscode-internalbacklog\n\t repo:microsoft/vscode-js-debug\n\t repo:microsoft/vscode-remote-release\n\t repo:microsoft/vscode-pull-request-github\n\t repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"\n\n$MINE=assignee:@me", + "editable": false + }, + { + "kind": 1, + "language": "markdown", + "value": "# Preparation", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Open Issues on the Milestone", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Feature Requests Missing Labels", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:closed label:feature-request -label:verification-needed -label:on-testplan -label:verified -label:*duplicate", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Test Plan Items", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE is:issue is:open author:@me label:testplan-item", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Verification Needed", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:closed label:feature-request label:verification-needed", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "# Testing", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Test Plan Items", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open label:testplan-item", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Verification Needed", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -assignee:@me label:feature-request label:verification-needed", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "# Fixing", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Open Issues", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Open Bugs", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open label:bug", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "# Verification", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## My Issues (verification-steps-needed)", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open label:bug label:verification-steps-needed", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## My Issues (verification-found)", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:issue is:open label:bug label:verification-found", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Issues filed by me", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "## Issues filed by others", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "# Release Notes", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "repo:microsoft/vscode $MILESTONE is:issue is:closed label:feature-request -label:on-release-notes", + "editable": true + } +] \ No newline at end of file From 6f87c1cf7f3e23226778503e32fce79767b2ab89 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 23 Nov 2020 20:20:01 +0100 Subject: [PATCH 0158/1837] Removed "duplicate" label --- .vscode/notebooks/endgame.github-issues | 2 +- .vscode/notebooks/my-endgame.github-issues | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 6954317e28d..605197ab069 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -80,7 +80,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "value": "$REPOS $MILESTONE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, { diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 155f1009909..7793fb88d32 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -164,7 +164,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE is:issue is:closed author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, { @@ -176,7 +176,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:duplicate -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, { From 206fbe0bb3847a43f8cd3a7caafeff2d219116b2 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 23 Nov 2020 11:19:31 -0800 Subject: [PATCH 0159/1837] debug: use native logging in extension host https://github.com/microsoft/vscode/issues/104686 --- src/bootstrap-fork.js | 35 ++++++++++++++++--- .../debug/common/extensionHostDebug.ts | 9 ----- .../debug/common/extensionHostDebugIpc.ts | 16 +-------- .../api/browser/mainThreadConsole.ts | 11 +----- .../contrib/debug/browser/debugService.ts | 11 ------ .../localProcessExtensionHost.ts | 10 ++---- 6 files changed, 34 insertions(+), 58 deletions(-) diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index 0cd75027286..91822e6d234 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -135,18 +135,43 @@ function pipeLoggingToParent() { && !(obj instanceof Date); } + /** + * + * @param {'log' | 'warn' | 'error'} severity + * @param {string} args + */ + function safeSendConsoleMessage(severity, args) { + safeSend({ type: '__$console', severity, arguments: args }); + } + + /** + * @param {'log' | 'info' | 'warn' | 'error'} method + * @param {'log' | 'warn' | 'error'} severity + */ + function wrapConsoleMethod(method, severity) { + if (process.env.VSCODE_LOG_NATIVE === 'true') { + const original = console[method]; + console[method] = function () { + safeSendConsoleMessage(severity, safeToArray(arguments)); + original.apply(console, arguments); + }; + } else { + console[method] = function () { safeSendConsoleMessage(severity, safeToArray(arguments)); }; + } + } + // Pass console logging to the outside so that we have it in the main side if told so if (process.env.VERBOSE_LOGGING === 'true') { - console.log = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); }; - console.info = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); }; - console.warn = function () { safeSend({ type: '__$console', severity: 'warn', arguments: safeToArray(arguments) }); }; - } else { + wrapConsoleMethod('log', 'log'); + wrapConsoleMethod('warn', 'log'); + wrapConsoleMethod('error', 'warn'); + } else if (process.env.VSCODE_LOG_NATIVE !== 'true') { console.log = function () { /* ignore */ }; console.warn = function () { /* ignore */ }; console.info = function () { /* ignore */ }; } - console.error = function () { safeSend({ type: '__$console', severity: 'error', arguments: safeToArray(arguments) }); }; + wrapConsoleMethod('error', 'error'); } function handleExceptions() { diff --git a/src/vs/platform/debug/common/extensionHostDebug.ts b/src/vs/platform/debug/common/extensionHostDebug.ts index b263bdd9c1c..b30c4e44e73 100644 --- a/src/vs/platform/debug/common/extensionHostDebug.ts +++ b/src/vs/platform/debug/common/extensionHostDebug.ts @@ -5,7 +5,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Event } from 'vs/base/common/event'; -import { IRemoteConsoleLog } from 'vs/base/common/console'; import { IProcessEnvironment } from 'vs/base/common/platform'; export const IExtensionHostDebugService = createDecorator('extensionHostDebugService'); @@ -16,11 +15,6 @@ export interface IAttachSessionEvent { port: number; } -export interface ILogToSessionEvent { - sessionId: string; - log: IRemoteConsoleLog; -} - export interface ITerminateSessionEvent { sessionId: string; subId?: string; @@ -50,9 +44,6 @@ export interface IExtensionHostDebugService { attachSession(sessionId: string, port: number, subId?: string): void; readonly onAttachSession: Event; - logToSession(sessionId: string, log: IRemoteConsoleLog): void; - readonly onLogToSession: Event; - terminateSession(sessionId: string, subId?: string): void; readonly onTerminateSession: Event; diff --git a/src/vs/platform/debug/common/extensionHostDebugIpc.ts b/src/vs/platform/debug/common/extensionHostDebugIpc.ts index 60011be13e3..09c2a1916fa 100644 --- a/src/vs/platform/debug/common/extensionHostDebugIpc.ts +++ b/src/vs/platform/debug/common/extensionHostDebugIpc.ts @@ -4,9 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug'; +import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug'; import { Event, Emitter } from 'vs/base/common/event'; -import { IRemoteConsoleLog } from 'vs/base/common/console'; import { Disposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment } from 'vs/base/common/platform'; @@ -17,7 +16,6 @@ export class ExtensionHostDebugBroadcastChannel implements IServerChan private readonly _onCloseEmitter = new Emitter(); private readonly _onReloadEmitter = new Emitter(); private readonly _onTerminateEmitter = new Emitter(); - private readonly _onLogToEmitter = new Emitter(); private readonly _onAttachEmitter = new Emitter(); call(ctx: TContext, command: string, arg?: any): Promise { @@ -28,8 +26,6 @@ export class ExtensionHostDebugBroadcastChannel implements IServerChan return Promise.resolve(this._onReloadEmitter.fire({ sessionId: arg[0] })); case 'terminate': return Promise.resolve(this._onTerminateEmitter.fire({ sessionId: arg[0] })); - case 'log': - return Promise.resolve(this._onLogToEmitter.fire({ sessionId: arg[0], log: arg[1] })); case 'attach': return Promise.resolve(this._onAttachEmitter.fire({ sessionId: arg[0], port: arg[1], subId: arg[2] })); } @@ -44,8 +40,6 @@ export class ExtensionHostDebugBroadcastChannel implements IServerChan return this._onReloadEmitter.event; case 'terminate': return this._onTerminateEmitter.event; - case 'log': - return this._onLogToEmitter.event; case 'attach': return this._onAttachEmitter.event; } @@ -85,14 +79,6 @@ export class ExtensionHostDebugChannelClient extends Disposable implements IExte return this.channel.listen('attach'); } - logToSession(sessionId: string, log: IRemoteConsoleLog): void { - this.channel.call('log', [sessionId, log]); - } - - get onLogToSession(): Event { - return this.channel.listen('log'); - } - terminateSession(sessionId: string, subId?: string): void { this.channel.call('terminate', [sessionId, subId]); } diff --git a/src/vs/workbench/api/browser/mainThreadConsole.ts b/src/vs/workbench/api/browser/mainThreadConsole.ts index 4a244875f42..d678f21bc67 100644 --- a/src/vs/workbench/api/browser/mainThreadConsole.ts +++ b/src/vs/workbench/api/browser/mainThreadConsole.ts @@ -10,22 +10,18 @@ import { IRemoteConsoleLog, log } from 'vs/base/common/console'; import { logRemoteEntry } from 'vs/workbench/services/extensions/common/remoteConsoleUtil'; import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions'; import { ILogService } from 'vs/platform/log/common/log'; -import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug'; @extHostNamedCustomer(MainContext.MainThreadConsole) export class MainThreadConsole implements MainThreadConsoleShape { - private readonly _isExtensionDevHost: boolean; private readonly _isExtensionDevTestFromCli: boolean; constructor( - extHostContext: IExtHostContext, + _extHostContext: IExtHostContext, @IEnvironmentService private readonly _environmentService: IEnvironmentService, @ILogService private readonly _logService: ILogService, - @IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService, ) { const devOpts = parseExtensionDevOptions(this._environmentService); - this._isExtensionDevHost = devOpts.isExtensionDevHost; this._isExtensionDevTestFromCli = devOpts.isExtensionDevTestFromCli; } @@ -43,10 +39,5 @@ export class MainThreadConsole implements MainThreadConsoleShape { if (this._isExtensionDevTestFromCli) { logRemoteEntry(this._logService, entry); } - - // Broadcast to other windows if we are in development mode - else if (this._environmentService.debugExtensionHost.debugId && (!this._environmentService.isBuilt || this._isExtensionDevHost)) { - this._extensionHostDebugService.logToSession(this._environmentService.debugExtensionHost.debugId, entry); - } } } diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 4e99febee24..03e5dd87899 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -25,7 +25,6 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { parse, getFirstFrame } from 'vs/base/common/console'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IAction, Action } from 'vs/base/common/actions'; @@ -149,16 +148,6 @@ export class DebugService implements IDebugService { session.disconnect(); } })); - this.toDispose.push(this.extensionHostDebugService.onLogToSession(event => { - const session = this.model.getSession(event.sessionId, true); - if (session) { - // extension logged output -> show it in REPL - const sev = event.log.severity === 'warn' ? severity.Warning : event.log.severity === 'error' ? severity.Error : severity.Info; - const { args, stack } = parse(event.log); - const frame = !!stack ? getFirstFrame(stack) : undefined; - session.logToRepl(sev, args, frame); - } - })); this.toDispose.push(this.viewModel.onDidFocusStackFrame(() => { this.onStateChange(); diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 5ec4c4bbae8..024c8f95fde 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -151,13 +151,12 @@ export class LocalProcessExtensionHost implements IExtensionHost { this._messageProtocol = Promise.all([ this._tryListenOnPipe(), this._tryFindDebugPort() - ]).then(data => { - const pipeName = data[0]; - const portNumber = data[1]; + ]).then(([pipeName, portNumber]) => { const env = objects.mixin(objects.deepClone(process.env), { AMD_ENTRYPOINT: 'vs/workbench/services/extensions/node/extensionHostProcess', PIPE_LOGGING: 'true', VERBOSE_LOGGING: true, + VSCODE_LOG_NATIVE: this._isExtensionDevHost, VSCODE_IPC_HOOK_EXTHOST: pipeName, VSCODE_HANDLES_UNCAUGHT_ERRORS: true, VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || this._productService.quality !== 'stable' || this._environmentService.verbose), @@ -497,11 +496,6 @@ export class LocalProcessExtensionHost implements IExtensionHost { // Send to local console log(entry, 'Extension Host'); - - // Broadcast to other windows if we are in development mode - if (this._environmentService.debugExtensionHost.debugId && (!this._environmentService.isBuilt || this._isExtensionDevHost)) { - this._extensionHostDebugService.logToSession(this._environmentService.debugExtensionHost.debugId, entry); - } } } From 10d92e5efaf67a39660260f4fa5e44b3f847c597 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 23 Nov 2020 17:51:57 -0500 Subject: [PATCH 0160/1837] Prompt user with info about terminal config, add settings search by @id, and add sendToShell setting (#110987) * something isn't right here * add parens and remove test z * something isn't right here * remove z * change name of setting, move promptChoices within conditional, use prefService instead of commandService and use set.has * only show prompt once and remove unnecessary conditional * don't show prompt if command is open terminal * don't alert on terminal open / close * Add another excluded command --- .../preferences/browser/settingsEditor2.ts | 8 ++- .../preferences/browser/settingsTreeModels.ts | 22 +++++++- .../contrib/preferences/browser/tocTree.ts | 3 +- .../contrib/preferences/common/preferences.ts | 1 + .../test/browser/settingsTreeModels.test.ts | 56 +++++++++++++++---- .../terminal/browser/terminalInstance.ts | 30 ++++++++-- .../contrib/terminal/common/terminal.ts | 3 +- .../terminal/common/terminalConfiguration.ts | 5 ++ 8 files changed, 106 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 790e22901d5..64d3da690d3 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -46,7 +46,7 @@ import { AbstractSettingRenderer, ISettingLinkClickEvent, ISettingOverrideClickE import { ISettingsEditorViewState, parseQuery, SearchResultIdx, SearchResultModel, SettingsTreeElement, SettingsTreeGroupChild, SettingsTreeGroupElement, SettingsTreeModel, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels'; import { settingsTextInputBorder } from 'vs/workbench/contrib/preferences/browser/settingsWidgets'; import { createTOCIterator, TOCTree, TOCTreeModel } from 'vs/workbench/contrib/preferences/browser/tocTree'; -import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, ID_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingsEditorOptions, SettingValueType } from 'vs/workbench/services/preferences/common/preferences'; import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; @@ -90,7 +90,7 @@ export class SettingsEditor2 extends EditorPane { private static CONFIG_SCHEMA_UPDATE_DELAYER = 500; private static readonly SUGGESTIONS: string[] = [ - `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` + `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${ID_SETTING_TAG}`, `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` ]; private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean { @@ -1135,19 +1135,21 @@ export class SettingsEditor2 extends EditorPane { this.viewState.tagFilters = new Set(); this.viewState.extensionFilters = new Set(); this.viewState.featureFilters = new Set(); + this.viewState.idFilters = new Set(); if (query) { const parsedQuery = parseQuery(query); query = parsedQuery.query; parsedQuery.tags.forEach(tag => this.viewState.tagFilters!.add(tag)); parsedQuery.extensionFilters.forEach(extensionId => this.viewState.extensionFilters!.add(extensionId)); parsedQuery.featureFilters!.forEach(feature => this.viewState.featureFilters!.add(feature)); + parsedQuery.idFilters!.forEach(id => this.viewState.idFilters!.add(id)); } if (query && query !== '@') { query = this.parseSettingFromJSON(query) || query; return this.triggerFilterPreferences(query); } else { - if (this.viewState.tagFilters.size || this.viewState.extensionFilters.size || this.viewState.featureFilters.size) { + if (this.viewState.tagFilters.size || this.viewState.extensionFilters.size || this.viewState.featureFilters.size || this.viewState.idFilters.size) { this.searchResultModel = this.createFilterModel(); } else { this.searchResultModel = null; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 94cf0a3cb1b..e2f231a83e3 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -26,6 +26,7 @@ export interface ISettingsEditorViewState { tagFilters?: Set; extensionFilters?: Set; featureFilters?: Set; + idFilters?: Set; filterToCategory?: SettingsTreeGroupElement; } @@ -311,6 +312,13 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } }); } + + matchesAnyId(idFilters?: Set): boolean { + if (!idFilters || !idFilters.size) { + return true; + } + return idFilters.has(this.setting.key); + } } @@ -641,7 +649,7 @@ export class SearchResultModel extends SettingsTreeModel { const isRemote = !!this.environmentService.remoteAuthority; this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true)); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches @@ -687,16 +695,19 @@ export interface IParsedQuery { tags: string[]; query: string; extensionFilters: string[]; + idFilters: string[]; featureFilters: string[]; } const tagRegex = /(^|\s)@tag:("([^"]*)"|[^"]\S*)/g; const extensionRegex = /(^|\s)@ext:("([^"]*)"|[^"]\S*)?/g; const featureRegex = /(^|\s)@feature:("([^"]*)"|[^"]\S*)?/g; +const idRegex = /(^|\s)@id:("([^"]*)"|[^"]\S*)?/g; export function parseQuery(query: string): IParsedQuery { const tags: string[] = []; const extensions: string[] = []; const features: string[] = []; + const ids: string[] = []; query = query.replace(tagRegex, (_, __, quotedTag, tag) => { tags.push(tag || quotedTag); return ''; @@ -723,12 +734,21 @@ export function parseQuery(query: string): IParsedQuery { return ''; }); + query = query.replace(idRegex, (_, __, quotedId, id) => { + const idRegex: string = id || quotedId; + if (idRegex) { + ids.push(...idRegex.split(',').map(s => s.trim()).filter(s => !isFalsyOrWhitespace(s))); + } + return ''; + }); + query = query.trim(); return { tags, extensionFilters: extensions, featureFilters: features, + idFilters: ids, query }; } diff --git a/src/vs/workbench/contrib/preferences/browser/tocTree.ts b/src/vs/workbench/contrib/preferences/browser/tocTree.ts index 3888aad4803..edb880108f3 100644 --- a/src/vs/workbench/contrib/preferences/browser/tocTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/tocTree.ts @@ -93,7 +93,8 @@ export class TOCTreeModel { return child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAllTags(this._viewState.tagFilters) && child.matchesAnyFeature(this._viewState.featureFilters) && - child.matchesAnyExtension(this._viewState.extensionFilters); + child.matchesAnyExtension(this._viewState.extensionFilters) && + child.matchesAnyId(this._viewState.idFilters); }).length; } } diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index ca97a3d6414..928106092b3 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -71,4 +71,5 @@ export const KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS = 'keybindings.editor.show export const MODIFIED_SETTING_TAG = 'modified'; export const EXTENSION_SETTING_TAG = 'ext:'; export const FEATURE_SETTING_TAG = 'feature:'; +export const ID_SETTING_TAG = 'id:'; export const KEYBOARD_LAYOUT_OPEN_PICKER = 'workbench.action.openKeyboardLayoutPicker'; diff --git a/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts b/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts index 7387f4519cb..b2ae0a9e85b 100644 --- a/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts +++ b/src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts @@ -147,8 +147,9 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: [], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( @@ -156,8 +157,9 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( @@ -165,8 +167,9 @@ suite('SettingsTree', () => { { tags: ['foo'], extensionFilters: [], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( @@ -174,8 +177,9 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + query: 'foo', featureFilters: [], - query: 'foo' + idFilters: [] }); testParseQuery( @@ -183,8 +187,9 @@ suite('SettingsTree', () => { { tags: ['foo', 'modified'], extensionFilters: [], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( @@ -192,8 +197,9 @@ suite('SettingsTree', () => { { tags: ['foo', 'modified'], extensionFilters: [], + query: 'my query', featureFilters: [], - query: 'my query' + idFilters: [] }); testParseQuery( @@ -201,8 +207,9 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + query: 'test query', featureFilters: [], - query: 'test query' + idFilters: [] }); testParseQuery( @@ -210,8 +217,9 @@ suite('SettingsTree', () => { { tags: ['modified'], extensionFilters: [], + query: 'test', featureFilters: [], - query: 'test' + idFilters: [] }); testParseQuery( @@ -221,6 +229,7 @@ suite('SettingsTree', () => { extensionFilters: [], query: 'query has @ for some reason', featureFilters: [], + idFilters: [] }); testParseQuery( @@ -228,8 +237,9 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: ['github.vscode-pull-request-github'], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( @@ -237,8 +247,9 @@ suite('SettingsTree', () => { { tags: [], extensionFilters: ['github.vscode-pull-request-github', 'vscode.git'], + query: '', featureFilters: [], - query: '' + idFilters: [] }); testParseQuery( '@feature:scm', @@ -246,7 +257,8 @@ suite('SettingsTree', () => { tags: [], extensionFilters: [], featureFilters: ['scm'], - query: '' + query: '', + idFilters: [] }); testParseQuery( @@ -255,7 +267,27 @@ suite('SettingsTree', () => { tags: [], extensionFilters: [], featureFilters: ['scm', 'terminal'], - query: '' + query: '', + idFilters: [] + }); + testParseQuery( + '@id:files.autoSave', + { + tags: [], + extensionFilters: [], + featureFilters: [], + query: '', + idFilters: ['files.autoSave'] + }); + + testParseQuery( + '@id:files.autoSave,terminal.integrated.commandsToSkipShell', + { + tags: [], + extensionFilters: [], + featureFilters: [], + query: '', + idFilters: ['files.autoSave', 'terminal.integrated.commandsToSkipShell'] }); }); }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 2a76b63a765..08dfc59ed0b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -25,7 +25,7 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, SHOW_TERMINAL_CONFIG_PROMPT } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; @@ -46,6 +46,7 @@ import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/e import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { TypeAheadAddon } from 'vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; // How long in milliseconds should an average frame take to render for a notification to appear // which suggests the fallback DOM-based renderer @@ -187,6 +188,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IKeybindingService private readonly _keybindingService: IKeybindingService, @INotificationService private readonly _notificationService: INotificationService, + @IPreferencesService private readonly _preferencesService: IPreferencesService, @IViewsService private readonly _viewsService: IViewsService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IClipboardService private readonly _clipboardService: IClipboardService, @@ -542,9 +544,29 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return false; } - // Skip processing by xterm.js of keyboard events that resolve to commands described - // within commandsToSkipShell - if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { + // for keyboard events that resolve to commands described + // within commandsToSkipShell, either alert or skip processing by xterm.js + if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) { + // don't alert when terminal is opened or closed + if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT, StorageScope.GLOBAL, true) && + resolveResult.commandId !== 'workbench.action.terminal.toggleTerminal' && + resolveResult.commandId !== 'workbench.action.terminal.new' && + resolveResult.commandId !== 'workbench.action.togglePanel' && + resolveResult.commandId !== 'workbench.action.terminal.focus') { + this._notificationService.prompt( + Severity.Info, + nls.localize('configure terminal settings', "Some keybindings are dispatched to the workbench by default."), + [ + { + label: nls.localize('configureTerminalSettings', "Configure Terminal Settings"), + run: () => { + this._preferencesService.openSettings(false, '@id:terminal.integrated.commandsToSkipShell,terminal.integrated.sendKeybindingsToShell,terminal.integrated.allowChords'); + } + } as IPromptChoice + ] + ); + this._storageService.store(SHOW_TERMINAL_CONFIG_PROMPT, false, StorageScope.GLOBAL, StorageTarget.USER); + } event.preventDefault(); return false; } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index edd076f6391..ef7ff2e50bd 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -50,7 +50,7 @@ export const KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED = new RawContextKey Date: Mon, 23 Nov 2020 15:31:03 -0800 Subject: [PATCH 0161/1837] chore: update to electron 11 (#110759) * chore: bump electron@11.0.0-beta.4 * build: add mac arm64 target * chore: bump electron@11.0.1 * fix: remove macOS workaround for devtools with custom titlebar https://github.com/electron/electron/pull/26395 * chore: bump vscode-windows-ca-certs@0.3.0 * chore: bump electron@11.0.2 * fixup! remove macOS workaround for devtools with custom titlebar --- .yarnrc | 2 +- build/.cachesalt | 2 +- .../darwin/continuous-build-darwin.yml | 2 +- .../darwin/product-build-darwin.yml | 114 +++-- build/azure-pipelines/darwin/publish.sh | 12 +- build/azure-pipelines/distro-build.yml | 2 +- build/azure-pipelines/exploration-build.yml | 2 +- .../linux/continuous-build-linux.yml | 2 +- .../linux/product-build-alpine.yml | 2 +- .../linux/product-build-linux.yml | 8 +- .../linux/snap-build-linux.yml | 2 +- build/azure-pipelines/product-build.yml | 28 +- build/azure-pipelines/product-compile.yml | 2 +- .../publish-types/publish-types.yml | 2 +- build/azure-pipelines/sync-mooncake.yml | 2 +- .../azure-pipelines/web/product-build-web.yml | 2 +- .../win32/continuous-build-win32.yml | 2 +- .../win32/product-build-win32-arm64.yml | 2 +- .../win32/product-build-win32.yml | 2 +- build/darwin/sign.ts | 3 +- build/gulpfile.vscode.js | 3 +- cgmanifest.json | 12 +- package.json | 10 +- remote/.yarnrc | 2 +- remote/package.json | 6 +- remote/yarn.lock | 40 +- src/vs/code/electron-main/window.ts | 10 +- .../test/electron-main/nativeHelpers.test.ts | 10 + .../platform/menubar/electron-main/menubar.ts | 10 +- .../electron-main/nativeHostMainService.ts | 6 +- .../electron-main/updateService.darwin.ts | 3 +- .../electron-main/webviewProtocolProvider.ts | 13 +- src/vs/platform/windows/common/windows.ts | 12 +- .../browser/actions/layoutActions.ts | 6 +- src/vs/workbench/browser/layout.ts | 12 +- .../parts/activitybar/activitybarActions.ts | 2 +- .../parts/activitybar/activitybarPart.ts | 6 +- .../browser/parts/titlebar/menubarControl.ts | 4 +- .../browser/parts/titlebar/titlebarPart.ts | 6 +- .../parts/titlebar/titlebarPart.ts | 2 +- src/vs/workbench/electron-sandbox/window.ts | 6 +- .../electron-sandbox/contextmenuService.ts | 2 +- .../services/extensions/node/proxyResolver.ts | 2 +- yarn.lock | 400 ++++++++++++++++-- 44 files changed, 604 insertions(+), 176 deletions(-) diff --git a/.yarnrc b/.yarnrc index d97527dab46..55af88729b8 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://electronjs.org/headers" -target "9.3.3" +target "11.0.2" runtime "electron" diff --git a/build/.cachesalt b/build/.cachesalt index 0e8a2d8b1a6..0afdafd1118 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-23T10:00:34.612Z +2020-11-23T17:57:03.428Z diff --git a/build/azure-pipelines/darwin/continuous-build-darwin.yml b/build/azure-pipelines/darwin/continuous-build-darwin.yml index 954e5bca636..3711d5c21d8 100644 --- a/build/azure-pipelines/darwin/continuous-build-darwin.yml +++ b/build/azure-pipelines/darwin/continuous-build-darwin.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 8f13bfb5b9b..e73ba836973 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: @@ -53,35 +53,68 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro +- script: | + echo -n $VSCODE_ARCH > .build/arch + displayName: Prepare arch cache flag + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' targetfolder: '**/node_modules, !**/node_modules/**/node_modules' vstsFeed: 'npm-vscode' - script: | set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile + sudo xcode-select -s /Applications/Xcode_12.2.app + displayName: Switch to Xcode 12 + condition: eq(variables['VSCODE_ARCH'], 'arm64') + +- script: | + set -e + npm install -g node-gyp@7.1.0 + node-gyp --version + displayName: Update node-gyp + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- script: | + set -e + export npm_config_arch=$(VSCODE_ARCH) + export npm_config_node_gyp=$(which node-gyp) + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + CHILD_CONCURRENCY=1 yarn --frozen-lockfile --verbose displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' targetfolder: '**/node_modules, !**/node_modules/**/node_modules' vstsFeed: 'npm-vscode' condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | set -e + export npm_config_arch=$(VSCODE_ARCH) + export npm_config_node_gyp=$(which node-gyp) + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ yarn postinstall displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) +- script: | + set -e + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + yarn electron-rebuild + displayName: Rebuild native modules for ARM64 + condition: eq(variables['VSCODE_ARCH'], 'arm64') + - script: | set -e node build/azure-pipelines/mixin @@ -90,63 +123,85 @@ steps: - script: | set -e VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-darwin-min-ci + yarn gulp vscode-darwin-$(VSCODE_ARCH)-min-ci + displayName: Build + +- script: | + set -e VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-reh-darwin-min-ci VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-reh-web-darwin-min-ci - displayName: Build + displayName: Build reh + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + +- script: | + set -e + yarn electron $(VSCODE_ARCH) + displayName: Download Electron + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + +- script: | + set -e + security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + security default-keychain -s $(agent.tempdirectory)/buildagent.keychain + security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12 + security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain + VSCODE_ARCH="$(VSCODE_ARCH)" DEBUG=electron-osx-sign* node build/darwin/sign.js + displayName: Set Hardened Entitlements - script: | set -e ./scripts/test.sh --build --tfs "Unit Tests" displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e yarn test-browser --build --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | # Figure out the full absolute path of the product we just built # including the remote server and configure the integration tests # to run with these builds instead of running out of sources. set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) APP_NAME="`ls $APP_ROOT | head -n 1`" INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ ./scripts/test-integration.sh --build --tfs "Integration Tests" displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ ./resources/server/test/test-web-integration.sh --browser webkit displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) APP_NAME="`ls $APP_ROOT | head -n 1`" INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ ./resources/server/test/test-remote-integration.sh displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) APP_NAME="`ls $APP_ROOT | head -n 1`" yarn smoketest --build "$APP_ROOT/$APP_NAME" continueOnError: true displayName: Run smoke tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e @@ -154,11 +209,11 @@ steps: yarn smoketest --web --headless continueOnError: true displayName: Run smoke tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - task: PublishPipelineArtifact@0 inputs: - artifactName: crash-dump-macos + artifactName: crash-dump-macos-$(VSCODE_ARCH) targetPath: .build/crashes displayName: 'Publish Crash Reports' continueOnError: true @@ -173,25 +228,14 @@ steps: - script: | set -e - security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain - security default-keychain -s $(agent.tempdirectory)/buildagent.keychain - security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain - echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12 - security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain - DEBUG=electron-osx-sign* node build/darwin/sign.js - displayName: Set Hardened Entitlements - -- script: | - set -e - pushd $(agent.builddirectory)/VSCode-darwin && zip -r -X -y $(agent.builddirectory)/VSCode-darwin.zip * && popd + pushd $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) && zip -r -X -y $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip * && popd displayName: Archive build - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: ConnectedServiceName: 'ESRP CodeSign' FolderPath: '$(agent.builddirectory)' - Pattern: 'VSCode-darwin.zip' + Pattern: 'VSCode-darwin-$(VSCODE_ARCH).zip' signConfigType: inlineSignParams inlineOperation: | [ @@ -212,11 +256,11 @@ steps: displayName: Codesign - script: | - zip -d $(agent.builddirectory)/VSCode-darwin.zip "*.pkg" + zip -d $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip "*.pkg" displayName: Clean Archive - script: | - APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) APP_NAME="`ls $APP_ROOT | head -n 1`" BUNDLE_IDENTIFIER=$(node -p "require(\"$APP_ROOT/$APP_NAME/Contents/Resources/app/product.json\").darwinBundleIdentifier") echo "##vso[task.setvariable variable=BundleIdentifier]$BUNDLE_IDENTIFIER" @@ -226,7 +270,7 @@ steps: inputs: ConnectedServiceName: 'ESRP CodeSign' FolderPath: '$(agent.builddirectory)' - Pattern: 'VSCode-darwin.zip' + Pattern: 'VSCode-darwin-$(VSCODE_ARCH).zip' signConfigType: inlineSignParams inlineOperation: | [ @@ -248,10 +292,11 @@ steps: - script: | set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) APP_NAME="`ls $APP_ROOT | head -n 1`" "$APP_ROOT/$APP_NAME/Contents/Resources/app/bin/code" --export-default-configuration=.build displayName: Verify start after signing (export configuration) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - script: | set -e @@ -267,6 +312,7 @@ steps: AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ yarn gulp upload-vscode-configuration displayName: Upload configuration (for Bing settings search) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) continueOnError: true - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/build/azure-pipelines/darwin/publish.sh b/build/azure-pipelines/darwin/publish.sh index 51ac2e6355d..c9f5b4bab53 100755 --- a/build/azure-pipelines/darwin/publish.sh +++ b/build/azure-pipelines/darwin/publish.sh @@ -1,12 +1,18 @@ #!/usr/bin/env bash set -e +# Publish DEB +case $VSCODE_ARCH in + x64) ASSET_ID="darwin" ;; + arm64) ASSET_ID="darwin-arm64" ;; +esac + # publish the build node build/azure-pipelines/common/createAsset.js \ - darwin \ + "$ASSET_ID" \ archive \ - "VSCode-darwin-$VSCODE_QUALITY.zip" \ - ../VSCode-darwin.zip + "VSCode-$ASSET_ID.zip" \ + ../VSCode-darwin-$VSCODE_ARCH.zip if [ "$VSCODE_ARCH" == "x64" ]; then # package Remote Extension Host diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml index f9bdf7fef8e..15526080abb 100644 --- a/build/azure-pipelines/distro-build.yml +++ b/build/azure-pipelines/distro-build.yml @@ -8,7 +8,7 @@ pr: steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - 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 cf1ced09dc8..a6a7dfe71a6 100644 --- a/build/azure-pipelines/exploration-build.yml +++ b/build/azure-pipelines/exploration-build.yml @@ -11,7 +11,7 @@ pr: steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: AzureKeyVault@1 displayName: 'Azure Key Vault: Get Secrets' diff --git a/build/azure-pipelines/linux/continuous-build-linux.yml b/build/azure-pipelines/linux/continuous-build-linux.yml index 58e14ab0dcd..4bc21fc89a7 100644 --- a/build/azure-pipelines/linux/continuous-build-linux.yml +++ b/build/azure-pipelines/linux/continuous-build-linux.yml @@ -10,7 +10,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index d58a2de2907..ce4a620f843 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index ebbc419a591..45d2cc29988 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: @@ -100,12 +100,6 @@ steps: yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci displayName: Build -- script: | - set -e - service xvfb start - displayName: Start xvfb - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - - script: | set -e DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 9084a9f6093..1cd7eb70c64 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: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 1c45de07f3e..28e3f2b4d05 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -11,8 +11,9 @@ schedules: resources: containers: - container: vscode-x64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:x64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic endpoint: VSCodeHub + options: --user 0:0 - container: vscode-arm64 image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 endpoint: VSCodeHub @@ -27,7 +28,7 @@ stages: jobs: - job: Compile pool: - vmImage: 'Ubuntu-16.04' + vmImage: 'Ubuntu-18.04' container: vscode-x64 steps: - template: product-compile.yml @@ -68,7 +69,7 @@ stages: - Compile condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) pool: - vmImage: 'Ubuntu-16.04' + vmImage: 'Ubuntu-18.04' jobs: - job: Linux condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) @@ -134,14 +135,30 @@ stages: steps: - template: darwin/product-build-darwin.yml +- stage: macOSARM64 + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: macOS-latest + jobs: + - job: macOSARM64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS_ARM64'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: arm64 + steps: + - template: darwin/product-build-darwin.yml + - stage: Mooncake dependsOn: - Windows - Linux - macOS + - macOSARM64 condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) pool: - vmImage: 'Ubuntu-16.04' + vmImage: 'Ubuntu-18.04' jobs: - job: SyncMooncake displayName: Sync Mooncake @@ -153,9 +170,10 @@ stages: - Windows - Linux - macOS + - macOSARM64 condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) pool: - vmImage: 'Ubuntu-16.04' + vmImage: 'Ubuntu-18.04' jobs: - job: BuildService displayName: Build Service diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 0f3357ddc83..a086149f053 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -16,7 +16,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml index 10b6aa4e16a..f3dfc213a7b 100644 --- a/build/azure-pipelines/publish-types/publish-types.yml +++ b/build/azure-pipelines/publish-types/publish-types.yml @@ -9,7 +9,7 @@ pr: none steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/sync-mooncake.yml b/build/azure-pipelines/sync-mooncake.yml index 49dfc9ced80..810024fced1 100644 --- a/build/azure-pipelines/sync-mooncake.yml +++ b/build/azure-pipelines/sync-mooncake.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index d7b4ac42485..f7588916064 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/win32/continuous-build-win32.yml b/build/azure-pipelines/win32/continuous-build-win32.yml index 6107eacc66c..6dd508a7c81 100644 --- a/build/azure-pipelines/win32/continuous-build-win32.yml +++ b/build/azure-pipelines/win32/continuous-build-win32.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index c536ed13eeb..29c795dfe15 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index db56dc95451..66f8c265140 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -21,7 +21,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/darwin/sign.ts b/build/darwin/sign.ts index ee5d2eeb17b..538dc97adf1 100644 --- a/build/darwin/sign.ts +++ b/build/darwin/sign.ts @@ -13,6 +13,7 @@ import * as product from '../../product.json'; async function main(): Promise { const buildDir = process.env['AGENT_BUILDDIRECTORY']; const tempDir = process.env['AGENT_TEMPDIRECTORY']; + const arch = process.env['VSCODE_ARCH']; if (!buildDir) { throw new Error('$AGENT_BUILDDIRECTORY not set'); @@ -23,7 +24,7 @@ async function main(): Promise { } const baseDir = path.dirname(__dirname); - const appRoot = path.join(buildDir, 'VSCode-darwin'); + const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`); const appName = product.nameLong + '.app'; const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks'); const helperAppBaseName = product.nameShort; diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 3c8bbe5b87f..4dbcd883f2e 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -326,7 +326,8 @@ const BUILD_TARGETS = [ { platform: 'win32', arch: 'ia32' }, { platform: 'win32', arch: 'x64' }, { platform: 'win32', arch: 'arm64' }, - { platform: 'darwin', arch: null, opts: { stats: true } }, + { platform: 'darwin', arch: 'x64', opts: { stats: true } }, + { platform: 'darwin', arch: 'arm64', opts: { stats: true } }, { platform: 'linux', arch: 'ia32' }, { platform: 'linux', arch: 'x64' }, { platform: 'linux', arch: 'armhf' }, diff --git a/cgmanifest.json b/cgmanifest.json index bd95a0d80b0..25cc4d5e980 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "894fb9eb56c6cbda65e3c3ae9ada6d4cb5850cc9" + "commitHash": "0387c513f0319231a8ca6dd0a265102af3d4455e" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "83.0.4103.122" + "version": "87.0.4280.67" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "9622fed3fb2cffcea9efff6c8cb4cc2def99d75d" + "commitHash": "e3e0927bb93ed92bcdfe81e7ad9af3d78ccc74fb" } }, "isOnlyProductionDependency": true, - "version": "12.14.1" + "version": "12.18.3" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "0b5f24002b4f18adee112ed39fe269aa51f6705c" + "commitHash": "edb67231577eb68eac1c955e271cb7a16f3eb1e3" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "9.3.3" + "version": "11.0.2" }, { "component": { diff --git a/package.json b/package.json index 97c1366c53b..d8f4da9ccd1 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "web": "node resources/web/code-web.js", "compile-web": "gulp compile-web --max_old_space_size=4095", "watch-web": "gulp watch-web --max_old_space_size=4095", - "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions" + "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", + "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.2" }, "dependencies": { "applicationinsights": "1.0.8", @@ -59,7 +60,7 @@ "native-is-elevated": "0.4.1", "native-keymap": "2.2.1", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta17", + "node-pty": "0.10.0-beta18", "spdlog": "^0.11.1", "sudo-prompt": "9.1.1", "tas-client-umd": "0.1.2", @@ -111,7 +112,8 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "9.3.3", + "electron": "11.0.2", + "electron-rebuild": "2.0.3", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "eslint-plugin-mocha": "8.0.0", @@ -189,7 +191,7 @@ "url": "https://github.com/microsoft/vscode/issues" }, "optionalDependencies": { - "vscode-windows-ca-certs": "0.2.0", + "vscode-windows-ca-certs": "^0.3.0", "vscode-windows-registry": "1.0.3", "windows-foreground-love": "0.2.0", "windows-mutex": "0.3.0", diff --git a/remote/.yarnrc b/remote/.yarnrc index c1a32ce532a..cd436416b56 100644 --- a/remote/.yarnrc +++ b/remote/.yarnrc @@ -1,3 +1,3 @@ disturl "http://nodejs.org/dist" -target "12.14.1" +target "12.18.3" runtime "node" diff --git a/remote/package.json b/remote/package.json index f68deac647c..57710a189ba 100644 --- a/remote/package.json +++ b/remote/package.json @@ -12,15 +12,15 @@ "jschardet": "2.2.1", "minimist": "^1.2.5", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta17", + "node-pty": "0.10.0-beta18", "spdlog": "^0.11.1", "tas-client-umd": "0.1.2", "vscode-nsfw": "1.2.9", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", + "vscode-regexpp": "^3.1.0", "vscode-ripgrep": "^1.11.1", "vscode-textmate": "5.2.0", - "vscode-regexpp": "^3.1.0", "xterm": "4.10.0-beta.4", "xterm-addon-search": "0.8.0-beta.3", "xterm-addon-unicode11": "0.3.0-beta.3", @@ -29,7 +29,7 @@ "yazl": "^2.4.3" }, "optionalDependencies": { - "vscode-windows-ca-certs": "0.2.0", + "vscode-windows-ca-certs": "0.3.0", "vscode-windows-registry": "1.0.2" } } diff --git a/remote/yarn.lock b/remote/yarn.lock index 2647e384aba..e15eb9d9839 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -167,11 +167,16 @@ glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -graceful-fs@4.2.3, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -279,7 +284,12 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -nan@^2.10.0, nan@^2.14.0: +nan@^2.10.0: + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== + +nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -289,15 +299,15 @@ native-watchdog@1.3.0: resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.3.0.tgz#88cee94c9dc766b85c8506eda14c8bd8c9618e27" integrity sha512-WOjGRNGkYZ5MXsntcvCYrKtSYMaewlbCFplbcUVo9bE80LPVt8TAVFHYWB8+a6fWCGYheq21+Wtt6CJrUaCJhw== -node-addon-api@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" - integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== +node-addon-api@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" + integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== -node-pty@0.10.0-beta17: - version "0.10.0-beta17" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" - integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== +node-pty@0.10.0-beta18: + version "0.10.0-beta18" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta18.tgz#7ed2d3f4a06b2b23fe2abdf5b41655e9dffc25d5" + integrity sha512-vpK4yB3A3VzgkvdOWegL7GcPapt45jfA4b3ejUe8k4RmqdWBRvFJngew8T3qAxmLhTkfo93psaN6izTlfkc6FA== dependencies: nan "^2.14.0" @@ -428,12 +438,12 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-windows-ca-certs@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.2.0.tgz#086f0f4de57e2760a35ac6920831bff246237115" - integrity sha512-YBrJRT0zos+Yb1Qdn73GD8QZr7pa2IE96b5Y1hmmp6XeR8aYB7Iiq5gDAF/+/AxL+caSR9KPZQ6jiYWh5biD7w== +vscode-windows-ca-certs@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.3.0.tgz#324e1f8ba842bbf048a39e7c0ee8fe655e9adfcc" + integrity sha512-CYrpCEKmAFQJoZNReOrelNL+VKyebOVRCqL9evrBlVcpWQDliliJgU5RggGS8FPGtQ3jAKLQt9frF0qlxYYPKA== dependencies: - node-addon-api "1.6.2" + node-addon-api "^3.0.2" vscode-windows-registry@1.0.2: version "1.0.2" diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 135f1b70b91..5b0fe508826 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -9,7 +9,7 @@ import * as nls from 'vs/nls'; import * as perf from 'vs/base/common/performance'; import { Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; -import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, Details } from 'electron'; +import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, RenderProcessGoneDetails } from 'electron'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -210,7 +210,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs } - const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom'; + const useCustomTitleStyle = getTitleBarStyle(this.configurationService) === 'custom'; if (useCustomTitleStyle) { options.titleBarStyle = 'hidden'; this.hiddenTitleBarStyle = true; @@ -543,8 +543,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { } private onWindowError(error: WindowError.UNRESPONSIVE): void; - private onWindowError(error: WindowError.CRASHED, details: Details): void; - private onWindowError(error: WindowError, details?: Details): void { + private onWindowError(error: WindowError.CRASHED, details: RenderProcessGoneDetails): void; + private onWindowError(error: WindowError, details?: RenderProcessGoneDetails): void { this.logService.error(error === WindowError.CRASHED ? `[VS Code]: renderer process crashed (detail: ${details?.reason})` : '[VS Code]: detected unresponsive'); // If we run extension tests from CLI, showing a dialog is not @@ -1145,7 +1145,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } private getMenuBarVisibility(): MenuBarVisibility { - let menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService, !!this.currentConfig?.extensionDevelopmentPath); + let menuBarVisibility = getMenuBarVisibility(this.configurationService); if (['visible', 'toggle', 'hidden'].indexOf(menuBarVisibility) < 0) { menuBarVisibility = 'default'; } diff --git a/src/vs/code/test/electron-main/nativeHelpers.test.ts b/src/vs/code/test/electron-main/nativeHelpers.test.ts index 1ce46448038..1e5724a810f 100644 --- a/src/vs/code/test/electron-main/nativeHelpers.test.ts +++ b/src/vs/code/test/electron-main/nativeHelpers.test.ts @@ -30,7 +30,17 @@ suite('Windows Native Helpers', () => { test('vscode-windows-ca-certs', async () => { // @ts-ignore Windows only const windowsCerts = await import('vscode-windows-ca-certs'); + const store = new windowsCerts.Crypt32(); assert.ok(windowsCerts, 'Unable to load vscode-windows-ca-certs dependency.'); + let certCount = 0; + try { + while (store.next()) { + certCount++; + } + } finally { + store.done(); + } + assert(certCount > 0); }); test('vscode-windows-registry', async () => { diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 4ecb3725163..e2a0efb0bd5 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { isMacintosh, language } from 'vs/base/common/platform'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; -import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, KeyboardEvent } from 'electron'; +import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, KeyboardEvent } from 'electron'; import { getTitleBarStyle, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -61,7 +61,7 @@ export class Menubar { private keybindings: { [commandId: string]: IMenubarKeybinding }; - private readonly fallbackMenuHandlers: { [id: string]: (menuItem: MenuItem, browserWindow: BrowserWindow | undefined, event: Event) => void } = Object.create(null); + private readonly fallbackMenuHandlers: { [id: string]: (menuItem: MenuItem, browserWindow: BrowserWindow | undefined, event: KeyboardEvent) => void } = Object.create(null); constructor( @IUpdateService private readonly updateService: IUpdateService, @@ -82,7 +82,7 @@ export class Menubar { this.menubarMenus = Object.create(null); this.keybindings = Object.create(null); - if (isMacintosh || getTitleBarStyle(this.configurationService, this.environmentService) === 'native') { + if (isMacintosh || getTitleBarStyle(this.configurationService) === 'native') { this.restoreCachedMenubarData(); } @@ -416,7 +416,7 @@ export class Menubar { private shouldDrawMenu(menuId: string): boolean { // We need to draw an empty menu to override the electron default - if (!isMacintosh && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if (!isMacintosh && getTitleBarStyle(this.configurationService) === 'custom') { return false; } @@ -638,7 +638,7 @@ export class Menubar { private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): MenuItem; private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): MenuItem { const label = this.mnemonicLabel(arg1); - const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: MenuItem & IMenuItemWithKeybinding, win: BrowserWindow, event: Event) => { + const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: MenuItem & IMenuItemWithKeybinding, win: BrowserWindow, event: KeyboardEvent) => { const userSettingsLabel = menuItem ? menuItem.userSettingsLabel : null; let commandId = arg2; if (Array.isArray(arg2)) { diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index 934914f8aaa..e24efa83cf1 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -615,11 +615,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain const window = this.windowById(windowId); if (window) { const contents = window.win.webContents; - if (isMacintosh && window.hasHiddenTitleBarStyle && !window.isFullScreen && !contents.isDevToolsOpened()) { - contents.openDevTools({ mode: 'undocked' }); // due to https://github.com/electron/electron/issues/3647 - } else { - contents.toggleDevTools(); - } + contents.toggleDevTools(); } } diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts index ce1033b12d9..2e18cc8cd02 100644 --- a/src/vs/platform/update/electron-main/updateService.darwin.ts +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -56,7 +56,8 @@ export class DarwinUpdateService extends AbstractUpdateService { } protected buildUpdateFeedUrl(quality: string): string | undefined { - const url = createUpdateURL('darwin', quality); + const assetID = process.arch === 'x64' ? 'darwin' : 'darwin-arm64'; + const url = createUpdateURL(assetID, quality); try { electron.autoUpdater.setFeedURL({ url }); } catch (e) { diff --git a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts index a019d267e69..ce6233924b0 100644 --- a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts +++ b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts @@ -125,7 +125,10 @@ export class WebviewProtocolProvider extends Disposable { } } - private async handleWebviewRequest(request: Electron.Request, callback: any) { + private async handleWebviewRequest( + request: Electron.ProtocolRequest, + callback: (response: string | Electron.ProtocolResponse) => void + ) { try { const uri = URI.parse(request.url); const entry = WebviewProtocolProvider.validWebviewFilePaths.get(uri.path); @@ -144,8 +147,8 @@ export class WebviewProtocolProvider extends Disposable { } private async handleWebviewResourceRequest( - request: Electron.Request, - callback: (stream?: NodeJS.ReadableStream | Electron.StreamProtocolResponse | undefined) => void + request: Electron.ProtocolRequest, + callback: (stream: NodeJS.ReadableStream | Electron.ProtocolResponse) => void ) { try { const uri = URI.parse(request.url); @@ -220,14 +223,14 @@ export class WebviewProtocolProvider extends Disposable { if (result.type === WebviewResourceResponse.Type.AccessDenied) { console.error('Webview: Cannot load resource outside of protocol root'); - return callback({ data: null, statusCode: 401 }); + return callback({ data: undefined, statusCode: 401 }); } } } catch { // noop } - return callback({ data: null, statusCode: 404 }); + return callback({ data: undefined, statusCode: 404 }); } public didLoadResource(requestId: number, content: VSBuffer | undefined) { diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index 74b87a5c529..40c952136ec 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { isMacintosh, isLinux, isWeb, IProcessEnvironment } from 'vs/base/common/platform'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; @@ -85,8 +84,8 @@ export function isFileToOpen(uriToOpen: IWindowOpenable): uriToOpen is IFileToOp export type MenuBarVisibility = 'default' | 'visible' | 'toggle' | 'hidden' | 'compact'; -export function getMenuBarVisibility(configurationService: IConfigurationService, environment: IEnvironmentService, isExtensionDevelopment = environment.isExtensionDevelopment): MenuBarVisibility { - const titleBarStyle = getTitleBarStyle(configurationService, environment, isExtensionDevelopment); +export function getMenuBarVisibility(configurationService: IConfigurationService): MenuBarVisibility { + const titleBarStyle = getTitleBarStyle(configurationService); const menuBarVisibility = configurationService.getValue('window.menuBarVisibility'); if (titleBarStyle === 'native' && menuBarVisibility === 'compact') { @@ -119,18 +118,13 @@ export interface IWindowSettings { enableExperimentalProxyLoginDialog: boolean; } -export function getTitleBarStyle(configurationService: IConfigurationService, environment: IEnvironmentService, isExtensionDevelopment = environment.isExtensionDevelopment): 'native' | 'custom' { +export function getTitleBarStyle(configurationService: IConfigurationService): 'native' | 'custom' { if (isWeb) { return 'custom'; } const configuration = configurationService.getValue('window'); - const isDev = !environment.isBuilt || isExtensionDevelopment; - if (isMacintosh && isDev) { - return 'native'; // not enabled when developing due to https://github.com/electron/electron/issues/3647 - } - if (configuration) { const useNativeTabs = isMacintosh && configuration.nativeTabs === true; if (useNativeTabs) { diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 68640c8bcd3..cdd2cdfc3c9 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -21,7 +21,6 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { InEditorZenModeContext, IsCenteredLayoutContext, EditorAreaVisibleContext } from 'vs/workbench/common/editor'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { SideBarVisibleContext } from 'vs/workbench/common/viewlet'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IViewDescriptorService, IViewsService, FocusedViewContext, ViewContainerLocation, IViewDescriptor } from 'vs/workbench/common/views'; import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -419,14 +418,13 @@ export class ToggleMenuBarAction extends Action { constructor( id: string, label: string, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IEnvironmentService private readonly environmentService: IEnvironmentService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(id, label); } run(): Promise { - let currentVisibilityValue = getMenuBarVisibility(this.configurationService, this.environmentService); + let currentVisibilityValue = getMenuBarVisibility(this.configurationService); if (typeof currentVisibilityValue !== 'string') { currentVisibilityValue = 'default'; } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index af930f93da7..460594ee0d0 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -303,7 +303,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this._register(addDisposableListener(this.container, EventType.SCROLL, () => this.container.scrollTop = 0)); // Menubar visibility changes - if ((isWindows || isLinux || isWeb) && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if ((isWindows || isLinux || isWeb) && getTitleBarStyle(this.configurationService) === 'custom') { this._register(this.titleService.onMenubarVisibilityChange(visible => this.onMenubarToggled(visible))); } @@ -345,7 +345,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.workbenchGrid.edgeSnapping = this.state.fullscreen; // Changing fullscreen state of the window has an impact on custom title bar visibility, so we need to update - if (getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if (getTitleBarStyle(this.configurationService) === 'custom') { // Propagate to grid this.workbenchGrid.setViewVisible(this.titleBarPartView, this.isVisible(Parts.TITLEBAR_PART)); @@ -394,7 +394,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } // Menubar visibility - const newMenubarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService); + const newMenubarVisibility = getMenuBarVisibility(this.configurationService); this.setMenubarVisibility(newMenubarVisibility, !!skipLayout); // Centered Layout @@ -438,7 +438,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } private updateWindowBorder(skipLayout: boolean = false) { - if (isWeb || getTitleBarStyle(this.configurationService, this.environmentService) !== 'custom') { + if (isWeb || getTitleBarStyle(this.configurationService) !== 'custom') { return; } @@ -482,7 +482,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.state.fullscreen = isFullscreen(); // Menubar visibility - this.state.menuBar.visibility = getMenuBarVisibility(this.configurationService, this.environmentService); + this.state.menuBar.visibility = getMenuBarVisibility(this.configurationService); // Activity bar visibility this.state.activityBar.hidden = !this.configurationService.getValue(Settings.ACTIVITYBAR_VISIBLE); @@ -878,7 +878,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi isVisible(part: Parts): boolean { switch (part) { case Parts.TITLEBAR_PART: - if (getTitleBarStyle(this.configurationService, this.environmentService) === 'native') { + if (getTitleBarStyle(this.configurationService) === 'native') { return false; } else if (!this.state.fullscreen && !isWeb) { return true; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 4e53f75857b..6dbeb2dd61c 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -151,7 +151,7 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { const menu = disposables.add(this.menuService.createMenu(this.menuId, this.contextKeyService)); const actions = await this.resolveActions(menu, disposables); - const isUsingCustomMenu = isWeb || (getTitleBarStyle(this.configurationService, this.environmentService) !== 'native' && !isMacintosh); // see #40262 + const isUsingCustomMenu = isWeb || (getTitleBarStyle(this.configurationService) !== 'native' && !isMacintosh); // see #40262 const position = this.configurationService.getValue('workbench.sideBar.location'); this.contextMenuService.showContextMenu({ diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 937bbd30de5..dfdcf0323ec 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -176,7 +176,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } // Menu - const menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService); + const menuBarVisibility = getMenuBarVisibility(this.configurationService); if (menuBarVisibility === 'compact' || (menuBarVisibility === 'hidden' && isWeb)) { actions.push(this.instantiationService.createInstance(ToggleMenuBarAction, ToggleMenuBarAction.ID, menuBarVisibility === 'compact' ? nls.localize('hideMenu', "Hide Menu") : nls.localize('showMenu', "Show Menu"))); } @@ -265,7 +265,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Register for configuration changes this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('window.menuBarVisibility')) { - if (getMenuBarVisibility(this.configurationService, this.environmentService) === 'compact') { + if (getMenuBarVisibility(this.configurationService) === 'compact') { this.installMenubar(); } else { this.uninstallMenubar(); @@ -463,7 +463,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } // Install menubar if compact - if (getMenuBarVisibility(this.configurationService, this.environmentService) === 'compact') { + if (getMenuBarVisibility(this.configurationService) === 'compact') { this.installMenubar(); } diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 6bb23035468..139b4530057 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -249,7 +249,7 @@ export abstract class MenubarControl extends Disposable { } const hasBeenNotified = this.storageService.getBoolean('menubar/accessibleMenubarNotified', StorageScope.GLOBAL, false); - const usingCustomMenubar = getTitleBarStyle(this.configurationService, this.environmentService) === 'custom'; + const usingCustomMenubar = getTitleBarStyle(this.configurationService) === 'custom'; if (hasBeenNotified || usingCustomMenubar || !this.accessibilityService.isScreenReaderOptimized()) { return; @@ -484,7 +484,7 @@ export class CustomMenubarControl extends MenubarControl { } private get currentMenubarVisibility(): MenuBarVisibility { - return getMenuBarVisibility(this.configurationService, this.environmentService); + return getMenuBarVisibility(this.configurationService); } private get currentDisableMenuBarAltFocus(): boolean { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 2eae92ccf1f..4783cb52259 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -100,7 +100,7 @@ export class TitlebarPart extends Part implements ITitleService { this.contextMenu = this._register(menuService.createMenu(MenuId.TitleBarContext, contextKeyService)); - this.titleBarStyle = getTitleBarStyle(this.configurationService, this.environmentService); + this.titleBarStyle = getTitleBarStyle(this.configurationService); this.registerListeners(); } @@ -461,13 +461,13 @@ export class TitlebarPart extends Part implements ITitleService { } protected get currentMenubarVisibility(): MenuBarVisibility { - return getMenuBarVisibility(this.configurationService, this.environmentService); + return getMenuBarVisibility(this.configurationService); } updateLayout(dimension: Dimension): void { this.lastLayoutDimensions = dimension; - if (getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if (getTitleBarStyle(this.configurationService) === 'custom') { // Only prevent zooming behavior on macOS or when the menubar is not visible if ((!isWeb && isMacintosh) || this.currentMenubarVisibility === 'hidden') { this.title.style.zoom = `${1 / getZoomFactor()}`; diff --git a/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts index 89e21a71ff0..ea147a06b41 100644 --- a/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts @@ -218,7 +218,7 @@ export class TitlebarPart extends BrowserTitleBarPart { updateLayout(dimension: DOM.Dimension): void { this.lastLayoutDimensions = dimension; - if (getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if (getTitleBarStyle(this.configurationService) === 'custom') { // Only prevent zooming behavior on macOS or when the menubar is not visible if (isMacintosh || this.currentMenubarVisibility === 'hidden') { this.title.style.zoom = `${1 / getZoomFactor()}`; diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index cd990d2a6b6..37afcaaf5a9 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -300,7 +300,7 @@ export class NativeWindow extends Disposable { } // Maximize/Restore on doubleclick (for macOS custom title) - if (isMacintosh && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { + if (isMacintosh && getTitleBarStyle(this.configurationService) === 'custom') { const titlePart = assertIsDefined(this.layoutService.getContainer(Parts.TITLEBAR_PART)); this._register(DOM.addDisposableListener(titlePart, DOM.EventType.DBLCLICK, e => { @@ -416,7 +416,7 @@ export class NativeWindow extends Disposable { this.customTitleContextMenuDisposable.clear(); // Provide new menu if a file is opened and we are on a custom title - if (!filePath || getTitleBarStyle(this.configurationService, this.environmentService) !== 'custom') { + if (!filePath || getTitleBarStyle(this.configurationService) !== 'custom') { return; } @@ -448,7 +448,7 @@ export class NativeWindow extends Disposable { private create(): void { // Native menu controller - if (isMacintosh || getTitleBarStyle(this.configurationService, this.environmentService) === 'native') { + if (isMacintosh || getTitleBarStyle(this.configurationService) === 'native') { this._register(this.instantiationService.createInstance(NativeMenubarControl)); } diff --git a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts index a2005fe6954..09a3e187bda 100644 --- a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts +++ b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts @@ -44,7 +44,7 @@ export class ContextMenuService extends Disposable implements IContextMenuServic super(); // Custom context menu: Linux/Windows if custom title is enabled - if (!isMacintosh && getTitleBarStyle(configurationService, environmentService) === 'custom') { + if (!isMacintosh && getTitleBarStyle(configurationService) === 'custom') { this.impl = new HTMLContextMenuService(telemetryService, notificationService, contextViewService, keybindingService, themeService); } diff --git a/src/vs/workbench/services/extensions/node/proxyResolver.ts b/src/vs/workbench/services/extensions/node/proxyResolver.ts index 3050bc6e2d6..80177b1fad9 100644 --- a/src/vs/workbench/services/extensions/node/proxyResolver.ts +++ b/src/vs/workbench/services/extensions/node/proxyResolver.ts @@ -498,7 +498,7 @@ async function readWindowsCaCertificates() { const winCA = await import('vscode-windows-ca-certs'); let ders: any[] = []; - const store = winCA(); + const store = new winCA.Crypt32(); try { let der: any; while (der = store.next()) { diff --git a/yarn.lock b/yarn.lock index a3f05fe9cb8..44086114c87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -160,6 +160,13 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== +"@malept/cross-spawn-promise@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.0.tgz#258fde4098f5004a56db67c35f33033af64810f6" + integrity sha512-GeIK5rfU1Yd7BZJQPTGZMMmcZy5nhRToPXZcjaDwQDRSewdhp648GT2E4dh+L7+Io7AOW6WQ+GR44QSzja4qxg== + dependencies: + cross-spawn "^7.0.1" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -186,6 +193,11 @@ dependencies: chokidar "*" +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/commander@^2.11.0": version "2.12.2" resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae" @@ -696,6 +708,16 @@ ajv@^6.10.0, ajv@^6.10.2: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.3: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^6.5.3, ajv@^6.6.1: version "6.8.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.8.1.tgz#0890b93742985ebf8973cd365c5b23920ce3cb20" @@ -805,6 +827,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -1104,6 +1134,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" @@ -1605,6 +1640,14 @@ chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1720,6 +1763,11 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + chrome-remote-interface@0.26.1: version "0.26.1" resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.26.1.tgz#6c7d4479742b6d236752d716a9bc2d322d7d8ad2" @@ -1789,6 +1837,11 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-spinners@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1812,6 +1865,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3" + integrity sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -1908,11 +1970,23 @@ color-convert@^1.3.0, color-convert@^1.9.0: dependencies: color-name "^1.1.1" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@^1.0.0, color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-string@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" @@ -1948,6 +2022,11 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.1.tgz#f4a3d302976aaf042356ba1ade3b1a2c62d9d794" integrity sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg== +colors@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -2209,6 +2288,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -2474,6 +2562,13 @@ default-resolution@^2.0.0: resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + defer-to-connect@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.1.tgz#88ae694b93f67b81815a2c8c769aef6574ac8f2f" @@ -2742,15 +2837,30 @@ editorconfig@^0.15.2: semver "^5.6.0" sigmund "^1.0.1" +electron-rebuild@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/electron-rebuild/-/electron-rebuild-2.0.3.tgz#fbcf34d35bf6795a0ded39bfe2aee24526a152c8" + integrity sha512-I8Oeey9afU+trFLd8/qRRiHC083CCoBnmw3q0qQaRFsg0OzMaeJQn7Nl6EYKPpntuQ/3yOqZQ7b3ObNuETN/Ig== + dependencies: + "@malept/cross-spawn-promise" "^1.1.0" + colors "^1.3.3" + debug "^4.1.1" + detect-libc "^1.0.3" + fs-extra "^9.0.1" + node-abi "^2.19.1" + node-gyp "^7.1.0" + ora "^5.1.0" + yargs "^16.0.0" + electron-to-chromium@^1.2.7: version "1.3.27" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@9.3.3: - version "9.3.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.3.tgz#99a6619d5df68f97697a5d1d82ef3a8a63fcdf36" - integrity sha512-xghKeUY1qgnEcJ5w2rXo/toH+8NT2Dktx2aAxBNPV7CIJr3mejJJAPwLbycwtddzr37tgKxHeHlc8ivfKtMkJQ== +electron@11.0.2: + version "11.0.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.0.2.tgz#c7bd2b9abdc1446f4578dbfa22573014b6b2df58" + integrity sha512-FTYtCm0oj8B8EJhp99BQSW2bd40xYEG/txMj+W3Ed0CNu5zVIIXb5WIrhXLvhcasN5LKy9nkmSZ+u220lCaARg== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -2916,6 +3026,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" +escalade@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== + escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" @@ -3359,6 +3474,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -3688,6 +3808,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -3695,6 +3825,13 @@ fs-minipass@^1.2.5: dependencies: minipass "^2.2.1" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -3780,7 +3917,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U= -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -4094,7 +4231,7 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= -graceful-fs@^4.1.15: +graceful-fs@^4.1.15, graceful-fs@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -4380,6 +4517,14 @@ har-validator@~5.1.0: ajv "^5.3.0" har-schema "^2.0.0" +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -4976,6 +5121,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -5383,6 +5533,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -5648,6 +5807,13 @@ lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + lolex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" @@ -6011,6 +6177,13 @@ minipass@^2.2.1, minipass@^2.3.3: safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + dependencies: + yallist "^4.0.0" + minizlib@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" @@ -6018,6 +6191,14 @@ minizlib@^1.1.0: dependencies: minipass "^2.2.1" +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mississippi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" @@ -6082,6 +6263,11 @@ mkdirp@^0.5.3: dependencies: minimist "^1.2.5" +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mocha-junit-reporter@^1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz#2e5149ed40fc5d2e3ca71e42db5ab1fec9c6d85c" @@ -6161,7 +6347,12 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.10.0, nan@^2.13.2, nan@^2.14.0: +nan@^2.10.0: + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== + +nan@^2.13.2, nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -6237,23 +6428,34 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== -node-abi@^2.7.0: +node-abi@^2.19.1, node-abi@^2.7.0: version "2.19.3" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d" integrity sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg== dependencies: semver "^5.4.1" -node-addon-api@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" - integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== - -node-addon-api@^3.0.0: +node-addon-api@^3.0.0, node-addon-api@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== +node-gyp@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.0.tgz#cb8aed7ab772e73ad592ae0c71b0e3741099fe39" + integrity sha512-rjlHQlnl1dqiDZxZYiKqQdrjias7V+81OVR5PTzZioCBtWkNdrKy06M05HLKxy/pcKikKRCabeDRoZaEc6nIjw== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.3" + nopt "^4.0.3" + npmlog "^4.1.2" + request "^2.88.2" + rimraf "^2.6.3" + semver "^7.3.2" + tar "^6.0.1" + which "^2.0.2" + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -6299,10 +6501,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-pty@0.10.0-beta17: - version "0.10.0-beta17" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" - integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== +node-pty@0.10.0-beta18: + version "0.10.0-beta18" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta18.tgz#7ed2d3f4a06b2b23fe2abdf5b41655e9dffc25d5" + integrity sha512-vpK4yB3A3VzgkvdOWegL7GcPapt45jfA4b3ejUe8k4RmqdWBRvFJngew8T3qAxmLhTkfo93psaN6izTlfkc6FA== dependencies: nan "^2.14.0" @@ -6327,6 +6529,14 @@ nopt@^4.0.1, nopt@~4.0.1: abbrev "1" osenv "^0.1.4" +nopt@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" @@ -6414,7 +6624,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.1, npmlog@^4.0.2: +npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -6610,6 +6820,20 @@ optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" +ora@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.1.0.tgz#b188cf8cd2d4d9b13fd25383bc3e5cba352c94f8" + integrity sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w== + dependencies: + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.4.0" + is-interactive "^1.0.0" + log-symbols "^4.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + ordered-read-streams@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" @@ -6886,6 +7110,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -7464,6 +7693,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + public-encrypt@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" @@ -7518,7 +7752,7 @@ punycode@^1.2.4, punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -7934,6 +8168,32 @@ request@^2.86.0, request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + requestretry@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/requestretry/-/requestretry-4.0.0.tgz#4e9e7280a7d8561bf33e9925264cf026e2be3e89" @@ -8316,11 +8576,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shimmer@^1.1.0, shimmer@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" @@ -8712,7 +8984,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: +string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -8983,6 +9255,18 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +tar@^6.0.1: + version "6.0.5" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" + integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + tas-client-umd@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.2.tgz#fe93ae085f65424292ac79feff4f1add3e50e624" @@ -9190,6 +9474,14 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -9402,6 +9694,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -9765,12 +10062,12 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-windows-ca-certs@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.2.0.tgz#086f0f4de57e2760a35ac6920831bff246237115" - integrity sha512-YBrJRT0zos+Yb1Qdn73GD8QZr7pa2IE96b5Y1hmmp6XeR8aYB7Iiq5gDAF/+/AxL+caSR9KPZQ6jiYWh5biD7w== +vscode-windows-ca-certs@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.3.0.tgz#324e1f8ba842bbf048a39e7c0ee8fe655e9adfcc" + integrity sha512-CYrpCEKmAFQJoZNReOrelNL+VKyebOVRCqL9evrBlVcpWQDliliJgU5RggGS8FPGtQ3jAKLQt9frF0qlxYYPKA== dependencies: - node-addon-api "1.6.2" + node-addon-api "^3.0.2" vscode-windows-registry@1.0.3: version "1.0.3" @@ -9805,6 +10102,13 @@ watchpack@^1.6.1: chokidar "^3.4.0" watchpack-chokidar2 "^2.0.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + webpack-cli@^3.3.12: version "3.3.12" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" @@ -9913,6 +10217,13 @@ which@^1.2.9: dependencies: isexe "^2.0.0" +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -9979,6 +10290,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -10101,6 +10421,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.1.tgz#1ad2a7eddfa8bce7caa2e1f6b5da96c39d99d571" + integrity sha512-/jJ831jEs4vGDbYPQp4yGKDYPSCCEQ45uZWJHE1AoYBzqdZi8+LDWas0z4HrmJXmKdpFsTiowSHXdxyFhpmdMg== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -10111,6 +10436,11 @@ yallist@^3.0.0, yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= +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== + yargs-parser@^13.1.0: version "13.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" @@ -10127,6 +10457,11 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.0.0: + version "20.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.0.0.tgz#c65a1daaa977ad63cebdd52159147b789a4e19a9" + integrity sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA== + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -10167,6 +10502,19 @@ yargs@^13.3.0, yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" +yargs@^16.0.0: + version "16.0.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c" + integrity sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA== + dependencies: + cliui "^7.0.0" + escalade "^3.0.2" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.1" + yargs-parser "^20.0.0" + yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From e66547a1d9f880747de81310764cf809639e462b Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 23 Nov 2020 15:30:43 -0800 Subject: [PATCH 0162/1837] ensure the editor has enough top padding when there is decoration ::after: { top } --- .../services/abstractCodeEditorService.ts | 3 ++ .../browser/services/codeEditorService.ts | 2 + .../browser/services/codeEditorServiceImpl.ts | 30 ++++++++++++- .../contrib/notebook/browser/constants.ts | 2 +- .../notebook/browser/diff/cellComponents.ts | 9 ++-- .../notebook/browser/notebookBrowser.ts | 16 ++++++- .../notebook/browser/notebookServiceImpl.ts | 45 ++++++++++++++++++- .../browser/view/renderers/cellRenderer.ts | 13 ++++-- .../browser/view/renderers/codeCell.ts | 6 +-- .../browser/view/renderers/markdownCell.ts | 6 +-- .../browser/viewModel/baseCellViewModel.ts | 8 ++-- .../browser/viewModel/codeCellViewModel.ts | 6 +-- 12 files changed, 119 insertions(+), 27 deletions(-) diff --git a/src/vs/editor/browser/services/abstractCodeEditorService.ts b/src/vs/editor/browser/services/abstractCodeEditorService.ts index f48a9cff839..3ebb6454bb8 100644 --- a/src/vs/editor/browser/services/abstractCodeEditorService.ts +++ b/src/vs/editor/browser/services/abstractCodeEditorService.ts @@ -31,6 +31,8 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC private readonly _onDidChangeTransientModelProperty: Emitter = this._register(new Emitter()); public readonly onDidChangeTransientModelProperty: Event = this._onDidChangeTransientModelProperty.event; + protected readonly _onDecorationTypeRegistered: Emitter = this._register(new Emitter()); + public onDecorationTypeRegistered: Event = this._onDecorationTypeRegistered.event; private readonly _codeEditors: { [editorId: string]: ICodeEditor; }; private readonly _diffEditors: { [editorId: string]: IDiffEditor; }; @@ -93,6 +95,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC abstract registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string, editor?: ICodeEditor): void; abstract removeDecorationType(key: string): void; abstract resolveDecorationOptions(decorationTypeKey: string | undefined, writable: boolean): IModelDecorationOptions; + abstract resolveDecorationCSSRules(decorationTypeKey: string): CSSRuleList | null; private readonly _transientWatchers: { [uri: string]: ModelTransientSettingWatcher; } = {}; private readonly _modelProperties = new Map>(); diff --git a/src/vs/editor/browser/services/codeEditorService.ts b/src/vs/editor/browser/services/codeEditorService.ts index 0174886d201..8665de00275 100644 --- a/src/vs/editor/browser/services/codeEditorService.ts +++ b/src/vs/editor/browser/services/codeEditorService.ts @@ -23,6 +23,7 @@ export interface ICodeEditorService { readonly onDiffEditorRemove: Event; readonly onDidChangeTransientModelProperty: Event; + readonly onDecorationTypeRegistered: Event; addCodeEditor(editor: ICodeEditor): void; @@ -41,6 +42,7 @@ export interface ICodeEditorService { registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string, editor?: ICodeEditor): void; removeDecorationType(key: string): void; resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions; + resolveDecorationCSSRules(decorationTypeKey: string): CSSRuleList | null; setModelProperty(resource: URI, key: string, value: any): void; getModelProperty(resource: URI, key: string): any; diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index 464c1a33d41..c961bfd7956 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -21,6 +21,10 @@ export class RefCountedStyleSheet { private readonly _styleSheet: HTMLStyleElement; private _refCount: number; + public get sheet() { + return this._styleSheet.sheet as CSSStyleSheet; + } + constructor(parent: CodeEditorServiceImpl, editorId: string, styleSheet: HTMLStyleElement) { this._parent = parent; this._editorId = editorId; @@ -53,6 +57,10 @@ export class RefCountedStyleSheet { export class GlobalStyleSheet { private readonly _styleSheet: HTMLStyleElement; + public get sheet() { + return this._styleSheet.sheet as CSSStyleSheet; + } + constructor(styleSheet: HTMLStyleElement) { this._styleSheet = styleSheet; } @@ -129,6 +137,7 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { provider = new DecorationSubTypeOptionsProvider(this._themeService, styleSheet, providerArgs); } this._decorationOptionProviders.set(key, provider); + this._onDecorationTypeRegistered.fire(key); } provider.refCount++; } @@ -153,6 +162,14 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { return provider.getOptions(this, writable); } + public resolveDecorationCSSRules(decorationTypeKey: string) { + const provider = this._decorationOptionProviders.get(decorationTypeKey); + if (!provider) { + return null; + } + return provider.resolveDecorationCSSRules(); + } + abstract getActiveCodeEditor(): ICodeEditor | null; abstract openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise; } @@ -160,9 +177,10 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { interface IModelDecorationOptionsProvider extends IDisposable { refCount: number; getOptions(codeEditorService: AbstractCodeEditorService, writable: boolean): IModelDecorationOptions; + resolveDecorationCSSRules(): CSSRuleList; } -class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvider { +export class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvider { private readonly _styleSheet: GlobalStyleSheet | RefCountedStyleSheet; public refCount: number; @@ -192,6 +210,10 @@ class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvide return options; } + public resolveDecorationCSSRules(): CSSRuleList { + return this._styleSheet.sheet.cssRules; + } + public dispose(): void { if (this._beforeContentRules) { this._beforeContentRules.dispose(); @@ -213,7 +235,7 @@ interface ProviderArguments { } -class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { +export class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { private readonly _disposables = new DisposableStore(); private readonly _styleSheet: GlobalStyleSheet | RefCountedStyleSheet; @@ -295,6 +317,10 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { }; } + public resolveDecorationCSSRules(): CSSRuleList { + return this._styleSheet.sheet.rules; + } + public dispose(): void { this._disposables.dispose(); this._styleSheet.unref(); diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 245f72a8786..3232b04744f 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -22,7 +22,7 @@ export const CELL_TOP_MARGIN = 6; export const CELL_BOTTOM_MARGIN = 6; // Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight` -export const EDITOR_TOP_PADDING = 12; +// export const EDITOR_TOP_PADDING = 12; export const EDITOR_BOTTOM_PADDING = 4; export const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 098838e7112..f18929bbd0e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -9,7 +9,7 @@ import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/edit import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffViewModel, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { CellDiffRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { renderCodicons } from 'vs/base/browser/codicons'; @@ -28,6 +28,7 @@ import { IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; +import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; const fixedEditorOptions: IEditorOptions = { padding: { @@ -758,7 +759,7 @@ export class DeletedCell extends AbstractCellRenderer { const originalCell = this.cell.original!; const lineCount = originalCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); @@ -858,7 +859,7 @@ export class InsertCell extends AbstractCellRenderer { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); this._editor = this.instantiationService.createInstance(CodeEditorWidget, editorContainer, { @@ -962,7 +963,7 @@ export class ModifiedCell extends AbstractCellRenderer { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; this._editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container')); this._editor = this.instantiationService.createInstance(DiffEditorWidget, this._editorContainer, { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 5db3402f081..0a135c6fed9 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -8,7 +8,7 @@ import { IListContextMenuEvent, IListEvent, IListMouseEvent } from 'vs/base/brow import { IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { ScrollEvent } from 'vs/base/common/scrollable'; import { URI } from 'vs/base/common/uri'; @@ -720,3 +720,17 @@ export function getActiveNotebookEditor(editorService: IEditorService): INoteboo const activeEditorPane = editorService.activeEditorPane as unknown as { isNotebookEditor?: boolean } | undefined; return activeEditorPane?.isNotebookEditor ? (editorService.activeEditorPane?.getControl() as INotebookEditor) : undefined; } + +let EDITOR_TOP_PADDING = 12; +const editorTopPaddingChangeEmitter = new Emitter(); + +export const EditorTopPaddingChangeEvent = editorTopPaddingChangeEmitter.event; + +export function updateEditorTopPadding(top: number) { + EDITOR_TOP_PADDING = top; + editorTopPaddingChangeEmitter.fire(); +} + +export function getEditorTopPadding() { + return EDITOR_TOP_PADDING; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 8179b4ed84d..c2c20888e16 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { getZoomLevel } from 'vs/base/browser/browser'; import { flatten } from 'vs/base/common/arrays'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Emitter, Event } from 'vs/base/common/event'; @@ -13,6 +14,9 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/clipboard'; import * as nls from 'vs/nls'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @@ -23,7 +27,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol'; import { Memento } from 'vs/workbench/common/memento'; import { INotebookEditorContribution, notebookProviderExtensionPoint, notebookRendererExtensionPoint } from 'vs/workbench/contrib/notebook/browser/extensionPoint'; -import { CellEditState, getActiveNotebookEditor, INotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, getActiveNotebookEditor, INotebookEditor, NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRegistry, updateNotebookKernelProvideAssociationSchema } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; @@ -276,7 +280,9 @@ export class NotebookService extends Disposable implements INotebookService, ICu @IConfigurationService private readonly _configurationService: IConfigurationService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IStorageService private readonly _storageService: IStorageService, - @IInstantiationService private readonly _instantiationService: IInstantiationService + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ICodeEditorService private readonly _codeEditorService: ICodeEditorService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(); @@ -336,6 +342,41 @@ export class NotebookService extends Disposable implements INotebookService, ICu updateOrder(); })); + let decorationTriggeredAdjustment = false; + let decorationCheckSet = new Set(); + this._register(this._codeEditorService.onDecorationTypeRegistered(e => { + if (decorationTriggeredAdjustment) { + return; + } + + if (decorationCheckSet.has(e)) { + return; + } + + const options = this._codeEditorService.resolveDecorationOptions(e, true); + if (options.afterContentClassName || options.beforeContentClassName) { + const cssRules = this._codeEditorService.resolveDecorationCSSRules(e); + if (cssRules !== null) { + for (let i = 0; i < cssRules.length; i++) { + // The following ways to index into the list are equivalent + if ( + ((cssRules[i] as CSSStyleRule).selectorText.endsWith('::after') || (cssRules[i] as CSSStyleRule).selectorText.endsWith('::after')) + && (cssRules[i] as CSSStyleRule).cssText.indexOf('top:') > -1 + ) { + // there is a `::before` or `::after` text decoration whose position is above or below current line + // we at least make sure that the editor top padding is at least one line + const editorOptions = this.configurationService.getValue('editor'); + updateEditorTopPadding(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel()).lineHeight + 2); + decorationTriggeredAdjustment = true; + break; + } + } + } + } + + decorationCheckSet.add(e); + })); + const getContext = () => { const editor = getActiveNotebookEditor(this._editorService); const activeCell = editor?.getActiveCell(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 62aa3a4f1ab..9c54b9cbd8c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -35,9 +35,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { BOTTOM_CELL_TOOLBAR_GAP, CELL_BOTTOM_MARGIN, CELL_TOP_MARGIN, EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { BOTTOM_CELL_TOOLBAR_GAP, CELL_BOTTOM_MARGIN, CELL_TOP_MARGIN, EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { CancelCellAction, DeleteCellAction, ExecuteCellAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; -import { BaseCellRenderTemplate, CellEditState, CodeCellRenderTemplate, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CodeCellRenderTemplate, EditorTopPaddingChangeEvent, EXPAND_CELL_CONTENT_COMMAND_ID, getEditorTopPadding, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys'; import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; @@ -117,10 +117,16 @@ export class CellEditorOptions { } }); + EditorTopPaddingChangeEvent(() => { + this._value = computeEditorOptions(); + this._onDidChange.fire(this.value); + + }); + const computeEditorOptions = () => { const showCellStatusBar = configurationService.getValue(ShowCellStatusBarKey); const editorPadding = { - top: EDITOR_TOP_PADDING, + top: getEditorTopPadding(), bottom: showCellStatusBar ? EDITOR_BOTTOM_PADDING : EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR }; @@ -717,7 +723,6 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende }, {}); disposables.add(this.editorOptions.onDidChange(newValue => editor.updateOptions(newValue))); - const { collapsedPart, expandButton } = this.setupCollapsedPart(container); const progressBar = new ProgressBar(editorPart); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index d876198e3fe..f86890dedba 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -11,8 +11,8 @@ import { IDimension } from 'vs/editor/common/editorCommon'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -46,7 +46,7 @@ export class CodeCell extends Disposable { const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; const editorHeight = this.viewCell.layoutInfo.editorHeight === 0 - ? lineNum * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + ? lineNum * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING : this.viewCell.layoutInfo.editorHeight; this.layoutEditor( diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index bbdf6f99ec0..cd949babf5b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -11,8 +11,8 @@ import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, INotebookEditor, MarkdownCellRenderTemplate, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellEditState, CellFocusMode, INotebookEditor, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellFoldingState } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -214,7 +214,7 @@ export class StatefulMarkdownCell extends Disposable { const width = this.viewCell.layoutInfo.editorWidth; const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; - editorHeight = Math.max(lineNum, 1) * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + editorHeight = Math.max(lineNum, 1) * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; this.templateData.editorContainer.innerText = ''; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index d49dc929cb0..3d4b3b4e522 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -12,8 +12,8 @@ import { IPosition } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; -import { CELL_STATUSBAR_HEIGHT, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CELL_STATUSBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, NotebookCellMetadata, NotebookDocumentMetadata, INotebookSearchOptions, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -341,7 +341,7 @@ export abstract class BaseCellViewModel extends Disposable { return 0; } - return this._textEditor.getTopForLineNumber(line) + EDITOR_TOP_PADDING; + return this._textEditor.getTopForLineNumber(line) + getEditorTopPadding(); } getPositionScrollTopOffset(line: number, column: number): number { @@ -349,7 +349,7 @@ export abstract class BaseCellViewModel extends Disposable { return 0; } - return this._textEditor.getTopForPosition(line, column) + EDITOR_TOP_PADDING; + return this._textEditor.getTopForPosition(line, column) + getEditorTopPadding(); } cursorAtBeginEnd(): boolean { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index eee92f542e5..0760fbf4d82 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -9,8 +9,8 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { CellKind, INotebookSearchOptions, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -221,7 +221,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private estimateEditorHeight(lineHeight: number | undefined = 20): number { - return this.lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + return this.lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; } private computeTotalHeight(editorHeight: number, outputsTotalHeight: number, outputShowMoreContainerHeight: number): number { From 0b7158b1900484686e55ef287e9a53a6e0714213 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 23 Nov 2020 15:36:31 -0800 Subject: [PATCH 0163/1837] :lipstick: --- src/vs/editor/test/browser/editorTestServices.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/test/browser/editorTestServices.ts b/src/vs/editor/test/browser/editorTestServices.ts index e9fba5fbb91..55ceb3734a2 100644 --- a/src/vs/editor/test/browser/editorTestServices.ts +++ b/src/vs/editor/test/browser/editorTestServices.ts @@ -22,6 +22,7 @@ export class TestCodeEditorService extends AbstractCodeEditorService { public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void { } public removeDecorationType(key: string): void { } public resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions { return {}; } + public resolveDecorationCSSRules(decorationTypeKey: string): CSSRuleList | null { return null; } } export class TestCommandService implements ICommandService { From 9ce365f085ab8c2d5584ddd20cb4e1a8dbc8a02c Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 23 Nov 2020 15:43:31 -0800 Subject: [PATCH 0164/1837] chore: bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8f4da9ccd1..37c7917ca23 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "2c1e3052a2a83d9f37ebad5aaaf49401c19231d9", + "distro": "645d71eca7b3cb5addb7e2251dd11a1af5f5fbc5", "author": { "name": "Microsoft Corporation" }, From c3e1f0e02a15060689e7fed196f025e265841cfe Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 23 Nov 2020 16:25:32 -0800 Subject: [PATCH 0165/1837] re #102503. allow open notebook on the side. --- .../browser/parts/editor/editorCommands.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 5d9e68ebc39..36b37447e55 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -487,8 +487,20 @@ function registerOpenEditorAPICommands(): void { const quickInputService = accessor.get(IQuickInputService); const [resource, id, optionsArg, columnArg] = payload; + let group: IEditorGroup | undefined = undefined; + + if (columnArg === SIDE_GROUP) { + const direction = preferredSideBySideGroupDirection(configurationService); + + let neighbourGroup = editorGroupsService.findGroup({ direction }); + if (!neighbourGroup) { + neighbourGroup = editorGroupsService.addGroup(editorGroupsService.activeGroup, direction); + } + group = neighbourGroup; + } else { + group = editorGroupsService.getGroup(viewColumnToEditorGroup(editorGroupsService, columnArg)) ?? editorGroupsService.activeGroup; + } - const group = editorGroupsService.getGroup(viewColumnToEditorGroup(editorGroupsService, columnArg)) ?? editorGroupsService.activeGroup; const textOptions: ITextEditorOptions = optionsArg ? { ...optionsArg, override: false } : { override: false }; const input = editorService.createEditorInput({ resource: URI.revive(resource) }); From abf396492174cb4e6e653d94699483eb3a6896af Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 23 Nov 2020 16:38:59 -0800 Subject: [PATCH 0166/1837] Updating Codicons: Add 'pass-filled' https://github.com/microsoft/vscode-codicons/ --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 62324 -> 62456 bytes src/vs/base/common/codicons.ts | 1 + 2 files changed, 1 insertion(+) diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 4c16209d6a9203bb2b9f9b2e160fc20e947e7f36..17d60f4fd13ad9b723431d50efc243ebeec378a7 100644 GIT binary patch delta 2667 zcmYM$3s6+&83y3@-Q|8!6ciz9FsLL1@d5!{ma7QJO+aoU7mz z{on5#?_PIK+;ARD^y~t706;@$f5*_h-R&hn@GKzu^v1sDdcJ?S@E5?GZNU4pdb>Ni z;xANBk>CAHWc11l!IuJ;%Kp1zesBM_;V63syaoiO_YHP-guRx#6NtYII9~1V7#?!; z;#YEBu8)L)j{fd>Z^joqFV~X~;0PNU+`26OoNdsyk6%eU$CU0_k*OO60$Mc?*8*#T6!Fl)*T~aAa^L z9x#AT^dSi!V*`%hEu``(G-3*iupM2vA^+ZA;xyCXg$Mh&h%?c{Bu?dA&Sn%J=R(e7 zJPvRM6MeUX6Y2R4ev9AX_xK1GaS5042YiB0@hADx|BNyG1=sLbT*v450tPoRj=$kH z{*F8N2kzoa{1X%S7w+TVctntNFpxnEVJO2G!AMTybVf6Vv7E&?KE^pr;1itBr{YUG@NZH$CAnG2V#5Cw zg$&6)B?}CHKQPyB@IVd*6ayp&6`kHM!xQn)h79 zV$UM^UHf5$Gywi@DcBFZPccbyzv5KM?TqyaH;yg(& zkZdc_~Or2$Q0ujxh51Eh#2Us*;MrELKuhm?cVT3nO<0 zO9~9LOi7ht(v*}MCS6IrVV+S^bQoCxkKIV;VKNmylgv^w2QbT(OazQe$!x%6E141) zw~~2*$x$*nFu6)*2qsU-G{NL6nJW)WfgA`KF_=On!v?cL$=JaZDH%W*sfs0|2ve+N zC}B#Jj3-Q~l0k)8rDSAb%9IQ*Ou6Ne3r)yQg_4PesZ=uCFjY#X9Hv^~kz|dcyxr6) z%7Iy)$5_(qPlCXj?p>Xq!8zXq!8vD5W)DRm_y!qG*e|RnZoAo1!i2 z*A#78w=3qz`kQAJZCi&G^CX{B%$MAuXbbvvMO)CFinfT~P_#wdrD%(2|AwF~;%-G- z#OK8{+0Zs|kCOZR-dQhjfj2Df1-iT=aV2s0DxW$&&%*rwaBPdQ-8$+Z?}!SG_0VVPOY%#GOMX_GP})^` zY?XV}@v`Ky?PU+jbIW&^->k^0I9YL};-RN1s;a7LbJgLhiPf`L*RFoGy0&^}^?Nlz zHK{clYWCNhsU4{uUE^3&RTov~t{bfntKU<9qW)&XP{WCaiN@T=*EQ#jp-u z%8Zr&2;6}WX+X@0MRBSt*MO|T+|Mw zHlxyGDZ@Xt6cuRy5SE!b8K!004pO8xZBwD8P?{p@eoAkssix5P=qm0^Lcz zPZ00=!2XWQ$0x7+Kkt0*`q=fMoW~)`J}W=+8Ty_1Ji(LUaaP1Qv)yScQ}135E-zen zALU4Tfap|2M_rQ-CEmS2Y-C?#H1byDSEj+7bh_LtLm%No?8Rk%32!qNWAtD(EARzf zj6xq4V**=n5N}{9A4Dq>S&k>rgB$Y4{tRch0uDlWo;jR}?Rv#|E;{!xs@G)-U@AwD)iGShW_ynKgGfd$>_#C%!haefv7`hq98H}fw$xLA? z(|9juaW>PL!TY#?SeVSj8i&WZ>7bzOhcOXWA+8xRbng$&+5O$Ghw9i_Z#v1Vpwf zSw2Lh#g;52BHI)$OKw-PxQOgfcw4ep$$}&DsKS`!V~QT`?E@P*_~MVI7& zVw5u-pT!9$(_6>~oepmn%bh)Pyx|=2F5?Pk!n-UXN8W3{ncz$(Ibl}l0XchKQKl&J zZAF>Th)k@-xsop`CP}`eIA3zV;v&iKC}v7JN{WZb%L?{--&K_9j~oDE?Sc1)f1GeJ zR=Nk1qojo}4=L#*%u*%IgjuGfqcE~FSkhLQTqV7QS)ruCFe{aG8D^D|R>M53q~9>B zfsj2&)nV2sDLqV{vfGi#S274NvSnE^5-^2Ih6Bc@WK3YzDj67&p4N8U^rcue5!!#+}k=&qUUxeAHC?}>_FlD&#cBxSHI+Cs}z&cr&vBuXJm)#) zJ1@_v4&9PhzOQ5phj~TGW)AZMCEGg8VI>i&P%?kWc!DCP05V_=5-~v z1el`=_WyKDb}M^eiL*I<Fq)Cnaw3Ye41-ZH|M(!a;h>HN(6;rvev`~{~9&K2A) ztSQ`Ac%*QmaLPC0JF~WV?U|zNqJu>jic5<36dx^#E6Fa&EA^J{D}AFZuWYnDwtT4k zor>&=u8Knyw<~)q$E!S5tEyV64pd#QPOPq~{zmo9niVy}wVv8twNrH!b?587^$qo7 z{#gHB|8f6?byq_T84Y<2Jq>3YBI`5PKh~JpSl2k(IMF!Ww7e_1H)d?S z+U#jQ)O=}E;7r?waxA~gWjM_Yj|khtApX) ZFZi12506bAj0!iuw|GYQn>Pny{s)EfwABCr diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 3c4fffd3b5c..5f192ee2b93 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -484,6 +484,7 @@ export namespace Codicon { export const redo = new Codicon('redo', { character: '\\ebb0' }); export const checkAll = new Codicon('check-all', { character: '\\ebb1' }); export const pinnedDirty = new Codicon('pinned-dirty', { character: '\\ebb2' }); + export const passFilled = new Codicon('pass-filled', { character: '\\ebb3' }); } From 4aae8510635946fa5fa273f6dc224ad5a3e16b20 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 23 Nov 2020 19:41:37 -0800 Subject: [PATCH 0167/1837] Update Codicons: Add 'circle-large-outline' and 'circle-large-filled' https://github.com/microsoft/vscode-codicons/commit/7ddcbfb5f46e97691028f19b475d9183f43ac245 --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 62456 -> 62836 bytes src/vs/base/common/codicons.ts | 2 ++ 2 files changed, 2 insertions(+) diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 17d60f4fd13ad9b723431d50efc243ebeec378a7..7b9d1812e32e9543c5b16ce115e96ed34453f264 100644 GIT binary patch delta 5595 zcmZA533yf25eM-9yo3ak5MK6$?7?hg-^fM?0TPywge?RULly!71Br-$h&)6@#T3z4 zYN=AH6cMeZg0{65Eu~s5QcBfYq*f6T&nZf&B1MJ%FVlXl<@n}x1UUr^sp#$N>R6QjNCgo672w*jq+?aTYcXEt-y`{; zgryxzx)Y!9jJq9p{{$c4*WY*3@|Al&ZUH_x0|ae?0A4%-yi^X$T> z_#5uVyON0`at&UPVJMMWToxZ0f~82spD-WW@C;oGI2eA3N{^Jc`HgLp+Y%coI+J$JmRXU_YM4bNDHK zhF{>9IDi-N5`K+C%%NBC8h(f0%x#K`8)hw-hrHoBhjD%h;);h^ zr*M$*cEu_HvtF?tz}%r&8DKUj3^3lQB!_XMa%!u&OTqd1ol8ZM&V^|<@q{FZ@m?hf zjLwUZ#4+BdB$#oFl0?S)m83B~pd^`bP_a0{JgBgl(fQyc5sX_M-aNT>@Tp-hjv33- z#}!Kz%x=Y^1@nYr`GVP_Sjb?WR4i$`1AoVo2J=hB;s$d-vCP4|s95k|UQ#T5FuzhP zf-ugnO)Q5nzg8@aFozUNB+PFVizUp80MH_MTYsKVr_rumtJn%){_61X4cd9|o??H1d0(+pz?@X< z889Cxb`O|SihTs;L&c5)b6T;tzpAl!wyyK*s#|qe3#$S`YEJTX6({4N@EiV1pIM0@x760Rc9YJiOto02`(_HNb`|&JVB= zijxFvq~c5g8>Kj1z(y<18L%T1Cl1&c#n}TkR&fe}jZ>UQ;IZ*MA&w@n35r7sY@*`0 z0-K~bxWFbWjxewz6<%VzR&lI>O;H?hU{jSdF55K4p$9hoDi1jSz-A~;La?J0XCl~4 z#pwt(OL0zu%~qV4U~?2_C)ixYDGD}Eah`(BSDdV13lwK8*h0R)E#$X9!C0g?c)=Dc zj$p8(6^Aj{62-9$wp4LIgDq1W)nLmNhc?&>#qkYxjN%{%TdACp4tA_^mVm8N9P?nu zDGq$F)rzAZ?0Cf?5O#v%I0!pYaWI6fQ5+FrYZZq@*hz|GBkW}7`tybpBUn&G0suq z&)BTQS(0;=1TtQy#94+dNKZ&KnU=yK%|Co6AO;$-CtB~DVVRN^G%DkV-*-lD`w z%GFAoM7&jrlZb1SI0<)~66Ts+tHjASk8}Ny+@(Jx$c`3w=uByDsE_C2Nay;^DV_q4(w*d z?GEgHiW?u;Es9$p*!vYK2dkoz^M1~=Z!2z#V7Dr6kYK-~Fv$3jl8V6xqmn(&FZZzG z_6hb8#f=o~c7-n(zpuEtg59CG&4T@bg7cjoRRYGx6gOe8&g&9hXZ)e!#te3sQyO@~ zJsRxein}$~-3m_HI9GwVgM)Rh0&y<~`=sKo4%WFM#Qhztb47?dJ=mue_k6HFR^0u; z?p1h?1E>87Pl#JW*k=?shp^6*h}%Ti{fZk#*k={e2j7mK?aA`%#fOp#UX1$4uqTu4GnDy?G1B0dK}x~;f@caY7FHInD}282Tv1X{bJ32Xqs8vx z?Zp>HUn(gpSy6JjG_rJk>FKh{vKPvO%U73gE$dP2Do}SY2q{y1K*D>ZbKid!T-2{mJ^v z4H*ps4SO3-H|92;p6;GLWBRt~2d7_{5jUfCX41^|nOkR`oV9b-(b?^@w>O11RX44h z)8IX)dd|R{W6jacz0F&jPtOgUTQ#?J?t$y#u6v^;yd|xrtfj7{t>w3^?$(~xhg;8I zzxw*aZLYSOwq0%K=S`Tmc;4oDN7`NO8`^hutnE0~nXqqpY*vWJSwZ~IJg+@qdyxEy zIEe@k_3`!b4V0v8@518I#iJ{wz?DCyq;F@OJ3h9oE3bcLe`jN9ydGD0?QzFH)?c!! zFTb-qHa@wz@Qv;7f{R0C0!a`#uCOMgZE$0VZ z!4FubAMnPNCH;@ZyW_nQ1H|7iETcBLadzXx()5UM9w(*o2~EyRCdWu@XqeyE7ykcC z{QJx8+nzh(8EM$}{K;)DZ&!n>ao?;DpOf^Eu0_kbdb_iFJC-f%&RVdjx3_zK=r``` RyLox#UBTB?*%OZ+S!ZK)z{DN>}CB1LK~wTOEIMJtvfmA=Qfe|$X8@2q>0d+sIYti9IS zpS$quABS)45qbo$%>bs&Us~UEt$EHEpnWnB|HfTQ9&C7i`-qZt{08{=>!0wag(+8-&xt9!hK{=8{qt>K4Bn}D>qhwH@K1Q!0b&2Wp4af|gJ|hy`>eI) zq`lU(O$vebb29!yL>-J?3K}?!sc+gGMYv6Yj-w z+=mso9}i#^9>i)qgf(~=kDwWkVlChE7}nwO5H?^Vp1?QpB(~ydY{N6yj%V>dcn;sf zPCSnn@NMkEckm*MOu_~vN(&k1nX?cmSSBj-7>Aa^|XH0-*Rn$RbiSOdqxMqFu4!(h}@Nc|r(Kv}eVTcV!J`Uh+Y{8H57Ct~4 zPT&|bwOz~bi0duY5gkL3LH@?DHhAPRje!HQ({?+Pm6V94E}?}f&;fr z5PaS}{W^G* zJg{KG{YF?i;f@Q7DBN#_6J35zlx zp;J0q;#aDNomak#U>iVpX_u(rdU6IOY+KMCtS+y}zS5BKLl zh+kaC7at1S0o-2%a~aPITLj!+h0Ox)BVpTs`2)@5?7=q6cjz#df!T||>fN)fT&l3(!@cF{=3BEu$NWm8hM=JOte!nl` zUw@Wypm5HDFBVQ*@Ph;&GL{IZF!;g3c?`Z(IGMo@5zc7vWx{C zoaNvvBv=l9xNyFMA0eFd;71B)KKN0>=?{Lia1Mm86i$TjV}!FI{8-_X2tO`({ycDC zgdZ;)9pNVkhe-H|!f_IQl5ntuuM&=!@YRA_jFZLqvA#x(C;kqxFvcljZMpvaRGyHv zW1J?|fpNOnZHzO-f~9(=SR~_2u_(q_Vx1Uk#o`!ei^Vh6i6t=33558?o%v#}1e-En zFP6eMPpk{$e6e6DEfC9OTqxF^u|cdS<6UAwLN5{v68dhjAc;eZc_0h2_#Uw!iU%?006L(thFADcu@GlA8X8fLT9|pfW zC=EPtO9mg@ZQ|w(KDgV2AZ=a|ZrI?1J5SuY!3TGqxQT<`E8Nb(|4_KGgWo6I;=%t& zxY>h$Rk-bIc{4RB>I6?)1;<)$rcMn-M{JHb+%c_VZO4@z&qa=id?E5kgnX6Ny)ol9H;D)+X&qI@>v-b4llylM9lU zgpxNVpGYZ4X->JCTAjKj^oN{yeBQM& zGcB_z^I*5iZXa~t)cr({^*u9tUg))|*P&kTW_8b6lC>@CZ0}LM*Y`fqr(K^VeZJf0 zM&D_D_w>D<-9LL>zsi1V`d#T?+kaP1SWab5Q_crDH*!O%xyN!Z42T|3IbeU@g1k5K zzQ~`F-<-cY|71a%f>i}i7hEaKC|ppur|?oyR#9!ymZBpABL|iZTvHrTJa16LpxuMc zm(-N3E4ebbX7HZUKBbS8UMRgWByY&-AqR(?E^AkoUAC|6v!UyUepX&veysefVatc@ zA9l8)w4%0R@$mBD2Zx^zjaWS5(8!XJyGLPE?WnDzj*re8{aj^OWm#oI<;KdRW0J;H zj9E42^|6^_7mVFAu58@i@!8{7j=wpfd_wbtOA|{b9+-G;;#XC%RaI4stF~8Nzdh~t zn%j3)*Ho{mJ~X-AgCU2U2v}Q}q@jJrqsG1TxrEJRasS#7xPTe>4(zK>&`=(8} zKD~VU`srt8gw3d#v3kbd8AtETzH`&eikWL?ZkxG#=7E{VW);m^GwW1shuXT@3$sgR zH_qN)7gtwT_iEkgx*Ky!=QPf_IyY{vt1qwL+`2P8C%*O5{N(*MsWsxG=fYZFzVN!W KZn$_k((oTxn2(qM diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 5f192ee2b93..3cf6193de8d 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -485,6 +485,8 @@ export namespace Codicon { export const checkAll = new Codicon('check-all', { character: '\\ebb1' }); export const pinnedDirty = new Codicon('pinned-dirty', { character: '\\ebb2' }); export const passFilled = new Codicon('pass-filled', { character: '\\ebb3' }); + export const circleLargeFilled = new Codicon('circle-large-filled', { character: '\\ebb4' }); + export const circleLargeOutline = new Codicon('circle-large-outline', { character: '\\ebb5' }); } From 2046205637958e9d25fe6eb08eb900b7edabc7c0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 07:57:47 +0100 Subject: [PATCH 0168/1837] debt - fix layer break with dependency to v8-inspect-profiler --- .../extensions/electron-browser/extensionsAutoProfiler.ts | 2 +- .../extensionsSlowActions.ts | 0 .../extensions/electron-browser/runtimeExtensionsEditor.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/vs/workbench/contrib/extensions/{electron-sandbox => electron-browser}/extensionsSlowActions.ts (100%) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts index cf44269ccab..ee0eb2b5f5f 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts @@ -19,7 +19,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions'; +import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts similarity index 100% rename from src/vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions.ts rename to src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 101597bdee2..7fc9af89f9f 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -38,7 +38,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { renderCodicons } from 'vs/base/browser/codicons'; import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { Schemas } from 'vs/base/common/network'; -import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-sandbox/extensionsSlowActions'; +import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; From 155b218dcfb19f742707808b5637baed4673c7d1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 08:35:05 +0100 Subject: [PATCH 0169/1837] web - home indicator :lipstick: --- .../browser/parts/activitybar/activitybarPart.ts | 8 ++++++-- .../browser/parts/activitybar/media/activityaction.css | 4 ---- .../browser/parts/activitybar/media/activitybarpart.css | 8 -------- src/vs/workbench/browser/parts/panel/media/panelpart.css | 4 ---- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index dfdcf0323ec..ef4a9b5caa9 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -434,7 +434,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.menuBarContainer.classList.add('menubar'); const content = assertIsDefined(this.content); - content.prepend(this.menuBarContainer); + if (this.homeBarContainer) { + content.insertBefore(this.menuBarContainer, this.homeBarContainer.nextSibling); + } else { + content.prepend(this.menuBarContainer); + } // Menubar: install a custom menu bar depending on configuration this.menuBar = this._register(this.instantiationService.createInstance(CustomMenubarControl)); @@ -572,7 +576,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { }))); const content = assertIsDefined(this.content); - content.prepend(this.homeBarContainer); + content.appendChild(this.homeBarContainer); } private createGlobalActivityActionBar(container: HTMLElement): void { diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index 39fa9ebde59..57d6f2a8588 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -9,10 +9,6 @@ margin-bottom: 4px; } -.monaco-workbench .activitybar > .content > .home-bar > .monaco-action-bar .action-item { - margin-bottom: 0; -} - .monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::before, .monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::after { position: absolute; diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index ced2d815834..4f2d86b17a0 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -51,10 +51,6 @@ position: relative; width: 100%; height: 48px; - display: flex; - align-items: center; - justify-content: center; - order: -1; } .monaco-workbench .activitybar > .content > .home-bar > .home-bar-icon-badge { @@ -88,10 +84,6 @@ margin-bottom: auto; } -.monaco-workbench .activitybar > .content > .composite-bar-excess { - height: 100%; -} - /** Menu Bar */ .monaco-workbench .activitybar .menubar { diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 96d407d0538..27fc613ff4e 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -84,10 +84,6 @@ justify-content: center; } -.monaco-workbench .part.panel > .composite.title > .composite-bar-excess { - width: 100px; -} - .monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar { line-height: 27px; /* matches panel titles in settings */ height: 35px; From ff281d39f30202ae95790d6fa0586054e375aef0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 09:21:40 +0100 Subject: [PATCH 0170/1837] fix - pass the action runner --- src/vs/base/browser/ui/button/button.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index 6b24fbbbf38..867579df102 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -256,6 +256,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.dropdownButton.element.classList.add('monaco-dropdown-button'); this.dropdownButton.icon = 'codicon codicon-chevron-down'; const dropdownMenu = this._register(new DropdownMenu(this.dropdownButton.element, options.dropdownMenuOptions)); + dropdownMenu.menuOptions = options.dropdownMenuOptions; this._register(dropdownMenu.onDidChangeVisibility(visible => this.dropdownButton.element.setAttribute('aria-expanded', `${visible}`))); this._register(this.dropdownButton.onDidClick(() => dropdownMenu.show())); } From 44281ba1d5e1ee7069cf6f51a4315b9220a8b983 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 09:29:27 +0100 Subject: [PATCH 0171/1837] do not support secondary option on menu --- .../notification/common/notification.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index 487ed4484b6..f36b3958608 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -209,19 +209,13 @@ export interface INotificationHandle { close(): void; } -export interface IPromptChoice { +interface IBasePromptChoice { /** * Label to show for the choice to the user. */ readonly label: string; - /** - * Primary choices show up as buttons in the notification below the message. - * Secondary choices show up under the gear icon in the header of the notification. - */ - readonly isSecondary?: boolean; - /** * Whether to keep the notification open after the choice was selected * by the user. By default, will close the notification upon click. @@ -234,17 +228,26 @@ export interface IPromptChoice { run: () => void; } +export interface IPromptChoice extends IBasePromptChoice { + + /** + * Primary choices show up as buttons in the notification below the message. + * Secondary choices show up under the gear icon in the header of the notification. + */ + readonly isSecondary?: boolean; +} + export interface IPromptChoiceWithMenu extends IPromptChoice { /** * Additional choices those will be shown in the dropdown menu for this choice. */ - readonly menu: IPromptChoice[]; + readonly menu: IBasePromptChoice[]; /** * Menu is not supported on secondary choices */ - readonly isSecondary: undefined; + readonly isSecondary: false | undefined; } export interface IPromptOptions extends INotificationProperties { From 2efde187ac670b6821ba38ffda018f0dad07b5d9 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 09:31:21 +0100 Subject: [PATCH 0172/1837] HTML Semantic Tokens test failures. Fixes #111214 --- .../server/src/test/semanticTokens.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/html-language-features/server/src/test/semanticTokens.test.ts b/extensions/html-language-features/server/src/test/semanticTokens.test.ts index 61fc1d5441e..548ce7d8458 100644 --- a/extensions/html-language-features/server/src/test/semanticTokens.test.ts +++ b/extensions/html-language-features/server/src/test/semanticTokens.test.ts @@ -115,9 +115,9 @@ suite('HTML Semantic Tokens', () => { t(3, 8, 1, 'class.declaration'), t(4, 11, 1, 'property.declaration.static'), t(5, 4, 1, 'property.declaration'), - t(6, 10, 1, 'member.declaration.async'), t(6, 23, 1, 'class'), t(6, 25, 1, 'property.static'), t(6, 40, 1, 'member.async'), + t(6, 10, 1, 'method.declaration.async'), t(6, 23, 1, 'class'), t(6, 25, 1, 'property.static'), t(6, 40, 1, 'method.async'), t(7, 8, 1, 'property.declaration'), t(7, 26, 1, 'property'), - t(8, 11, 1, 'member.declaration.static'), t(8, 28, 1, 'class'), t(8, 32, 1, 'property'), + t(8, 11, 1, 'method.declaration.static'), t(8, 28, 1, 'class'), t(8, 32, 1, 'property'), ]); }); From 60388238797740e39e08b1fd185f378553762225 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 09:38:32 +0100 Subject: [PATCH 0173/1837] add doc --- src/vs/platform/notification/common/notification.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index f36b3958608..74c26363838 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -114,6 +114,8 @@ export interface INotificationActions { /** * Primary actions show up as buttons as part of the message and will close * the notification once clicked. + * + * Pass `ActionWithMenuAction` for an action that has additional menu actions. */ readonly primary?: ReadonlyArray; From e8ba7e51eef6a6a36e810005a0841f59a45a3245 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 09:53:00 +0100 Subject: [PATCH 0174/1837] bootstrap - fix compile errors --- src/bootstrap-window.js | 10 ++++------ src/bootstrap.js | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 8036d457adf..fcd68b1f309 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -57,17 +57,15 @@ developerToolsUnbind = registerDeveloperKeybindings(options && options.disallowReloadKeybinding); } - // Enable ASAR support (TODO@sandbox non-sandboxed only) - if (!sandbox) { - globalThis.MonacoBootstrap.enableASARSupport(configuration.appRoot); - } + // Enable ASAR support + globalThis.MonacoBootstrap.enableASARSupport(configuration.appRoot); if (options && typeof options.canModifyDOM === 'function') { options.canModifyDOM(configuration); } - // Get the nls configuration into the process.env as early as possible (TODO@sandbox non-sandboxed only) - const nlsConfig = sandbox ? { availableLanguages: {} } : globalThis.MonacoBootstrap.setupNLS(); + // Get the nls configuration into the process.env as early as possible + const nlsConfig = globalThis.MonacoBootstrap.setupNLS(); let locale = nlsConfig.availableLanguages['*'] || 'en'; if (locale === 'zh-tw') { diff --git a/src/bootstrap.js b/src/bootstrap.js index 4ec4c258967..ead7ef17411 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -46,7 +46,7 @@ */ function enableASARSupport(appRoot) { if (!path || !Module) { - console.warn('enableASARSupport() is only available in node.js environments'); + console.warn('enableASARSupport() is only available in node.js environments'); // TODO@sandbox ASAR is currently non-sandboxed only return; } @@ -129,7 +129,7 @@ function setupNLS() { if (!path || !fs) { console.warn('setupNLS() is only available in node.js environments'); - return; + return { availableLanguages: {} }; // TODO@sandbox NLS is currently non-sandboxed only } // Get the nls configuration into the process.env as early as possible. @@ -185,13 +185,16 @@ */ function configurePortable(product) { if (!path || !fs) { - console.warn('configurePortable() is only available in node.js environments'); + console.warn('configurePortable() is only available in node.js environments'); // TODO@sandbox Portable is currently non-sandboxed only return; } const appRoot = path.dirname(__dirname); - function getApplicationPath() { + /** + * @param {import('path')} path + */ + function getApplicationPath(path) { if (process.env['VSCODE_DEV']) { return appRoot; } @@ -203,21 +206,24 @@ return path.dirname(path.dirname(appRoot)); } - function getPortableDataPath() { + /** + * @param {import('path')} path + */ + function getPortableDataPath(path) { if (process.env['VSCODE_PORTABLE']) { return process.env['VSCODE_PORTABLE']; } if (process.platform === 'win32' || process.platform === 'linux') { - return path.join(getApplicationPath(), 'data'); + return path.join(getApplicationPath(path), 'data'); } // @ts-ignore const portableDataName = product.portable || `${product.applicationName}-portable-data`; - return path.join(path.dirname(getApplicationPath()), portableDataName); + return path.join(path.dirname(getApplicationPath(path)), portableDataName); } - const portableDataPath = getPortableDataPath(); + const portableDataPath = getPortableDataPath(path); const isPortable = !('target' in product) && fs.existsSync(portableDataPath); const portableTempPath = path.join(portableDataPath, 'tmp'); const isTempPortable = isPortable && fs.existsSync(portableTempPath); From de85ef3a2065c051204919085e4baea14fd43f1c Mon Sep 17 00:00:00 2001 From: Pablo Sebastian Greco Date: Tue, 24 Nov 2020 05:59:00 -0300 Subject: [PATCH 0175/1837] Fix hardcoded rpm dependencies for armv7hl and aarch64 (#111198) Co-authored-by: Pablo Greco --- resources/linux/rpm/dependencies.json | 252 +++++++++++++------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/resources/linux/rpm/dependencies.json b/resources/linux/rpm/dependencies.json index 7f95cd3e5db..dec9b480689 100644 --- a/resources/linux/rpm/dependencies.json +++ b/resources/linux/rpm/dependencies.json @@ -66,133 +66,133 @@ "libgbm.so.1()(64bit)" ], "aarch64": [ - "libpthread.so.0()(aarch64)", - "libpthread.so.0(GLIBC_2.2.5)(aarch64)", - "libpthread.so.0(GLIBC_2.3.2)(aarch64)", - "libpthread.so.0(GLIBC_2.3.3)(aarch64)", - "libgtk-3.so.0()(aarch64)", - "libgdk-x11-2.0.so.0()(aarch64)", - "libatk-1.0.so.0()(aarch64)", - "libgio-2.0.so.0()(aarch64)", - "libpangocairo-1.0.so.0()(aarch64)", - "libgdk_pixbuf-2.0.so.0()(aarch64)", - "libcairo.so.2()(aarch64)", - "libpango-1.0.so.0()(aarch64)", - "libfreetype.so.6()(aarch64)", - "libfontconfig.so.1()(aarch64)", - "libgobject-2.0.so.0()(aarch64)", - "libdbus-1.so.3()(aarch64)", - "libXi.so.6()(aarch64)", - "libXcursor.so.1()(aarch64)", - "libXdamage.so.1()(aarch64)", - "libXrandr.so.2()(aarch64)", - "libXcomposite.so.1()(aarch64)", - "libXext.so.6()(aarch64)", - "libXfixes.so.3()(aarch64)", - "libXrender.so.1()(aarch64)", - "libX11.so.6()(aarch64)", - "libXss.so.1()(aarch64)", - "libXtst.so.6()(aarch64)", - "libgmodule-2.0.so.0()(aarch64)", - "librt.so.1()(aarch64)", - "libglib-2.0.so.0()(aarch64)", - "libnss3.so()(aarch64)", - "libnssutil3.so()(aarch64)", - "libsmime3.so()(aarch64)", - "libnspr4.so()(aarch64)", - "libasound.so.2()(aarch64)", - "libcups.so.2()(aarch64)", - "libdl.so.2()(aarch64)", - "libexpat.so.1()(aarch64)", - "libstdc++.so.6()(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4)(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4.10)(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4.11)(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4.14)(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4.15)(aarch64)", - "libstdc++.so.6(GLIBCXX_3.4.9)(aarch64)", - "libm.so.6()(aarch64)", - "libm.so.6(GLIBC_2.2.5)(aarch64)", - "libgcc_s.so.1()(aarch64)", - "libgcc_s.so.1(GCC_3.0)(aarch64)", - "libgcc_s.so.1(GCC_4.0.0)(aarch64)", - "libc.so.6()(aarch64)", - "libc.so.6(GLIBC_2.11)(aarch64)", - "libc.so.6(GLIBC_2.2.5)(aarch64)", - "libc.so.6(GLIBC_2.3)(aarch64)", - "libc.so.6(GLIBC_2.3.2)(aarch64)", - "libc.so.6(GLIBC_2.3.4)(aarch64)", - "libc.so.6(GLIBC_2.4)(aarch64)", - "libc.so.6(GLIBC_2.6)(aarch64)", - "libc.so.6(GLIBC_2.7)(aarch64)", - "libc.so.6(GLIBC_2.9)(aarch64)", - "libxcb.so.1()(aarch64)", - "libxkbfile.so.1()(aarch64)", - "libsecret-1.so.0()(aarch64)" + "libpthread.so.0()(64bit)", + "libpthread.so.0(GLIBC_2.2.5)(64bit)", + "libpthread.so.0(GLIBC_2.3.2)(64bit)", + "libpthread.so.0(GLIBC_2.3.3)(64bit)", + "libgtk-3.so.0()(64bit)", + "libgdk-x11-2.0.so.0()(64bit)", + "libatk-1.0.so.0()(64bit)", + "libgio-2.0.so.0()(64bit)", + "libpangocairo-1.0.so.0()(64bit)", + "libgdk_pixbuf-2.0.so.0()(64bit)", + "libcairo.so.2()(64bit)", + "libpango-1.0.so.0()(64bit)", + "libfreetype.so.6()(64bit)", + "libfontconfig.so.1()(64bit)", + "libgobject-2.0.so.0()(64bit)", + "libdbus-1.so.3()(64bit)", + "libXi.so.6()(64bit)", + "libXcursor.so.1()(64bit)", + "libXdamage.so.1()(64bit)", + "libXrandr.so.2()(64bit)", + "libXcomposite.so.1()(64bit)", + "libXext.so.6()(64bit)", + "libXfixes.so.3()(64bit)", + "libXrender.so.1()(64bit)", + "libX11.so.6()(64bit)", + "libXss.so.1()(64bit)", + "libXtst.so.6()(64bit)", + "libgmodule-2.0.so.0()(64bit)", + "librt.so.1()(64bit)", + "libglib-2.0.so.0()(64bit)", + "libnss3.so()(64bit)", + "libnssutil3.so()(64bit)", + "libsmime3.so()(64bit)", + "libnspr4.so()(64bit)", + "libasound.so.2()(64bit)", + "libcups.so.2()(64bit)", + "libdl.so.2()(64bit)", + "libexpat.so.1()(64bit)", + "libstdc++.so.6()(64bit)", + "libstdc++.so.6(GLIBCXX_3.4)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.10)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.11)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.14)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.15)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.9)(64bit)", + "libm.so.6()(64bit)", + "libm.so.6(GLIBC_2.2.5)(64bit)", + "libgcc_s.so.1()(64bit)", + "libgcc_s.so.1(GCC_3.0)(64bit)", + "libgcc_s.so.1(GCC_4.0.0)(64bit)", + "libc.so.6()(64bit)", + "libc.so.6(GLIBC_2.11)(64bit)", + "libc.so.6(GLIBC_2.2.5)(64bit)", + "libc.so.6(GLIBC_2.3)(64bit)", + "libc.so.6(GLIBC_2.3.2)(64bit)", + "libc.so.6(GLIBC_2.3.4)(64bit)", + "libc.so.6(GLIBC_2.4)(64bit)", + "libc.so.6(GLIBC_2.6)(64bit)", + "libc.so.6(GLIBC_2.7)(64bit)", + "libc.so.6(GLIBC_2.9)(64bit)", + "libxcb.so.1()(64bit)", + "libxkbfile.so.1()(64bit)", + "libsecret-1.so.0()(64bit)" ], "armv7hl": [ - "libpthread.so.0()(armv7hl)", - "libpthread.so.0(GLIBC_2.2.5)(armv7hl)", - "libpthread.so.0(GLIBC_2.3.2)(armv7hl)", - "libpthread.so.0(GLIBC_2.3.3)(armv7hl)", - "libgtk-3.so.0()(armv7hl)", - "libgdk-x11-2.0.so.0()(armv7hl)", - "libatk-1.0.so.0()(armv7hl)", - "libgio-2.0.so.0()(armv7hl)", - "libpangocairo-1.0.so.0()(armv7hl)", - "libgdk_pixbuf-2.0.so.0()(armv7hl)", - "libcairo.so.2()(armv7hl)", - "libpango-1.0.so.0()(armv7hl)", - "libfreetype.so.6()(armv7hl)", - "libfontconfig.so.1()(armv7hl)", - "libgobject-2.0.so.0()(armv7hl)", - "libdbus-1.so.3()(armv7hl)", - "libXi.so.6()(armv7hl)", - "libXcursor.so.1()(armv7hl)", - "libXdamage.so.1()(armv7hl)", - "libXrandr.so.2()(armv7hl)", - "libXcomposite.so.1()(armv7hl)", - "libXext.so.6()(armv7hl)", - "libXfixes.so.3()(armv7hl)", - "libXrender.so.1()(armv7hl)", - "libX11.so.6()(armv7hl)", - "libXss.so.1()(armv7hl)", - "libXtst.so.6()(armv7hl)", - "libgmodule-2.0.so.0()(armv7hl)", - "librt.so.1()(armv7hl)", - "libglib-2.0.so.0()(armv7hl)", - "libnss3.so()(armv7hl)", - "libnssutil3.so()(armv7hl)", - "libsmime3.so()(armv7hl)", - "libnspr4.so()(armv7hl)", - "libasound.so.2()(armv7hl)", - "libcups.so.2()(armv7hl)", - "libdl.so.2()(armv7hl)", - "libexpat.so.1()(armv7hl)", - "libstdc++.so.6()(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4)(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4.10)(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4.11)(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4.14)(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4.15)(armv7hl)", - "libstdc++.so.6(GLIBCXX_3.4.9)(armv7hl)", - "libm.so.6()(armv7hl)", - "libm.so.6(GLIBC_2.2.5)(armv7hl)", - "libgcc_s.so.1()(armv7hl)", - "libgcc_s.so.1(GCC_3.0)(armv7hl)", - "libgcc_s.so.1(GCC_4.0.0)(armv7hl)", - "libc.so.6()(armv7hl)", - "libc.so.6(GLIBC_2.11)(armv7hl)", - "libc.so.6(GLIBC_2.2.5)(armv7hl)", - "libc.so.6(GLIBC_2.3)(armv7hl)", - "libc.so.6(GLIBC_2.3.2)(armv7hl)", - "libc.so.6(GLIBC_2.3.4)(armv7hl)", - "libc.so.6(GLIBC_2.4)(armv7hl)", - "libc.so.6(GLIBC_2.6)(armv7hl)", - "libc.so.6(GLIBC_2.7)(armv7hl)", - "libc.so.6(GLIBC_2.9)(armv7hl)", - "libxcb.so.1()(armv7hl)", - "libxkbfile.so.1()(armv7hl)", - "libsecret-1.so.0()(armv7hl)" + "libpthread.so.0()", + "libpthread.so.0(GLIBC_2.2.5)", + "libpthread.so.0(GLIBC_2.3.2)", + "libpthread.so.0(GLIBC_2.3.3)", + "libgtk-3.so.0()", + "libgdk-x11-2.0.so.0()", + "libatk-1.0.so.0()", + "libgio-2.0.so.0()", + "libpangocairo-1.0.so.0()", + "libgdk_pixbuf-2.0.so.0()", + "libcairo.so.2()", + "libpango-1.0.so.0()", + "libfreetype.so.6()", + "libfontconfig.so.1()", + "libgobject-2.0.so.0()", + "libdbus-1.so.3()", + "libXi.so.6()", + "libXcursor.so.1()", + "libXdamage.so.1()", + "libXrandr.so.2()", + "libXcomposite.so.1()", + "libXext.so.6()", + "libXfixes.so.3()", + "libXrender.so.1()", + "libX11.so.6()", + "libXss.so.1()", + "libXtst.so.6()", + "libgmodule-2.0.so.0()", + "librt.so.1()", + "libglib-2.0.so.0()", + "libnss3.so()", + "libnssutil3.so()", + "libsmime3.so()", + "libnspr4.so()", + "libasound.so.2()", + "libcups.so.2()", + "libdl.so.2()", + "libexpat.so.1()", + "libstdc++.so.6()", + "libstdc++.so.6(GLIBCXX_3.4)", + "libstdc++.so.6(GLIBCXX_3.4.10)", + "libstdc++.so.6(GLIBCXX_3.4.11)", + "libstdc++.so.6(GLIBCXX_3.4.14)", + "libstdc++.so.6(GLIBCXX_3.4.15)", + "libstdc++.so.6(GLIBCXX_3.4.9)", + "libm.so.6()", + "libm.so.6(GLIBC_2.2.5)", + "libgcc_s.so.1()", + "libgcc_s.so.1(GCC_3.0)", + "libgcc_s.so.1(GCC_4.0.0)", + "libc.so.6()", + "libc.so.6(GLIBC_2.11)", + "libc.so.6(GLIBC_2.2.5)", + "libc.so.6(GLIBC_2.3)", + "libc.so.6(GLIBC_2.3.2)", + "libc.so.6(GLIBC_2.3.4)", + "libc.so.6(GLIBC_2.4)", + "libc.so.6(GLIBC_2.6)", + "libc.so.6(GLIBC_2.7)", + "libc.so.6(GLIBC_2.9)", + "libxcb.so.1()", + "libxkbfile.so.1()", + "libsecret-1.so.0()" ] } From ae64039e432f21afc36465c18c0e9e38c58d7113 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 24 Nov 2020 10:01:03 +0100 Subject: [PATCH 0176/1837] Move `runtimeExtensionsInput` to `/common/` --- .../{electron-browser => common}/runtimeExtensionsInput.ts | 0 .../extensions/electron-browser/extensionProfileService.ts | 2 +- .../extensions/electron-browser/extensions.contribution.ts | 2 +- .../extensions/electron-browser/extensionsAutoProfiler.ts | 2 +- .../extensions/electron-browser/runtimeExtensionsEditor.ts | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/vs/workbench/contrib/extensions/{electron-browser => common}/runtimeExtensionsInput.ts (100%) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput.ts b/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts similarity index 100% rename from src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput.ts rename to src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts index 651b01e8796..1befb2a7fdc 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts @@ -16,7 +16,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { randomPort } from 'vs/base/node/ports'; import { IProductService } from 'vs/platform/product/common/productService'; -import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index f7fb0e3bda3..9cf0ec19766 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -17,7 +17,7 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, DebugExtensionHostAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; -import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts index ee0eb2b5f5f..d8f182cffbb 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts @@ -16,7 +16,7 @@ import { IExtensionHostProfileService } from 'vs/workbench/contrib/extensions/el import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { localize } from 'vs/nls'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 7fc9af89f9f..c775e9d0042 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -28,7 +28,7 @@ import { memoize } from 'vs/base/common/decorators'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { randomPort } from 'vs/base/node/ports'; From 41025928ad3d71ac5f7b65588ded8ad172c8d095 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 10:03:14 +0100 Subject: [PATCH 0177/1837] bootstrap - fix more compile errors --- src/bootstrap-fork.js | 2 +- src/bootstrap.js | 2 +- src/cli.js | 2 +- src/main.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index 0cd75027286..68e2219bad8 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -13,7 +13,7 @@ const bootstrapNode = require('./bootstrap-node'); bootstrapNode.removeGlobalNodeModuleLookupPaths(); // Enable ASAR in our forked processes -bootstrap.enableASARSupport(); +bootstrap.enableASARSupport(undefined); if (process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']) { bootstrapNode.injectNodeModuleLookupPath(process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']); diff --git a/src/bootstrap.js b/src/bootstrap.js index ead7ef17411..53b554cf1fe 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -180,7 +180,7 @@ //#region Portable helpers /** - * @param {{ portable: string; applicationName: string; }} product + * @param {{ portable: string | undefined; applicationName: string; }} product * @returns {{ portableDataPath: string; isPortable: boolean; } | undefined} */ function configurePortable(product) { diff --git a/src/cli.js b/src/cli.js index 872cd66733d..c59d5ae2f6d 100644 --- a/src/cli.js +++ b/src/cli.js @@ -16,7 +16,7 @@ bootstrap.avoidMonkeyPatchFromAppInsights(); bootstrap.configurePortable(product); // Enable ASAR support -bootstrap.enableASARSupport(); +bootstrap.enableASARSupport(undefined); // Load CLI through AMD loader require('./bootstrap-amd').load('vs/code/node/cli'); diff --git a/src/main.js b/src/main.js index b75dd6ad33f..699ccb5b1ab 100644 --- a/src/main.js +++ b/src/main.js @@ -28,7 +28,7 @@ app.allowRendererProcessReuse = false; const portable = bootstrap.configurePortable(product); // Enable ASAR support -bootstrap.enableASARSupport(); +bootstrap.enableASARSupport(undefined); // Set userData path before app 'ready' event const args = parseCLIArgs(); From d2365da65c42972a5627e6cb7e54126a1a4f6cf9 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2020 10:15:37 +0100 Subject: [PATCH 0178/1837] rename doNotUseTrash to skipTrashBin --- src/vs/editor/common/modes.ts | 2 +- src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 4 ++-- src/vs/workbench/contrib/files/browser/fileActions.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 30d7fc55691..d5e6aa10124 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1387,7 +1387,7 @@ export interface WorkspaceFileEditOptions { recursive?: boolean; copy?: boolean; folder?: boolean; - doNotUseTrash?: boolean; + skipTrashBin?: boolean; maxSize?: number; } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index e1bef23b490..c1fbb07562e 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -166,13 +166,13 @@ class DeleteOperation implements IFileOperation { let fileContent: IFileContent | undefined; if (!this._undoesCreateOperation && !this.options.folder) { try { - fileContent = (await this._fileService.readFile(this.oldUri)); + fileContent = await this._fileService.readFile(this.oldUri); } catch (err) { this._logService.critical(err); } } - const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash') && !this.options.doNotUseTrash; + const useTrash = !this.options.skipTrashBin && this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }); if (typeof this.options.maxSize === 'number' && fileContent && (fileContent?.size > this.options.maxSize)) { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index c6b285a6e2d..bc7fb098071 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -226,7 +226,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I // Call function try { - const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, doNotUseTrash: !useTrash })); + const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash })); await bulkEditService.apply(resourceFileEdits, { undoRedoSource: explorerService.undoRedoSource, label: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name) From 723ee37c02c8c090cba0f1bfe09eebff791adc16 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 10:23:00 +0100 Subject: [PATCH 0179/1837] bootstrap - expose preload process to base lib --- src/bootstrap.js | 16 +++++++++++++--- src/vs/base/common/platform.ts | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/bootstrap.js b/src/bootstrap.js index 53b554cf1fe..250ac23b987 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -45,7 +45,7 @@ * @param {string | undefined} appRoot */ function enableASARSupport(appRoot) { - if (!path || !Module) { + if (!path || !Module || typeof process === 'undefined') { console.warn('enableASARSupport() is only available in node.js environments'); // TODO@sandbox ASAR is currently non-sandboxed only return; } @@ -127,7 +127,7 @@ * @returns {{locale?: string, availableLanguages: {[lang: string]: string;}, pseudo?: boolean } | undefined} */ function setupNLS() { - if (!path || !fs) { + if (!path || !fs || typeof process === 'undefined') { console.warn('setupNLS() is only available in node.js environments'); return { availableLanguages: {} }; // TODO@sandbox NLS is currently non-sandboxed only } @@ -184,7 +184,7 @@ * @returns {{ portableDataPath: string; isPortable: boolean; } | undefined} */ function configurePortable(product) { - if (!path || !fs) { + if (!path || !fs || typeof process === 'undefined') { console.warn('configurePortable() is only available in node.js environments'); // TODO@sandbox Portable is currently non-sandboxed only return; } @@ -267,6 +267,16 @@ global['diagnosticsSource'] = {}; // Prevents diagnostic channel (which patches "require") from initializing entirely } + function safeProcess() { + const globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {}); + + if (typeof process !== 'undefined') { + return process; // Native environment (non-sandboxed) + } else if (typeof globals.vscode !== 'undefined') { + return globals.vscode.process; // Native environment (sandboxed) + } + } + //#endregion diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index a28fe0e0d41..c03aef236d8 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -54,7 +54,7 @@ if (typeof process !== 'undefined') { // Native environment (non-sandboxed) nodeProcess = process; } else if (typeof _globals.vscode !== 'undefined') { - // Native envionment (sandboxed) + // Native environment (sandboxed) nodeProcess = _globals.vscode.process; } From a486099d30d404c5fbf4a72a66d3fa2bde45cbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 10:44:48 +0100 Subject: [PATCH 0180/1837] fixes #111221 --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 1 + src/vs/workbench/contrib/extensions/browser/extensionsList.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 992c9b7c86a..cbefe73bf05 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -186,6 +186,7 @@ export class ActionWithDropDownAction extends ExtensionAction { super(id, label); this.update(); this._register(Event.any(...actions.map(a => a.onDidChange))(() => this.update(true))); + actions.forEach(a => this._register(a)); } update(donotUpdateActions?: boolean): void { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts index 731a2c9aa5e..6b0ed05167f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts @@ -223,10 +223,14 @@ export class Renderer implements IPagedRenderer { }); } }, this, data.extensionDisposables); + } + disposeElement(extension: IExtension, index: number, data: ITemplateData): void { + data.extensionDisposables = dispose(data.extensionDisposables); } disposeTemplate(data: ITemplateData): void { + data.extensionDisposables = dispose(data.extensionDisposables); data.disposables = dispose(data.disposables); } } From a53d75097a16628ee02dbee6e517cd52d959c805 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 10:47:33 +0100 Subject: [PATCH 0181/1837] add file decorations to editor titles (tab and no tab) --- src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts | 3 ++- src/vs/workbench/browser/parts/editor/tabsTitleControl.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 66a7caec173..318a5c130c0 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -291,7 +291,8 @@ export class NoTabsTitleControl extends TitleControl { { title, italic: !isEditorPinned, - extraClasses: ['no-tabs', 'title-label'] + extraClasses: ['no-tabs', 'title-label'], + fileDecorations: { colors: true, badges: true }, } ); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index bcd835f4cc5..f5318a8878a 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1116,7 +1116,7 @@ export class TabsTitleControl extends TitleControl { // Label tabLabelWidget.setResource( { name, description, resource: EditorResourceAccessor.getOriginalUri(editor, { supportSideBySide: SideBySideEditor.BOTH }) }, - { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel } + { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel, fileDecorations: { colors: true, badges: true } } ); // Tests helper From 08d9b152458331644a3b6b3bac1ea36838b528d0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 10:52:56 +0100 Subject: [PATCH 0182/1837] fix dropdown position --- src/vs/base/browser/ui/button/button.ts | 19 ++++++++++++------- .../notifications/notificationsViewer.ts | 7 ++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index 867579df102..f2e25e442ac 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -13,8 +13,8 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch'; import { renderCodicons } from 'vs/base/browser/codicons'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; -import { DropdownMenu, IDropdownMenuOptions } from 'vs/base/browser/ui/dropdown/dropdown'; -import { IMenuOptions } from 'vs/base/browser/ui/menu/menu'; +import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; +import { IAction } from 'vs/base/common/actions'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; @@ -231,7 +231,8 @@ export class Button extends Disposable implements IButton { } export interface IButtonWithDropdownOptions extends IButtonOptions { - readonly dropdownMenuOptions: IDropdownMenuOptions & IMenuOptions; + readonly contextMenuProvider: IContextMenuProvider; + readonly actions: IAction[]; } export class ButtonWithDropdown extends Disposable implements IButton { @@ -255,10 +256,14 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportCodicons: true })); this.dropdownButton.element.classList.add('monaco-dropdown-button'); this.dropdownButton.icon = 'codicon codicon-chevron-down'; - const dropdownMenu = this._register(new DropdownMenu(this.dropdownButton.element, options.dropdownMenuOptions)); - dropdownMenu.menuOptions = options.dropdownMenuOptions; - this._register(dropdownMenu.onDidChangeVisibility(visible => this.dropdownButton.element.setAttribute('aria-expanded', `${visible}`))); - this._register(this.dropdownButton.onDidClick(() => dropdownMenu.show())); + this._register(this.dropdownButton.onDidClick(() => { + options.contextMenuProvider.showContextMenu({ + getAnchor: () => this.dropdownButton.element, + getActions: () => options.actions, + onHide: () => this.dropdownButton.element.setAttribute('aria-expanded', 'false') + }); + this.dropdownButton.element.setAttribute('aria-expanded', 'true'); + })); } set label(value: string) { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts index 21e87488da1..b56a1cf09f5 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts @@ -463,11 +463,8 @@ export class NotificationTemplateRenderer extends Disposable { dropdownActions ? buttonToolbar.addButtonWithDropdown({ ...buttonOptions, - dropdownMenuOptions: { - contextMenuProvider: this.contextMenuService, - actions: dropdownActions, - actionRunner - } + contextMenuProvider: this.contextMenuService, + actions: dropdownActions, }) : buttonToolbar.addButton(buttonOptions)); button.label = action.label; From d970e263c76e18e916371f62a545a9b900c309d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 11:05:08 +0100 Subject: [PATCH 0183/1837] more fixes for #111221 --- .../extensions/browser/extensionsActions.ts | 5 +- .../extensions/browser/extensionsViewlet.ts | 48 +++++++++---------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index cbefe73bf05..5fbd09c9a4d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1804,18 +1804,17 @@ export class ClearExtensionsInputAction extends ClearExtensionsSearchResultsActi id: string, label: string, onSearchChange: Event, - value: string, + getValue: () => string, @IViewsService viewsService: IViewsService ) { super(id, label, viewsService); - this.onSearchChange(value); + this.onSearchChange(getValue()); this._register(onSearchChange(this.onSearchChange, this)); } private onSearchChange(value: string): void { this.enabled = !!value; } - } export class RefreshExtensionsAction extends Action { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 06d74acce15..7fabf9803d5 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -62,6 +62,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { isWeb } from 'vs/base/common/platform'; +import { memoize } from 'vs/base/common/decorators'; const DefaultViewsContext = new RawContextKey('defaultExtensionViews', true); const SearchMarketplaceExtensionsContext = new RawContextKey('searchMarketplaceExtensions', false); @@ -552,39 +553,36 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE return 400; } + @memoize getActions(): IAction[] { - const filterActions: IAction[] = []; - // Local extensions filters - filterActions.push(...[ - this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, localize('builtin filter', "Built-in")), - this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, localize('installed filter', "Installed")), - this.instantiationService.createInstance(ShowEnabledExtensionsAction, ShowEnabledExtensionsAction.ID, localize('enabled filter', "Enabled")), - this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, localize('disabled filter', "Disabled")), - this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, localize('outdated filter', "Outdated")), - ]); + let filterActions: IAction[] = [ + this._register(this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, localize('builtin filter', "Built-in"))), + this._register(this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, localize('installed filter', "Installed"))), + this._register(this.instantiationService.createInstance(ShowEnabledExtensionsAction, ShowEnabledExtensionsAction.ID, localize('enabled filter', "Enabled"))), + this._register(this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, localize('disabled filter', "Disabled"))), + this._register(this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, localize('outdated filter', "Outdated"))), + ]; if (this.extensionGalleryService.isEnabled()) { - const galleryFilterActions = [ - this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.featured', localize('featured filter', "Featured"), '@featured'), - this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.popular', localize('most popular filter', "Most Popular"), '@popular'), - this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.recommended', localize('most popular recommended', "Recommended"), '@recommended'), - this.instantiationService.createInstance(RecentlyPublishedExtensionsAction, RecentlyPublishedExtensionsAction.ID, localize('recently published filter', "Recently Published")), - new Separator(), - new SubmenuAction('workbench.extensions.action.filterExtensionsByCategory', localize('filter by category', "Category"), EXTENSION_CATEGORIES.map(category => this.instantiationService.createInstance(SearchCategoryAction, `extensions.actions.searchByCategory.${category}`, category, category))), - new Separator(), + filterActions = [ + this._register(this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.featured', localize('featured filter', "Featured"), '@featured')), + this._register(this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.popular', localize('most popular filter', "Most Popular"), '@popular')), + this._register(this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.recommended', localize('most popular recommended', "Recommended"), '@recommended')), + this._register(this.instantiationService.createInstance(RecentlyPublishedExtensionsAction, RecentlyPublishedExtensionsAction.ID, localize('recently published filter', "Recently Published"))), + this._register(new Separator()), + this._register(new SubmenuAction('workbench.extensions.action.filterExtensionsByCategory', localize('filter by category', "Category"), EXTENSION_CATEGORIES.map(category => this.instantiationService.createInstance(SearchCategoryAction, `extensions.actions.searchByCategory.${category}`, category, category)))), + this._register(new Separator()), + ...filterActions, + this._register(new Separator()), + this._register(new SubmenuAction('workbench.extensions.action.sortBy', localize('sorty by', "Sort By"), this.sortActions)), ]; - filterActions.splice(0, 0, ...galleryFilterActions); - filterActions.push(...[ - new Separator(), - new SubmenuAction('workbench.extensions.action.sortBy', localize('sorty by', "Sort By"), this.sortActions), - ]); } return [ - new SubmenuAction('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), filterActions, 'codicon-filter'), - this.instantiationService.createInstance(RefreshExtensionsAction, RefreshExtensionsAction.ID, RefreshExtensionsAction.LABEL), - this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, this.searchBox ? this.searchBox.getValue() : ''), + this._register(new SubmenuAction('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), filterActions, 'codicon-filter')), + this._register(this.instantiationService.createInstance(RefreshExtensionsAction, RefreshExtensionsAction.ID, RefreshExtensionsAction.LABEL)), + this._register(this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, () => this.searchBox!.getValue() || '')), ]; } From 4ddf7bc0a789dac66c384450b27cbaeac0101857 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 24 Nov 2020 11:16:58 +0100 Subject: [PATCH 0184/1837] Fix null characters showing in forwarded ports --- .../services/remote/common/remoteExplorerService.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 9d9bb61126d..63808d13255 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -258,13 +258,17 @@ export class TunnelModel extends Disposable { this._onCandidatesChanged.fire(removedCandidates); } + private polishProcessDetail(detail: string): string { + const nullIndex = detail.indexOf('\0'); + return detail.substr(0, nullIndex > 0 ? nullIndex : detail.length).trim(); + } + // Returns removed candidates private updateInResponseToCandidates(candidates: { host: string, port: number, detail: string }[]): Map { const removedCandidates = this._candidates; this._candidates = new Map(); candidates.forEach(value => { - const nullIndex = value.detail.indexOf('\0'); - const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim(); + const detail = this.polishProcessDetail(value.detail); const addressKey = makeAddress(value.host, value.port); this._candidates.set(addressKey, { host: value.host, @@ -276,7 +280,7 @@ export class TunnelModel extends Disposable { } const forwardedValue = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, value.host, value.port); if (forwardedValue) { - forwardedValue.runningProcess = value.detail; + forwardedValue.runningProcess = detail; } }); removedCandidates.forEach((_value, key) => { From 384d7b5e9e682ac248b572f9913232f5a5a5f323 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 11:37:22 +0100 Subject: [PATCH 0185/1837] implement review comments --- src/vs/platform/theme/common/iconRegistry.ts | 6 ++++++ src/vs/workbench/contrib/debug/browser/debugIcons.ts | 11 ++++------- .../contrib/debug/browser/exceptionWidget.ts | 6 +++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/vs/platform/theme/common/iconRegistry.ts b/src/vs/platform/theme/common/iconRegistry.ts index da0df3677c6..ca0d27b503a 100644 --- a/src/vs/platform/theme/common/iconRegistry.ts +++ b/src/vs/platform/theme/common/iconRegistry.ts @@ -12,6 +12,12 @@ import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/plat import { RunOnceScheduler } from 'vs/base/common/async'; import * as Codicons from 'vs/base/common/codicons'; +// common icons + +export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.')); + + + // ------ API types diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts index fdf87e6edd9..bf6ee24f24a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugIcons.ts +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -17,7 +17,7 @@ export const loadedScriptsViewIcon = registerIcon('loaded-scripts-view-icon', Co export const debugBreakpoint = registerIcon('debug-breakpoint', Codicon.debugBreakpoint, localize('debugBreakpoint', 'Icon for breakpoints.')); export const debugBreakpointDisabled = registerIcon('debug-breakpoint-disabled', Codicon.debugBreakpointDisabled, localize('debugBreakpointDisabled', 'Icon for disabled breakpoints.')); export const debugBreakpointUnverified = registerIcon('debug-breakpoint-unverified', Codicon.debugBreakpointUnverified, localize('debugBreakpointUnverified', 'Icon for unverified breakpoints.')); -export const debugBreakpointHint = registerIcon('debug-hint', Codicon.debugHint, localize('debugBreakpointHint', 'Icon for breakpoint hints.')); +export const debugBreakpointHint = registerIcon('debug-hint', Codicon.debugHint, localize('debugBreakpointHint', 'Icon for breakpoint hints shown on hover in editor glyph margin.')); export const debugBreakpointFunction = registerIcon('debug-breakpoint-function', Codicon.debugBreakpointFunction, localize('debugBreakpointFunction', 'Icon for function breakpoints.')); export const debugBreakpointFunctionUnverified = registerIcon('debug-breakpoint-function-unverified', Codicon.debugBreakpointFunctionUnverified, localize('debugBreakpointFunctionUnverified', 'Icon for unverified function breakpoints.')); export const debugBreakpointFunctionDisabled = registerIcon('debug-breakpoint-function-disabled', Codicon.debugBreakpointFunctionDisabled, localize('debugBreakpointFunctionDisabled', 'Icon for disabled function breakpoints.')); @@ -34,10 +34,8 @@ export const debugBreakpointLogUnverified = registerIcon('debug-breakpoint-log-u export const debugBreakpointLog = registerIcon('debug-breakpoint-log', Codicon.debugBreakpointLog, localize('debugBreakpointLog', 'Icon for log breakpoints.')); export const debugBreakpointLogDisabled = registerIcon('debug-breakpoint-log-disabled', Codicon.debugBreakpointLogDisabled, localize('debugBreakpointLogDisabled', 'Icon for disabled log breakpoint.')); -export const debugStackframeActive = registerIcon('debug-stackframe-active', Codicon.debugStackframeActive, localize('debugStackframeActive', 'Icon for an active stackframe.')); -export const debugStackframeDot = registerIcon('debug-stackframe-dot', Codicon.debugStackframeDot, localize('debugStackframeDot', 'Icon for a stackframe dot.')); -export const debugStackframe = registerIcon('debug-stackframe', Codicon.debugStackframe, localize('debugStackframe', 'Icon for a stackframe.')); -export const debugStackframeFocused = registerIcon('debug-stackframe-focused', Codicon.debugStackframeFocused, localize('debugStackframeFocused', 'Icon for a focused stackframe.')); +export const debugStackframe = registerIcon('debug-stackframe', Codicon.debugStackframe, localize('debugStackframe', 'Icon for a stackframe shown in the editor glyph margin.')); +export const debugStackframeFocused = registerIcon('debug-stackframe-focused', Codicon.debugStackframeFocused, localize('debugStackframeFocused', 'Icon for a focused stackframe shown in the editor glyph margin.')); export const debugGripper = registerIcon('debug-gripper', Codicon.gripper, localize('debugGripper', 'Icon for the debug bar gripper.')); @@ -66,8 +64,7 @@ export const watchExpressionsAdd = registerIcon('watch-expressions-add', Codicon export const watchExpressionsAddFuncBreakpoint = registerIcon('watch-expressions-add-function-breakpoint', Codicon.add, localize('watchExpressionsAddFuncBreakpoint', 'Icon for the add function breakpoint action in the watch view.')); export const breakpointsRemoveAll = registerIcon('breakpoints-remove-all', Codicon.closeAll, localize('breakpointsRemoveAll', 'Icon for the remove all action in the breakpoints view.')); -export const breakpointsActivate = registerIcon('breakpoints-activate', Codicon.activateBreakpoints, localize('breakpointsActivate', 'Icon for the activatel action in the breakpoints view.')); +export const breakpointsActivate = registerIcon('breakpoints-activate', Codicon.activateBreakpoints, localize('breakpointsActivate', 'Icon for the activate action in the breakpoints view.')); export const debugConsoleEvaluationInput = registerIcon('debug-console-evaluation-input', Codicon.arrowSmallRight, localize('debugConsoleEvaluationInput', 'Icon for the debug evaluation input marker.')); export const debugConsoleEvaluationPrompt = registerIcon('debug-console-evaluation-prompt', Codicon.chevronRight, localize('debugConsoleEvaluationPrompt', 'Icon for the debug evaluation prompt.')); -export const debugExceptionWidgetClose = registerIcon('debug-exception-widget-close', Codicon.close, localize('debugExceptionWidgetClose', 'Icon for the close action of the debug exception widget.')); diff --git a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts index 0fc8890c1f8..cd8159ad070 100644 --- a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts @@ -10,7 +10,7 @@ import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IExceptionInfo, IDebugSession, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID } from 'vs/workbench/contrib/debug/common/debug'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -18,7 +18,7 @@ import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { Action } from 'vs/base/common/actions'; -import { debugExceptionWidgetClose } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { widgetClose } from 'vs/platform/theme/common/iconRegistry'; const $ = dom.$; // theming @@ -80,7 +80,7 @@ export class ExceptionWidget extends ZoneWidget { let ariaLabel = label.textContent; const actionBar = new ActionBar(actions); - actionBar.push(new Action('editor.closeExceptionWidget', nls.localize('close', "Close"), debugExceptionWidgetClose.classNames, true, async () => { + actionBar.push(new Action('editor.closeExceptionWidget', nls.localize('close', "Close"), ThemeIcon.asClassName(widgetClose), true, async () => { const contribution = this.editor.getContribution(EDITOR_CONTRIBUTION_ID); contribution.closeExceptionWidget(); }), { label: false, icon: true }); From 9a657db088e1e22f7ad14b5ef812bc76ee7f07f7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 11:43:50 +0100 Subject: [PATCH 0186/1837] add tiny util to allow performance mark collection (via perf_hooks) independent of amd or commonjs usage --- src/vs/base/node/startupPerf.d.ts | 12 ++++++++ src/vs/base/node/startupPerf.js | 48 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/vs/base/node/startupPerf.d.ts create mode 100644 src/vs/base/node/startupPerf.js diff --git a/src/vs/base/node/startupPerf.d.ts b/src/vs/base/node/startupPerf.d.ts new file mode 100644 index 00000000000..62be9ef72ac --- /dev/null +++ b/src/vs/base/node/startupPerf.d.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PerformanceEntry } from 'perf_hooks'; + +/** + * Return all performance entries captured so far and stop startup + * performance recording. + */ +export function consumeAndStop(): PerformanceEntry[]; diff --git a/src/vs/base/node/startupPerf.js b/src/vs/base/node/startupPerf.js new file mode 100644 index 00000000000..2f3e03f1cca --- /dev/null +++ b/src/vs/base/node/startupPerf.js @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +//@ts-check + +function _factory(sharedObj, nodeRequire) { + if (!sharedObj.MonacoStartupPerformanceMarks) { + + const { PerformanceObserver } = nodeRequire('perf_hooks'); + + let startupEntries = []; + + const startupObs = new PerformanceObserver(list => { startupEntries = startupEntries.concat(list.getEntries()); }); + startupObs.observe({ buffered: true, entryTypes: ['mark'] }); + + sharedObj.MonacoStartupPerformanceMarks = { + startupEntries, + dispose() { + startupObs.disconnect(); + startupEntries.length = 0; + delete sharedObj.MonacoStartupPerformanceMarks; + }, + }; + } + + return { + consumeAndStop() { + const entries = sharedObj.startupEntries.slice(0); + sharedObj.MonacoStartupPerformanceMarks.dispose(); + return entries; + } + }; +} + +// This module can be loaded in an amd and commonjs-context. +// Because we want both instances to use the same perf-data +// we store them globally +if (typeof define === 'function') { + // amd + define([], function () { return _factory(global, require.__$__nodeRequire); }); +} else if (typeof module === 'object' && typeof module.exports === 'object') { + // commonjs + module.exports = _factory(global, require); +} From 7e4f90277da57cac7e5a8081878a400a77600e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 11:44:18 +0100 Subject: [PATCH 0187/1837] run prettier over yml files --- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/calendar.yml | 68 +-- .github/commands.yml | 21 +- .github/endgame/insiders.yml | 10 +- .github/insiders.yml | 10 +- .github/similarity.yml | 6 +- .github/workflows/author-verified.yml | 2 +- .github/workflows/ci.yml | 38 +- .github/workflows/codeql.yml | 61 +- .github/workflows/commands.yml | 2 +- .github/workflows/deep-classifier-monitor.yml | 2 +- .github/workflows/deep-classifier-runner.yml | 2 +- .github/workflows/deep-classifier-scraper.yml | 2 +- .github/workflows/devcontainer-cache.yml | 7 +- .github/workflows/english-please.yml | 2 +- .github/workflows/feature-request.yml | 2 +- .github/workflows/latest-release-monitor.yml | 2 +- .github/workflows/locker.yml | 2 +- .github/workflows/needs-more-info-closer.yml | 4 +- .github/workflows/on-label.yml | 2 +- .github/workflows/on-open.yml | 2 +- .../workflows/release-pipeline-labeler.yml | 2 +- .github/workflows/rich-navigation.yml | 42 +- .../workflows/test-plan-item-validator.yml | 2 +- .../darwin/continuous-build-darwin.yml | 126 ++-- .../darwin/product-build-darwin.yml | 556 +++++++++--------- build/azure-pipelines/distro-build.yml | 54 +- build/azure-pipelines/exploration-build.yml | 50 +- .../linux/continuous-build-linux.yml | 148 ++--- .../linux/product-build-linux.yml | 368 ++++++------ build/azure-pipelines/product-build.yml | 324 +++++----- build/azure-pipelines/product-compile.yml | 260 ++++---- .../publish-types/publish-types.yml | 128 ++-- build/azure-pipelines/release.yml | 32 +- build/azure-pipelines/sync-mooncake.yml | 36 +- .../azure-pipelines/web/product-build-web.yml | 197 +++---- .../win32/continuous-build-win32.yml | 140 ++--- .../win32/product-build-win32-arm64.yml | 344 +++++------ .../win32/product-build-win32.yml | 454 +++++++------- 39 files changed, 1755 insertions(+), 1757 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 4a04784b892..51e7f366043 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: Question - url: https://stackoverflow.com/questions/tagged/visual-studio-code + url: https://stackoverflow.com/questions/tagged/visual-studio-code about: Please ask and answer questions here. diff --git a/.github/calendar.yml b/.github/calendar.yml index f149579600b..c1b5a256980 100644 --- a/.github/calendar.yml +++ b/.github/calendar.yml @@ -1,37 +1,37 @@ { - '2018-01-29 18:00, US/Pacific': 'endgame', - '2018-02-07 12:00, US/Pacific': 'release', # 1.20.0 - '2018-02-12 12:00, US/Pacific': 'development', - '2018-02-14 16:00, Europe/Zurich': 'release', # 1.20.1 - '2018-02-19 16:00, Europe/Zurich': 'development', - '2018-02-26 18:00, US/Pacific': 'endgame', - '2018-03-07 12:00, US/Pacific': 'release', # 1.21.0 - '2018-03-12 12:00, US/Pacific': 'development', - '2018-03-15 12:00, US/Pacific': 'release', # 1.21.1 - '2018-03-20 12:00, US/Pacific': 'development', - '2018-03-26 18:00, US/Pacific': 'endgame', - '2018-04-06 18:00, US/Pacific': 'release', # 1.22.1 - '2018-04-11 18:00, US/Pacific': 'development', - '2018-04-12 12:00, US/Pacific': 'release', # 1.22.2 - '2018-04-17 12:00, US/Pacific': 'development', - '2018-04-23 18:00, US/Pacific': 'endgame', - '2018-05-03 12:00, US/Pacific': 'release', # 1.23.0 - '2018-05-08 12:00, US/Pacific': 'development', - '2018-05-10 12:00, US/Pacific': 'release', # 1.23.1 - '2018-05-15 12:00, US/Pacific': 'development', - '2018-05-28 18:00, US/Pacific': 'endgame', + "2018-01-29 18:00, US/Pacific": "endgame", + "2018-02-07 12:00, US/Pacific": "release", # 1.20.0 + "2018-02-12 12:00, US/Pacific": "development", + "2018-02-14 16:00, Europe/Zurich": "release", # 1.20.1 + "2018-02-19 16:00, Europe/Zurich": "development", + "2018-02-26 18:00, US/Pacific": "endgame", + "2018-03-07 12:00, US/Pacific": "release", # 1.21.0 + "2018-03-12 12:00, US/Pacific": "development", + "2018-03-15 12:00, US/Pacific": "release", # 1.21.1 + "2018-03-20 12:00, US/Pacific": "development", + "2018-03-26 18:00, US/Pacific": "endgame", + "2018-04-06 18:00, US/Pacific": "release", # 1.22.1 + "2018-04-11 18:00, US/Pacific": "development", + "2018-04-12 12:00, US/Pacific": "release", # 1.22.2 + "2018-04-17 12:00, US/Pacific": "development", + "2018-04-23 18:00, US/Pacific": "endgame", + "2018-05-03 12:00, US/Pacific": "release", # 1.23.0 + "2018-05-08 12:00, US/Pacific": "development", + "2018-05-10 12:00, US/Pacific": "release", # 1.23.1 + "2018-05-15 12:00, US/Pacific": "development", + "2018-05-28 18:00, US/Pacific": "endgame", # 'release' not needed anymore, return to 'development' after releasing. - '2018-06-06 12:00, US/Pacific': 'development', # 1.24.0 released - '2018-06-25 18:00, US/Pacific': 'endgame', - '2018-07-05 12:00, US/Pacific': 'development', # 1.25.0 released - '2018-07-30 18:00, US/Pacific': 'endgame', - '2018-08-13 12:00, US/Pacific': 'development', # 1.26.0 released - '2018-08-27 18:00, US/Pacific': 'endgame', - '2018-09-05 12:00, US/Pacific': 'development', # 1.27.0 released - '2018-09-24 18:00, US/Pacific': 'endgame', - '2018-10-08 09:00, US/Pacific': 'development', # 1.28.0 released - '2018-10-29 18:00, US/Pacific': 'endgame', - '2018-11-12 11:00, US/Pacific': 'development', # 1.29.0 released - '2018-12-03 18:00, US/Pacific': 'endgame', - '2018-12-12 13:00, US/Pacific': 'development', # 1.30.0 released + "2018-06-06 12:00, US/Pacific": "development", # 1.24.0 released + "2018-06-25 18:00, US/Pacific": "endgame", + "2018-07-05 12:00, US/Pacific": "development", # 1.25.0 released + "2018-07-30 18:00, US/Pacific": "endgame", + "2018-08-13 12:00, US/Pacific": "development", # 1.26.0 released + "2018-08-27 18:00, US/Pacific": "endgame", + "2018-09-05 12:00, US/Pacific": "development", # 1.27.0 released + "2018-09-24 18:00, US/Pacific": "endgame", + "2018-10-08 09:00, US/Pacific": "development", # 1.28.0 released + "2018-10-29 18:00, US/Pacific": "endgame", + "2018-11-12 11:00, US/Pacific": "development", # 1.29.0 released + "2018-12-03 18:00, US/Pacific": "endgame", + "2018-12-12 13:00, US/Pacific": "development", # 1.30.0 released } diff --git a/.github/commands.yml b/.github/commands.yml index 64fdf683bfe..5073658e526 100644 --- a/.github/commands.yml +++ b/.github/commands.yml @@ -1,12 +1,13 @@ { - perform: true, - commands: [ - { - type: 'comment', - name: 'findDuplicates', - allowUsers: ['cleidigh', 'usernamehw', 'gjsjohnmurray', 'IllusionMH'], - action: 'comment', - comment: "Potential duplicates:\n${potentialDuplicates}" - } - ] + perform: true, + commands: + [ + { + type: "comment", + name: "findDuplicates", + allowUsers: ["cleidigh", "usernamehw", "gjsjohnmurray", "IllusionMH"], + action: "comment", + comment: "Potential duplicates:\n${potentialDuplicates}", + }, + ], } diff --git a/.github/endgame/insiders.yml b/.github/endgame/insiders.yml index f11bd611cb2..4996474f4d2 100644 --- a/.github/endgame/insiders.yml +++ b/.github/endgame/insiders.yml @@ -1,6 +1,6 @@ { - insidersLabel: 'insiders', - insidersColor: '006b75', - action: 'add', - perform: true -} \ No newline at end of file + insidersLabel: "insiders", + insidersColor: "006b75", + action: "add", + perform: true, +} diff --git a/.github/insiders.yml b/.github/insiders.yml index e9a49ce7858..ab59e873bee 100644 --- a/.github/insiders.yml +++ b/.github/insiders.yml @@ -1,6 +1,6 @@ { - insidersLabel: 'insiders', - insidersColor: '006b75', - action: 'remove', - perform: true -} \ No newline at end of file + insidersLabel: "insiders", + insidersColor: "006b75", + action: "remove", + perform: true, +} diff --git a/.github/similarity.yml b/.github/similarity.yml index cd51cd2da64..cb00a4c9a8e 100644 --- a/.github/similarity.yml +++ b/.github/similarity.yml @@ -1,5 +1,5 @@ { - perform: true, - whenCreatedByTeam: false, - comment: "(Experimental duplicate detection)\nThanks for submitting this issue. Please also check if it is already covered by an existing one, like:\n${potentialDuplicates}" + perform: true, + whenCreatedByTeam: false, + comment: "(Experimental duplicate detection)\nThanks for submitting this issue. Please also check if it is already covered by an existing one, like:\n${potentialDuplicates}", } diff --git a/.github/workflows/author-verified.yml b/.github/workflows/author-verified.yml index 72b56f59110..a066c194d99 100644 --- a/.github/workflows/author-verified.yml +++ b/.github/workflows/author-verified.yml @@ -16,7 +16,7 @@ jobs: if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'author-verification-requested') uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d509cce2a33..08775eab933 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,22 +123,22 @@ jobs: CHILD_CONCURRENCY: "1" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v1 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - name: Setup Build Environment - - uses: actions/setup-node@v1 - with: - node-version: 10 - - run: yarn --frozen-lockfile - name: Install Dependencies - - run: yarn monaco-compile-check - name: Run Monaco Editor Checks - - run: yarn gulp editor-esm-bundle - name: Editor Distro & ESM Bundle + - uses: actions/checkout@v1 + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + name: Setup Build Environment + - uses: actions/setup-node@v1 + with: + node-version: 10 + - run: yarn --frozen-lockfile + name: Install Dependencies + - run: yarn monaco-compile-check + name: Run Monaco Editor Checks + - run: yarn gulp editor-esm-bundle + name: Editor Distro & ESM Bundle diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 017708844a4..88761f8aa9a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,48 +2,47 @@ name: "Code Scanning" on: schedule: - - cron: '0 0 * * 2' + - cron: "0 0 * * 2" jobs: CodeQL-Build: - # CodeQL runs on ubuntu-latest and windows-latest runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: javascript + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: javascript - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 37b6f626fe2..bda1b25092d 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -11,7 +11,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions diff --git a/.github/workflows/deep-classifier-monitor.yml b/.github/workflows/deep-classifier-monitor.yml index eff700780cc..439d2f2a46b 100644 --- a/.github/workflows/deep-classifier-monitor.yml +++ b/.github/workflows/deep-classifier-monitor.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/deep-classifier-runner.yml b/.github/workflows/deep-classifier-runner.yml index 541e756f068..ffa11badc9c 100644 --- a/.github/workflows/deep-classifier-runner.yml +++ b/.github/workflows/deep-classifier-runner.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/deep-classifier-scraper.yml b/.github/workflows/deep-classifier-scraper.yml index 9e8e58b274e..1ce6faed4b2 100644 --- a/.github/workflows/deep-classifier-scraper.yml +++ b/.github/workflows/deep-classifier-scraper.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/devcontainer-cache.yml b/.github/workflows/devcontainer-cache.yml index 82290a475ee..a250b56cd7a 100644 --- a/.github/workflows/devcontainer-cache.yml +++ b/.github/workflows/devcontainer-cache.yml @@ -4,12 +4,12 @@ on: push: # Currently doing this for master, but could be done for PRs as well branches: - - 'master' + - "master" # Only updates to these files result in changes to installed packages, so skip otherwise paths: - - '**/package-lock.json' - - '**/yarn.lock' + - "**/package-lock.json" + - "**/yarn.lock" jobs: devcontainer: @@ -38,4 +38,3 @@ jobs: if [ "$GIT_BRANCH" == "" ]; then GIT_BRANCH=master; fi .devcontainer/cache/build-cache-image.sh "${{ secrets.CONTAINER_IMAGE_REGISTRY }}/public/vscode/devcontainers/repos/microsoft/vscode" "${GIT_BRANCH}" - diff --git a/.github/workflows/english-please.yml b/.github/workflows/english-please.yml index 22ea39a221c..7336c429df1 100644 --- a/.github/workflows/english-please.yml +++ b/.github/workflows/english-please.yml @@ -12,7 +12,7 @@ jobs: if: contains(github.event.issue.labels.*.name, '*english-please') uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml index 29e2b734123..4a3c30065f7 100644 --- a/.github/workflows/feature-request.yml +++ b/.github/workflows/feature-request.yml @@ -16,7 +16,7 @@ jobs: if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions diff --git a/.github/workflows/latest-release-monitor.yml b/.github/workflows/latest-release-monitor.yml index 8b246ec01d2..190da52ba32 100644 --- a/.github/workflows/latest-release-monitor.yml +++ b/.github/workflows/latest-release-monitor.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml index 9f3a32b7be3..abfce92748b 100644 --- a/.github/workflows/locker.yml +++ b/.github/workflows/locker.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions diff --git a/.github/workflows/needs-more-info-closer.yml b/.github/workflows/needs-more-info-closer.yml index 6f3d68cd0b8..3475b3ae878 100644 --- a/.github/workflows/needs-more-info-closer.yml +++ b/.github/workflows/needs-more-info-closer.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions @@ -24,7 +24,7 @@ jobs: token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}} label: needs more info closeDays: 7 - additionalTeam: "cleidigh|usernamehw|gjsjohnmurray|IllusionMH" + additionalTeam: "cleidigh|usernamehw|gjsjohnmurray|IllusionMH" closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" pingDays: 80 pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/on-label.yml b/.github/workflows/on-label.yml index b678a00ba00..f06ba0f4ea0 100644 --- a/.github/workflows/on-label.yml +++ b/.github/workflows/on-label.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/on-open.yml b/.github/workflows/on-open.yml index dfdee7c7f86..9e9076c11fa 100644 --- a/.github/workflows/on-open.yml +++ b/.github/workflows/on-open.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Install Actions diff --git a/.github/workflows/release-pipeline-labeler.yml b/.github/workflows/release-pipeline-labeler.yml index a9c0bb26e5c..b4a4f355fb5 100644 --- a/.github/workflows/release-pipeline-labeler.yml +++ b/.github/workflows/release-pipeline-labeler.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout Actions uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" ref: v40 path: ./actions - name: Checkout Repo diff --git a/.github/workflows/rich-navigation.yml b/.github/workflows/rich-navigation.yml index 0f00e8071d6..aee0796fa28 100644 --- a/.github/workflows/rich-navigation.yml +++ b/.github/workflows/rich-navigation.yml @@ -9,28 +9,28 @@ jobs: richnav: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - uses: actions/cache@v2 - id: caching-stage - name: Cache VS Code dependencies - with: - path: node_modules - key: ${{ runner.os }}-dependencies-${{ hashfiles('yarn.lock') }} - restore-keys: ${{ runner.os }}-dependencies- + - uses: actions/cache@v2 + id: caching-stage + name: Cache VS Code dependencies + with: + path: node_modules + key: ${{ runner.os }}-dependencies-${{ hashfiles('yarn.lock') }} + restore-keys: ${{ runner.os }}-dependencies- - - uses: actions/setup-node@v1 - with: - node-version: 10 + - uses: actions/setup-node@v1 + with: + node-version: 10 - - name: Install dependencies - if: steps.caching-stage.outputs.cache-hit != 'true' - run: yarn --frozen-lockfile - env: - CHILD_CONCURRENCY: 1 + - name: Install dependencies + if: steps.caching-stage.outputs.cache-hit != 'true' + run: yarn --frozen-lockfile + env: + CHILD_CONCURRENCY: 1 - - uses: microsoft/RichCodeNavIndexer@v0.1 - with: - languages: typescript - repo-token: ${{ secrets.GITHUB_TOKEN }} - continue-on-error: true + - uses: microsoft/RichCodeNavIndexer@v0.1 + with: + languages: typescript + repo-token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true diff --git a/.github/workflows/test-plan-item-validator.yml b/.github/workflows/test-plan-item-validator.yml index 0c26549d1d8..57fcaa53165 100644 --- a/.github/workflows/test-plan-item-validator.yml +++ b/.github/workflows/test-plan-item-validator.yml @@ -12,7 +12,7 @@ jobs: if: contains(github.event.issue.labels.*.name, 'testplan-item') || contains(github.event.issue.labels.*.name, 'invalid-testplan-item') uses: actions/checkout@v2 with: - repository: 'microsoft/vscode-github-triage-actions' + repository: "microsoft/vscode-github-triage-actions" path: ./actions ref: v40 - name: Install Actions diff --git a/build/azure-pipelines/darwin/continuous-build-darwin.yml b/build/azure-pipelines/darwin/continuous-build-darwin.yml index 3711d5c21d8..75c28106c5e 100644 --- a/build/azure-pipelines/darwin/continuous-build-darwin.yml +++ b/build/azure-pipelines/darwin/continuous-build-darwin.yml @@ -1,79 +1,79 @@ steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" -- script: | - CHILD_CONCURRENCY=1 yarn --frozen-lockfile - displayName: Install Dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- script: | - yarn electron x64 - displayName: Download Electron + - script: | + yarn electron x64 + displayName: Download Electron -- script: | - yarn monaco-compile-check - displayName: Run Monaco Editor Checks + - script: | + yarn monaco-compile-check + displayName: Run Monaco Editor Checks -- script: | - yarn valid-layers-check - displayName: Run Valid Layers Checks + - script: | + yarn valid-layers-check + displayName: Run Valid Layers Checks -- script: | - yarn compile - displayName: Compile Sources + - script: | + yarn compile + displayName: Compile Sources -- script: | - yarn download-builtin-extensions - displayName: Download Built-in Extensions + - script: | + yarn download-builtin-extensions + displayName: Download Built-in Extensions -- script: | - ./scripts/test.sh --tfs "Unit Tests" - displayName: Run Unit Tests (Electron) + - script: | + ./scripts/test.sh --tfs "Unit Tests" + displayName: Run Unit Tests (Electron) -- script: | - yarn test-browser --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" - displayName: Run Unit Tests (Browser) + - script: | + yarn test-browser --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" + displayName: Run Unit Tests (Browser) -- script: | - ./scripts/test-integration.sh --tfs "Integration Tests" - displayName: Run Integration Tests (Electron) + - script: | + ./scripts/test-integration.sh --tfs "Integration Tests" + displayName: Run Integration Tests (Electron) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: crash-dump-macos - targetPath: .build/crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: crash-dump-macos + targetPath: .build/crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: succeededOrFailed() diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index e73ba836973..1afa0d2ca5c 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -1,320 +1,320 @@ steps: -- script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - displayName: Prepare cache flag + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- script: | - set -e - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e + - script: | + set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling -- script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro -- script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag + - script: | + echo -n $VSCODE_ARCH > .build/arch + displayName: Prepare arch cache flag -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" -- script: | - set -e - sudo xcode-select -s /Applications/Xcode_12.2.app - displayName: Switch to Xcode 12 - condition: eq(variables['VSCODE_ARCH'], 'arm64') + - script: | + set -e + sudo xcode-select -s /Applications/Xcode_12.2.app + displayName: Switch to Xcode 12 + condition: eq(variables['VSCODE_ARCH'], 'arm64') -- script: | - set -e - npm install -g node-gyp@7.1.0 - node-gyp --version - displayName: Update node-gyp - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + set -e + npm install -g node-gyp@7.1.0 + node-gyp --version + displayName: Update node-gyp + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - export npm_config_arch=$(VSCODE_ARCH) - export npm_config_node_gyp=$(which node-gyp) - export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - CHILD_CONCURRENCY=1 yarn --frozen-lockfile --verbose - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + set -e + export npm_config_arch=$(VSCODE_ARCH) + export npm_config_node_gyp=$(which node-gyp) + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + CHILD_CONCURRENCY=1 yarn --frozen-lockfile --verbose + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - export npm_config_arch=$(VSCODE_ARCH) - export npm_config_node_gyp=$(which node-gyp) - export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + export npm_config_arch=$(VSCODE_ARCH) + export npm_config_node_gyp=$(which node-gyp) + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- script: | - set -e - export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - yarn electron-rebuild - displayName: Rebuild native modules for ARM64 - condition: eq(variables['VSCODE_ARCH'], 'arm64') + - script: | + set -e + export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + yarn electron-rebuild + displayName: Rebuild native modules for ARM64 + condition: eq(variables['VSCODE_ARCH'], 'arm64') -- script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-darwin-$(VSCODE_ARCH)-min-ci - displayName: Build + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-darwin-$(VSCODE_ARCH)-min-ci + displayName: Build -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-darwin-min-ci - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-web-darwin-min-ci - displayName: Build reh - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-darwin-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-web-darwin-min-ci + displayName: Build reh + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) -- script: | - set -e - yarn electron $(VSCODE_ARCH) - displayName: Download Electron - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + yarn electron $(VSCODE_ARCH) + displayName: Download Electron + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain - security default-keychain -s $(agent.tempdirectory)/buildagent.keychain - security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain - echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12 - security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain - VSCODE_ARCH="$(VSCODE_ARCH)" DEBUG=electron-osx-sign* node build/darwin/sign.js - displayName: Set Hardened Entitlements + - script: | + set -e + security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + security default-keychain -s $(agent.tempdirectory)/buildagent.keychain + security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12 + security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain + VSCODE_ARCH="$(VSCODE_ARCH)" DEBUG=electron-osx-sign* node build/darwin/sign.js + displayName: Set Hardened Entitlements -- script: | - set -e - ./scripts/test.sh --build --tfs "Unit Tests" - displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + ./scripts/test.sh --build --tfs "Unit Tests" + displayName: Run unit tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - yarn test-browser --build --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" - displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + yarn test-browser --build --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" + displayName: Run unit tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - # Figure out the full absolute path of the product we just built - # including the remote server and configure the integration tests - # to run with these builds instead of running out of sources. - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) - APP_NAME="`ls $APP_ROOT | head -n 1`" - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ - ./scripts/test-integration.sh --build --tfs "Integration Tests" - displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + # Figure out the full absolute path of the product we just built + # including the remote server and configure the integration tests + # to run with these builds instead of running out of sources. + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) + APP_NAME="`ls $APP_ROOT | head -n 1`" + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ + ./scripts/test-integration.sh --build --tfs "Integration Tests" + displayName: Run integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ - ./resources/server/test/test-web-integration.sh --browser webkit - displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ + ./resources/server/test/test-web-integration.sh --browser webkit + displayName: Run integration tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) - APP_NAME="`ls $APP_ROOT | head -n 1`" - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ - ./resources/server/test/test-remote-integration.sh - displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) + APP_NAME="`ls $APP_ROOT | head -n 1`" + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ + ./resources/server/test/test-remote-integration.sh + displayName: Run remote integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) - APP_NAME="`ls $APP_ROOT | head -n 1`" - yarn smoketest --build "$APP_ROOT/$APP_NAME" - continueOnError: true - displayName: Run smoke tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) + APP_NAME="`ls $APP_ROOT | head -n 1`" + yarn smoketest --build "$APP_ROOT/$APP_NAME" + continueOnError: true + displayName: Run smoke tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ - yarn smoketest --web --headless - continueOnError: true - displayName: Run smoke tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ + yarn smoketest --web --headless + continueOnError: true + displayName: Run smoke tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: crash-dump-macos-$(VSCODE_ARCH) - targetPath: .build/crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: crash-dump-macos-$(VSCODE_ARCH) + targetPath: .build/crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: succeededOrFailed() -- script: | - set -e - pushd $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) && zip -r -X -y $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip * && popd - displayName: Archive build + - script: | + set -e + pushd $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) && zip -r -X -y $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip * && popd + displayName: Archive build -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '$(agent.builddirectory)' - Pattern: 'VSCode-darwin-$(VSCODE_ARCH).zip' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-401337-Apple", - "operationSetCode": "MacAppDeveloperSign", - "parameters": [ - { - "parameterName": "Hardening", - "parameterValue": "--options=runtime" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 60 - displayName: Codesign + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: "$(agent.builddirectory)" + Pattern: "VSCode-darwin-$(VSCODE_ARCH).zip" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401337-Apple", + "operationSetCode": "MacAppDeveloperSign", + "parameters": [ + { + "parameterName": "Hardening", + "parameterValue": "--options=runtime" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 60 + displayName: Codesign -- script: | - zip -d $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip "*.pkg" - displayName: Clean Archive + - script: | + zip -d $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip "*.pkg" + displayName: Clean Archive -- script: | - APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) - APP_NAME="`ls $APP_ROOT | head -n 1`" - BUNDLE_IDENTIFIER=$(node -p "require(\"$APP_ROOT/$APP_NAME/Contents/Resources/app/product.json\").darwinBundleIdentifier") - echo "##vso[task.setvariable variable=BundleIdentifier]$BUNDLE_IDENTIFIER" - displayName: Export bundle identifier + - script: | + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) + APP_NAME="`ls $APP_ROOT | head -n 1`" + BUNDLE_IDENTIFIER=$(node -p "require(\"$APP_ROOT/$APP_NAME/Contents/Resources/app/product.json\").darwinBundleIdentifier") + echo "##vso[task.setvariable variable=BundleIdentifier]$BUNDLE_IDENTIFIER" + displayName: Export bundle identifier -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '$(agent.builddirectory)' - Pattern: 'VSCode-darwin-$(VSCODE_ARCH).zip' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-401337-Apple", - "operationSetCode": "MacAppNotarize", - "parameters": [ - { - "parameterName": "BundleId", - "parameterValue": "$(BundleIdentifier)" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 60 - displayName: Notarization + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: "$(agent.builddirectory)" + Pattern: "VSCode-darwin-$(VSCODE_ARCH).zip" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401337-Apple", + "operationSetCode": "MacAppNotarize", + "parameters": [ + { + "parameterName": "BundleId", + "parameterValue": "$(BundleIdentifier)" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 60 + displayName: Notarization -- script: | - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) - APP_NAME="`ls $APP_ROOT | head -n 1`" - "$APP_ROOT/$APP_NAME/Contents/Resources/app/bin/code" --export-default-configuration=.build - displayName: Verify start after signing (export configuration) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) + APP_NAME="`ls $APP_ROOT | head -n 1`" + "$APP_ROOT/$APP_NAME/Contents/Resources/app/bin/code" --export-default-configuration=.build + displayName: Verify start after signing (export configuration) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - VSCODE_ARCH="$(VSCODE_ARCH)" \ - ./build/azure-pipelines/darwin/publish.sh - displayName: Publish + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_ARCH="$(VSCODE_ARCH)" \ + ./build/azure-pipelines/darwin/publish.sh + displayName: Publish -- script: | - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ - yarn gulp upload-vscode-configuration - displayName: Upload configuration (for Bing settings search) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - continueOnError: true + - script: | + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + yarn gulp upload-vscode-configuration + displayName: Upload configuration (for Bing settings search) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + continueOnError: true -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: "Component Detection" + continueOnError: true diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml index 15526080abb..331fbf9675e 100644 --- a/build/azure-pipelines/distro-build.yml +++ b/build/azure-pipelines/distro-build.yml @@ -1,42 +1,42 @@ trigger: branches: - include: ['master', 'release/*'] + include: ["master", "release/*"] pr: branches: - include: ['master', 'release/*'] + include: ["master", "release/*"] steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e + - script: | + set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" - git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git" - git fetch distro + git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git" + git fetch distro - # Push master branch into oss/master - git push distro origin/master:refs/heads/oss/master + # Push master branch into oss/master + git push distro origin/master:refs/heads/oss/master - # Push every release branch into oss/release - git for-each-ref --format="%(refname:short)" refs/remotes/origin/release/* | sed 's/^origin\/\(.*\)$/\0:refs\/heads\/oss\/\1/' | xargs git push distro + # Push every release branch into oss/release + git for-each-ref --format="%(refname:short)" refs/remotes/origin/release/* | sed 's/^origin\/\(.*\)$/\0:refs\/heads\/oss\/\1/' | xargs git push distro - git merge $(node -p "require('./package.json').distro") + git merge $(node -p "require('./package.json').distro") - displayName: Sync & Merge Distro + displayName: Sync & Merge Distro diff --git a/build/azure-pipelines/exploration-build.yml b/build/azure-pipelines/exploration-build.yml index a6a7dfe71a6..d4788edfd1d 100644 --- a/build/azure-pipelines/exploration-build.yml +++ b/build/azure-pipelines/exploration-build.yml @@ -1,40 +1,40 @@ pool: - vmImage: 'Ubuntu-16.04' + vmImage: "Ubuntu-16.04" trigger: branches: - include: ['master'] + include: ["master"] pr: branches: - include: ['master'] + include: ["master"] steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e + - script: | + set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" - git checkout origin/electron-11.x.y - git merge origin/master + git checkout origin/electron-11.x.y + git merge origin/master - # Push master branch into exploration branch - git push origin HEAD:electron-11.x.y + # Push master branch into exploration branch + git push origin HEAD:electron-11.x.y - displayName: Sync & Merge Exploration + displayName: Sync & Merge Exploration diff --git a/build/azure-pipelines/linux/continuous-build-linux.yml b/build/azure-pipelines/linux/continuous-build-linux.yml index 4bc21fc89a7..44cb9829472 100644 --- a/build/azure-pipelines/linux/continuous-build-linux.yml +++ b/build/azure-pipelines/linux/continuous-build-linux.yml @@ -1,92 +1,92 @@ steps: -- script: | - set -e - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start + - script: | + set -e + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" -- script: | - CHILD_CONCURRENCY=1 yarn --frozen-lockfile - displayName: Install Dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- script: | - yarn electron x64 - displayName: Download Electron + - script: | + yarn electron x64 + displayName: Download Electron -- script: | - yarn gulp hygiene - displayName: Run Hygiene Checks + - script: | + yarn gulp hygiene + displayName: Run Hygiene Checks -- script: | - yarn monaco-compile-check - displayName: Run Monaco Editor Checks + - script: | + yarn monaco-compile-check + displayName: Run Monaco Editor Checks -- script: | - yarn valid-layers-check - displayName: Run Valid Layers Checks + - script: | + yarn valid-layers-check + displayName: Run Valid Layers Checks -- script: | - yarn compile - displayName: Compile Sources + - script: | + yarn compile + displayName: Compile Sources -- script: | - yarn download-builtin-extensions - displayName: Download Built-in Extensions + - script: | + yarn download-builtin-extensions + displayName: Download Built-in Extensions -- script: | - DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" - displayName: Run Unit Tests (Electron) + - script: | + DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" + displayName: Run Unit Tests (Electron) -- script: | - DISPLAY=:10 yarn test-browser --browser chromium --tfs "Browser Unit Tests" - displayName: Run Unit Tests (Browser) + - script: | + DISPLAY=:10 yarn test-browser --browser chromium --tfs "Browser Unit Tests" + displayName: Run Unit Tests (Browser) -- script: | - DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" - displayName: Run Integration Tests (Electron) + - script: | + DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" + displayName: Run Integration Tests (Electron) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: crash-dump-linux - targetPath: .build/crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: crash-dump-linux + targetPath: .build/crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: succeededOrFailed() diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 45d2cc29988..1baa784b50e 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,215 +1,215 @@ steps: -- script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - displayName: Prepare cache flag + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- script: | - set -e - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling -- script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages -- script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag + - script: | + echo -n $VSCODE_ARCH > .build/arch + displayName: Prepare arch cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" -- script: | - set -e - CHILD_CONCURRENCY=1 npm_config_arch=$(NPM_ARCH) yarn --frozen-lockfile - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | + set -e + CHILD_CONCURRENCY=1 npm_config_arch=$(NPM_ARCH) yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-linux-$(VSCODE_ARCH)-min-ci - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci - displayName: Build + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-linux-$(VSCODE_ARCH)-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci + displayName: Build -- script: | - set -e - DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" - displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" + displayName: Run unit tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - DISPLAY=:10 yarn test-browser --build --browser chromium --tfs "Browser Unit Tests" - displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + DISPLAY=:10 yarn test-browser --build --browser chromium --tfs "Browser Unit Tests" + displayName: Run unit tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - # Figure out the full absolute path of the product we just built - # including the remote server and configure the integration tests - # to run with these builds instead of running out of sources. - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" - displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + # Figure out the full absolute path of the product we just built + # including the remote server and configure the integration tests + # to run with these builds instead of running out of sources. + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" + displayName: Run integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium - displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium + displayName: Run integration tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - DISPLAY=:10 ./resources/server/test/test-remote-integration.sh - displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-remote-integration.sh + displayName: Run remote integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: 'crash-dump-linux-$(VSCODE_ARCH)' - targetPath: .build/crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: "crash-dump-linux-$(VSCODE_ARCH)" + targetPath: .build/crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: and(succeededOrFailed(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: and(succeededOrFailed(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set -e - yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-deb" - yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm" - displayName: Build deb, rpm packages + - script: | + set -e + yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-deb" + yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm" + displayName: Build deb, rpm packages -- script: | - set -e - yarn gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap" - displayName: Prepare snap package - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - script: | + set -e + yarn gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap" + displayName: Prepare snap package + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) -# needed for code signing -- task: UseDotNet@2 - displayName: 'Install .NET Core SDK 2.x' - inputs: - version: 2.x + # needed for code signing + - task: UseDotNet@2 + displayName: "Install .NET Core SDK 2.x" + inputs: + version: 2.x -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '.build/linux/rpm' - Pattern: '*.rpm' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-450779-Pgp", - "operationSetCode": "LinuxSign", - "parameters": [ ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 120 - displayName: Codesign rpm + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: ".build/linux/rpm" + Pattern: "*.rpm" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-450779-Pgp", + "operationSetCode": "LinuxSign", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 120 + displayName: Codesign rpm -- script: | - set -e - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - VSCODE_ARCH="$(VSCODE_ARCH)" \ - ./build/azure-pipelines/linux/publish.sh - displayName: Publish + - script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + VSCODE_ARCH="$(VSCODE_ARCH)" \ + ./build/azure-pipelines/linux/publish.sh + displayName: Publish -- task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline Artifact' - inputs: - artifactName: 'snap-$(VSCODE_ARCH)' - targetPath: .build/linux/snap-tarball - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + - task: PublishPipelineArtifact@0 + displayName: "Publish Pipeline Artifact" + inputs: + artifactName: "snap-$(VSCODE_ARCH)" + targetPath: .build/linux/snap-tarball + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: "Component Detection" + continueOnError: true diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 28e3f2b4d05..57c0fac5d4e 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -2,180 +2,180 @@ trigger: none pr: none schedules: -- cron: "0 5 * * Mon-Fri" - displayName: Mon-Fri at 7:00 - branches: - include: - - master + - cron: "0 5 * * Mon-Fri" + displayName: Mon-Fri at 7:00 + branches: + include: + - master resources: containers: - - container: vscode-x64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic - endpoint: VSCodeHub - options: --user 0:0 - - container: vscode-arm64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 - endpoint: VSCodeHub - - container: vscode-armhf - image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-armhf - endpoint: VSCodeHub - - container: snapcraft - image: snapcore/snapcraft:stable + - container: vscode-x64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic + endpoint: VSCodeHub + options: --user 0:0 + - container: vscode-arm64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 + endpoint: VSCodeHub + - container: vscode-armhf + image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-armhf + endpoint: VSCodeHub + - container: snapcraft + image: snapcore/snapcraft:stable stages: -- stage: Compile - jobs: - - job: Compile - pool: - vmImage: 'Ubuntu-18.04' - container: vscode-x64 - steps: - - template: product-compile.yml + - stage: Compile + jobs: + - job: Compile + pool: + vmImage: "Ubuntu-18.04" + container: vscode-x64 + steps: + - template: product-compile.yml -- stage: Windows - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: VS2017-Win2016 - jobs: - - job: Windows - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: x64 - steps: - - template: win32/product-build-win32.yml - - - job: Windows32 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: ia32 - steps: - - template: win32/product-build-win32.yml - - - job: WindowsARM64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: arm64 - steps: - - template: win32/product-build-win32-arm64.yml - -- stage: Linux - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: 'Ubuntu-18.04' - jobs: - - job: Linux - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) - container: vscode-x64 - variables: - VSCODE_ARCH: x64 - NPM_ARCH: x64 - steps: - - template: linux/product-build-linux.yml - - - job: LinuxSnap + - stage: Windows dependsOn: - - Linux - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) - container: snapcraft - variables: - VSCODE_ARCH: x64 - steps: - - template: linux/snap-build-linux.yml + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: VS2017-Win2016 + jobs: + - job: Windows + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: x64 + steps: + - template: win32/product-build-win32.yml - - job: LinuxArmhf - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) - container: vscode-armhf - variables: - VSCODE_ARCH: armhf - NPM_ARCH: armv7l - steps: - - template: linux/product-build-linux.yml + - job: Windows32 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: ia32 + steps: + - template: win32/product-build-win32.yml - - job: LinuxArm64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) - container: vscode-arm64 - variables: - VSCODE_ARCH: arm64 - NPM_ARCH: arm64 - steps: - - template: linux/product-build-linux.yml + - job: WindowsARM64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: arm64 + steps: + - template: win32/product-build-win32-arm64.yml - - job: LinuxAlpine - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true')) - steps: - - template: linux/product-build-alpine.yml + - stage: Linux + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: "Ubuntu-18.04" + jobs: + - job: Linux + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) + container: vscode-x64 + variables: + VSCODE_ARCH: x64 + NPM_ARCH: x64 + steps: + - template: linux/product-build-linux.yml - - job: LinuxWeb - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true')) - variables: - VSCODE_ARCH: x64 - steps: - - template: web/product-build-web.yml + - job: LinuxSnap + dependsOn: + - Linux + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) + container: snapcraft + variables: + VSCODE_ARCH: x64 + steps: + - template: linux/snap-build-linux.yml -- stage: macOS - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: macOS-latest - jobs: - - job: macOS - condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: x64 - steps: - - template: darwin/product-build-darwin.yml + - job: LinuxArmhf + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) + container: vscode-armhf + variables: + VSCODE_ARCH: armhf + NPM_ARCH: armv7l + steps: + - template: linux/product-build-linux.yml -- stage: macOSARM64 - dependsOn: - - Compile - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: macOS-latest - jobs: - - job: macOSARM64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS_ARM64'], 'true')) - timeoutInMinutes: 90 - variables: - VSCODE_ARCH: arm64 - steps: - - template: darwin/product-build-darwin.yml + - job: LinuxArm64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) + container: vscode-arm64 + variables: + VSCODE_ARCH: arm64 + NPM_ARCH: arm64 + steps: + - template: linux/product-build-linux.yml -- stage: Mooncake - dependsOn: - - Windows - - Linux - - macOS - - macOSARM64 - condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) - pool: - vmImage: 'Ubuntu-18.04' - jobs: - - job: SyncMooncake - displayName: Sync Mooncake - steps: - - template: sync-mooncake.yml + - job: LinuxAlpine + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true')) + steps: + - template: linux/product-build-alpine.yml -- stage: Publish - dependsOn: - - Windows - - Linux - - macOS - - macOSARM64 - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) - pool: - vmImage: 'Ubuntu-18.04' - jobs: - - job: BuildService - displayName: Build Service - steps: - - template: release.yml + - job: LinuxWeb + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true')) + variables: + VSCODE_ARCH: x64 + steps: + - template: web/product-build-web.yml + + - stage: macOS + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: macOS-latest + jobs: + - job: macOS + condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: x64 + steps: + - template: darwin/product-build-darwin.yml + + - stage: macOSARM64 + dependsOn: + - Compile + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: macOS-latest + jobs: + - job: macOSARM64 + condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS_ARM64'], 'true')) + timeoutInMinutes: 90 + variables: + VSCODE_ARCH: arm64 + steps: + - template: darwin/product-build-darwin.yml + + - stage: Mooncake + dependsOn: + - Windows + - Linux + - macOS + - macOSARM64 + condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + pool: + vmImage: "Ubuntu-18.04" + jobs: + - job: SyncMooncake + displayName: Sync Mooncake + steps: + - template: sync-mooncake.yml + + - stage: Publish + dependsOn: + - Windows + - Linux + - macOS + - macOSARM64 + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) + pool: + vmImage: "Ubuntu-18.04" + jobs: + - job: BuildService + displayName: Build Service + steps: + - template: release.yml diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index a086149f053..5ea3587a31f 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -1,152 +1,152 @@ steps: -- script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - displayName: Prepare cache flag + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' - dryRun: true + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" + dryRun: true -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + echo -n $VSCODE_ARCH > .build/arch + displayName: Prepare arch cache flag + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + - script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) -# Mixin must run before optimize, because the CSS loader will -# inline small SVGs -- script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + # Mixin must run before optimize, because the CSS loader will + # inline small SVGs + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - yarn gulp hygiene - yarn monaco-compile-check - yarn valid-layers-check - displayName: Run hygiene, monaco compile & valid layers checks - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + yarn gulp hygiene + yarn monaco-compile-check + yarn valid-layers-check + displayName: Run hygiene, monaco compile & valid layers checks + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- script: | - set - - ./build/azure-pipelines/common/extract-telemetry.sh - displayName: Extract Telemetry - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set - + ./build/azure-pipelines/common/extract-telemetry.sh + displayName: Extract Telemetry + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ - ./build/azure-pipelines/common/publish-webview.sh - displayName: Publish Webview - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set -e + AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ + ./build/azure-pipelines/common/publish-webview.sh + displayName: Publish Webview + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - yarn gulp compile-build - yarn gulp compile-extensions-build - yarn gulp minify-vscode - yarn gulp minify-vscode-reh - yarn gulp minify-vscode-reh-web - displayName: Compile - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set -e + yarn gulp compile-build + yarn gulp compile-extensions-build + yarn gulp minify-vscode + yarn gulp minify-vscode-reh + yarn gulp minify-vscode-reh-web + displayName: Compile + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ - node build/azure-pipelines/upload-sourcemaps - displayName: Upload sourcemaps - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set -e + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + node build/azure-pipelines/upload-sourcemaps + displayName: Upload sourcemaps + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- script: | - set -e - VERSION=`node -p "require(\"./package.json\").version"` - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - node build/azure-pipelines/common/createBuild.js $VERSION - displayName: Create build - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - script: | + set -e + VERSION=`node -p "require(\"./package.json\").version"` + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + node build/azure-pipelines/common/createBuild.js $VERSION + displayName: Create build + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml index f3dfc213a7b..0e3f4e4daa4 100644 --- a/build/azure-pipelines/publish-types/publish-types.yml +++ b/build/azure-pipelines/publish-types/publish-types.yml @@ -2,82 +2,82 @@ trigger: branches: - include: ['refs/tags/*'] + include: ["refs/tags/*"] pr: none steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- bash: | - TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) - CHANNEL="G1C14HJ2F" + - bash: | + TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + CHANNEL="G1C14HJ2F" - if [ "$TAG_VERSION" == "1.999.0" ]; then - MESSAGE=". Someone pushed 1.999.0 tag. Please delete it ASAP from remote and local." + if [ "$TAG_VERSION" == "1.999.0" ]; then + MESSAGE=". Someone pushed 1.999.0 tag. Please delete it ASAP from remote and local." + + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \ + https://slack.com/api/chat.postMessage + + exit 1 + fi + displayName: Check 1.999.0 tag + + - bash: | + # Install build dependencies + (cd build && yarn) + node build/azure-pipelines/publish-types/check-version.js + displayName: Check version + + - bash: | + git config --global user.email "vscode@microsoft.com" + git config --global user.name "VSCode" + + git clone https://$(GITHUB_TOKEN)@github.com/DefinitelyTyped/DefinitelyTyped.git --depth=1 + node build/azure-pipelines/publish-types/update-types.js + + TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + + cd DefinitelyTyped + + git diff --color | cat + git add -A + git status + git checkout -b "vscode-types-$TAG_VERSION" + git commit -m "VS Code $TAG_VERSION Extension API" + git push origin "vscode-types-$TAG_VERSION" + + displayName: Push update to DefinitelyTyped + + - bash: | + TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + CHANNEL="G1C14HJ2F" + + MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:" + LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details." + MESSAGE2="[@eamodio, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode." curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ -H 'Content-type: application/json; charset=utf-8' \ --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \ https://slack.com/api/chat.postMessage - exit 1 - fi - displayName: Check 1.999.0 tag + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$LINK"'"}' \ + https://slack.com/api/chat.postMessage -- bash: | - # Install build dependencies - (cd build && yarn) - node build/azure-pipelines/publish-types/check-version.js - displayName: Check version + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE2"'"}' \ + https://slack.com/api/chat.postMessage -- bash: | - git config --global user.email "vscode@microsoft.com" - git config --global user.name "VSCode" - - git clone https://$(GITHUB_TOKEN)@github.com/DefinitelyTyped/DefinitelyTyped.git --depth=1 - node build/azure-pipelines/publish-types/update-types.js - - TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) - - cd DefinitelyTyped - - git diff --color | cat - git add -A - git status - git checkout -b "vscode-types-$TAG_VERSION" - git commit -m "VS Code $TAG_VERSION Extension API" - git push origin "vscode-types-$TAG_VERSION" - - displayName: Push update to DefinitelyTyped - -- bash: | - TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) - CHANNEL="G1C14HJ2F" - - MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:" - LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details." - MESSAGE2="[@eamodio, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode." - - curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ - -H 'Content-type: application/json; charset=utf-8' \ - --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \ - https://slack.com/api/chat.postMessage - - curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ - -H 'Content-type: application/json; charset=utf-8' \ - --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$LINK"'"}' \ - https://slack.com/api/chat.postMessage - - curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ - -H 'Content-type: application/json; charset=utf-8' \ - --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE2"'"}' \ - https://slack.com/api/chat.postMessage - - displayName: Send message on Slack + displayName: Send message on Slack diff --git a/build/azure-pipelines/release.yml b/build/azure-pipelines/release.yml index f5365b80c7e..edd293c04f6 100644 --- a/build/azure-pipelines/release.yml +++ b/build/azure-pipelines/release.yml @@ -1,22 +1,22 @@ steps: -- task: NodeTool@0 - inputs: - versionSpec: "10.x" + - task: NodeTool@0 + inputs: + versionSpec: "10.x" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e + - script: | + set -e - (cd build ; yarn) + (cd build ; yarn) - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - node build/azure-pipelines/common/releaseBuild.js + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + node build/azure-pipelines/common/releaseBuild.js diff --git a/build/azure-pipelines/sync-mooncake.yml b/build/azure-pipelines/sync-mooncake.yml index 810024fced1..280c9e6372d 100644 --- a/build/azure-pipelines/sync-mooncake.yml +++ b/build/azure-pipelines/sync-mooncake.yml @@ -1,24 +1,24 @@ steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e + - script: | + set -e - (cd build ; yarn) + (cd build ; yarn) - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(vscode-mooncake-storage-key)" \ - node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY" + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + MOONCAKE_STORAGE_ACCESS_KEY="$(vscode-mooncake-storage-key)" \ + node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY" diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index f7588916064..23a755f3f6f 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -1,117 +1,116 @@ steps: -- script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - displayName: Prepare cache flag + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- script: | - set -e - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling -- script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages -# - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 -# inputs: -# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' -# targetfolder: '**/node_modules, !**/node_modules/**/node_modules' -# vstsFeed: 'npm-vscode' + # - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + # inputs: + # keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + # targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + # vstsFeed: 'npm-vscode' + - script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile - displayName: Install dependencies - # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + # - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + # inputs: + # keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + # targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + # vstsFeed: 'npm-vscode' + # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -# - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 -# inputs: -# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' -# targetfolder: '**/node_modules, !**/node_modules/**/node_modules' -# vstsFeed: 'npm-vscode' -# condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + # - script: | + # set -e + # yarn postinstall + # displayName: Run postinstall scripts + # condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -# - script: | -# set -e -# yarn postinstall -# displayName: Run postinstall scripts -# condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality -- script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-web-min-ci + displayName: Build -- script: | - set -e - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - yarn gulp vscode-web-min-ci - displayName: Build + - script: | + set -e + AZURE_STORAGE_ACCOUNT="$(web-storage-account)" \ + AZURE_STORAGE_ACCESS_KEY="$(web-storage-key)" \ + node build/azure-pipelines/upload-cdn.js + displayName: Upload to CDN -- script: | - set -e - AZURE_STORAGE_ACCOUNT="$(web-storage-account)" \ - AZURE_STORAGE_ACCESS_KEY="$(web-storage-key)" \ - node build/azure-pipelines/upload-cdn.js - displayName: Upload to CDN + # upload only the workbench.web.api.js source maps because + # we just compiled these bits in the previous step and the + # general task to upload source maps has already been run + - script: | + set -e + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.api.js.map + displayName: Upload sourcemaps (Web) - # upload only the workbench.web.api.js source maps because - # we just compiled these bits in the previous step and the - # general task to upload source maps has already been run -- script: | - set -e - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ - node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.api.js.map - displayName: Upload sourcemaps (Web) - -- script: | - set -e - AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ - VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ - ./build/azure-pipelines/web/publish.sh - displayName: Publish + - script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + ./build/azure-pipelines/web/publish.sh + displayName: Publish diff --git a/build/azure-pipelines/win32/continuous-build-win32.yml b/build/azure-pipelines/win32/continuous-build-win32.yml index 6dd508a7c81..7bd18707381 100644 --- a/build/azure-pipelines/win32/continuous-build-win32.yml +++ b/build/azure-pipelines/win32/continuous-build-win32.yml @@ -1,87 +1,87 @@ steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: UsePythonVersion@0 - inputs: - versionSpec: '2.x' - addToPath: true + - task: UsePythonVersion@0 + inputs: + versionSpec: "2.x" + addToPath: true -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" -- powershell: | - yarn --frozen-lockfile - env: - CHILD_CONCURRENCY: "1" - displayName: Install Dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - powershell: | + yarn --frozen-lockfile + env: + CHILD_CONCURRENCY: "1" + displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'vscode-build-cache' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "vscode-build-cache" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn postinstall } - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn postinstall } + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- powershell: | - yarn electron - displayName: Download Electron + - powershell: | + yarn electron + displayName: Download Electron -- powershell: | - yarn monaco-compile-check - displayName: Run Monaco Editor Checks + - powershell: | + yarn monaco-compile-check + displayName: Run Monaco Editor Checks -- script: | - yarn valid-layers-check - displayName: Run Valid Layers Checks + - script: | + yarn valid-layers-check + displayName: Run Valid Layers Checks -- powershell: | - yarn compile - displayName: Compile Sources + - powershell: | + yarn compile + displayName: Compile Sources -- powershell: | - yarn download-builtin-extensions - displayName: Download Built-in Extensions + - powershell: | + yarn download-builtin-extensions + displayName: Download Built-in Extensions -- powershell: | - .\scripts\test.bat --tfs "Unit Tests" - displayName: Run Unit Tests (Electron) + - powershell: | + .\scripts\test.bat --tfs "Unit Tests" + displayName: Run Unit Tests (Electron) -- powershell: | - yarn test-browser --browser chromium --browser firefox --tfs "Browser Unit Tests" - displayName: Run Unit Tests (Browser) + - powershell: | + yarn test-browser --browser chromium --browser firefox --tfs "Browser Unit Tests" + displayName: Run Unit Tests (Browser) -- powershell: | - .\scripts\test-integration.bat --tfs "Integration Tests" - displayName: Run Integration Tests (Electron) + - powershell: | + .\scripts\test-integration.bat --tfs "Integration Tests" + displayName: Run Integration Tests (Electron) -- task: PublishPipelineArtifact@0 - displayName: 'Publish Crash Reports' - inputs: - artifactName: crash-dump-windows - targetPath: .build\crashes - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + displayName: "Publish Crash Reports" + inputs: + artifactName: crash-dump-windows + targetPath: .build\crashes + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: succeededOrFailed() diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index 29c795dfe15..9b75df2fd8d 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -1,196 +1,196 @@ steps: -- powershell: | - mkdir .build -ea 0 - "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit - "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality - displayName: Prepare cache flag + - powershell: | + mkdir .build -ea 0 + "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit + "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- powershell: | - $ErrorActionPreference = "Stop" - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - powershell: | + $ErrorActionPreference = "Stop" + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: UsePythonVersion@0 - inputs: - versionSpec: '2.x' - addToPath: true + - task: UsePythonVersion@0 + inputs: + versionSpec: "2.x" + addToPath: true -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII - exec { git config user.email "vscode@microsoft.com" } - exec { git config user.name "VSCode" } + exec { git config user.email "vscode@microsoft.com" } + exec { git config user.name "VSCode" } - mkdir .build -ea 0 - "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch - displayName: Prepare tooling + mkdir .build -ea 0 + "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch + displayName: Prepare tooling -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } - exec { git fetch distro } - exec { git merge $(node -p "require('./package.json').distro") } - displayName: Merge distro + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } + exec { git fetch distro } + exec { git merge $(node -p "require('./package.json').distro") } + displayName: Merge distro -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:npm_config_arch="$(VSCODE_ARCH)" - $env:CHILD_CONCURRENCY="1" - exec { yarn --frozen-lockfile } - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:npm_config_arch="$(VSCODE_ARCH)" + $env:CHILD_CONCURRENCY="1" + exec { yarn --frozen-lockfile } + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn postinstall } - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn postinstall } + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { node build/azure-pipelines/mixin } - displayName: Mix in quality + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { node build/azure-pipelines/mixin } + displayName: Mix in quality -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } - displayName: Build + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } + displayName: Build -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)' - Pattern: '*.dll,*.exe,*.node' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolSign", - "parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "VS Code" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "https://code.visualstudio.com/" - }, - { - "parameterName": "Append", - "parameterValue": "/as" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd \"SHA256\"" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - }, - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolVerify", - "parameters": [ - { - "parameterName": "VerifyAll", - "parameterValue": "/all" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 120 + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: "$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" + Pattern: "*.dll,*.exe,*.node" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "VS Code" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "https://code.visualstudio.com/" + }, + { + "parameterName": "Append", + "parameterValue": "/as" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolVerify", + "parameters": [ + { + "parameterName": "VerifyAll", + "parameterValue": "/all" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 120 -- task: NuGetCommand@2 - displayName: Install ESRPClient.exe - inputs: - restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config' - feedsToUse: config - nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' - externalFeedCredentials: 3fc0b7f7-da09-4ae7-a9c8-d69824b1819b - restoreDirectory: packages + - task: NuGetCommand@2 + displayName: Install ESRPClient.exe + inputs: + restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config' + feedsToUse: config + nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' + externalFeedCredentials: 3fc0b7f7-da09-4ae7-a9c8-d69824b1819b + restoreDirectory: packages -- task: ESRPImportCertTask@1 - displayName: Import ESRP Request Signing Certificate - inputs: - ESRP: 'ESRP CodeSign' + - task: ESRPImportCertTask@1 + displayName: Import ESRP Request Signing Certificate + inputs: + ESRP: "ESRP CodeSign" -- task: PowerShell@2 - inputs: - targetType: filePath - filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 - arguments: "$(ESRP-SSL-AADAuth)" - displayName: Import ESRP Auth Certificate + - task: PowerShell@2 + inputs: + targetType: filePath + filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 + arguments: "$(ESRP-SSL-AADAuth)" + displayName: Import ESRP Auth Certificate -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" - $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - .\build\azure-pipelines\win32\publish.ps1 - displayName: Publish + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" + $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + .\build\azure-pipelines\win32\publish.ps1 + displayName: Publish -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: "Component Detection" + continueOnError: true diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 66f8c265140..ce40e016fe7 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -1,258 +1,258 @@ steps: -- powershell: | - mkdir .build -ea 0 - "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit - "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality - displayName: Prepare cache flag + - powershell: | + mkdir .build -ea 0 + "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit + "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality + displayName: Prepare cache flag -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/commit, .build/quality' - targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' - vstsFeed: 'npm-vscode' - platformIndependent: true - alias: 'Compilation' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" -- powershell: | - $ErrorActionPreference = "Stop" - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - powershell: | + $ErrorActionPreference = "Stop" + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) -- task: NodeTool@0 - inputs: - versionSpec: "12.18.3" + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" -- task: UsePythonVersion@0 - inputs: - versionSpec: '2.x' - addToPath: true + - task: UsePythonVersion@0 + inputs: + versionSpec: "2.x" + addToPath: true -- task: AzureKeyVault@1 - displayName: 'Azure Key Vault: Get Secrets' - inputs: - azureSubscription: 'vscode-builds-subscription' - KeyVaultName: vscode + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII - exec { git config user.email "vscode@microsoft.com" } - exec { git config user.name "VSCode" } + exec { git config user.email "vscode@microsoft.com" } + exec { git config user.name "VSCode" } - mkdir .build -ea 0 - "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch - displayName: Prepare tooling + mkdir .build -ea 0 + "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch + displayName: Prepare tooling -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } - exec { git fetch distro } - exec { git merge $(node -p "require('./package.json').distro") } - displayName: Merge distro + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } + exec { git fetch distro } + exec { git merge $(node -p "require('./package.json').distro") } + displayName: Merge distro -- script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages -- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:npm_config_arch="$(VSCODE_ARCH)" - $env:CHILD_CONCURRENCY="1" - exec { yarn --frozen-lockfile } - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:npm_config_arch="$(VSCODE_ARCH)" + $env:CHILD_CONCURRENCY="1" + exec { yarn --frozen-lockfile } + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - vstsFeed: 'npm-vscode' - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn postinstall } - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn postinstall } + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { node build/azure-pipelines/mixin } - displayName: Mix in quality + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { node build/azure-pipelines/mixin } + displayName: Mix in quality -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } - displayName: Build + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } + displayName: Build -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn electron $(VSCODE_ARCH) } - exec { .\scripts\test.bat --build --tfs "Unit Tests" } - displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn electron $(VSCODE_ARCH) } + exec { .\scripts\test.bat --build --tfs "Unit Tests" } + displayName: Run unit tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn test-browser --build --browser chromium --browser firefox --tfs "Browser Unit Tests" } - displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn test-browser --build --browser chromium --browser firefox --tfs "Browser Unit Tests" } + displayName: Run unit tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- powershell: | - # Figure out the full absolute path of the product we just built - # including the remote server and configure the integration tests - # to run with these builds instead of running out of sources. - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" - $AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json - $AppNameShort = $AppProductJson.nameShort - exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\scripts\test-integration.bat --build --tfs "Integration Tests" } - displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - powershell: | + # Figure out the full absolute path of the product we just built + # including the remote server and configure the integration tests + # to run with these builds instead of running out of sources. + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" + $AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json + $AppNameShort = $AppProductJson.nameShort + exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\scripts\test-integration.bat --build --tfs "Integration Tests" } + displayName: Run integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-web-integration.bat --browser firefox } - displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-web-integration.bat --browser firefox } + displayName: Run integration tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" - $AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json - $AppNameShort = $AppProductJson.nameShort - exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-remote-integration.bat } - displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" + $AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json + $AppNameShort = $AppProductJson.nameShort + exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-remote-integration.bat } + displayName: Run remote integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) -- task: PublishPipelineArtifact@0 - inputs: - artifactName: crash-dump-windows-$(VSCODE_ARCH) - targetPath: .build\crashes - displayName: 'Publish Crash Reports' - continueOnError: true - condition: failed() + - task: PublishPipelineArtifact@0 + inputs: + artifactName: crash-dump-windows-$(VSCODE_ARCH) + targetPath: .build\crashes + displayName: "Publish Crash Reports" + continueOnError: true + condition: failed() -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + - task: PublishTestResults@2 + displayName: Publish Tests Results + inputs: + testResultsFiles: "*-results.xml" + searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" + condition: succeededOrFailed() -- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)' - Pattern: '*.dll,*.exe,*.node' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolSign", - "parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "VS Code" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "https://code.visualstudio.com/" - }, - { - "parameterName": "Append", - "parameterValue": "/as" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd \"SHA256\"" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - }, - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolVerify", - "parameters": [ - { - "parameterName": "VerifyAll", - "parameterValue": "/all" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 120 + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: "ESRP CodeSign" + FolderPath: "$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)" + Pattern: "*.dll,*.exe,*.node" + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "VS Code" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "https://code.visualstudio.com/" + }, + { + "parameterName": "Append", + "parameterValue": "/as" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolVerify", + "parameters": [ + { + "parameterName": "VerifyAll", + "parameterValue": "/all" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 120 -- task: NuGetCommand@2 - displayName: Install ESRPClient.exe - inputs: - restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config' - feedsToUse: config - nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' - externalFeedCredentials: 'ESRP Nuget' - restoreDirectory: packages + - task: NuGetCommand@2 + displayName: Install ESRPClient.exe + inputs: + restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config' + feedsToUse: config + nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' + externalFeedCredentials: "ESRP Nuget" + restoreDirectory: packages -- task: ESRPImportCertTask@1 - displayName: Import ESRP Request Signing Certificate - inputs: - ESRP: 'ESRP CodeSign' + - task: ESRPImportCertTask@1 + displayName: Import ESRP Request Signing Certificate + inputs: + ESRP: "ESRP CodeSign" -- task: PowerShell@2 - inputs: - targetType: filePath - filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 - arguments: "$(ESRP-SSL-AADAuth)" - displayName: Import ESRP Auth Certificate + - task: PowerShell@2 + inputs: + targetType: filePath + filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 + arguments: "$(ESRP-SSL-AADAuth)" + displayName: Import ESRP Auth Certificate -- powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" - $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - .\build\azure-pipelines\win32\publish.ps1 - displayName: Publish + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" + $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + .\build\azure-pipelines\win32\publish.ps1 + displayName: Publish -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: "Component Detection" + continueOnError: true From 875ad7bdd7c1725d2e56ed218d6af9c0199367bd Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 11:48:54 +0100 Subject: [PATCH 0188/1837] Fix #111168 --- src/vs/workbench/api/browser/viewsExtensionPoint.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index 611a5b121c8..841d2ce349b 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -471,10 +471,9 @@ class ViewsExtensionHandler implements IWorkbenchContribution { ? container.viewOrderDelegate.getOrder(item.group) : undefined; - let icon: string | URI | undefined; + let icon: ThemeIcon | URI | undefined; if (typeof item.icon === 'string') { - const themeIcon = ThemeIcon.fromString(item.icon); - icon = themeIcon ? ThemeIcon.asClassName(themeIcon) : resources.joinPath(extension.description.extensionLocation, item.icon); + icon = ThemeIcon.fromString(item.icon) || resources.joinPath(extension.description.extensionLocation, item.icon); } const initialVisibility = this.convertInitialVisibility(item.visibility); From 900e4474e9ab9a7be4691a4be12c51a17b7789a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 12:11:03 +0100 Subject: [PATCH 0189/1837] missing terrapin usage --- build/azure-pipelines/linux/product-build-alpine.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index ce4a620f843..c5515dc8933 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -62,6 +62,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: "build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" From ad3adfa28e906ff88d37e24f227a504d985c9e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 12:22:28 +0100 Subject: [PATCH 0190/1837] retry yarn install --- .../darwin/product-build-darwin.yml | 9 +++++++-- .../linux/product-build-alpine.yml | 7 ++++++- .../linux/product-build-linux.yml | 8 +++++++- build/azure-pipelines/product-compile.yml | 7 ++++++- .../azure-pipelines/web/product-build-web.yml | 7 ++++++- .../win32/product-build-win32-arm64.yml | 8 +++++--- .../win32/product-build-win32.yml | 8 +++++--- build/azure-pipelines/win32/retry.ps1 | 19 +++++++++++++++++++ 8 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 build/azure-pipelines/win32/retry.ps1 diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 1afa0d2ca5c..6c18decddc9 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -85,8 +85,13 @@ steps: export npm_config_arch=$(VSCODE_ARCH) export npm_config_node_gyp=$(which node-gyp) export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - CHILD_CONCURRENCY=1 yarn --frozen-lockfile --verbose + + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + echo "Yarn failed, trying again..." + done + env: + CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index c5515dc8933..b489de4a97e 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -74,7 +74,12 @@ steps: - script: | set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + echo "Yarn failed, trying again..." + done + env: + CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 1baa784b50e..f1f5b9173ac 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -68,7 +68,13 @@ steps: - script: | set -e - CHILD_CONCURRENCY=1 npm_config_arch=$(NPM_ARCH) yarn --frozen-lockfile + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + echo "Yarn failed, trying again..." + done + env: + CHILD_CONCURRENCY: 1 + npm_config_arch: $(NPM_ARCH) displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 5ea3587a31f..a975e8a9fb7 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -71,7 +71,12 @@ steps: - script: | set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + echo "Yarn failed, trying again..." + done + env: + CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 23a755f3f6f..d6c48fb1b9b 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -63,7 +63,12 @@ steps: # vstsFeed: 'npm-vscode' - script: | set -e - CHILD_CONCURRENCY=1 yarn --frozen-lockfile + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + echo "Yarn failed, trying again..." + done + env: + CHILD_CONCURRENCY: 1 displayName: Install dependencies # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index 9b75df2fd8d..7c75bace832 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -70,10 +70,12 @@ steps: - powershell: | . build/azure-pipelines/win32/exec.ps1 + . build/azure-pipelines/win32/retry.ps1 $ErrorActionPreference = "Stop" - $env:npm_config_arch="$(VSCODE_ARCH)" - $env:CHILD_CONCURRENCY="1" - exec { yarn --frozen-lockfile } + retry { exec { yarn --frozen-lockfile } } + env: + npm_config_arch: $(VSCODE_ARCH) + CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index ce40e016fe7..01310e32544 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -70,10 +70,12 @@ steps: - powershell: | . build/azure-pipelines/win32/exec.ps1 + . build/azure-pipelines/win32/retry.ps1 $ErrorActionPreference = "Stop" - $env:npm_config_arch="$(VSCODE_ARCH)" - $env:CHILD_CONCURRENCY="1" - exec { yarn --frozen-lockfile } + retry { exec { yarn --frozen-lockfile } } + env: + npm_config_arch: $(VSCODE_ARCH) + CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/retry.ps1 b/build/azure-pipelines/win32/retry.ps1 new file mode 100644 index 00000000000..6f46bb3f450 --- /dev/null +++ b/build/azure-pipelines/win32/retry.ps1 @@ -0,0 +1,19 @@ +function Retry +{ + [CmdletBinding()] + param( + [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd + ) + $retry = 0 + + while ($retry++ -lt 3) { + try { + & $cmd + return + } catch { + Write-Error -ErrorRecord $_ + } + } + + throw "Max retries reached" +} From 050963b8d1f5b5cf2398a3217c886eb984d1e971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 12:11:03 +0100 Subject: [PATCH 0191/1837] missing terrapin usage --- build/azure-pipelines/linux/product-build-alpine.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index ce4a620f843..c5515dc8933 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -62,6 +62,10 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: "build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" From b7851bfc806e768da46c1d821a05fe454ba36257 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 12:32:31 +0100 Subject: [PATCH 0192/1837] :chore: bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37c7917ca23..5431bf0d816 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "645d71eca7b3cb5addb7e2251dd11a1af5f5fbc5", + "distro": "afc45bb534b564ffd3acd5b4a63d2b350f3512e4", "author": { "name": "Microsoft Corporation" }, From 4563ba1f941fa9c2f07dd031f359ba78d0e4ee3b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 12:49:41 +0100 Subject: [PATCH 0193/1837] add start function to explicitly start performance observer --- src/vs/base/node/startupPerf.d.ts | 5 +++++ src/vs/base/node/startupPerf.js | 37 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/vs/base/node/startupPerf.d.ts b/src/vs/base/node/startupPerf.d.ts index 62be9ef72ac..18ad7e11ba3 100644 --- a/src/vs/base/node/startupPerf.d.ts +++ b/src/vs/base/node/startupPerf.d.ts @@ -5,6 +5,11 @@ import { PerformanceEntry } from 'perf_hooks'; +/** + * Start the startup performace observer + */ +export function start(): void; + /** * Return all performance entries captured so far and stop startup * performance recording. diff --git a/src/vs/base/node/startupPerf.js b/src/vs/base/node/startupPerf.js index 2f3e03f1cca..540f8a37cc0 100644 --- a/src/vs/base/node/startupPerf.js +++ b/src/vs/base/node/startupPerf.js @@ -8,30 +8,33 @@ //@ts-check function _factory(sharedObj, nodeRequire) { - if (!sharedObj.MonacoStartupPerformanceMarks) { - const { PerformanceObserver } = nodeRequire('perf_hooks'); + let _data = sharedObj.MonacoStartupPerformanceMarks; - let startupEntries = []; - - const startupObs = new PerformanceObserver(list => { startupEntries = startupEntries.concat(list.getEntries()); }); - startupObs.observe({ buffered: true, entryTypes: ['mark'] }); - - sharedObj.MonacoStartupPerformanceMarks = { - startupEntries, - dispose() { - startupObs.disconnect(); - startupEntries.length = 0; - delete sharedObj.MonacoStartupPerformanceMarks; - }, + if (!_data) { + _data = sharedObj.MonacoStartupPerformanceMarks = { + startupEntries =[], + observer: undefined, }; } return { + start() { + if (!_data.observer) { + const { PerformanceObserver } = nodeRequire('perf_hooks'); + const observer = new PerformanceObserver(list => _data = _data.concat(list.getEntries())); + observer.observe({ buffered: true, entryTypes: ['mark'] }); + _data.observer = observer; + } + }, consumeAndStop() { - const entries = sharedObj.startupEntries.slice(0); - sharedObj.MonacoStartupPerformanceMarks.dispose(); - return entries; + if (_data.observer) { + const entries = _data.startupEntries.slice(0); + _data.observer.disconnect(); + _data.startupEntries.length = 0; + return entries; + } + return []; // never started } }; } From b5861b0330e2079c6fd7a094a439fe840a68bb64 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2020 13:20:35 +0100 Subject: [PATCH 0194/1837] update the monaco.d.ts --- src/vs/monaco.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index c57c8a5198c..6d61191086b 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -6269,7 +6269,7 @@ declare namespace monaco.languages { recursive?: boolean; copy?: boolean; folder?: boolean; - doNotUseTrash?: boolean; + skipTrashBin?: boolean; maxSize?: number; } From ff0785571f7f6e25f8f8d17d9f6281470ca433f7 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2020 13:40:02 +0100 Subject: [PATCH 0195/1837] explorer: limit undo file content to 5mb --- src/vs/workbench/contrib/files/browser/fileActions.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index bc7fb098071..379a46e5be9 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -56,23 +56,16 @@ import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/b export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); - export const NEW_FOLDER_COMMAND_ID = 'explorer.newFolder'; export const NEW_FOLDER_LABEL = nls.localize('newFolder', "New Folder"); - export const TRIGGER_RENAME_LABEL = nls.localize('rename', "Rename"); - export const MOVE_FILE_TO_TRASH_LABEL = nls.localize('delete', "Delete"); - export const COPY_FILE_LABEL = nls.localize('copyFile', "Copy"); - export const PASTE_FILE_LABEL = nls.localize('pasteFile', "Paste"); - export const FileCopiedContext = new RawContextKey('fileCopied', false); - export const DOWNLOAD_LABEL = nls.localize('download', "Download..."); - const CONFIRM_DELETE_SETTING_KEY = 'explorer.confirmDelete'; +const MAX_UNDO_FILE_SIZE = 5000000; // 5mb function onError(notificationService: INotificationService, error: any): void { if (error.message === 'string') { @@ -226,7 +219,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I // Call function try { - const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash })); + const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash, maxSize: MAX_UNDO_FILE_SIZE })); await bulkEditService.apply(resourceFileEdits, { undoRedoSource: explorerService.undoRedoSource, label: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name) From 95e32fc67eef90b92995e937fb373efd2860e5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2020 14:04:48 +0100 Subject: [PATCH 0196/1837] update cache salt --- build/.cachesalt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/.cachesalt b/build/.cachesalt index 0afdafd1118..621845b3dd8 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-23T17:57:03.428Z +2020-11-24T13:04:41.269Z From fed34f982e9e97eab245a2cf3a2abc84d090f645 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 13:51:19 +0100 Subject: [PATCH 0197/1837] startup util fixes --- src/vs/base/node/startupPerf.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/base/node/startupPerf.js b/src/vs/base/node/startupPerf.js index 540f8a37cc0..964d01b75c5 100644 --- a/src/vs/base/node/startupPerf.js +++ b/src/vs/base/node/startupPerf.js @@ -13,7 +13,7 @@ function _factory(sharedObj, nodeRequire) { if (!_data) { _data = sharedObj.MonacoStartupPerformanceMarks = { - startupEntries =[], + startupEntries: [], observer: undefined, }; } @@ -22,14 +22,16 @@ function _factory(sharedObj, nodeRequire) { start() { if (!_data.observer) { const { PerformanceObserver } = nodeRequire('perf_hooks'); - const observer = new PerformanceObserver(list => _data = _data.concat(list.getEntries())); + const observer = new PerformanceObserver(list => { + _data.startupEntries.push(list.getEntries()); + }); observer.observe({ buffered: true, entryTypes: ['mark'] }); _data.observer = observer; } }, consumeAndStop() { if (_data.observer) { - const entries = _data.startupEntries.slice(0); + const entries = [].concat(..._data.startupEntries); _data.observer.disconnect(); _data.startupEntries.length = 0; return entries; From 8df4bc17dabd0e3b4b2671c3ce888c1fefd053ac Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 14:19:23 +0100 Subject: [PATCH 0198/1837] Merge .nativeignore and .moduleignore. Fixes #111220 --- build/.moduleignore | 114 ++++++++++++++++++++++++++++++++++++++- build/.nativeignore | 110 ------------------------------------- build/gulpfile.vscode.js | 1 - 3 files changed, 113 insertions(+), 112 deletions(-) delete mode 100644 build/.nativeignore diff --git a/build/.moduleignore b/build/.moduleignore index 489d4709f0a..d1f9194ba2a 100644 --- a/build/.moduleignore +++ b/build/.moduleignore @@ -1,5 +1,117 @@ +# cleanup rules for node modules, .gitignore style -# additional cleanup rules for node modules, .gitignore style +# native node modules + +nan/** +*/node_modules/nan/** + +fsevents/binding.gyp +fsevents/fsevents.cc +fsevents/build/** +fsevents/src/** +fsevents/test/** +!fsevents/**/*.node + +vscode-sqlite3/binding.gyp +vscode-sqlite3/benchmark/** +vscode-sqlite3/cloudformation/** +vscode-sqlite3/deps/** +vscode-sqlite3/test/** +vscode-sqlite3/build/** +vscode-sqlite3/src/** +!vscode-sqlite3/build/Release/*.node + +windows-mutex/binding.gyp +windows-mutex/build/** +windows-mutex/src/** +!windows-mutex/**/*.node + +native-keymap/binding.gyp +native-keymap/build/** +native-keymap/src/** +native-keymap/deps/** +!native-keymap/build/Release/*.node + +native-is-elevated/binding.gyp +native-is-elevated/build/** +native-is-elevated/src/** +native-is-elevated/deps/** +!native-is-elevated/build/Release/*.node + +native-watchdog/binding.gyp +native-watchdog/build/** +native-watchdog/src/** +!native-watchdog/build/Release/*.node + +spdlog/binding.gyp +spdlog/build/** +spdlog/deps/** +spdlog/src/** +spdlog/test/** +spdlog/*.yml +!spdlog/build/Release/*.node + +jschardet/dist/** + +windows-foreground-love/binding.gyp +windows-foreground-love/build/** +windows-foreground-love/src/** +!windows-foreground-love/**/*.node + +windows-process-tree/binding.gyp +windows-process-tree/build/** +windows-process-tree/src/** +!windows-process-tree/**/*.node + +keytar/binding.gyp +keytar/build/** +keytar/src/** +keytar/script/** +keytar/node_modules/** +!keytar/**/*.node + +node-pty/binding.gyp +node-pty/build/** +node-pty/src/** +node-pty/tools/** +node-pty/deps/** +node-pty/scripts/** +!node-pty/build/Release/*.exe +!node-pty/build/Release/*.dll +!node-pty/build/Release/*.node + +vscode-nsfw/binding.gyp +vscode-nsfw/build/** +vscode-nsfw/src/** +vscode-nsfw/openpa/** +vscode-nsfw/includes/** +!vscode-nsfw/build/Release/*.node +!vscode-nsfw/**/*.a + +vsda/build/** +vsda/ci/** +vsda/src/** +vsda/.gitignore +vsda/binding.gyp +vsda/README.md +vsda/targets +!vsda/build/Release/vsda.node + +vscode-encrypt/build/** +vscode-encrypt/src/** +vscode-encrypt/vendor/** +vscode-encrypt/.gitignore +vscode-encrypt/binding.gyp +vscode-encrypt/README.md +!vscode-encrypt/build/Release/vscode-encrypt-native.node + +vscode-windows-ca-certs/**/* +!vscode-windows-ca-certs/package.json +!vscode-windows-ca-certs/**/*.node + +node-addon-api/**/* + +# other node modules **/docs/** **/example/** diff --git a/build/.nativeignore b/build/.nativeignore deleted file mode 100644 index 8a40a72f311..00000000000 --- a/build/.nativeignore +++ /dev/null @@ -1,110 +0,0 @@ -# cleanup rules for native node modules, .gitignore style - -nan/** -*/node_modules/nan/** - -fsevents/binding.gyp -fsevents/fsevents.cc -fsevents/build/** -fsevents/src/** -fsevents/test/** -!fsevents/**/*.node - -vscode-sqlite3/binding.gyp -vscode-sqlite3/benchmark/** -vscode-sqlite3/cloudformation/** -vscode-sqlite3/deps/** -vscode-sqlite3/test/** -vscode-sqlite3/build/** -vscode-sqlite3/src/** -!vscode-sqlite3/build/Release/*.node - -windows-mutex/binding.gyp -windows-mutex/build/** -windows-mutex/src/** -!windows-mutex/**/*.node - -native-keymap/binding.gyp -native-keymap/build/** -native-keymap/src/** -native-keymap/deps/** -!native-keymap/build/Release/*.node - -native-is-elevated/binding.gyp -native-is-elevated/build/** -native-is-elevated/src/** -native-is-elevated/deps/** -!native-is-elevated/build/Release/*.node - -native-watchdog/binding.gyp -native-watchdog/build/** -native-watchdog/src/** -!native-watchdog/build/Release/*.node - -spdlog/binding.gyp -spdlog/build/** -spdlog/deps/** -spdlog/src/** -spdlog/test/** -spdlog/*.yml -!spdlog/build/Release/*.node - -jschardet/dist/** - -windows-foreground-love/binding.gyp -windows-foreground-love/build/** -windows-foreground-love/src/** -!windows-foreground-love/**/*.node - -windows-process-tree/binding.gyp -windows-process-tree/build/** -windows-process-tree/src/** -!windows-process-tree/**/*.node - -keytar/binding.gyp -keytar/build/** -keytar/src/** -keytar/script/** -keytar/node_modules/** -!keytar/**/*.node - -node-pty/binding.gyp -node-pty/build/** -node-pty/src/** -node-pty/tools/** -node-pty/deps/** -node-pty/scripts/** -!node-pty/build/Release/*.exe -!node-pty/build/Release/*.dll -!node-pty/build/Release/*.node - -vscode-nsfw/binding.gyp -vscode-nsfw/build/** -vscode-nsfw/src/** -vscode-nsfw/openpa/** -vscode-nsfw/includes/** -!vscode-nsfw/build/Release/*.node -!vscode-nsfw/**/*.a - -vsda/build/** -vsda/ci/** -vsda/src/** -vsda/.gitignore -vsda/binding.gyp -vsda/README.md -vsda/targets -!vsda/build/Release/vsda.node - -vscode-encrypt/build/** -vscode-encrypt/src/** -vscode-encrypt/vendor/** -vscode-encrypt/.gitignore -vscode-encrypt/binding.gyp -vscode-encrypt/README.md -!vscode-encrypt/build/Release/vscode-encrypt-native.node - -vscode-windows-ca-certs/**/* -!vscode-windows-ca-certs/package.json -!vscode-windows-ca-certs/**/*.node - -node-addon-api/**/* diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 4dbcd883f2e..e0d3c5bd9cd 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -207,7 +207,6 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op const deps = gulp.src(dependenciesSrc, { base: '.', dot: true }) .pipe(filter(['**', '!**/package-lock.json', '!**/yarn.lock', '!**/*.js.map'])) - .pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore'))) .pipe(util.cleanNodeModules(path.join(__dirname, '.moduleignore'))) .pipe(jsFilter) .pipe(util.rewriteSourceMappingURL(sourceMappingURLBase)) From c2d3d7f8574dc2bbac62f1319e7fe07513c70365 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 14:23:59 +0100 Subject: [PATCH 0199/1837] bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5431bf0d816..aa1dbada1d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "afc45bb534b564ffd3acd5b4a63d2b350f3512e4", + "distro": "e5fdc430f3622754e5b5838e4c4a93751b6f3ed7", "author": { "name": "Microsoft Corporation" }, From cf4f2fa6c811ea264797b9a6f9effea0d1281fc5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 15:10:57 +0100 Subject: [PATCH 0200/1837] #11123 more fixes --- .../extensions/browser/extensionsViewlet.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 7fabf9803d5..58756f6ba69 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -379,6 +379,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE private searchBox: SuggestEnabledInput | undefined; private readonly searchViewletState: MementoObject; private readonly sortActions: ChangeSortAction[]; + private secondaryActions: IAction[] | undefined = undefined; constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @@ -421,6 +422,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { + this.secondaryActions = undefined; this.updateTitleArea(); } }, this)); @@ -587,23 +589,23 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE } getSecondaryActions(): IAction[] { - const actions: IAction[] = []; + if (!this.secondaryActions) { + this.secondaryActions = []; + this.secondaryActions.push(this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL)); + if (this.configurationService.getValue(AutoUpdateConfigurationKey)) { + this.secondaryActions.push(this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)); + } else { + this.secondaryActions.push(this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL, false), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)); + } - actions.push(this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL)); - if (this.configurationService.getValue(AutoUpdateConfigurationKey)) { - actions.push(this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)); - } else { - actions.push(this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL, false), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)); + this.secondaryActions.push(new Separator()); + this.secondaryActions.push(this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL, false)); + this.secondaryActions.push(this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL, false)); + + this.secondaryActions.push(new Separator()); + this.secondaryActions.push(this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL)); } - - actions.push(new Separator()); - actions.push(this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL, false)); - actions.push(this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL, false)); - - actions.push(new Separator()); - actions.push(this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL)); - - return actions; + return this.secondaryActions; } search(value: string): void { From afce5c425da6ab38be89fb86d41d5ce297ce43f9 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 24 Nov 2020 15:21:05 +0100 Subject: [PATCH 0201/1837] Add simple check for task dependency cycles Fixes #111186 --- .../tasks/browser/terminalTaskSystem.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 4a4becc173e..15f0a23d5a1 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -174,6 +174,7 @@ export class TerminalTaskSystem implements ITaskSystem { }; private activeTasks: IStringDictionary; + private dependencyCycleCheck: Set; private instances: IStringDictionary; private busyTasks: IStringDictionary; private terminals: IStringDictionary; @@ -210,6 +211,7 @@ export class TerminalTaskSystem implements ITaskSystem { ) { this.activeTasks = Object.create(null); + this.dependencyCycleCheck = new Set(); this.instances = Object.create(null); this.busyTasks = Object.create(null); this.terminals = Object.create(null); @@ -437,7 +439,31 @@ export class TerminalTaskSystem implements ITaskSystem { return Promise.all(promises); } + private hasDependencyCycle(task: Task): boolean { + const key = task.getCommonTaskId(); + if (this.dependencyCycleCheck.has(key)) { + this.showDependencyCycleMessage(task); + return true; + } else { + this.dependencyCycleCheck.add(key); + return false; + } + } + + private showDependencyCycleMessage(task: Task) { + this.log(nls.localize('dependencyCycle', + 'There is a dependency cycle. See task {0}.', + task._label + )); + this.showOutput(); + } + private async executeTask(task: Task, resolver: ITaskResolver, trigger: string, alreadyResolved?: Map): Promise { + if (this.hasDependencyCycle(task)) { + this.dependencyCycleCheck.delete(task.getCommonTaskId()); + return {}; + } + alreadyResolved = alreadyResolved ?? new Map(); let promises: Promise[] = []; if (task.configurationProperties.dependsOn) { @@ -480,6 +506,7 @@ export class TerminalTaskSystem implements ITaskSystem { return { exitCode: summary.exitCode }; } } + this.dependencyCycleCheck.delete(task.getCommonTaskId()); if (this.isRerun) { return this.reexecuteCommand(task, trigger, alreadyResolved!); } else { @@ -487,6 +514,7 @@ export class TerminalTaskSystem implements ITaskSystem { } }); } else { + this.dependencyCycleCheck.delete(task.getCommonTaskId()); return Promise.all(promises).then((summaries): ITaskSummary => { for (let summary of summaries) { if (summary.exitCode !== 0) { From 2a8ee68eaaf744677905cdf63ef2af470a6e3b99 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 15:26:13 +0100 Subject: [PATCH 0202/1837] #110721 pass action runner --- src/vs/base/browser/ui/button/button.ts | 4 +++- .../browser/parts/notifications/notificationsViewer.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index f2e25e442ac..92114b6a0c7 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -14,7 +14,7 @@ import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch'; import { renderCodicons } from 'vs/base/browser/codicons'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; -import { IAction } from 'vs/base/common/actions'; +import { IAction, IActionRunner } from 'vs/base/common/actions'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; @@ -233,6 +233,7 @@ export class Button extends Disposable implements IButton { export interface IButtonWithDropdownOptions extends IButtonOptions { readonly contextMenuProvider: IContextMenuProvider; readonly actions: IAction[]; + readonly actionRunner?: IActionRunner; } export class ButtonWithDropdown extends Disposable implements IButton { @@ -260,6 +261,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { options.contextMenuProvider.showContextMenu({ getAnchor: () => this.dropdownButton.element, getActions: () => options.actions, + actionRunner: options.actionRunner, onHide: () => this.dropdownButton.element.setAttribute('aria-expanded', 'false') }); this.dropdownButton.element.setAttribute('aria-expanded', 'true'); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts index b56a1cf09f5..51272ab8a81 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts @@ -465,6 +465,7 @@ export class NotificationTemplateRenderer extends Disposable { ...buttonOptions, contextMenuProvider: this.contextMenuService, actions: dropdownActions, + actionRunner }) : buttonToolbar.addButton(buttonOptions)); button.label = action.label; From 197f1341e63e548721cd1f0162b6310d246271c5 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2020 15:40:23 +0100 Subject: [PATCH 0203/1837] explorerService: consolidate bulkFileService apply in one location --- .../browser/externalTerminal.contribution.ts | 3 +- .../files/browser/editors/textFileEditor.ts | 3 +- .../{common => browser}/explorerService.ts | 17 +++++-- .../files/browser/fileActions.contribution.ts | 3 +- .../contrib/files/browser/fileActions.ts | 47 +++++-------------- .../contrib/files/browser/fileCommands.ts | 4 +- .../files/browser/files.contribution.ts | 9 ++-- .../workbench/contrib/files/browser/files.ts | 47 ++++++++++++++++++- .../views/explorerDecorationsProvider.ts | 2 +- .../files/browser/views/explorerView.ts | 3 +- .../files/browser/views/explorerViewer.ts | 30 ++++-------- .../workbench/contrib/files/common/files.ts | 45 ------------------ .../fileActions.contribution.ts | 2 +- .../files/electron-sandbox/textFileEditor.ts | 2 +- .../search/browser/search.contribution.ts | 4 +- 15 files changed, 99 insertions(+), 122 deletions(-) rename src/vs/workbench/contrib/files/{common => browser}/explorerService.ts (95%) diff --git a/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts b/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts index 7b38b373bea..148401905f6 100644 --- a/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts +++ b/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts @@ -12,14 +12,13 @@ import { ITerminalService as IIntegratedTerminalService } from 'vs/workbench/con import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IFileService } from 'vs/platform/files/common/files'; import { IListService } from 'vs/platform/list/browser/listService'; -import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; +import { getMultiSelectedResources, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { Schemas } from 'vs/base/common/network'; import { distinct } from 'vs/base/common/arrays'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { optional } from 'vs/platform/instantiation/common/instantiation'; -import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Disposable } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 82731d702fa..ec837dc487e 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -9,7 +9,7 @@ import { isFunction, assertIsDefined } from 'vs/base/common/types'; import { isValidBasename } from 'vs/base/common/extpath'; import { basename } from 'vs/base/common/resources'; import { Action } from 'vs/base/common/actions'; -import { VIEWLET_ID, TEXT_FILE_EDITOR_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files'; +import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { EditorOptions, TextEditorOptions, IEditorInput, IEditorOpenContext } from 'vs/workbench/common/editor'; @@ -30,6 +30,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; import { EditorActivation, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; /** * An implementation of editor for file system resources. diff --git a/src/vs/workbench/contrib/files/common/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts similarity index 95% rename from src/vs/workbench/contrib/files/common/explorerService.ts rename to src/vs/workbench/contrib/files/browser/explorerService.ts index f3436ac27e1..e337ee9236b 100644 --- a/src/vs/workbench/contrib/files/common/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -6,7 +6,7 @@ import { Event } from 'vs/base/common/event'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { IExplorerService, IFilesConfiguration, SortOrder, IExplorerView } from 'vs/workbench/contrib/files/common/files'; +import { IFilesConfiguration, SortOrder } from 'vs/workbench/contrib/files/common/files'; import { ExplorerItem, ExplorerModel } from 'vs/workbench/contrib/files/common/explorerModel'; import { URI } from 'vs/base/common/uri'; import { FileOperationEvent, FileOperation, IFileService, FileChangesEvent, FileChangeType, IResolveFileOptions } from 'vs/platform/files/common/files'; @@ -16,13 +16,16 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditableData } from 'vs/workbench/common/views'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; +import { IExplorerView, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; + +export const UNDO_REDO_SOURCE = new UndoRedoSource(); export class ExplorerService implements IExplorerService { declare readonly _serviceBrand: undefined; private static readonly EXPLORER_FILE_CHANGES_REACT_DELAY = 500; // delay in ms to react to file changes to give our internal events a chance to react first - private static readonly UNDO_REDO_SOURCE = new UndoRedoSource(); private readonly disposables = new DisposableStore(); private editable: { stat: ExplorerItem, data: IEditableData } | undefined; @@ -37,7 +40,8 @@ export class ExplorerService implements IExplorerService { @IWorkspaceContextService private contextService: IWorkspaceContextService, @IClipboardService private clipboardService: IClipboardService, @IEditorService private editorService: IEditorService, - @IUriIdentityService private readonly uriIdentityService: IUriIdentityService + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, + @IBulkEditService private readonly bulkEditService: IBulkEditService ) { this._sortOrder = this.configurationService.getValue('explorer.sortOrder'); @@ -86,8 +90,11 @@ export class ExplorerService implements IExplorerService { return this.view.getContext(respectMultiSelection); } - get undoRedoSource(): UndoRedoSource { - return ExplorerService.UNDO_REDO_SOURCE; + async applyBulkEdit(edit: ResourceFileEdit[], label: string): Promise { + await this.bulkEditService.apply(edit, { + undoRedoSource: UNDO_REDO_SOURCE, + label, + }); } hasViewFocus(): boolean { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index fd399160c73..bba59809909 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -15,7 +15,7 @@ import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/c import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { isMacintosh } from 'vs/base/common/platform'; -import { FilesExplorerFocusCondition, ExplorerRootContext, ExplorerFolderContext, ExplorerResourceNotReadonlyContext, ExplorerResourceCut, IExplorerService, ExplorerResourceMoveableToTrash, ExplorerViewletVisibleContext, ExplorerResourceAvailableEditorIdsContext } from 'vs/workbench/contrib/files/common/files'; +import { FilesExplorerFocusCondition, ExplorerRootContext, ExplorerFolderContext, ExplorerResourceNotReadonlyContext, ExplorerResourceCut, ExplorerResourceMoveableToTrash, ExplorerViewletVisibleContext, ExplorerResourceAvailableEditorIdsContext } from 'vs/workbench/contrib/files/common/files'; import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL } from 'vs/workbench/browser/actions/workspaceCommands'; import { CLOSE_SAVED_EDITORS_COMMAND_ID, CLOSE_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_EDITOR_COMMAND_ID, CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; @@ -29,6 +29,7 @@ import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAc import { ActiveEditorContext } from 'vs/workbench/common/editor'; import { SidebarFocusContext } from 'vs/workbench/common/viewlet'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; // Contribute Global Actions const category = { value: nls.localize('filesCategory', "File"), original: 'File' }; diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 379a46e5be9..bfcb7dd6975 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Action } from 'vs/base/common/actions'; import { DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { VIEWLET_ID, IExplorerService, IFilesConfiguration, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; +import { VIEWLET_ID, IFilesConfiguration, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; import { ByteSize, IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; @@ -52,7 +52,8 @@ import { IProgressService, IProgressStep, ProgressLocation } from 'vs/platform/p import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; +import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); @@ -116,7 +117,7 @@ export class NewFolderAction extends Action { } } -async function deleteFiles(explorerService: IExplorerService, bulkEditService: IBulkEditService, workingCopyFileService: IWorkingCopyFileService, dialogService: IDialogService, configurationService: IConfigurationService, elements: ExplorerItem[], useTrash: boolean, skipConfirm = false): Promise { +async function deleteFiles(explorerService: IExplorerService, workingCopyFileService: IWorkingCopyFileService, dialogService: IDialogService, configurationService: IConfigurationService, elements: ExplorerItem[], useTrash: boolean, skipConfirm = false): Promise { let primaryButton: string; if (useTrash) { primaryButton = isWindows ? nls.localize('deleteButtonLabelRecycleBin', "&&Move to Recycle Bin") : nls.localize({ key: 'deleteButtonLabelTrash', comment: ['&& denotes a mnemonic'] }, "&&Move to Trash"); @@ -220,10 +221,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I // Call function try { const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash, maxSize: MAX_UNDO_FILE_SIZE })); - await bulkEditService.apply(resourceFileEdits, { - undoRedoSource: explorerService.undoRedoSource, - label: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name) - }); + await explorerService.applyBulkEdit(resourceFileEdits, distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name)); } catch (error) { // Handle error to delete file(s) from a modal confirmation dialog @@ -253,7 +251,7 @@ async function deleteFiles(explorerService: IExplorerService, bulkEditService: I skipConfirm = true; - return deleteFiles(explorerService, bulkEditService, workingCopyFileService, dialogService, configurationService, elements, useTrash, skipConfirm); + return deleteFiles(explorerService, workingCopyFileService, dialogService, configurationService, elements, useTrash, skipConfirm); } } } @@ -875,7 +873,6 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole const viewsService = accessor.get(IViewsService); const notificationService = accessor.get(INotificationService); const commandService = accessor.get(ICommandService); - const bulkEditService = accessor.get(IBulkEditService); const view = await viewsService.openView(VIEW_ID, true); if (!view) { @@ -907,10 +904,7 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole const onSuccess = async (value: string): Promise => { try { const resourceToCreate = resources.joinPath(folder.resource, value); - await bulkEditService.apply([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], { - undoRedoSource: explorerService.undoRedoSource, - label: nls.localize('newBulkEdit', "New {0}", value) - }); + await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], nls.localize('newBulkEdit', "New {0}", value)); await refreshIfSeparator(value, explorerService); if (isFolder) { @@ -951,7 +945,6 @@ CommandsRegistry.registerCommand({ export const renameHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - const bulkEditService = accessor.get(IBulkEditService); const notificationService = accessor.get(INotificationService); const stats = explorerService.getContext(false); @@ -968,10 +961,7 @@ export const renameHandler = async (accessor: ServicesAccessor) => { const targetResource = resources.joinPath(parentResource, value); if (stat.resource.toString() !== targetResource.toString()) { try { - await bulkEditService.apply([new ResourceFileEdit(stat.resource, targetResource)], { - undoRedoSource: explorerService.undoRedoSource, - label: nls.localize('renameBulkEdit', "Rename {0} to {1}", stat.name, value) - }); + await explorerService.applyBulkEdit([new ResourceFileEdit(stat.resource, targetResource)], nls.localize('renameBulkEdit', "Rename {0} to {1}", stat.name, value)); await refreshIfSeparator(value, explorerService); } catch (e) { notificationService.error(e); @@ -987,7 +977,7 @@ export const moveFileToTrashHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); const stats = explorerService.getContext(true).filter(s => !s.isRoot); if (stats.length) { - await deleteFiles(accessor.get(IExplorerService), accessor.get(IBulkEditService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, true); + await deleteFiles(accessor.get(IExplorerService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, true); } }; @@ -996,7 +986,7 @@ export const deleteFileHandler = async (accessor: ServicesAccessor) => { const stats = explorerService.getContext(true).filter(s => !s.isRoot); if (stats.length) { - await deleteFiles(accessor.get(IExplorerService), accessor.get(IBulkEditService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, false); + await deleteFiles(accessor.get(IExplorerService), accessor.get(IWorkingCopyFileService), accessor.get(IDialogService), accessor.get(IConfigurationService), stats, false); } }; @@ -1024,7 +1014,6 @@ const downloadFileHandler = (accessor: ServicesAccessor) => { const logService = accessor.get(ILogService); const fileService = accessor.get(IFileService); const fileDialogService = accessor.get(IFileDialogService); - const bulkEditService = accessor.get(IBulkEditService); const explorerService = accessor.get(IExplorerService); const progressService = accessor.get(IProgressService); @@ -1243,10 +1232,7 @@ const downloadFileHandler = (accessor: ServicesAccessor) => { }); if (destination) { - await bulkEditService.apply([new ResourceFileEdit(explorerItem.resource, destination, { overwrite: true, copy: true })], { - undoRedoSource: explorerService.undoRedoSource, - label: nls.localize('downloadBulkEdit', "Download {0}", explorerItem.name) - }); + await explorerService.applyBulkEdit([new ResourceFileEdit(explorerItem.resource, destination, { overwrite: true, copy: true })], nls.localize('downloadBulkEdit', "Download {0}", explorerItem.name)); } else { cts.cancel(); // User canceled a download. In case there were multiple files selected we should cancel the remainder of the prompts #86100 } @@ -1268,7 +1254,6 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); const fileService = accessor.get(IFileService); const notificationService = accessor.get(INotificationService); - const bulkEditService = accessor.get(IBulkEditService); const editorService = accessor.get(IEditorService); const configurationService = accessor.get(IConfigurationService); const uriIdentityService = accessor.get(IUriIdentityService); @@ -1303,16 +1288,10 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { // Move/Copy File if (pasteShouldMove) { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target)); - await bulkEditService.apply(resourceFileEdits, { - undoRedoSource: explorerService.undoRedoSource, - label: sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) - }); + await explorerService.applyBulkEdit(resourceFileEdits, sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target))); } else { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target, { copy: true })); - await bulkEditService.apply(resourceFileEdits, { - undoRedoSource: explorerService.undoRedoSource, - label: sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) - }); + await explorerService.applyBulkEdit(resourceFileEdits, sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target))); } if (sourceTargetPairs.length >= 1) { diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index adfb39346e6..8e1badc5fe5 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -11,7 +11,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, IExplorerService, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, FilesExplorerFocusCondition, ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; +import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, FilesExplorerFocusCondition, ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { toErrorMessage } from 'vs/base/common/errorMessage'; @@ -23,7 +23,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { isWindows } from 'vs/base/common/platform'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection } from 'vs/workbench/contrib/files/browser/files'; +import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; import { Schemas } from 'vs/base/common/network'; diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 8adeb7faa60..7ea77d336c6 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -14,7 +14,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IEditorInputFactory, EditorInput, IFileEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions } from 'vs/workbench/common/editor'; import { AutoSaveConfiguration, HotExitConfiguration, FILES_EXCLUDE_CONFIG, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; -import { VIEWLET_ID, SortOrder, FILE_EDITOR_INPUT_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files'; +import { VIEWLET_ID, SortOrder, FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files'; import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; @@ -33,7 +33,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { ILabelService } from 'vs/platform/label/common/label'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { ExplorerService } from 'vs/workbench/contrib/files/common/explorerService'; +import { ExplorerService, UNDO_REDO_SOURCE } from 'vs/workbench/contrib/files/browser/explorerService'; import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/encoding'; import { Schemas } from 'vs/base/common/network'; import { WorkspaceWatcher } from 'vs/workbench/contrib/files/common/workspaceWatcher'; @@ -42,6 +42,7 @@ import { DirtyFilesIndicator } from 'vs/workbench/contrib/files/common/dirtyFile import { isEqual } from 'vs/base/common/resources'; import { UndoCommand, RedoCommand } from 'vs/editor/browser/editorExtensions'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; // Viewlet Action export class OpenExplorerViewletAction extends ShowViewletAction { @@ -492,7 +493,7 @@ UndoCommand.addImplementation(110, (accessor: ServicesAccessor) => { const undoRedoService = accessor.get(IUndoRedoService); const explorerService = accessor.get(IExplorerService); if (explorerService.hasViewFocus()) { - undoRedoService.undo(explorerService.undoRedoSource); + undoRedoService.undo(UNDO_REDO_SOURCE); return true; } @@ -503,7 +504,7 @@ RedoCommand.addImplementation(110, (accessor: ServicesAccessor) => { const undoRedoService = accessor.get(IUndoRedoService); const explorerService = accessor.get(IExplorerService); if (explorerService.hasViewFocus()) { - undoRedoService.redo(explorerService.undoRedoSource); + undoRedoService.redo(UNDO_REDO_SOURCE); return true; } diff --git a/src/vs/workbench/contrib/files/browser/files.ts b/src/vs/workbench/contrib/files/browser/files.ts index eb7102f947c..f60f26d9085 100644 --- a/src/vs/workbench/contrib/files/browser/files.ts +++ b/src/vs/workbench/contrib/files/browser/files.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { IListService } from 'vs/platform/list/browser/listService'; -import { OpenEditor, IExplorerService } from 'vs/workbench/contrib/files/common/files'; +import { OpenEditor, SortOrder } from 'vs/workbench/contrib/files/common/files'; import { EditorResourceAccessor, SideBySideEditor, IEditorIdentifier } from 'vs/workbench/common/editor'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -13,6 +13,51 @@ import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { coalesce } from 'vs/base/common/arrays'; import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditableData } from 'vs/workbench/common/views'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; + + +export interface IExplorerService { + readonly _serviceBrand: undefined; + readonly roots: ExplorerItem[]; + readonly sortOrder: SortOrder; + + getContext(respectMultiSelection: boolean): ExplorerItem[]; + hasViewFocus(): boolean; + setEditable(stat: ExplorerItem, data: IEditableData | null): Promise; + getEditable(): { stat: ExplorerItem, data: IEditableData } | undefined; + getEditableData(stat: ExplorerItem): IEditableData | undefined; + // If undefined is passed checks if any element is currently being edited. + isEditable(stat: ExplorerItem | undefined): boolean; + findClosest(resource: URI): ExplorerItem | null; + refresh(): Promise; + setToCopy(stats: ExplorerItem[], cut: boolean): Promise; + isCut(stat: ExplorerItem): boolean; + applyBulkEdit(edit: ResourceFileEdit[], label: string): Promise; + + /** + * Selects and reveal the file element provided by the given resource if its found in the explorer. + * Will try to resolve the path in case the explorer is not yet expanded to the file yet. + */ + select(resource: URI, reveal?: boolean | string): Promise; + + registerView(contextAndRefreshProvider: IExplorerView): void; +} + +export const IExplorerService = createDecorator('explorerService'); + +export interface IExplorerView { + getContext(respectMultiSelection: boolean): ExplorerItem[]; + refresh(recursive: boolean, item?: ExplorerItem): Promise; + selectResource(resource: URI | undefined, reveal?: boolean | string): Promise; + setTreeInput(): Promise; + itemsCopied(tats: ExplorerItem[], cut: boolean, previousCut: ExplorerItem[] | undefined): void; + setEditable(stat: ExplorerItem, isEditing: boolean): Promise; + focusNeighbourIfItemFocused(item: ExplorerItem): void; + isItemVisible(item: ExplorerItem): boolean; + hasFocus(): boolean; +} function getFocus(listService: IListService): unknown | undefined { let list = listService.lastFocusedList; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts b/src/vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts index d3a6797c90c..8816edd6e4e 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts @@ -10,9 +10,9 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { listInvalidItemForeground, listDeemphasizedForeground } from 'vs/platform/theme/common/colorRegistry'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { explorerRootErrorEmitter } from 'vs/workbench/contrib/files/browser/views/explorerViewer'; import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; export function provideDecorations(fileStat: ExplorerItem): IDecorationData | undefined { if (fileStat.isRoot && fileStat.isError) { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index ddd418e28f5..a9309b46767 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri'; import * as perf from 'vs/base/common/performance'; import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { memoize } from 'vs/base/common/decorators'; -import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, ExplorerRootContext, ExplorerResourceReadonlyContext, IExplorerService, ExplorerResourceCut, ExplorerResourceMoveableToTrash, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, ExplorerResourceAvailableEditorIdsContext } from 'vs/workbench/contrib/files/common/files'; +import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, ExplorerRootContext, ExplorerResourceReadonlyContext, ExplorerResourceCut, ExplorerResourceMoveableToTrash, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, ExplorerResourceAvailableEditorIdsContext } from 'vs/workbench/contrib/files/common/files'; import { NewFolderAction, NewFileAction, FileCopiedContext, RefreshExplorerView, CollapseExplorerView } from 'vs/workbench/contrib/files/browser/fileActions'; import * as DOM from 'vs/base/browser/dom'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -51,6 +51,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; interface IExplorerViewColors extends IColorMapping { listDropBackground?: ColorValue | undefined; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index de32dad57e7..4efc2368c53 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -19,7 +19,7 @@ import { ITreeNode, ITreeFilter, TreeVisibility, IAsyncDataSource, ITreeSorter, import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IFilesConfiguration, IExplorerService, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; +import { IFilesConfiguration, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; import { dirname, joinPath, basename, distinctParents, basenameOrAuthority } from 'vs/base/common/resources'; import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { localize } from 'vs/nls'; @@ -57,7 +57,8 @@ import { IEditableData } from 'vs/workbench/common/views'; import { IEditorInput } from 'vs/workbench/common/editor'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; +import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; export class ExplorerDelegate implements IListVirtualDelegate { @@ -812,8 +813,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { @IHostService private hostService: IHostService, @IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService, @IProgressService private readonly progressService: IProgressService, - @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, - @IBulkEditService private readonly bulkEditService: IBulkEditService + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService ) { this.toDispose = []; @@ -1074,10 +1074,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { continue; } - await this.bulkEditService.apply([new ResourceFileEdit(joinPath(target.resource, entry.name), undefined, { recursive: true })], { - undoRedoSource: this.explorerService.undoRedoSource, - label: localize('overwrite', "Overwrite {0}", entry.name) - }); + await this.explorerService.applyBulkEdit([new ResourceFileEdit(joinPath(target.resource, entry.name), undefined, { recursive: true })], localize('overwrite', "Overwrite {0}", entry.name)); if (token.isCancellationRequested) { break; @@ -1351,10 +1348,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { progress.report({ message: sourceFileName }); - await this.bulkEditService.apply([new ResourceFileEdit(sourceFile, targetFile, { overwrite: true, copy: true })], { - undoRedoSource: this.explorerService.undoRedoSource, - label: localize('copyFile', "Copy {0}", sourceFileName) - }); + await this.explorerService.applyBulkEdit([new ResourceFileEdit(sourceFile, targetFile, { overwrite: true, copy: true })], localize('copyFile', "Copy {0}", sourceFileName)); // if we only add one file, just open it directly const item = this.explorerService.findClosest(targetFile); @@ -1449,10 +1443,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Reuse duplicate action when user copies const incrementalNaming = this.configurationService.getValue().explorer.incrementalNaming; const resourceFileEdits = sources.map(({ resource, isDirectory }) => (new ResourceFileEdit(resource, findValidPasteFileTarget(this.explorerService, target, { resource, isDirectory, allowOverwrite: false }, incrementalNaming), { copy: true }))); - await this.bulkEditService.apply(resourceFileEdits, { - undoRedoSource: this.explorerService.undoRedoSource, - label: resourceFileEdits.length > 1 ? localize('copy', "Copy {0} files", resourceFileEdits.length) : localize('copyOneFile', "Copy {0}", basenameOrAuthority(resourceFileEdits[0].newResource!)) - }); + await this.explorerService.applyBulkEdit(resourceFileEdits, resourceFileEdits.length > 1 ? localize('copy', "Copy {0} files", resourceFileEdits.length) : localize('copyOneFile', "Copy {0}", basenameOrAuthority(resourceFileEdits[0].newResource!))); const editors = resourceFileEdits.filter(edit => { const item = edit.newResource ? this.explorerService.findClosest(edit.newResource) : undefined; @@ -1469,7 +1460,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const label = sources.length > 1 ? localize('move', "Move {0} files", sources.length) : localize('moveOneFile', "Move {0}", sources[0].name); try { - await this.bulkEditService.apply(resourceFileEdits, { undoRedoSource: this.explorerService.undoRedoSource, label }); + await this.explorerService.applyBulkEdit(resourceFileEdits, label); } catch (error) { // Conflict if ((error).fileOperationResult === FileOperationResult.FILE_MOVE_CONFLICT) { @@ -1486,10 +1477,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const { confirmed } = await this.dialogService.confirm(confirm); if (confirmed) { try { - await this.bulkEditService.apply(resourceFileEdits.map(re => new ResourceFileEdit(re.oldResource, re.newResource, { overwrite: true })), { - undoRedoSource: this.explorerService.undoRedoSource, - label - }); + await this.explorerService.applyBulkEdit(resourceFileEdits.map(re => new ResourceFileEdit(re.oldResource, re.newResource, { overwrite: true })), label); } catch (error) { this.notificationService.error(error); } diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 0933c9e8ed0..c4b563af882 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -15,14 +15,10 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkeys'; -import { IEditableData } from 'vs/workbench/common/views'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { once } from 'vs/base/common/functional'; import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; /** * Explorer viewlet id. @@ -34,47 +30,6 @@ export const VIEWLET_ID = 'workbench.view.explorer'; */ export const VIEW_ID = 'workbench.explorer.fileView'; -export interface IExplorerService { - readonly _serviceBrand: undefined; - readonly roots: ExplorerItem[]; - readonly sortOrder: SortOrder; - undoRedoSource: UndoRedoSource; - - getContext(respectMultiSelection: boolean): ExplorerItem[]; - hasViewFocus(): boolean; - setEditable(stat: ExplorerItem, data: IEditableData | null): Promise; - getEditable(): { stat: ExplorerItem, data: IEditableData } | undefined; - getEditableData(stat: ExplorerItem): IEditableData | undefined; - // If undefined is passed checks if any element is currently being edited. - isEditable(stat: ExplorerItem | undefined): boolean; - findClosest(resource: URI): ExplorerItem | null; - refresh(): Promise; - setToCopy(stats: ExplorerItem[], cut: boolean): Promise; - isCut(stat: ExplorerItem): boolean; - - /** - * Selects and reveal the file element provided by the given resource if its found in the explorer. - * Will try to resolve the path in case the explorer is not yet expanded to the file yet. - */ - select(resource: URI, reveal?: boolean | string): Promise; - - registerView(contextAndRefreshProvider: IExplorerView): void; -} - -export interface IExplorerView { - getContext(respectMultiSelection: boolean): ExplorerItem[]; - refresh(recursive: boolean, item?: ExplorerItem): Promise; - selectResource(resource: URI | undefined, reveal?: boolean | string): Promise; - setTreeInput(): Promise; - itemsCopied(tats: ExplorerItem[], cut: boolean, previousCut: ExplorerItem[] | undefined): void; - setEditable(stat: ExplorerItem, isEditing: boolean): Promise; - focusNeighbourIfItemFocused(item: ExplorerItem): void; - isItemVisible(item: ExplorerItem): boolean; - hasFocus(): boolean; -} - -export const IExplorerService = createDecorator('explorerService'); - /** * Context Keys to use with keybindings for the Explorer and Open Editors view */ diff --git a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index 934a85904b3..8fdd7c5b600 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -19,9 +19,9 @@ import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-sandbox import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution'; -import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { SideBySideEditor, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { ContextKeyOrExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS'; const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in File Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder"); diff --git a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index c6655f26307..d310e987250 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -21,9 +21,9 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; -import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; /** * An implementation of editor for file system resources. diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 84ecac2c414..6e2a09c5327 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -28,8 +28,8 @@ import { defaultQuickAccessContextKeyValue } from 'vs/workbench/browser/quickacc import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { Extensions as ViewExtensions, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; -import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; -import { ExplorerFolderContext, ExplorerRootContext, FilesExplorerFocusCondition, IExplorerService, VIEWLET_ID as VIEWLET_ID_FILES } from 'vs/workbench/contrib/files/common/files'; +import { getMultiSelectedResources, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { ExplorerFolderContext, ExplorerRootContext, FilesExplorerFocusCondition, VIEWLET_ID as VIEWLET_ID_FILES } from 'vs/workbench/contrib/files/common/files'; import { registerContributions as replaceContributions } from 'vs/workbench/contrib/search/browser/replaceContributions'; import { clearHistoryCommand, ClearSearchResultsAction, CloseReplaceAction, CollapseDeepestExpandedLevelAction, copyAllCommand, copyMatchCommand, copyPathCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, RefreshAction, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, togglePreserveCaseCommand, toggleRegexCommand, toggleWholeWordCommand, FindInFilesCommand, ToggleSearchOnTypeAction, ExpandAllAction } from 'vs/workbench/contrib/search/browser/searchActions'; import { SearchView } from 'vs/workbench/contrib/search/browser/searchView'; From e052c8e0451f6345a57045560e34d75140207a58 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 15:47:56 +0100 Subject: [PATCH 0204/1837] move down common icons --- src/vs/platform/theme/common/iconRegistry.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/theme/common/iconRegistry.ts b/src/vs/platform/theme/common/iconRegistry.ts index ca0d27b503a..63fcc3787de 100644 --- a/src/vs/platform/theme/common/iconRegistry.ts +++ b/src/vs/platform/theme/common/iconRegistry.ts @@ -12,11 +12,6 @@ import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/plat import { RunOnceScheduler } from 'vs/base/common/async'; import * as Codicons from 'vs/base/common/codicons'; -// common icons - -export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.')); - - // ------ API types @@ -220,3 +215,8 @@ iconRegistry.onDidChangeSchema(() => { //setTimeout(_ => console.log(iconRegistry.toString()), 5000); + + +// common icons + +export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.')); From c4b7d109123ca612cbe3d40e9c67575a145ec020 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 24 Nov 2020 16:03:40 +0100 Subject: [PATCH 0205/1837] Use property bag for tunnel creation elevation Fixes #110795 --- src/vs/platform/remote/common/tunnel.ts | 15 +++++++++++++-- src/vs/platform/remote/node/tunnelService.ts | 5 ++++- src/vs/vscode.proposed.d.ts | 9 ++++++++- .../api/browser/mainThreadTunnelService.ts | 6 +++--- src/vs/workbench/api/common/extHost.protocol.ts | 4 ++-- .../workbench/api/common/extHostTunnelService.ts | 4 ++-- src/vs/workbench/api/node/extHostTunnelService.ts | 8 ++++---- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index 52dfacbc403..7d9cde74bd2 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -26,8 +26,12 @@ export interface TunnelOptions { label?: string; } +export interface TunnelCreationInformation { + elevationRequired?: boolean; +} + export interface ITunnelProvider { - forwardPort(tunnelOptions: TunnelOptions): Promise | undefined; + forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined; } export interface ITunnelService { @@ -198,6 +202,10 @@ export abstract class AbstractTunnelService implements ITunnelService { } protected abstract retainOrCreateTunnel(addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort?: number): Promise | undefined; + + protected isPortPrivileged(port: number): boolean { + return port < 1024; + } } export class TunnelService extends AbstractTunnelService { @@ -209,7 +217,10 @@ export class TunnelService extends AbstractTunnelService { } if (this._tunnelProvider) { - const tunnel = this._tunnelProvider.forwardPort({ remoteAddress: { host: remoteHost, port: remotePort } }); + const preferredLocalPort = localPort === undefined ? remotePort : localPort; + const tunnelOptions = { remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort }; + const creationInfo = { elevationRequired: this.isPortPrivileged(preferredLocalPort) }; + const tunnel = this._tunnelProvider.forwardPort(tunnelOptions, creationInfo); if (tunnel) { this.addTunnelToMap(remoteHost, remotePort, tunnel); } diff --git a/src/vs/platform/remote/node/tunnelService.ts b/src/vs/platform/remote/node/tunnelService.ts index 0a27aabb5e5..19ec1efd67a 100644 --- a/src/vs/platform/remote/node/tunnelService.ts +++ b/src/vs/platform/remote/node/tunnelService.ts @@ -146,7 +146,10 @@ export class TunnelService extends AbstractTunnelService { } if (this._tunnelProvider) { - const tunnel = this._tunnelProvider.forwardPort({ remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort }); + const preferredLocalPort = localPort === undefined ? remotePort : localPort; + const creationInfo = { elevationRequired: this.isPortPrivileged(preferredLocalPort) }; + const tunnelOptions = { remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort }; + const tunnel = this._tunnelProvider.forwardPort(tunnelOptions, creationInfo); if (tunnel) { this.addTunnelToMap(remoteHost, remotePort, tunnel); } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 7de4a986580..8828df86fde 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -223,6 +223,13 @@ declare module 'vscode' { } + export interface TunnelCreationInformation { + /** + * True when the local operating system will require elevation to use the requested local port. + */ + elevationRequired?: boolean; + } + export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; export class RemoteAuthorityResolverError extends Error { @@ -239,7 +246,7 @@ declare module 'vscode' { * When not implemented, the core will use its default forwarding logic. * When implemented, the core will use this to forward ports. */ - tunnelFactory?: (tunnelOptions: TunnelOptions, elevate?: boolean) => Thenable | undefined; + tunnelFactory?: (tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => Thenable | undefined; /** * Provides filtering for candidate ports. diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index af625d0871d..cd71308d349 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -7,7 +7,7 @@ import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostCont import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { IRemoteExplorerService, makeAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; -import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { ITunnelProvider, ITunnelService, TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver'; @@ -57,8 +57,8 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun async $setTunnelProvider(): Promise { const tunnelProvider: ITunnelProvider = { - forwardPort: (tunnelOptions: TunnelOptions) => { - const forward = this._proxy.$forwardPort(tunnelOptions); + forwardPort: (tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => { + const forward = this._proxy.$forwardPort(tunnelOptions, tunnelCreationInformation); if (forward) { return forward.then(tunnel => { return { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6ca43431728..0cc07a41590 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -47,7 +47,7 @@ import * as search from 'vs/workbench/services/search/common/search'; import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor'; import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; -import { TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline'; import { revive } from 'vs/base/common/marshalling'; import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -1742,7 +1742,7 @@ export interface MainThreadThemingShape extends IDisposable { } export interface ExtHostTunnelServiceShape { - $forwardPort(tunnelOptions: TunnelOptions): Promise | undefined; + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined; $closeTunnel(remote: { host: string, port: number }, silent?: boolean): Promise; $onDidTunnelsChange(): Promise; } diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index 2ac455c6acf..ecc33e5016a 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -6,7 +6,7 @@ import { ExtHostTunnelServiceShape, MainContext, MainThreadTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import * as vscode from 'vscode'; -import { RemoteTunnel, TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { RemoteTunnel, TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; @@ -61,7 +61,7 @@ export class ExtHostTunnelService implements IExtHostTunnelService { await this._proxy.$tunnelServiceReady(); return { dispose: () => { } }; } - $forwardPort(tunnelOptions: TunnelOptions): Promise | undefined { return undefined; } + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined { return undefined; } async $closeTunnel(remote: { host: string, port: number }): Promise { } async $onDidTunnelsChange(): Promise { } } diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index c9faff3d01f..23b1357afd3 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -16,7 +16,7 @@ import { isLinux } from 'vs/base/common/platform'; import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { asPromise } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; -import { TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { TunnelOptions, TunnelCreationInformation } from 'vs/platform/remote/common/tunnel'; class ExtensionTunnel implements vscode.Tunnel { private _onDispose: Emitter = new Emitter(); @@ -36,7 +36,7 @@ class ExtensionTunnel implements vscode.Tunnel { export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService { readonly _serviceBrand: undefined; private readonly _proxy: MainThreadTunnelServiceShape; - private _forwardPortProvider: ((tunnelOptions: TunnelOptions) => Thenable | undefined) | undefined; + private _forwardPortProvider: ((tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => Thenable | undefined) | undefined; private _showCandidatePort: (host: string, port: number, detail: string) => Thenable = () => { return Promise.resolve(true); }; private _extensionTunnels: Map> = new Map(); private _onDidChangeTunnels: Emitter = new Emitter(); @@ -119,9 +119,9 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe this._onDidChangeTunnels.fire(); } - $forwardPort(tunnelOptions: TunnelOptions): Promise | undefined { + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined { if (this._forwardPortProvider) { - const providedPort = this._forwardPortProvider!(tunnelOptions); + const providedPort = this._forwardPortProvider(tunnelOptions, tunnelCreationInformation); if (providedPort !== undefined) { return asPromise(() => providedPort).then(tunnel => { if (!this._extensionTunnels.has(tunnelOptions.remoteAddress.host)) { From c0ecf176e71bf0f53aad09b39c499aaab13ba672 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 24 Nov 2020 17:44:28 +0100 Subject: [PATCH 0206/1837] Move ports view into the panel Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/remoteExplorer.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 70e167d1245..e6285ec948f 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { Extensions, IViewDescriptorService, IViewsRegistry, IViewsService } from 'vs/workbench/common/views'; +import { Extensions, IViewContainersRegistry, IViewsRegistry, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -22,6 +22,10 @@ import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { OperatingSystem } from 'vs/base/common/platform'; import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { Codicon } from 'vs/base/common/codicons'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; export const VIEWLET_ID = 'workbench.view.remote'; @@ -33,7 +37,6 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu @IContextKeyService private readonly contextKeyService: IContextKeyService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, - @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, @IStatusbarService private readonly statusbarService: IStatusbarService ) { super(); @@ -52,9 +55,18 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService); if (this.environmentService.remoteAuthority && viewEnabled) { + const viewContainer = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer({ + id: TunnelPanel.ID, + name: nls.localize('ports', "Ports"), + icon: ThemeIcon.fromCodicon(Codicon.plug), + ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TunnelPanel.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), + storageId: TunnelPanel.ID, + hideIfEmpty: true, + order: 5 + }, ViewContainerLocation.Panel); + const tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService); const viewsRegistry = Registry.as(Extensions.ViewsRegistry); - const viewContainer = this.viewDescriptorService.getViewContainerById(VIEWLET_ID); if (viewContainer) { viewsRegistry.registerViews([tunnelPanelDescriptor!], viewContainer); } From 950c942b7c96c4492cf4ab5e51cfbc82020e2044 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 24 Nov 2020 17:52:13 +0100 Subject: [PATCH 0207/1837] TunnelCreationInformation -> TunnelCreationOptions Fixes #110795 --- src/vs/platform/remote/common/tunnel.ts | 4 ++-- src/vs/vscode.proposed.d.ts | 4 ++-- src/vs/workbench/api/browser/mainThreadTunnelService.ts | 6 +++--- src/vs/workbench/api/common/extHost.protocol.ts | 4 ++-- src/vs/workbench/api/common/extHostTunnelService.ts | 4 ++-- src/vs/workbench/api/node/extHostTunnelService.ts | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index 7d9cde74bd2..a15e58462a6 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -26,12 +26,12 @@ export interface TunnelOptions { label?: string; } -export interface TunnelCreationInformation { +export interface TunnelCreationOptions { elevationRequired?: boolean; } export interface ITunnelProvider { - forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined; + forwardPort(tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined; } export interface ITunnelService { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 8828df86fde..b25d5aa1fc0 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -223,7 +223,7 @@ declare module 'vscode' { } - export interface TunnelCreationInformation { + export interface TunnelCreationOptions { /** * True when the local operating system will require elevation to use the requested local port. */ @@ -246,7 +246,7 @@ declare module 'vscode' { * When not implemented, the core will use its default forwarding logic. * When implemented, the core will use this to forward ports. */ - tunnelFactory?: (tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => Thenable | undefined; + tunnelFactory?: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => Thenable | undefined; /** * Provides filtering for candidate ports. diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index cd71308d349..25723794d5f 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -7,7 +7,7 @@ import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostCont import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { IRemoteExplorerService, makeAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; -import { ITunnelProvider, ITunnelService, TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver'; @@ -57,8 +57,8 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun async $setTunnelProvider(): Promise { const tunnelProvider: ITunnelProvider = { - forwardPort: (tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => { - const forward = this._proxy.$forwardPort(tunnelOptions, tunnelCreationInformation); + forwardPort: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => { + const forward = this._proxy.$forwardPort(tunnelOptions, tunnelCreationOptions); if (forward) { return forward.then(tunnel => { return { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 0cc07a41590..7ecee0d3c41 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -47,7 +47,7 @@ import * as search from 'vs/workbench/services/search/common/search'; import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor'; import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; -import { TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { TunnelCreationOptions, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline'; import { revive } from 'vs/base/common/marshalling'; import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -1742,7 +1742,7 @@ export interface MainThreadThemingShape extends IDisposable { } export interface ExtHostTunnelServiceShape { - $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined; + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined; $closeTunnel(remote: { host: string, port: number }, silent?: boolean): Promise; $onDidTunnelsChange(): Promise; } diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index ecc33e5016a..7444920d47d 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -6,7 +6,7 @@ import { ExtHostTunnelServiceShape, MainContext, MainThreadTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import * as vscode from 'vscode'; -import { RemoteTunnel, TunnelCreationInformation, TunnelOptions } from 'vs/platform/remote/common/tunnel'; +import { RemoteTunnel, TunnelCreationOptions, TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; @@ -61,7 +61,7 @@ export class ExtHostTunnelService implements IExtHostTunnelService { await this._proxy.$tunnelServiceReady(); return { dispose: () => { } }; } - $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined { return undefined; } + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined { return undefined; } async $closeTunnel(remote: { host: string, port: number }): Promise { } async $onDidTunnelsChange(): Promise { } } diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 23b1357afd3..de8123426f7 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -16,7 +16,7 @@ import { isLinux } from 'vs/base/common/platform'; import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { asPromise } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; -import { TunnelOptions, TunnelCreationInformation } from 'vs/platform/remote/common/tunnel'; +import { TunnelOptions, TunnelCreationOptions } from 'vs/platform/remote/common/tunnel'; class ExtensionTunnel implements vscode.Tunnel { private _onDispose: Emitter = new Emitter(); @@ -36,7 +36,7 @@ class ExtensionTunnel implements vscode.Tunnel { export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService { readonly _serviceBrand: undefined; private readonly _proxy: MainThreadTunnelServiceShape; - private _forwardPortProvider: ((tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation) => Thenable | undefined) | undefined; + private _forwardPortProvider: ((tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => Thenable | undefined) | undefined; private _showCandidatePort: (host: string, port: number, detail: string) => Thenable = () => { return Promise.resolve(true); }; private _extensionTunnels: Map> = new Map(); private _onDidChangeTunnels: Emitter = new Emitter(); @@ -119,9 +119,9 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe this._onDidChangeTunnels.fire(); } - $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationInformation: TunnelCreationInformation): Promise | undefined { + $forwardPort(tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined { if (this._forwardPortProvider) { - const providedPort = this._forwardPortProvider(tunnelOptions, tunnelCreationInformation); + const providedPort = this._forwardPortProvider(tunnelOptions, tunnelCreationOptions); if (providedPort !== undefined) { return asPromise(() => providedPort).then(tunnel => { if (!this._extensionTunnels.has(tunnelOptions.remoteAddress.host)) { From a5344096a2d65153ab560b48e60bfeb8e7063e66 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 17:53:39 +0100 Subject: [PATCH 0208/1837] raceTimeout test failed (fix #111233) --- src/vs/base/test/common/async.test.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index 8ce05e26edd..d1baf9b5b7b 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -651,41 +651,39 @@ suite('Async', () => { test('raceCancellation', async () => { const cts = new CancellationTokenSource(); - const now = Date.now(); - - const p = async.raceCancellation(async.timeout(100), cts.token); + let triggered = false; + const p = async.raceCancellation(async.timeout(100).then(() => triggered = true), cts.token); cts.cancel(); await p; - assert.ok(Date.now() - now < 100); + assert.ok(!triggered); }); test('raceTimeout', async () => { const cts = new CancellationTokenSource(); // timeout wins - let now = Date.now(); let timedout = false; + let triggered = false; - const p1 = async.raceTimeout(async.timeout(100), 1, () => timedout = true); + const p1 = async.raceTimeout(async.timeout(100).then(() => triggered = true), 1, () => timedout = true); cts.cancel(); await p1; - assert.ok(Date.now() - now < 100); + assert.ok(!triggered); assert.equal(timedout, true); // promise wins - now = Date.now(); timedout = false; - const p2 = async.raceTimeout(async.timeout(1), 100, () => timedout = true); + const p2 = async.raceTimeout(async.timeout(1).then(() => triggered = true), 100, () => timedout = true); cts.cancel(); await p2; - assert.ok(Date.now() - now < 100); + assert.ok(triggered); assert.equal(timedout, false); }); From bd40e2555b3d3119d78cb1c383d1b14d7f1ab30a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2020 17:58:22 +0100 Subject: [PATCH 0209/1837] remove TS on-type-rename feature, https://github.com/microsoft/vscode/issues/109923, fyi @mjbvz --- .../src/languageFeatures/renameOnType.ts | 73 ------------------- .../src/languageProvider.ts | 1 - 2 files changed, 74 deletions(-) delete mode 100644 extensions/typescript-language-features/src/languageFeatures/renameOnType.ts diff --git a/extensions/typescript-language-features/src/languageFeatures/renameOnType.ts b/extensions/typescript-language-features/src/languageFeatures/renameOnType.ts deleted file mode 100644 index ac2537de4dc..00000000000 --- a/extensions/typescript-language-features/src/languageFeatures/renameOnType.ts +++ /dev/null @@ -1,73 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { Kind } from '../protocol.const'; -import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService'; -import { conditionalRegistration, requireSomeCapability } from '../utils/dependentRegistration'; -import { DocumentSelector } from '../utils/documentSelector'; -import * as typeConverters from '../utils/typeConverters'; - - -class TypeScriptOnTypeRenameProvider implements vscode.OnTypeRenameRangeProvider { - - private static enabledKinds = new Set([ - Kind.let, Kind.const, Kind.localVariable, Kind.parameter, Kind.typeParameter - ]); - - public constructor( - private readonly client: ITypeScriptServiceClient - ) { } - - public async provideOnTypeRenameRanges( - document: vscode.TextDocument, - position: vscode.Position, - token: vscode.CancellationToken - ): Promise { - const file = this.client.toOpenedFilePath(document); - if (!file) { - return undefined; - } - const args = typeConverters.Position.toFileLocationRequestArgs(file, position); - // - - const quickInfoResponse = await this.client.interruptGetErr(() => this.client.execute('quickinfo', args, token)); - if (quickInfoResponse.type !== 'response' || !quickInfoResponse.body) { - return undefined; - } - - if (!TypeScriptOnTypeRenameProvider.enabledKinds.has(quickInfoResponse.body.kind)) { - return undefined; - } - - const renameResponse = await this.client.execute('rename', args, token); - if (!renameResponse || renameResponse.type !== 'response' || !renameResponse.body) { - return undefined; - } - - if (renameResponse.body.locs.length !== 1 || renameResponse.body.locs[0].file !== file) { - return undefined; // not a local? - } - - const ranges = renameResponse.body.locs[0].locs.map(typeConverters.Range.fromTextSpan); - if (ranges.length <= 1) { - return undefined; // not enough usages - } - return new vscode.OnTypeRenameRanges(ranges); - } - -} - -export function register( - selector: DocumentSelector, - client: ITypeScriptServiceClient -): vscode.Disposable { - return conditionalRegistration([ - requireSomeCapability(client, ClientCapability.EnhancedSyntax, ClientCapability.Semantic), - ], () => { - return vscode.languages.registerOnTypeRenameRangeProvider(selector.syntax, - new TypeScriptOnTypeRenameProvider(client)); - }); -} diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 888fa79350b..92ab84be308 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -76,7 +76,6 @@ export default class LanguageProvider extends Disposable { import('./languageFeatures/references').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/codeLens/referencesCodeLens').then(provider => this._register(provider.register(selector, this.description.id, this.client, cachedResponse))), import('./languageFeatures/rename').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager))), - import('./languageFeatures/renameOnType').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/smartSelect').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/signatureHelp').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/tagClosing').then(provider => this._register(provider.register(selector, this.description.id, this.client))), From c37ffd83ba22619c017c41d77268e5888f5ecb4a Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Tue, 24 Nov 2020 16:59:46 +0000 Subject: [PATCH 0210/1837] fixes #111240 --- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 92a6459dab8..37a681a161b 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -26,7 +26,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { assertIsDefined, isString } from 'vs/base/common/types'; +import { assertIsDefined } from 'vs/base/common/types'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -357,9 +357,9 @@ export abstract class ViewPane extends Pane implements IView { -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; -webkit-mask-size: 16px; `); - } else if (isString(icon)) { + } else if (ThemeIcon.isThemeIcon(icon)) { this.iconContainer.classList.add('codicon'); - cssClass = icon; + cssClass = ThemeIcon.asClassName(icon); } if (cssClass) { From 5987e4076572afbac347b1ec7946ecc59ecaf682 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Tue, 24 Nov 2020 09:04:03 -0800 Subject: [PATCH 0211/1837] Add vscode.Uri to types for vscode.RelativePattern's base parameter (#111155) --- src/vs/vscode.d.ts | 2 +- src/vs/workbench/api/common/extHostTypes.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 117744ceb92..ada25847aad 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1905,7 +1905,7 @@ declare module 'vscode' { * @param pattern A file glob pattern like `*.{ts,js}` that will be matched on file paths * relative to the base path. */ - constructor(base: WorkspaceFolder | string, pattern: string) + constructor(base: Uri | WorkspaceFolder | string, pattern: string) } /** diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 8788574ca1b..5e103f86870 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2193,9 +2193,9 @@ export class RelativePattern implements IRelativePattern { pattern: string; - constructor(base: vscode.WorkspaceFolder | string, pattern: string) { + constructor(base: URI | vscode.WorkspaceFolder | string, pattern: string) { if (typeof base !== 'string') { - if (!base || !URI.isUri(base.uri)) { + if (!base || !URI.isUri(base) && !URI.isUri(base.uri)) { throw illegalArgument('base'); } } @@ -2206,6 +2206,9 @@ export class RelativePattern implements IRelativePattern { if (typeof base === 'string') { this.base = base; + } else if (URI.isUri(base)) { + this.baseFolder = base; + this.base = base.fsPath; } else { this.baseFolder = base.uri; this.base = base.uri.fsPath; From 66cb21b0b1dfe33dfa8499bc96c2bb3603bce327 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 18:10:23 +0100 Subject: [PATCH 0212/1837] Fix #107999 --- .../extensions/browser/fileBasedRecommendations.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index fd76f1ac299..b11bc39dacf 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -150,8 +150,15 @@ export class FileBasedRecommendations extends ExtensionRecommendations { } private onModelAdded(model: ITextModel): void { + const uri = model.uri; + const supportedSchemes = [Schemas.untitled, Schemas.file, Schemas.vscodeRemote]; + if (!uri || !supportedSchemes.includes(uri.scheme)) { + return; + } + this.promptRecommendationsForModel(model); - this._register(model.onDidChangeLanguage(() => this.promptRecommendationsForModel(model))); + const disposable = model.onDidChangeLanguage(() => this.promptRecommendationsForModel(model)); + model.onWillDispose(() => disposable.dispose()); } /** @@ -160,11 +167,6 @@ export class FileBasedRecommendations extends ExtensionRecommendations { */ private promptRecommendationsForModel(model: ITextModel): void { const uri = model.uri; - const supportedSchemes = [Schemas.untitled, Schemas.file, Schemas.vscodeRemote]; - if (!uri || !supportedSchemes.includes(uri.scheme)) { - return; - } - const language = model.getLanguageIdentifier().language; const fileExtension = extname(uri).toLowerCase(); if (this.processedLanguages.includes(language) && this.processedFileExtensions.includes(fileExtension)) { From 562d9451bc007696e417584b048a76e54812b656 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 24 Nov 2020 09:13:13 -0800 Subject: [PATCH 0213/1837] Fix #109114 --- src/vs/workbench/browser/parts/activitybar/activitybarActions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 6dbeb2dd61c..49bbae451e9 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -471,6 +471,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = left: 9px; height: 32px; width: 32px; + z-index: 1; } .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:before, From 2be5cc18457b9eef894a8119cae3acb3a16d3dab Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 24 Nov 2020 18:16:47 +0100 Subject: [PATCH 0214/1837] #107999 Use disposable store and add onWillDispose listener --- .../contrib/extensions/browser/fileBasedRecommendations.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index b11bc39dacf..cab0ed9a70a 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -27,6 +27,7 @@ import { setImmediate } from 'vs/base/common/platform'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IExtensionRecommendationNotificationService, RecommendationsNotificationResult, RecommendationSource } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { distinct } from 'vs/base/common/arrays'; +import { DisposableStore } from 'vs/base/common/lifecycle'; type FileExtensionSuggestionClassification = { userReaction: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; @@ -157,8 +158,9 @@ export class FileBasedRecommendations extends ExtensionRecommendations { } this.promptRecommendationsForModel(model); - const disposable = model.onDidChangeLanguage(() => this.promptRecommendationsForModel(model)); - model.onWillDispose(() => disposable.dispose()); + const disposables = new DisposableStore(); + disposables.add(model.onDidChangeLanguage(() => this.promptRecommendationsForModel(model))); + disposables.add(model.onWillDispose(() => disposables.dispose())); } /** From 2e8bbdb41e03752c16d84dcaae54b159f0c13d62 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 18:30:46 +0100 Subject: [PATCH 0215/1837] api - test relative pattern with URI --- .../test/browser/api/extHostWorkspace.test.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/test/browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/browser/api/extHostWorkspace.test.ts index b36ec55951c..a3eacd6e298 100644 --- a/src/vs/workbench/test/browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/browser/api/extHostWorkspace.test.ts @@ -605,7 +605,7 @@ suite('ExtHostWorkspace', function () { }); }); - test('findFiles - RelativePattern include', () => { + function testFindFilesInclude(pattern: RelativePattern) { const root = '/project/foo'; const rpcProtocol = new TestRPCProtocol(); @@ -614,16 +614,24 @@ suite('ExtHostWorkspace', function () { $startFileSearch(includePattern: string, _includeFolder: UriComponents | null, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { mainThreadCalled = true; assert.equal(includePattern, 'glob/**'); - assert.deepEqual(_includeFolder, URI.file('/other/folder').toJSON()); + assert.deepEqual(_includeFolder ? URI.from(_includeFolder).toJSON() : null, URI.file('/other/folder').toJSON()); assert.equal(excludePatternOrDisregardExcludes, null); return Promise.resolve(null); } }); const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService()); - return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), undefined, 10, new ExtensionIdentifier('test')).then(() => { + return ws.findFiles(pattern, undefined, 10, new ExtensionIdentifier('test')).then(() => { assert(mainThreadCalled, 'mainThreadCalled'); }); + } + + test('findFiles - RelativePattern include (string)', () => { + return testFindFilesInclude(new RelativePattern('/other/folder', 'glob/**')); + }); + + test('findFiles - RelativePattern include (URI)', () => { + return testFindFilesInclude(new RelativePattern(URI.file('/other/folder'), 'glob/**')); }); test('findFiles - no excludes', () => { From f9aa23fb6c1f01ccc7bc783c2d4db130d38b5145 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 18:38:53 +0100 Subject: [PATCH 0216/1837] relative pattern - update JSDoc comment --- src/vs/vscode.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index ada25847aad..baa0c1e9dcd 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1901,7 +1901,9 @@ declare module 'vscode' { * Creates a new relative pattern object with a base path and pattern to match. This pattern * will be matched on file paths relative to the base path. * - * @param base A base file path to which this pattern will be matched against relatively. + * @param base A base to which this pattern will be matched against relatively. It is recommended + * to pass in a [workspace folder](#WorkspaceFolder) if the pattern should match inside that folder. + * Otherwise, a uri or string should only be used if the pattern is for a path outside the workspace. * @param pattern A file glob pattern like `*.{ts,js}` that will be matched on file paths * relative to the base path. */ From 160baa3b8d3c2c7e8ed17272b7ffe770221cf4af Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2020 18:40:29 +0100 Subject: [PATCH 0217/1837] :lipstick: --- src/vs/vscode.d.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index baa0c1e9dcd..c908c01ba7b 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1898,14 +1898,13 @@ declare module 'vscode' { pattern: string; /** - * Creates a new relative pattern object with a base path and pattern to match. This pattern - * will be matched on file paths relative to the base path. + * Creates a new relative pattern object with a base and pattern to match. This pattern + * will be matched on paths relative to the base path. * * @param base A base to which this pattern will be matched against relatively. It is recommended - * to pass in a [workspace folder](#WorkspaceFolder) if the pattern should match inside that folder. + * to pass in a [workspace folder](#WorkspaceFolder) if the pattern should match inside the workspace. * Otherwise, a uri or string should only be used if the pattern is for a path outside the workspace. - * @param pattern A file glob pattern like `*.{ts,js}` that will be matched on file paths - * relative to the base path. + * @param pattern A file glob pattern like `*.{ts,js}` that will be matched on paths relative to the base. */ constructor(base: Uri | WorkspaceFolder | string, pattern: string) } From 23e7e2fef0280cfc9e5881a951ccafee46f47dc3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 24 Nov 2020 10:26:09 -0800 Subject: [PATCH 0218/1837] showNotebookDocument. --- src/vs/vscode.proposed.d.ts | 8 +++ .../api/browser/mainThreadNotebook.ts | 57 ++++++++++++++++++- .../workbench/api/common/extHost.api.impl.ts | 4 ++ .../workbench/api/common/extHost.protocol.ts | 8 +++ .../workbench/api/common/extHostNotebook.ts | 31 +++++++++- .../contrib/notebook/common/notebookCommon.ts | 1 + 6 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b25d5aa1fc0..4ee34c795b5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1849,6 +1849,13 @@ declare module 'vscode' { dispose(): void; } + export interface NotebookDocumentShowOptions { + viewColumn?: ViewColumn; + preserveFocus?: boolean; + preview?: boolean; + selection?: NotebookCellRange; + } + export namespace notebook { export function registerNotebookContentProvider( @@ -1916,6 +1923,7 @@ declare module 'vscode' { export const onDidChangeActiveNotebookEditor: Event; export const onDidChangeNotebookEditorSelection: Event; export const onDidChangeNotebookEditorVisibleRanges: Event; + export function showNotebookDocument(document: NotebookDocument, options?: NotebookDocumentShowOptions): Promise; } //#endregion diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 06ee86ff822..f98ed6bb833 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -14,8 +14,11 @@ import { IExtUri } from 'vs/base/common/resources'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { EditorActivation, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { ILogService } from 'vs/platform/log/common/log'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; +import { viewColumnToEditorGroup } from 'vs/workbench/common/editor'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -23,10 +26,12 @@ import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/com import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, IMainCellDto, INotebookDecorationRenderOptions, INotebookDocumentFilter, INotebookEditorModel, INotebookExclusiveDocumentFilter, NotebookCellOutputsSplice, NotebookCellsChangeType, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorGroup, IEditorGroupsService, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith'; +import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; -import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, INotebookModelAddedData, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol'; +import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookModelAddedData, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol'; class DocumentAndEditorState { static ofSets(before: Set, after: Set): { removed: T[], added: T[] } { @@ -152,7 +157,10 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo @INotebookService private _notebookService: INotebookService, @IConfigurationService private readonly configurationService: IConfigurationService, @IEditorService private readonly editorService: IEditorService, + @IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService, + @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, @IAccessibilityService private readonly accessibilityService: IAccessibilityService, + @IQuickInputService private readonly quickInputService: IQuickInputService, @ILogService private readonly logService: ILogService, @INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService, @IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService, @@ -722,6 +730,51 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo return uri; } + + async $tryShowNotebookDocument(resource: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise { + const editorOptions: ITextEditorOptions = { + preserveFocus: options.preserveFocus, + pinned: options.pinned, + // selection: options.selection, + // preserve pre 1.38 behaviour to not make group active when preserveFocus: true + // but make sure to restore the editor to fix https://github.com/microsoft/vscode/issues/79633 + activation: options.preserveFocus ? EditorActivation.RESTORE : undefined, + override: false, + }; + + const columnArg = viewColumnToEditorGroup(this._editorGroupService, options.position); + + let group: IEditorGroup | undefined = undefined; + + if (columnArg === SIDE_GROUP) { + const direction = preferredSideBySideGroupDirection(this.configurationService); + + let neighbourGroup = this.editorGroupsService.findGroup({ direction }); + if (!neighbourGroup) { + neighbourGroup = this.editorGroupsService.addGroup(this.editorGroupsService.activeGroup, direction); + } + group = neighbourGroup; + } else { + group = this.editorGroupsService.getGroup(viewColumnToEditorGroup(this.editorGroupsService, columnArg)) ?? this.editorGroupsService.activeGroup; + } + + const input = this.editorService.createEditorInput({ resource: URI.revive(resource), options: editorOptions }); + + // TODO: handle options.selection + const editorPane = await openEditorWith(input, viewType, options, group, this.editorService, this.configurationService, this.quickInputService); + const notebookEditor = (editorPane as unknown as { isNotebookEditor?: boolean })?.isNotebookEditor ? (editorPane!.getControl() as INotebookEditor) : undefined; + + if (notebookEditor) { + if (notebookEditor.viewModel && options.selection && notebookEditor.viewModel.viewCells[options.selection.start]) { + const focusedCell = notebookEditor.viewModel.viewCells[options.selection.start]; + notebookEditor.revealInCenterIfOutsideViewport(focusedCell); + notebookEditor.selectElement(focusedCell); + } + return notebookEditor.getId(); + } else { + throw new Error(`Notebook Editor creation failure for documenet ${resource}`); + } + } } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index ee9a8ef8c3c..a8d42e2e243 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -688,6 +688,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension); return extHostNotebook.onDidChangeNotebookEditorVisibleRanges(listener, thisArgs, disposables); }, + showNotebookDocument(document, options?) { + checkProposedApiEnabled(extension); + return extHostNotebook.showNotebookDocument(document, options); + } }; // namespace: workspace diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7ecee0d3c41..ac101e511bb 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -741,6 +741,13 @@ export enum NotebookEditorRevealType { InCenterIfOutsideViewport = 2, } +export interface INotebookDocumentShowOptions { + position?: EditorGroupColumn; + preserveFocus?: boolean; + pinned?: boolean; + selection?: ICellRange; +} + export type INotebookCellStatusBarEntryDto = Dto; export interface MainThreadNotebookShape extends IDisposable { @@ -760,6 +767,7 @@ export interface MainThreadNotebookShape extends IDisposable { $postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise; $setStatusBarEntry(id: number, statusBarEntry: INotebookCellStatusBarEntryDto): Promise; $tryOpenDocument(uriComponents: UriComponents, viewType?: string): Promise; + $tryShowNotebookDocument(uriComponents: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise; $tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType): Promise; $registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void; $removeNotebookEditorDecorationType(key: string): void; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 0846a2d55bb..07e0673ae62 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -9,7 +9,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { ExtHostNotebookShape, ICommandDto, IMainContext, IModelAddedData, INotebookDocumentPropertiesChangeData, INotebookDocumentsAndEditorsDelta, INotebookEditorPropertiesChangeData, MainContext, MainThreadBulkEditsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostNotebookShape, ICommandDto, IMainContext, IModelAddedData, INotebookDocumentPropertiesChangeData, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorPropertiesChangeData, MainContext, MainThreadBulkEditsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol'; import { ILogService } from 'vs/platform/log/common/log'; import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; @@ -414,6 +414,35 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN return callback(provider, document); } + async showNotebookDocument(notebookDocument: vscode.NotebookDocument, options?: vscode.NotebookDocumentShowOptions): Promise { + let resolvedOptions: INotebookDocumentShowOptions; + if (typeof options === 'object') { + resolvedOptions = { + position: typeConverters.ViewColumn.from(options.viewColumn), + preserveFocus: options.preserveFocus, + selection: options.selection, + pinned: typeof options.preview === 'boolean' ? !options.preview : undefined + }; + } else { + resolvedOptions = { + preserveFocus: false + }; + } + + const editorId = await this._proxy.$tryShowNotebookDocument(notebookDocument.uri, notebookDocument.viewType, resolvedOptions); + const editor = editorId && this._editors.get(editorId)?.editor; + + if (editor) { + return editor; + } + + if (editorId) { + throw new Error(`Could NOT open editor for "${document.documentURI.toString()}" because another editor opened in the meantime.`); + } else { + throw new Error(`Could NOT open editor for "${document.documentURI.toString()}".`); + } + } + async $provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise { return this._withAdapter(handle, uri, (adapter, document) => { return adapter.provideKernels(document, token); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index dcab1f736e6..0a9b17b2139 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -888,3 +888,4 @@ export interface INotebookDecorationRenderOptions { borderColor?: string | ThemeColor; top?: editorCommon.IContentDecorationRenderOptions; } + From 07bd0e3c351dab4f30c6b6b43ff6f0a5db0ae6ff Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 24 Nov 2020 10:37:22 -0800 Subject: [PATCH 0219/1837] :lipstick: --- .../contrib/notebook/browser/notebook.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 0bf87835e03..b3e9c30f768 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -241,7 +241,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri }); }, open: (editor, options, group) => { - return this.onEditorOpening2(editor, options, group); + return this.onEditorOpening(editor, options, group); } })); @@ -285,7 +285,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri return this.notebookService.getContributedNotebookProviders(resource); } - private onEditorOpening2(originalInput: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined { + private onEditorOpening(originalInput: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined { let id = typeof options?.override === 'string' ? options.override : undefined; if (id === undefined && originalInput.resource?.scheme === Schemas.untitled) { From 40a81495f298ddfda8fc7e8b174b3eb1569e9f1b Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 24 Nov 2020 11:00:51 -0800 Subject: [PATCH 0220/1837] fix: removed plugin helper entitlement we build with enable_plugins=false for the internal builds https://chromium-review.googlesource.com/c/chromium/src/+/2173416 --- .../darwin/helper-plugin-entitlements.plist | 10 ---------- build/darwin/sign.ts | 10 ---------- 2 files changed, 20 deletions(-) delete mode 100644 build/azure-pipelines/darwin/helper-plugin-entitlements.plist diff --git a/build/azure-pipelines/darwin/helper-plugin-entitlements.plist b/build/azure-pipelines/darwin/helper-plugin-entitlements.plist deleted file mode 100644 index 7cd9df032bd..00000000000 --- a/build/azure-pipelines/darwin/helper-plugin-entitlements.plist +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.cs.allow-unsigned-executable-memory - - com.apple.security.cs.disable-library-validation - - - diff --git a/build/darwin/sign.ts b/build/darwin/sign.ts index 538dc97adf1..f1908b14749 100644 --- a/build/darwin/sign.ts +++ b/build/darwin/sign.ts @@ -29,7 +29,6 @@ async function main(): Promise { const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks'); const helperAppBaseName = product.nameShort; const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app'; - const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app'; const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app'; const defaultOpts: codesign.SignOptions = { @@ -51,7 +50,6 @@ async function main(): Promise { // TODO(deepak1556): Incorrectly declared type in electron-osx-sign ignore: (filePath: string) => { return filePath.includes(gpuHelperAppName) || - filePath.includes(pluginHelperAppName) || filePath.includes(rendererHelperAppName); } }; @@ -63,13 +61,6 @@ async function main(): Promise { 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), }; - const pluginHelperOpts: codesign.SignOptions = { - ...defaultOpts, - app: path.join(appFrameworkPath, pluginHelperAppName), - entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), - 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), - }; - const rendererHelperOpts: codesign.SignOptions = { ...defaultOpts, app: path.join(appFrameworkPath, rendererHelperAppName), @@ -78,7 +69,6 @@ async function main(): Promise { }; await codesign.signAsync(gpuHelperOpts); - await codesign.signAsync(pluginHelperOpts); await codesign.signAsync(rendererHelperOpts); await codesign.signAsync(appOpts as any); } From fd15b932611ef5295d8a700ac57be691c166b1ac Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 24 Nov 2020 11:12:15 -0800 Subject: [PATCH 0221/1837] remove layer breaker --- src/vs/workbench/api/common/extHostNotebook.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 07e0673ae62..9cc0cf8d2c1 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -437,9 +437,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN } if (editorId) { - throw new Error(`Could NOT open editor for "${document.documentURI.toString()}" because another editor opened in the meantime.`); + throw new Error(`Could NOT open editor for "${notebookDocument.toString()}" because another editor opened in the meantime.`); } else { - throw new Error(`Could NOT open editor for "${document.documentURI.toString()}".`); + throw new Error(`Could NOT open editor for "${notebookDocument.toString()}".`); } } From 24e9b29b39672cfe5f85d059c0142ab86c1aa7d5 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 24 Nov 2020 11:28:55 -0800 Subject: [PATCH 0222/1837] wording for output show more. --- .../notebook/browser/view/output/transforms/textHelper.ts | 2 +- .../contrib/notebook/browser/view/renderers/cellOutput.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts index b3a6b38b115..8ef36f85029 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts @@ -20,7 +20,7 @@ const LINES_LIMIT = 500; function generateViewMoreElement(outputs: string[], openerService: IOpenerService, textFileService: ITextFileService) { const md: IMarkdownString = { - value: '[show more ...](command:workbench.action.openLargeOutput)', + value: '[show more (open the raw output data in a text editor) ...](command:workbench.action.openLargeOutput)', isTrusted: true, supportThemeIcons: true }; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index fc6f6a9aeec..f2dbc30f49e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -478,7 +478,7 @@ export class OutputContainer extends Disposable { private _generateShowMoreElement(): any { const md: IMarkdownString = { - value: `There are more than ${OUTPUT_COUNT_LIMIT} outputs, [show more ...](command:workbench.action.openLargeOutput)`, + value: `There are more than ${OUTPUT_COUNT_LIMIT} outputs, [show more (open the raw output data in a text editor) ...](command:workbench.action.openLargeOutput)`, isTrusted: true, supportThemeIcons: true }; From 668b1d24399e3df2a517d1d18f2b406b1cef8cee Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2020 21:02:16 +0100 Subject: [PATCH 0223/1837] explorer file operations: show progress fixes #73996 --- .../contrib/files/browser/explorerService.ts | 23 +++- .../contrib/files/browser/fileActions.ts | 33 +++++- .../workbench/contrib/files/browser/files.ts | 2 +- .../files/browser/views/explorerViewer.ts | 111 +++++++++--------- 4 files changed, 103 insertions(+), 66 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index e337ee9236b..70b1b8f59e8 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -19,6 +19,7 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/ur import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; import { IExplorerView, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; export const UNDO_REDO_SOURCE = new UndoRedoSource(); @@ -41,7 +42,8 @@ export class ExplorerService implements IExplorerService { @IClipboardService private clipboardService: IClipboardService, @IEditorService private editorService: IEditorService, @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, - @IBulkEditService private readonly bulkEditService: IBulkEditService + @IBulkEditService private readonly bulkEditService: IBulkEditService, + @IProgressService private readonly progressService: IProgressService ) { this._sortOrder = this.configurationService.getValue('explorer.sortOrder'); @@ -90,11 +92,22 @@ export class ExplorerService implements IExplorerService { return this.view.getContext(respectMultiSelection); } - async applyBulkEdit(edit: ResourceFileEdit[], label: string): Promise { - await this.bulkEditService.apply(edit, { - undoRedoSource: UNDO_REDO_SOURCE, - label, + async applyBulkEdit(edit: ResourceFileEdit[], options: { undoLabel: string, progressLabel: string }): Promise { + const promise = this.progressService.withProgress({ + location: ProgressLocation.Window, + delay: 500, + title: options.progressLabel + }, async progress => { + + await this.bulkEditService.apply(edit, { + undoRedoSource: UNDO_REDO_SOURCE, + label: options.undoLabel, + progress + }); }); + this.progressService.withProgress({ location: ProgressLocation.Explorer, delay: 500 }, () => promise); + + return promise; } hasViewFocus(): boolean { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index bfcb7dd6975..ced14610695 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -221,7 +221,11 @@ async function deleteFiles(explorerService: IExplorerService, workingCopyFileSer // Call function try { const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash, maxSize: MAX_UNDO_FILE_SIZE })); - await explorerService.applyBulkEdit(resourceFileEdits, distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name)); + const options = { + undoLabel: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name), + progressLabel: distinctElements.length > 1 ? nls.localize('deletingBulkEdit', "Deleting {0} files", distinctElements.length) : nls.localize('deletingFileBulkEdit', "Deleting {0}", distinctElements[0].name), + }; + await explorerService.applyBulkEdit(resourceFileEdits, options); } catch (error) { // Handle error to delete file(s) from a modal confirmation dialog @@ -904,7 +908,10 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole const onSuccess = async (value: string): Promise => { try { const resourceToCreate = resources.joinPath(folder.resource, value); - await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], nls.localize('newBulkEdit', "New {0}", value)); + await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], { + progressLabel: nls.localize('newBulkEdit', "New {0}", value), + undoLabel: nls.localize('newBulkEdit', "New {0}", value) + }); await refreshIfSeparator(value, explorerService); if (isFolder) { @@ -961,7 +968,10 @@ export const renameHandler = async (accessor: ServicesAccessor) => { const targetResource = resources.joinPath(parentResource, value); if (stat.resource.toString() !== targetResource.toString()) { try { - await explorerService.applyBulkEdit([new ResourceFileEdit(stat.resource, targetResource)], nls.localize('renameBulkEdit', "Rename {0} to {1}", stat.name, value)); + await explorerService.applyBulkEdit([new ResourceFileEdit(stat.resource, targetResource)], { + undoLabel: nls.localize('renameBulkEdit', "Rename {0} to {1}", stat.name, value), + progressLabel: nls.localize('renamingBulkEdit', "Renaming {0} to {1}", stat.name, value), + }); await refreshIfSeparator(value, explorerService); } catch (e) { notificationService.error(e); @@ -1232,7 +1242,10 @@ const downloadFileHandler = (accessor: ServicesAccessor) => { }); if (destination) { - await explorerService.applyBulkEdit([new ResourceFileEdit(explorerItem.resource, destination, { overwrite: true, copy: true })], nls.localize('downloadBulkEdit', "Download {0}", explorerItem.name)); + await explorerService.applyBulkEdit([new ResourceFileEdit(explorerItem.resource, destination, { overwrite: true, copy: true })], { + undoLabel: nls.localize('downloadBulkEdit', "Download {0}", explorerItem.name), + progressLabel: nls.localize('downloadingBulkEdit', "Downloading {0}", explorerItem.name), + }); } else { cts.cancel(); // User canceled a download. In case there were multiple files selected we should cancel the remainder of the prompts #86100 } @@ -1288,10 +1301,18 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { // Move/Copy File if (pasteShouldMove) { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target)); - await explorerService.applyBulkEdit(resourceFileEdits, sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target))); + const options = { + progressLabel: sourceTargetPairs.length > 1 ? nls.localize('movingBulkEdit', "Moving {0} files", sourceTargetPairs.length) : nls.localize('movingFileBulkEdit', "Moving {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + }; + await explorerService.applyBulkEdit(resourceFileEdits, options); } else { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target, { copy: true })); - await explorerService.applyBulkEdit(resourceFileEdits, sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target))); + const options = { + progressLabel: sourceTargetPairs.length > 1 ? nls.localize('copyingBulkEdit', "Copying {0} files", sourceTargetPairs.length) : nls.localize('copyingFileBulkEdit', "Copying {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + }; + await explorerService.applyBulkEdit(resourceFileEdits, options); } if (sourceTargetPairs.length >= 1) { diff --git a/src/vs/workbench/contrib/files/browser/files.ts b/src/vs/workbench/contrib/files/browser/files.ts index f60f26d9085..95e137cb3a8 100644 --- a/src/vs/workbench/contrib/files/browser/files.ts +++ b/src/vs/workbench/contrib/files/browser/files.ts @@ -34,7 +34,7 @@ export interface IExplorerService { refresh(): Promise; setToCopy(stats: ExplorerItem[], cut: boolean): Promise; isCut(stat: ExplorerItem): boolean; - applyBulkEdit(edit: ResourceFileEdit[], label: string): Promise; + applyBulkEdit(edit: ResourceFileEdit[], options: { undoLabel: string, progressLabel: string }): Promise; /** * Selects and reveal the file element provided by the given resource if its found in the explorer. diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 4efc2368c53..71b44a81d1d 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -40,7 +40,7 @@ import { IDialogService, IConfirmation, getFileNamesMessage } from 'vs/platform/ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { URI } from 'vs/base/common/uri'; -import { ITask, RunOnceWorker, sequence } from 'vs/base/common/async'; +import { RunOnceWorker } from 'vs/base/common/async'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; import { findValidPasteFileTarget } from 'vs/workbench/contrib/files/browser/fileActions'; @@ -1014,25 +1014,24 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const cts = new CancellationTokenSource(); // Indicate progress globally - const dropPromise = this.progressService.withProgress({ - location: ProgressLocation.Window, - delay: 800, - cancellable: true, - title: isWeb ? localize('uploadingFiles', "Uploading") : localize('copyingFiles', "Copying") - }, async progress => { - try { - if (isWeb) { - await this.handleWebExternalDrop(data, resolvedTarget, originalEvent, progress, cts.token); - } else { - await this.handleExternalDrop(data, resolvedTarget, originalEvent, progress, cts.token); - } - } catch (error) { - this.notificationService.warn(error); + try { + if (isWeb) { + const dropPromise = this.progressService.withProgress({ + location: ProgressLocation.Window, + delay: 800, + cancellable: true, + title: localize('uploadingFiles', "Uploading") + }, async progress => { + this.handleWebExternalDrop(resolvedTarget, originalEvent, progress, cts.token); + }, () => cts.dispose(true)); + // Also indicate progress in the files view + this.progressService.withProgress({ location: VIEW_ID, delay: 500 }, () => dropPromise); + } else { + this.handleExternalDrop(resolvedTarget, originalEvent, cts.token); } - }, () => cts.dispose(true)); - - // Also indicate progress in the files view - this.progressService.withProgress({ location: VIEW_ID, delay: 800 }, () => dropPromise); + } catch (error) { + this.notificationService.warn(error); + } } // In-Explorer DND (Move/Copy file) else { @@ -1040,7 +1039,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } } - private async handleWebExternalDrop(data: NativeDragAndDropData, target: ExplorerItem, originalEvent: DragEvent, progress: IProgress, token: CancellationToken): Promise { + private async handleWebExternalDrop(target: ExplorerItem, originalEvent: DragEvent, progress: IProgress, token: CancellationToken): Promise { const items = (originalEvent.dataTransfer as unknown as IWebkitDataTransfer).items; // Somehow the items thing is being modified at random, maybe as a security @@ -1074,7 +1073,10 @@ export class FileDragAndDrop implements ITreeDragAndDrop { continue; } - await this.explorerService.applyBulkEdit([new ResourceFileEdit(joinPath(target.resource, entry.name), undefined, { recursive: true })], localize('overwrite', "Overwrite {0}", entry.name)); + await this.explorerService.applyBulkEdit([new ResourceFileEdit(joinPath(target.resource, entry.name), undefined, { recursive: true })], { + undoLabel: localize('overwrite', "Overwriting {0}", entry.name), + progressLabel: localize('overwriting', "Overwriting {0}", entry.name), + }); if (token.isCancellationRequested) { break; @@ -1262,7 +1264,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { }); } - private async handleExternalDrop(data: NativeDragAndDropData, target: ExplorerItem, originalEvent: DragEvent, progress: IProgress, token: CancellationToken): Promise { + private async handleExternalDrop(target: ExplorerItem, originalEvent: DragEvent, token: CancellationToken): Promise { // Check for dropped external files to be folders const droppedResources = extractResources(originalEvent, true); @@ -1296,7 +1298,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { return this.workspaceEditingService.addFolders(folders); } if (choice === buttons.length - 2) { - return this.addResources(target, droppedResources.map(res => res.resource), progress, token); + return this.addResources(target, droppedResources.map(res => res.resource), token); } return undefined; @@ -1304,11 +1306,11 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Handle dropped files (only support FileStat as target) else if (target instanceof ExplorerItem) { - return this.addResources(target, droppedResources.map(res => res.resource), progress, token); + return this.addResources(target, droppedResources.map(res => res.resource), token); } } - private async addResources(target: ExplorerItem, resources: URI[], progress: IProgress, token: CancellationToken): Promise { + private async addResources(target: ExplorerItem, resources: URI[], token: CancellationToken): Promise { if (resources && resources.length > 0) { // Resolve target to check for name collisions and ask user @@ -1327,38 +1329,33 @@ export class FileDragAndDrop implements ITreeDragAndDrop { }); } - // Run add in sequence - const addPromisesFactory: ITask>[] = []; - await Promise.all(resources.map(async resource => { + const resourcesFiltered = (await Promise.all(resources.map(async resource => { if (targetNames.has(caseSensitive ? basename(resource) : basename(resource).toLowerCase())) { const confirmationResult = await this.dialogService.confirm(getFileOverwriteConfirm(basename(resource))); if (!confirmationResult.confirmed) { - return; + return undefined; } } + return resource; + }))).filter(r => r instanceof URI) as URI[]; + const resourceFileEdits = resourcesFiltered.map(resource => { + const sourceFileName = basename(resource); + const targetFile = joinPath(target.resource, sourceFileName); + return new ResourceFileEdit(resource, targetFile, { overwrite: true, copy: true }); + }); - addPromisesFactory.push(async () => { - if (token.isCancellationRequested) { - return; - } + await this.explorerService.applyBulkEdit(resourceFileEdits, { + undoLabel: resourcesFiltered.length === 1 ? localize('copyFile', "Copy {0}", basename(resourcesFiltered[0])) : localize('copynFile', "Copy {0} files", resourcesFiltered.length), + progressLabel: resourcesFiltered.length === 1 ? localize('copyingFile', "Copying {0}", basename(resourcesFiltered[0])) : localize('copyingnFile', "Copying {0} files", resourcesFiltered.length) + }); - const sourceFile = resource; - const sourceFileName = basename(sourceFile); - const targetFile = joinPath(target.resource, sourceFileName); - - progress.report({ message: sourceFileName }); - - await this.explorerService.applyBulkEdit([new ResourceFileEdit(sourceFile, targetFile, { overwrite: true, copy: true })], localize('copyFile', "Copy {0}", sourceFileName)); - // if we only add one file, just open it directly - - const item = this.explorerService.findClosest(targetFile); - if (resources.length === 1 && item && !item.isDirectory) { - this.editorService.openEditor({ resource: item.resource, options: { pinned: true } }); - } - }); - })); - - await sequence(addPromisesFactory); + // if we only add one file, just open it directly + if (resourceFileEdits.length === 1) { + const item = this.explorerService.findClosest(resourceFileEdits[0].newResource!); + if (item) { + this.editorService.openEditor({ resource: item.resource, options: { pinned: true } }); + } + } } } @@ -1443,7 +1440,10 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Reuse duplicate action when user copies const incrementalNaming = this.configurationService.getValue().explorer.incrementalNaming; const resourceFileEdits = sources.map(({ resource, isDirectory }) => (new ResourceFileEdit(resource, findValidPasteFileTarget(this.explorerService, target, { resource, isDirectory, allowOverwrite: false }, incrementalNaming), { copy: true }))); - await this.explorerService.applyBulkEdit(resourceFileEdits, resourceFileEdits.length > 1 ? localize('copy', "Copy {0} files", resourceFileEdits.length) : localize('copyOneFile', "Copy {0}", basenameOrAuthority(resourceFileEdits[0].newResource!))); + await this.explorerService.applyBulkEdit(resourceFileEdits, { + undoLabel: resourceFileEdits.length > 1 ? localize('copy', "Copy {0} files", resourceFileEdits.length) : localize('copyOneFile', "Copy {0}", basenameOrAuthority(resourceFileEdits[0].newResource!)), + progressLabel: resourceFileEdits.length > 1 ? localize('copying', "Copying {0} files", resourceFileEdits.length) : localize('copyingOneFile', "Copying {0}", basenameOrAuthority(resourceFileEdits[0].newResource!)), + }); const editors = resourceFileEdits.filter(edit => { const item = edit.newResource ? this.explorerService.findClosest(edit.newResource) : undefined; @@ -1457,10 +1457,13 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Do not allow moving readonly items const resourceFileEdits = sources.filter(source => !source.isReadonly).map(source => new ResourceFileEdit(source.resource, joinPath(target.resource, source.name))); - const label = sources.length > 1 ? localize('move', "Move {0} files", sources.length) : localize('moveOneFile', "Move {0}", sources[0].name); + const options = { + undoLabel: sources.length > 1 ? localize('move', "Move {0} files", sources.length) : localize('moveOneFile', "Move {0}", sources[0].name), + progressLabel: sources.length > 1 ? localize('moving', "Moving {0} files", sources.length) : localize('movingOneFile', "Moving {0}", sources[0].name), + }; try { - await this.explorerService.applyBulkEdit(resourceFileEdits, label); + await this.explorerService.applyBulkEdit(resourceFileEdits, options); } catch (error) { // Conflict if ((error).fileOperationResult === FileOperationResult.FILE_MOVE_CONFLICT) { @@ -1477,7 +1480,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const { confirmed } = await this.dialogService.confirm(confirm); if (confirmed) { try { - await this.explorerService.applyBulkEdit(resourceFileEdits.map(re => new ResourceFileEdit(re.oldResource, re.newResource, { overwrite: true })), label); + await this.explorerService.applyBulkEdit(resourceFileEdits.map(re => new ResourceFileEdit(re.oldResource, re.newResource, { overwrite: true })), options); } catch (error) { this.notificationService.error(error); } From 3cfc3ac372c05796bdd82e360afb533bafb76478 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 21:27:36 +0100 Subject: [PATCH 0224/1837] remove duplicate 'codicon' class (for #111240) --- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 37a681a161b..7092e6b0d91 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -358,7 +358,6 @@ export abstract class ViewPane extends Pane implements IView { -webkit-mask-size: 16px; `); } else if (ThemeIcon.isThemeIcon(icon)) { - this.iconContainer.classList.add('codicon'); cssClass = ThemeIcon.asClassName(icon); } From f645a8d8c876114390eb4786b5a8f57bf9bc5f40 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 21:57:17 +0100 Subject: [PATCH 0225/1837] Link to ThemeIcon id reference --- src/vs/vscode.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index c908c01ba7b..0c8d499f1ba 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -791,8 +791,8 @@ declare module 'vscode' { /** * A reference to a named icon. Currently, [File](#ThemeIcon.File), [Folder](#ThemeIcon.Folder), - * and [codicons](https://microsoft.github.io/vscode-codicons/dist/codicon.html) are supported. - * Using a theme icon is preferred over a custom icon as it gives theme authors the possibility to change the icons. + * and [ThemeIcon ids](https://code.visualstudio.com/api/references/icons-in-labels#icon-listing) are supported. + * Using a theme icon is preferred over a custom icon as it gives product theme authors the possibility to change the icons. * * *Note* that theme icons can also be rendered inside labels and descriptions. Places that support theme icons spell this out * and they use the `$()`-syntax, for instance `quickPick.label = "Hello World $(globe)"`. @@ -809,7 +809,7 @@ declare module 'vscode' { static readonly Folder: ThemeIcon; /** - * The id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. + * The id of the icon. The available icons are listed in https://code.visualstudio.com/api/references/icons-in-labels#icon-listing. */ readonly id: string; @@ -820,7 +820,7 @@ declare module 'vscode' { /** * Creates a reference to a theme icon. - * @param id id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. + * @param id id of the icon. The available icons are listed in https://code.visualstudio.com/api/references/icons-in-labels#icon-listing. * @param color optional `ThemeColor` for the icon. The color is currently only used in [TreeItem](#TreeItem). */ constructor(id: string, color?: ThemeColor); @@ -5346,7 +5346,7 @@ declare module 'vscode' { * * `My text $(icon-name) contains icons like $(icon-name) this one.` * - * Where the icon-name is taken from the [codicon](https://microsoft.github.io/vscode-codicons/dist/codicon.html) icon set, e.g. + * Where the icon-name is taken from the ThemeIcon [icon set](https://code.visualstudio.com/api/references/icons-in-labels#icon-listing), e.g. * `light-bulb`, `thumbsup`, `zap` etc. */ text: string; From 0728b59411f5b9e4b2904b380df42370e47f671a Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 24 Nov 2020 13:06:51 -0800 Subject: [PATCH 0226/1837] fix: upload-vscode-configuration task for macOS --- build/azure-pipelines/darwin/product-build-darwin.yml | 1 + build/gulpfile.vscode.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 6c18decddc9..478365c7bbd 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -315,6 +315,7 @@ steps: - script: | AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + VSCODE_ARCH="$(VSCODE_ARCH)" \ yarn gulp upload-vscode-configuration displayName: Upload configuration (for Bing settings search) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index e0d3c5bd9cd..6c51051b765 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -456,8 +456,10 @@ const generateVSCodeConfigurationTask = task.define('generate-vscode-configurati const userDataDir = path.join(os.tmpdir(), 'tmpuserdata'); const extensionsDir = path.join(os.tmpdir(), 'tmpextdir'); - const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app'; - const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`); + const arch = process.env['VSCODE_ARCH']; + const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`); + const appName = product.nameLong + '.app'; + const appPath = path.join(appRoot, appName, 'Contents', 'Resources', 'app', 'bin', 'code'); const codeProc = cp.exec( `${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`, (err, stdout, stderr) => { From 357fc9d16b43cf44f3cb7c38449fa39920f62a07 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 23:07:29 +0100 Subject: [PATCH 0227/1837] Use codicons instead of string literals --- src/vs/platform/theme/common/themeService.ts | 18 ++++++--- .../api/browser/mainThreadComments.ts | 5 +-- .../api/browser/viewsExtensionPoint.ts | 2 +- .../parts/editor/editor.contribution.ts | 38 +++++++++++-------- .../workbench/browser/parts/views/treeView.ts | 5 ++- .../browser/parts/views/viewPaneContainer.ts | 2 +- .../browser/preview/bulkEdit.contribution.ts | 15 ++++---- .../browser/preview/bulkEditPreview.ts | 3 +- .../codeEditor/browser/toggleWordWrap.ts | 9 ++--- .../debug/browser/debug.contribution.ts | 38 +++++++++---------- .../browser/extensions.contribution.ts | 3 +- .../extensions.contribution.ts | 17 +++------ .../contrib/files/browser/explorerViewlet.ts | 10 ++--- .../files/browser/fileActions.contribution.ts | 5 ++- .../markers/browser/markers.contribution.ts | 5 +-- .../contrib/markers/browser/markersView.ts | 2 +- .../notebook/browser/contrib/coreActions.ts | 31 +++++++-------- .../browser/contrib/status/editorStatus.ts | 3 +- .../browser/diff/notebookDiffActions.ts | 9 +++-- .../outline/browser/outline.contribution.ts | 3 +- .../output/browser/output.contribution.ts | 13 +++---- .../browser/preferences.contribution.ts | 13 ++++--- .../contrib/remote/browser/remote.ts | 4 +- .../contrib/remote/browser/remoteExplorer.ts | 3 +- .../contrib/remote/browser/tunnelView.ts | 9 +++-- .../contrib/scm/browser/scm.contribution.ts | 7 ++-- .../search/browser/search.contribution.ts | 5 +-- .../terminal/browser/terminal.contribution.ts | 5 +-- .../timeline/browser/timeline.contribution.ts | 9 +++-- .../contrib/timeline/browser/timelinePane.ts | 14 +++++-- .../userDataSync/browser/userDataSync.ts | 3 +- .../userDataSync/browser/userDataSyncViews.ts | 2 +- .../views/browser/viewDescriptorService.ts | 3 +- .../views/common/viewContainerModel.ts | 2 +- 34 files changed, 160 insertions(+), 155 deletions(-) diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 4ea8b3978e0..1632d1abc15 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -11,7 +11,6 @@ import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { Codicon } from 'vs/base/common/codicons'; export const IThemeService = createDecorator('themeService'); @@ -48,17 +47,24 @@ export namespace ThemeIcon { return undefined; } let [, owner, name] = match; - if (!owner) { - owner = `codicon/`; + if (!owner || owner === 'codicon/') { + return { id: name }; } return { id: owner + name }; } - export function fromCodicon(codicon: Codicon): ThemeIcon { - return { id: codicon.id }; + export function modify(icon: ThemeIcon, modifier: 'disabled' | 'spin' | undefined): ThemeIcon { + let id = icon.id; + const tildeIndex = id.lastIndexOf('~'); + if (tildeIndex !== -1) { + id = id.substring(0, tildeIndex); + } + if (modifier) { + id = `${id}~${modifier}`; + } + return { id }; } - export function isEqual(ti1: ThemeIcon, ti2: ThemeIcon): boolean { return ti1.id === ti2.id && ti1.color?.id === ti2.color?.id; } diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index 80c9a3948c7..d8aa4bfcda6 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -22,7 +22,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class MainThreadCommentThread implements modes.CommentThread { @@ -477,7 +476,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: COMMENTS_VIEW_TITLE, hideIfEmpty: true, - icon: ThemeIcon.fromCodicon(commentsViewIcon), + icon: commentsViewIcon, order: 10, }, ViewContainerLocation.Panel); @@ -487,7 +486,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(CommentsPanel), canMoveView: true, - containerIcon: ThemeIcon.fromCodicon(commentsViewIcon), + containerIcon: commentsViewIcon, focusCommand: { id: 'workbench.action.focusCommentsPanel' } diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index 841d2ce349b..6be78f4ec89 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -320,7 +320,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { private registerTestViewContainer(): void { const title = localize('test', "Test"); - const icon = ThemeIcon.fromCodicon(testViewIcon); + const icon = testViewIcon; this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, undefined, ViewContainerLocation.Sidebar); } diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 802966c808e..bfae9f51f2a 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -55,6 +55,7 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess, AllEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { FileAccess } from 'vs/base/common/network'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; // Register String Editor Registry.as(EditorExtensions.Editors).registerEditor( @@ -495,14 +496,14 @@ appendEditorToolItem( { id: SplitEditorAction.ID, title: nls.localize('splitEditorRight', "Split Editor Right"), - icon: { id: 'codicon/split-horizontal' } + icon: Codicon.splitHorizontal }, ContextKeyExpr.not('splitEditorsVertically'), 100000, // towards the end { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitEditorDown', "Split Editor Down"), - icon: { id: 'codicon/split-vertical' } + icon: Codicon.splitVertical } ); @@ -510,14 +511,14 @@ appendEditorToolItem( { id: SplitEditorAction.ID, title: nls.localize('splitEditorDown', "Split Editor Down"), - icon: { id: 'codicon/split-vertical' } + icon: Codicon.splitVertical }, ContextKeyExpr.has('splitEditorsVertically'), 100000, // towards the end { id: editorCommands.SPLIT_EDITOR_RIGHT, title: nls.localize('splitEditorRight', "Split Editor Right"), - icon: { id: 'codicon/split-horizontal' } + icon: Codicon.splitHorizontal } ); @@ -526,14 +527,14 @@ appendEditorToolItem( { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close"), - icon: { id: 'codicon/close' } + icon: Codicon.close }, ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext.toNegated(), ActiveEditorStickyContext.toNegated()), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All"), - icon: { id: 'codicon/close-all' } + icon: Codicon.closeAll } ); @@ -542,14 +543,14 @@ appendEditorToolItem( { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close"), - icon: { id: 'codicon/close-dirty' } + icon: Codicon.closeDirty }, ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext, ActiveEditorStickyContext.toNegated()), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All"), - icon: { id: 'codicon/close-all' } + icon: Codicon.closeAll } ); @@ -558,14 +559,14 @@ appendEditorToolItem( { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin"), - icon: { id: 'codicon/pinned' } + icon: Codicon.pinned }, ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext.toNegated(), ActiveEditorStickyContext), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close"), - icon: { id: 'codicon/close' } + icon: Codicon.close } ); @@ -574,23 +575,28 @@ appendEditorToolItem( { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin"), - icon: { id: 'codicon/pinned-dirty' } + icon: Codicon.pinnedDirty }, ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ActiveEditorDirtyContext, ActiveEditorStickyContext), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close"), - icon: { id: 'codicon/close' } + icon: Codicon.close } ); +const previousChangeIcon = registerIcon('diff-editor-previous-change', Codicon.arrowUp, nls.localize('previousChangeIcon', 'Icon for the previous change action in the diff editor')); +const nextChangeIcon = registerIcon('diff-editor-next-change', Codicon.arrowDown, nls.localize('nextChangeIcon', 'Icon for the next change action in the diff editor')); +const toggleWhitespace = registerIcon('diff-editor-toggle-whitespace', Codicon.whitespace, nls.localize('toggleWhitespace', 'Icon for the toggle whitespace action in the diff editor')); + + // Diff Editor Title Menu: Previous Change appendEditorToolItem( { id: editorCommands.GOTO_PREVIOUS_CHANGE, title: nls.localize('navigate.prev.label', "Previous Change"), - icon: { id: 'codicon/arrow-up' } + icon: previousChangeIcon }, TextCompareEditorActiveContext, 10 @@ -601,7 +607,7 @@ appendEditorToolItem( { id: editorCommands.GOTO_NEXT_CHANGE, title: nls.localize('navigate.next.label', "Next Change"), - icon: { id: 'codicon/arrow-down' } + icon: nextChangeIcon }, TextCompareEditorActiveContext, 11 @@ -612,7 +618,7 @@ appendEditorToolItem( { id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, title: nls.localize('ignoreTrimWhitespace.label', "Ignore Leading/Trailing Whitespace Differences"), - icon: { id: 'codicon/whitespace' } + icon: toggleWhitespace }, ContextKeyExpr.and(TextCompareEditorActiveContext, ContextKeyExpr.notEquals('config.diffEditor.ignoreTrimWhitespace', true)), 20 @@ -623,7 +629,7 @@ appendEditorToolItem( { id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, title: nls.localize('showTrimWhitespace.label', "Show Leading/Trailing Whitespace Differences"), - icon: { id: 'codicon/whitespace~disabled' } + icon: ThemeIcon.modify(toggleWhitespace, 'disabled') }, ContextKeyExpr.and(TextCompareEditorActiveContext, ContextKeyExpr.notEquals('config.diffEditor.ignoreTrimWhitespace', false)), 20 diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index 5962d6c7803..2d1654ec47a 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -51,6 +51,7 @@ import { IMarkdownString } from 'vs/base/common/htmlContent'; import { IIconLabelMarkdownString } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer'; import { API_OPEN_DIFF_EDITOR_COMMAND_ID, API_OPEN_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; +import { Codicon } from 'vs/base/common/codicons'; export class TreeViewPane extends ViewPane { @@ -366,7 +367,7 @@ export class TreeView extends Disposable implements ITreeView { group: 'navigation', order: Number.MAX_SAFE_INTEGER - 1, }, - icon: { id: 'codicon/refresh' } + icon: Codicon.refresh }); } async run(): Promise { @@ -385,7 +386,7 @@ export class TreeView extends Disposable implements ITreeView { order: Number.MAX_SAFE_INTEGER, }, precondition: that.collapseAllToggleContextKey, - icon: { id: 'codicon/collapse-all' } + icon: Codicon.collapseAll }); } async run(): Promise { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 7092e6b0d91..339357a5812 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -339,7 +339,7 @@ export abstract class ViewPane extends Pane implements IView { } private getIcon(): ThemeIcon | URI { - return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); + return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || defaultViewIcon; } protected renderHeaderTitle(container: HTMLElement, title: string): void { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts index 5177edd043a..eac6f2517d1 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts @@ -28,7 +28,6 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; async function getBulkEditPane(viewsService: IViewsService): Promise { const view = await viewsService.openView(BulkEditPane.ID, true); @@ -170,7 +169,7 @@ registerAction2(class ApplyAction extends Action2 { id: 'refactorPreview.apply', title: { value: localize('apply', "Apply Refactoring"), original: 'Apply Refactoring' }, category: { value: localize('cat', "Refactor Preview"), original: 'Refactor Preview' }, - icon: { id: 'codicon/check' }, + icon: Codicon.check, precondition: ContextKeyExpr.and(BulkEditPreviewContribution.ctxEnabled, BulkEditPane.ctxHasCheckedChanges), menu: [{ id: MenuId.BulkEditTitle, @@ -204,7 +203,7 @@ registerAction2(class DiscardAction extends Action2 { id: 'refactorPreview.discard', title: { value: localize('Discard', "Discard Refactoring"), original: 'Discard Refactoring' }, category: { value: localize('cat', "Refactor Preview"), original: 'Refactor Preview' }, - icon: { id: 'codicon/clear-all' }, + icon: Codicon.clearAll, precondition: BulkEditPreviewContribution.ctxEnabled, menu: [{ id: MenuId.BulkEditTitle, @@ -265,7 +264,7 @@ registerAction2(class GroupByFile extends Action2 { id: 'refactorPreview.groupByFile', title: { value: localize('groupByFile', "Group Changes By File"), original: 'Group Changes By File' }, category: { value: localize('cat', "Refactor Preview"), original: 'Refactor Preview' }, - icon: { id: 'codicon/ungroup-by-ref-type' }, + icon: Codicon.ungroupByRefType, precondition: ContextKeyExpr.and(BulkEditPane.ctxHasCategories, BulkEditPane.ctxGroupByFile.negate(), BulkEditPreviewContribution.ctxEnabled), menu: [{ id: MenuId.BulkEditTitle, @@ -292,7 +291,7 @@ registerAction2(class GroupByType extends Action2 { id: 'refactorPreview.groupByType', title: { value: localize('groupByType', "Group Changes By Type"), original: 'Group Changes By Type' }, category: { value: localize('cat', "Refactor Preview"), original: 'Refactor Preview' }, - icon: { id: 'codicon/group-by-ref-type' }, + icon: Codicon.groupByRefType, precondition: ContextKeyExpr.and(BulkEditPane.ctxHasCategories, BulkEditPane.ctxGroupByFile, BulkEditPreviewContribution.ctxEnabled), menu: [{ id: MenuId.BulkEditTitle, @@ -319,7 +318,7 @@ registerAction2(class ToggleGrouping extends Action2 { id: 'refactorPreview.toggleGrouping', title: { value: localize('groupByType', "Group Changes By Type"), original: 'Group Changes By Type' }, category: { value: localize('cat', "Refactor Preview"), original: 'Refactor Preview' }, - icon: { id: 'codicon/list-tree' }, + icon: Codicon.listTree, toggled: BulkEditPane.ctxGroupByFile.negate(), precondition: ContextKeyExpr.and(BulkEditPane.ctxHasCategories, BulkEditPreviewContribution.ctxEnabled), menu: [{ @@ -352,7 +351,7 @@ const container = Registry.as(ViewContainerExtensions.V ViewPaneContainer, [BulkEditPane.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }] ), - icon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), + icon: refactorPreviewViewIcon, storageId: BulkEditPane.ID }, ViewContainerLocation.Panel); @@ -361,5 +360,5 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews name: localize('panel', "Refactor Preview"), when: BulkEditPreviewContribution.ctxEnabled, ctorDescriptor: new SyncDescriptor(BulkEditPane), - containerIcon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), + containerIcon: refactorPreviewViewIcon, }], container); diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview.ts index 4aecbf746cf..a1b366c483e 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview.ts @@ -22,6 +22,7 @@ import { ResourceMap } from 'vs/base/common/map'; import { localize } from 'vs/nls'; import { extUri } from 'vs/base/common/resources'; import { ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; +import { Codicon } from 'vs/base/common/codicons'; export class CheckedStates { @@ -116,7 +117,7 @@ export class BulkCategory { private static readonly _defaultMetadata = Object.freeze({ label: localize('default', "Other"), - icon: { id: 'codicon/symbol-file' }, + icon: Codicon.symbolFile, needsConfirmation: false }); diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts index 7f983ef740e..29ce65162d2 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts @@ -19,6 +19,7 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { DefaultSettingsEditorContribution } from 'vs/workbench/contrib/preferences/browser/preferencesEditor'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { Codicon } from 'vs/base/common/codicons'; const transientWordWrapState = 'transientWordWrapState'; const isWordWrapMinifiedKey = 'isWordWrapMinified'; @@ -262,9 +263,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_WORD_WRAP_ID, title: nls.localize('unwrapMinified', "Disable wrapping for this file"), - icon: { - id: 'codicon/word-wrap' - } + icon: Codicon.wordWrap }, group: 'navigation', order: 1, @@ -277,9 +276,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_WORD_WRAP_ID, title: nls.localize('wrapMinified', "Enable wrapping for this file"), - icon: { - id: 'codicon/word-wrap' - } + icon: Codicon.wordWrap }, group: 'navigation', order: 1, diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index d7178990077..9438ac11cad 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -153,16 +153,16 @@ function registerCommandsAndActions(): void { }); }; - registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, ThemeIcon.fromCodicon(icons.debugContinue), CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, ThemeIcon.fromCodicon(icons.debugPause), CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); - registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, ThemeIcon.fromCodicon(icons.debugStop), CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); - registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, ThemeIcon.fromCodicon(icons.debugDisconnect), CONTEXT_FOCUSED_SESSION_IS_ATTACH); - registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, ThemeIcon.fromCodicon(icons.debugStepOver), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, ThemeIcon.fromCodicon(icons.debugStepInto), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, ThemeIcon.fromCodicon(icons.debugStepOut), undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, ThemeIcon.fromCodicon(icons.debugRestart)); - registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, ThemeIcon.fromCodicon(icons.debugStepBack), CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, ThemeIcon.fromCodicon(icons.debugReverseContinue), CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, icons.debugContinue, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, icons.debugPause, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); + registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); + registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH); + registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, icons.debugStepOver, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, icons.debugStepInto, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, icons.debugStepOut, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, icons.debugRestart); + registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, icons.debugStepBack, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); + registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, icons.debugReverseContinue, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); // Debug callstack context menu const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, order: number, when?: ContextKeyExpression, precondition?: ContextKeyExpression, group = 'navigation') => { @@ -460,7 +460,7 @@ function registerDebugPanel(): void { const VIEW_CONTAINER: ViewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: DEBUG_PANEL_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - icon: ThemeIcon.fromCodicon(icons.debugConsoleViewIcon), + icon: icons.debugConsoleViewIcon, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: DEBUG_PANEL_ID, focusCommand: { id: OpenDebugConsoleAction.ID }, @@ -471,7 +471,7 @@ function registerDebugPanel(): void { Registry.as(ViewExtensions.ViewsRegistry).registerViews([{ id: REPL_VIEW_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - containerIcon: ThemeIcon.fromCodicon(icons.debugConsoleViewIcon), + containerIcon: icons.debugConsoleViewIcon, canToggleVisibility: false, canMoveView: true, when: CONTEXT_DEBUGGERS_AVAILABLE, @@ -487,7 +487,7 @@ function registerDebugView(): void { id: VIEWLET_ID, name: nls.localize('run', "Run"), ctorDescriptor: new SyncDescriptor(DebugViewPaneContainer), - icon: ThemeIcon.fromCodicon(icons.runViewIcon), + icon: icons.runViewIcon, alwaysUseContainerInfo: true, order: 2 }, ViewContainerLocation.Sidebar); @@ -495,12 +495,12 @@ function registerDebugView(): void { // Register default debug views const viewsRegistry = Registry.as(ViewExtensions.ViewsRegistry); - viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: ThemeIcon.fromCodicon(icons.variablesViewIcon), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: ThemeIcon.fromCodicon(icons.watchViewIcon), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: ThemeIcon.fromCodicon(icons.callStackViewIcon), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: ThemeIcon.fromCodicon(icons.breakpointsViewIcon), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); - viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: ThemeIcon.fromCodicon(icons.runViewIcon), ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); - viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: ThemeIcon.fromCodicon(icons.loadedScriptsViewIcon), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: icons.variablesViewIcon, ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: icons.watchViewIcon, ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: icons.callStackViewIcon, ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: icons.breakpointsViewIcon, ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: icons.runViewIcon, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); + viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: icons.loadedScriptsViewIcon, ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); } function registerConfiguration(): void { diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 0354706380a..0435d1b1325 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -65,7 +65,6 @@ import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -111,7 +110,7 @@ Registry.as(ViewContainerExtensions.ViewContainersRegis id: VIEWLET_ID, name: localize('extensions', "Extensions"), ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer), - icon: ThemeIcon.fromCodicon(extensionsViewIcon), + icon: extensionsViewIcon, order: 4, rejectAddedViews: true, alwaysUseContainerInfo: true diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 9cf0ec19766..8d8712ac3c6 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -26,6 +26,7 @@ import { ExtensionsLabel } from 'vs/platform/extensionManagement/common/extensio import { IExtensionRecommendationNotificationService } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { ExtensionRecommendationNotificationServiceChannel } from 'vs/platform/extensionRecommendations/electron-sandbox/extensionRecommendationsIpc'; +import { Codicon } from 'vs/base/common/codicons'; // Singletons registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService, true); @@ -109,9 +110,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: DebugExtensionHostAction.ID, title: DebugExtensionHostAction.LABEL, - icon: { - id: 'codicon/debug-start' - } + icon: Codicon.debugStart }, group: 'navigation', when: ActiveEditorContext.isEqualTo(RuntimeExtensionsEditor.ID) @@ -121,9 +120,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: StartExtensionHostProfileAction.ID, title: StartExtensionHostProfileAction.LABEL, - icon: { - id: 'codicon/circle-filled' - } + icon: Codicon.circleFilled }, group: 'navigation', when: ContextKeyExpr.and(ActiveEditorContext.isEqualTo(RuntimeExtensionsEditor.ID), CONTEXT_PROFILE_SESSION_STATE.notEqualsTo('running')) @@ -133,9 +130,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: StopExtensionHostProfileAction.ID, title: StopExtensionHostProfileAction.LABEL, - icon: { - id: 'codicon/debug-stop' - } + icon: Codicon.debugStop }, group: 'navigation', when: ContextKeyExpr.and(ActiveEditorContext.isEqualTo(RuntimeExtensionsEditor.ID), CONTEXT_PROFILE_SESSION_STATE.isEqualTo('running')) @@ -145,9 +140,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: SaveExtensionHostProfileAction.ID, title: SaveExtensionHostProfileAction.LABEL, - icon: { - id: 'codicon/save-all' - }, + icon: Codicon.saveAll, precondition: CONTEXT_EXTENSION_HOST_PROFILE_RECORDED }, group: 'navigation', diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 313ba7adc97..7e1a9520b46 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -18,7 +18,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, ViewContentGroups } from 'vs/workbench/common/views'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -110,7 +110,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor id: OpenEditorsView.ID, name: OpenEditorsView.NAME, ctorDescriptor: new SyncDescriptor(OpenEditorsView), - containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), + containerIcon: explorerViewIcon, order: 0, when: OpenEditorsVisibleContext, canToggleVisibility: true, @@ -127,7 +127,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: EmptyView.ID, name: EmptyView.NAME, - containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), + containerIcon: explorerViewIcon, ctorDescriptor: new SyncDescriptor(EmptyView), order: 1, canToggleVisibility: true, @@ -141,7 +141,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: VIEW_ID, name: localize('folders', "Folders"), - containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), + containerIcon: explorerViewIcon, ctorDescriptor: new SyncDescriptor(ExplorerView), order: 1, canToggleVisibility: false, @@ -269,7 +269,7 @@ export const VIEW_CONTAINER: ViewContainer = viewContainerRegistry.registerViewC name: localize('explore', "Explorer"), ctorDescriptor: new SyncDescriptor(ExplorerViewPaneContainer), storageId: 'workbench.explorer.views.state', - icon: ThemeIcon.fromCodicon(explorerViewIcon), + icon: explorerViewIcon, alwaysUseContainerInfo: true, order: 0 }, ViewContainerLocation.Sidebar, true); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index bba59809909..80deb82690e 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -30,6 +30,7 @@ import { ActiveEditorContext } from 'vs/workbench/common/editor'; import { SidebarFocusContext } from 'vs/workbench/common/viewlet'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { Codicon } from 'vs/base/common/codicons'; // Contribute Global Actions const category = { value: nls.localize('filesCategory', "File"), original: 'File' }; @@ -183,8 +184,8 @@ export function appendEditorTitleContextMenuItem(id: string, title: string, when } // Editor Title Menu for Conflict Resolution -appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite file contents"), { id: 'codicon/check' }, -10, acceptLocalChangesCommand); -appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to file contents"), { id: 'codicon/discard' }, -9, revertLocalChangesCommand); +appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite file contents"), Codicon.check, -10, acceptLocalChangesCommand); +appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to file contents"), Codicon.discard, -9, revertLocalChangesCommand); function appendSaveConflictEditorTitleAction(id: string, title: string, icon: ThemeIcon, order: number, command: ICommandHandler): void { diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index ac6c5837298..6951a95e8e8 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -33,7 +33,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import type { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); @@ -131,7 +130,7 @@ const markersViewIcon = registerIcon('markers-view-icon', Codicon.warning, local const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: Constants.MARKERS_CONTAINER_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, - icon: ThemeIcon.fromCodicon(markersViewIcon), + icon: markersViewIcon, hideIfEmpty: true, order: 0, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), @@ -145,7 +144,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: Constants.MARKERS_VIEW_ID, - containerIcon: ThemeIcon.fromCodicon(markersViewIcon), + containerIcon: markersViewIcon, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, canToggleVisibility: false, canMoveView: true, diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 3505eb89de8..052477f4b43 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -227,7 +227,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { group: 'navigation', order: Number.MAX_SAFE_INTEGER, }, - icon: { id: 'codicon/collapse-all' } + icon: Codicon.collapseAll }); } async run(): Promise { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 8b680f19324..ca084aea984 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Codicon } from 'vs/base/common/codicons'; import * as glob from 'vs/base/common/glob'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; @@ -232,7 +233,7 @@ registerAction2(class extends NotebookCellAction { } ] }, - icon: { id: 'codicon/play' }, + icon: Codicon.play }); } @@ -266,7 +267,7 @@ registerAction2(class extends NotebookCellAction { super({ id: CANCEL_CELL_COMMAND_ID, title: localize('notebookActions.cancel', "Stop Cell Execution"), - icon: { id: 'codicon/primitive-square' }, + icon: Codicon.primitiveSquare, description: { description: localize('notebookActions.execute', "Execute Cell"), args: [ @@ -325,7 +326,7 @@ export class ExecuteCellAction extends MenuItemAction { { id: EXECUTE_CELL_COMMAND_ID, title: localize('notebookActions.executeCell', "Execute Cell"), - icon: { id: 'codicon/play' } + icon: Codicon.play }, undefined, { shouldForwardArgs: true }, @@ -343,7 +344,7 @@ export class CancelCellAction extends MenuItemAction { { id: CANCEL_CELL_COMMAND_ID, title: localize('notebookActions.CancelCell', "Cancel Execution"), - icon: { id: 'codicon/primitive-square' } + icon: Codicon.primitiveSquare }, undefined, { shouldForwardArgs: true }, @@ -361,7 +362,7 @@ export class DeleteCellAction extends MenuItemAction { { id: DELETE_CELL_COMMAND_ID, title: localize('notebookActions.deleteCell', "Delete Cell"), - icon: { id: 'codicon/trash' } + icon: Codicon.trash, }, undefined, { shouldForwardArgs: true }, @@ -507,7 +508,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: EXECUTE_NOTEBOOK_COMMAND_ID, title: localize('notebookActions.menu.executeNotebook', "Execute Notebook (Run all cells)"), - icon: { id: 'codicon/run-all' } + icon: Codicon.runAll, }, order: -1, group: 'navigation', @@ -518,7 +519,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CANCEL_NOTEBOOK_COMMAND_ID, title: localize('notebookActions.menu.cancelNotebook', "Stop Notebook Execution"), - icon: { id: 'codicon/primitive-square' } + icon: Codicon.primitiveSquare, }, order: -1, group: 'navigation', @@ -835,7 +836,7 @@ registerAction2(class extends NotebookCellAction { order: CellToolbarOrder.EditCell, group: CELL_TITLE_CELL_GROUP_ID }, - icon: { id: 'codicon/pencil' } + icon: Codicon.pencil, }); } @@ -859,7 +860,7 @@ registerAction2(class extends NotebookCellAction { order: CellToolbarOrder.SaveCell, group: CELL_TITLE_CELL_GROUP_ID }, - icon: { id: 'codicon/check' }, + icon: Codicon.check, keybinding: { when: ContextKeyExpr.and( NOTEBOOK_EDITOR_FOCUSED, @@ -901,7 +902,7 @@ registerAction2(class extends NotebookCellAction { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.not(InputFocusedContextKey)), weight: KeybindingWeight.WorkbenchContrib }, - icon: { id: 'codicon/trash' }, + icon: Codicon.trash }); } @@ -945,7 +946,7 @@ registerAction2(class extends NotebookCellAction { { id: MOVE_CELL_UP_COMMAND_ID, title: localize('notebookActions.moveCellUp', "Move Cell Up"), - icon: { id: 'codicon/arrow-up' }, + icon: Codicon.arrowUp, keybinding: { primary: KeyMod.Alt | KeyCode.UpArrow, when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, InputFocusedContext.toNegated()), @@ -965,7 +966,7 @@ registerAction2(class extends NotebookCellAction { { id: MOVE_CELL_DOWN_COMMAND_ID, title: localize('notebookActions.moveCellDown', "Move Cell Down"), - icon: { id: 'codicon/arrow-down' }, + icon: Codicon.arrowDown, keybinding: { primary: KeyMod.Alt | KeyCode.DownArrow, when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, InputFocusedContext.toNegated()), @@ -1408,7 +1409,7 @@ registerAction2(class extends NotebookCellAction { primary: KeyMod.Alt | KeyCode.Delete, weight: KeybindingWeight.WorkbenchContrib }, - icon: { id: 'codicon/clear-all' }, + icon: Codicon.clearAll }); } @@ -1558,7 +1559,7 @@ registerAction2(class extends NotebookAction { group: 'navigation', order: 0 }, - icon: { id: 'codicon/clear-all' }, + icon: Codicon.clearAll }); } @@ -1618,7 +1619,7 @@ registerAction2(class extends NotebookCellAction { // title: localize('notebookActions.joinCellBelow', "Join with Next Cell") // } }, - icon: { id: 'codicon/split-vertical' }, + icon: Codicon.splitVertical, keybinding: { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_EDITOR_CURSOR_BEGIN_END.toNegated()), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKSLASH), diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index 7c8413b9bdc..9d8041863b7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -21,6 +21,7 @@ import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/l import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { Codicon } from 'vs/base/common/codicons'; registerAction2(class extends Action2 { @@ -30,7 +31,7 @@ registerAction2(class extends Action2 { category: NOTEBOOK_ACTIONS_CATEGORY, title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' }, precondition: NOTEBOOK_IS_ACTIVE_EDITOR, - icon: { id: 'codicon/server-environment' }, + icon: Codicon.serverEnvironment, f1: true }); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index 970b76a7ba8..bf5df7503ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Codicon } from 'vs/base/common/codicons'; import { IBulkEditService, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; @@ -20,7 +21,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'notebook.diff.switchToText', - icon: { id: 'codicon/file-code' }, + icon: Codicon.fileCode, title: { value: localize('notebook.diff.switchToText', "Open Text Diff Editor"), original: 'Open Text Diff Editor' }, precondition: ActiveEditorContext.isEqualTo(NotebookTextDiffEditor.ID), menu: [{ @@ -56,7 +57,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertMetadata', title: localize('notebook.diff.cell.revertMetadata', "Revert Metadata"), - icon: { id: 'codicon/discard' }, + icon: Codicon.discard, f1: false, menu: { id: MenuId.NotebookDiffCellMetadataTitle @@ -86,7 +87,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertOutputs', title: localize('notebook.diff.cell.revertOutputs', "Revert Outputs"), - icon: { id: 'codicon/discard' }, + icon: Codicon.discard, f1: false, menu: { id: MenuId.NotebookDiffCellOutputsTitle @@ -116,7 +117,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertInput', title: localize('notebook.diff.cell.revertInput', "Revert Input"), - icon: { id: 'codicon/discard' }, + icon: Codicon.discard, f1: false, menu: { id: MenuId.NotebookDiffCellInputTitle diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 5fb485fa404..f43351c42ce 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -12,7 +12,6 @@ import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymb import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const PANEL_ID = 'panel.view.outline'; @@ -21,7 +20,7 @@ const outlineViewIcon = registerIcon('outline-view-icon', Codicon.symbolClass, l const _outlineDesc = { id: OutlineViewId, name: localize('name', "Outline"), - containerIcon: ThemeIcon.fromCodicon(outlineViewIcon), + containerIcon: outlineViewIcon, ctorDescriptor: new SyncDescriptor(OutlinePane), canToggleVisibility: true, canMoveView: true, diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index 058a20f3483..59365a234a2 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -34,7 +34,6 @@ import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/pla import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register Service registerSingleton(IOutputService, OutputService); @@ -67,7 +66,7 @@ const outputViewIcon = registerIcon('output-view-icon', Codicon.output, nls.loca const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - icon: ThemeIcon.fromCodicon(outputViewIcon), + icon: outputViewIcon, order: 1, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: OUTPUT_VIEW_ID, @@ -78,7 +77,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - containerIcon: ThemeIcon.fromCodicon(outputViewIcon), + containerIcon: outputViewIcon, canMoveView: true, canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(OutputViewPane), @@ -143,7 +142,7 @@ registerAction2(class extends Action2 { id: MenuId.EditorContext, when: CONTEXT_IN_OUTPUT }], - icon: { id: 'codicon/clear-all' } + icon: Codicon.clearAll }); } async run(accessor: ServicesAccessor): Promise { @@ -167,10 +166,10 @@ registerAction2(class extends Action2 { group: 'navigation', order: 3, }, - icon: { id: 'codicon/unlock' }, + icon: Codicon.unlock, toggled: { condition: CONTEXT_OUTPUT_SCROLL_LOCK, - icon: { id: 'codicon/lock' }, + icon: Codicon.lock, tooltip: { value: nls.localize('outputScrollOn', "Turn Auto Scrolling On"), original: 'Turn Auto Scrolling On' } } }); @@ -194,7 +193,7 @@ registerAction2(class extends Action2 { id: MenuId.CommandPalette, when: CONTEXT_ACTIVE_LOG_OUTPUT, }], - icon: { id: 'codicon/go-to-file' }, + icon: Codicon.goToFile, precondition: CONTEXT_ACTIVE_LOG_OUTPUT }); } diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index 99b0b58ffd1..9c28d342232 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -40,6 +40,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { DefaultPreferencesEditorInput, KeybindingsEditorInput, PreferencesEditorInput, SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; +import { Codicon } from 'vs/base/common/codicons'; const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search'; @@ -277,7 +278,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon super({ id: '_workbench.openUserSettingsEditor', title: OPEN_SETTINGS2_ACTION_TITLE, - icon: { id: 'codicon/go-to-file' }, + icon: Codicon.goToFile, menu: [{ id: MenuId.EditorTitle, when: ResourceContextKey.Resource.isEqualTo(that.environmentService.settingsResource.toString()), @@ -295,7 +296,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon super({ id: SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, title: { value: nls.localize('openSettingsJson', "Open Settings (JSON)"), original: 'Open Settings (JSON)' }, - icon: { id: 'codicon/go-to-file' }, + icon: Codicon.goToFile, menu: [{ id: MenuId.EditorTitle, when: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR.toNegated()), @@ -815,7 +816,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon id: 'workbench.action.openGlobalKeybindings', title: { value: nls.localize('openGlobalKeybindings', "Open Keyboard Shortcuts"), original: 'Open Keyboard Shortcuts' }, category, - icon: { id: 'codicon/go-to-file' }, + icon: Codicon.goToFile, keybinding: { when: null, weight: KeybindingWeight.WorkbenchContrib, @@ -872,7 +873,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon id: 'workbench.action.openGlobalKeybindingsFile', title: { value: nls.localize('openGlobalKeybindingsFile', "Open Keyboard Shortcuts (JSON)"), original: 'Open Keyboard Shortcuts (JSON)' }, category, - icon: { id: 'codicon/go-to-file' }, + icon: Codicon.goToFile, menu: [ { id: MenuId.CommandPalette }, { @@ -1123,7 +1124,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon command: { id: commandId, title: OPEN_SETTINGS2_ACTION_TITLE, - icon: { id: 'codicon/go-to-file' } + icon: Codicon.goToFile }, when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.workspaceSettingsResource!.toString()), WorkbenchStateContext.isEqualTo('workspace')), group: 'navigation', @@ -1148,7 +1149,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon command: { id: commandId, title: OPEN_SETTINGS2_ACTION_TITLE, - icon: { id: 'codicon/go-to-file' } + icon: Codicon.goToFile }, when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.getFolderSettingsResource(folder.uri)!.toString())), group: 'navigation', diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 58b510c028d..113481b4efb 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -13,7 +13,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet'; @@ -584,7 +584,7 @@ Registry.as(Extensions.ViewContainersRegistry).register return; } }, - icon: ThemeIcon.fromCodicon(remoteExplorerViewIcon), + icon: remoteExplorerViewIcon, order: 4 }, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index e6285ec948f..05ff17203f1 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -22,7 +22,6 @@ import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { OperatingSystem } from 'vs/base/common/platform'; import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { Codicon } from 'vs/base/common/codicons'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; @@ -58,7 +57,7 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu const viewContainer = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer({ id: TunnelPanel.ID, name: nls.localize('ports', "Ports"), - icon: ThemeIcon.fromCodicon(Codicon.plug), + icon: Codicon.plug, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TunnelPanel.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: TunnelPanel.ID, hideIfEmpty: true, diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 61f640248b8..c54d3fccb2a 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -42,6 +42,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { Codicon } from 'vs/base/common/codicons'; export const forwardedPortsViewEnabled = new RawContextKey('forwardedPortsViewEnabled', false); @@ -1036,7 +1037,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({ command: { id: ForwardPortAction.INLINE_ID, title: ForwardPortAction.LABEL, - icon: { id: 'codicon/plus' } + icon: Codicon.plus } })); MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ @@ -1099,7 +1100,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({ command: { id: OpenPortInBrowserAction.ID, title: OpenPortInBrowserAction.LABEL, - icon: { id: 'codicon/globe' } + icon: Codicon.globe }, when: ContextKeyExpr.or(TunnelTypeContextKey.isEqualTo(TunnelType.Forwarded), TunnelTypeContextKey.isEqualTo(TunnelType.Detected)) })); @@ -1108,7 +1109,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({ command: { id: ForwardPortAction.INLINE_ID, title: ForwardPortAction.TREEITEM_LABEL, - icon: { id: 'codicon/plus' } + icon: Codicon.plus }, when: TunnelTypeContextKey.isEqualTo(TunnelType.Candidate) })); @@ -1117,7 +1118,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({ command: { id: ClosePortAction.INLINE_ID, title: ClosePortAction.LABEL, - icon: { id: 'codicon/x' } + icon: Codicon.x }, when: TunnelCloseableContextKey })); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 3358221ade6..a7d173b5ec7 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -28,7 +28,6 @@ import { SCMViewService } from 'vs/workbench/contrib/scm/browser/scmViewService' import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRepositoriesViewPane'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Context as SuggestContext } from 'vs/editor/contrib/suggest/suggest'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; ModesRegistry.registerLanguage({ id: 'scminput', @@ -46,7 +45,7 @@ const viewContainer = Registry.as(ViewContainerExtensio name: localize('source control', "Source Control"), ctorDescriptor: new SyncDescriptor(SCMViewPaneContainer), storageId: 'workbench.scm.views.state', - icon: ThemeIcon.fromCodicon(sourceControlViewIcon), + icon: sourceControlViewIcon, alwaysUseContainerInfo: true, order: 2, hideIfEmpty: true @@ -68,7 +67,7 @@ viewsRegistry.registerViews([{ canMoveView: true, weight: 80, order: -999, - containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) + containerIcon: sourceControlViewIcon }], viewContainer); viewsRegistry.registerViews([{ @@ -83,7 +82,7 @@ viewsRegistry.registerViews([{ order: -1000, when: ContextKeyExpr.and(ContextKeyExpr.has('scm.providerCount'), ContextKeyExpr.notEquals('scm.providerCount', 0)), // readonly when = ContextKeyExpr.or(ContextKeyExpr.equals('config.scm.alwaysShowProviders', true), ContextKeyExpr.and(ContextKeyExpr.notEquals('scm.providerCount', 0), ContextKeyExpr.notEquals('scm.providerCount', 1))); - containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) + containerIcon: sourceControlViewIcon }], viewContainer); Registry.as(WorkbenchExtensions.Workbench) diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 6e2a09c5327..b0ccc88477d 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -55,7 +55,6 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess'; import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; import { searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true); registerSingleton(ISearchHistoryService, SearchHistoryService, true); @@ -510,11 +509,11 @@ const viewContainer = Registry.as(ViewExtensions.ViewCo name: nls.localize('name', "Search"), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), hideIfEmpty: true, - icon: ThemeIcon.fromCodicon(searchViewIcon), + icon: searchViewIcon, order: 1 }, ViewContainerLocation.Sidebar); -const viewDescriptor = { id: VIEW_ID, containerIcon: ThemeIcon.fromCodicon(searchViewIcon), name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; +const viewDescriptor = { id: VIEW_ID, containerIcon: searchViewIcon, name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; // Register search default location to sidebar Registry.as(ViewExtensions.ViewsRegistry).registerViews([viewDescriptor], viewContainer); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 67ad70e5ec0..d0cab873588 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -37,7 +37,6 @@ import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/brows import { terminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register services registerSingleton(ITerminalService, TerminalService, true); @@ -67,7 +66,7 @@ const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nl const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - icon: ThemeIcon.fromCodicon(terminalViewIcon), + icon: terminalViewIcon, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: TERMINAL_VIEW_ID, focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS }, @@ -78,7 +77,7 @@ Registry.as(panel.Extensions.Panels).setDefaultPanelId(TERM Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - containerIcon: ThemeIcon.fromCodicon(terminalViewIcon), + containerIcon: terminalViewIcon, canToggleVisibility: false, canMoveView: true, ctorDescriptor: new SyncDescriptor(TerminalViewPane) diff --git a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts index 4caef263d11..212f827bfee 100644 --- a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts +++ b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts @@ -18,16 +18,17 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ResourceContextKey } from 'vs/workbench/common/resources'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const timelineViewIcon = registerIcon('timeline-view-icon', Codicon.history, localize('timelineViewIcon', 'View icon of the timeline view.')); +const timelineOpenIcon = registerIcon('timeline-open', Codicon.history, localize('timelineOpenIcon', 'Icon for the open timeline action.')); export class TimelinePaneDescriptor implements IViewDescriptor { readonly id = TimelinePaneId; readonly name = TimelinePane.TITLE; - readonly containerIcon = ThemeIcon.fromCodicon(timelineViewIcon); + readonly containerIcon = timelineViewIcon; readonly ctorDescriptor = new SyncDescriptor(TimelinePane); readonly order = 2; readonly weight = 30; @@ -92,7 +93,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, ({ command: { id: OpenTimelineAction.ID, title: OpenTimelineAction.LABEL, - icon: { id: 'codicon/history' } + icon: timelineOpenIcon }, when: ContextKeyExpr.and(ExplorerFolderContext.toNegated(), ResourceContextKey.HasResource) })); diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 78ae88936df..05a0b4e0b23 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -42,6 +42,7 @@ import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2, MenuReg import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; const ItemHeight = 22; @@ -208,7 +209,7 @@ class LoadMoreCommand { return this.loading ? localize('timeline.loadingMore', "Loading...") : localize('timeline.loadMore', "Load more"); } - get themeIcon(): { id: string; } | undefined { + get themeIcon(): ThemeIcon | undefined { return undefined; //this.loading ? { id: 'sync~spin' } : undefined; } } @@ -1150,6 +1151,11 @@ class TimelineTreeRenderer implements ITreeRenderer('conflictsSources', ''); @@ -1125,7 +1124,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo UserDataSyncViewPaneContainer, [SYNC_VIEW_CONTAINER_ID] ), - icon: ThemeIcon.fromCodicon(SYNC_VIEW_ICON), + icon: SYNC_VIEW_ICON, hideIfEmpty: true, }, ViewContainerLocation.Sidebar); } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts index c0773ff28f9..d26d9dd1aa0 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts @@ -237,7 +237,7 @@ export class UserDataSyncDataViews extends Disposable { super({ id: `workbench.actions.sync.replaceCurrent`, title: localize('workbench.actions.sync.replaceCurrent', "Restore"), - icon: { id: 'codicon/discard' }, + icon: Codicon.discard, menu: { id: MenuId.ViewItemContext, when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /sync-resource-.*/i)), diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index d9d2bf79326..a721466c9d9 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -19,7 +19,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { getViewsStateStorageId, ViewContainerModel } from 'vs/workbench/services/views/common/viewContainerModel'; import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions'; import { localize } from 'vs/nls'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; interface ICachedViewContainerInfo { containerId: string; @@ -461,7 +460,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor id, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), name: 'Custom Views', // we don't want to see this, so no need to localize - icon: location === ViewContainerLocation.Sidebar ? ThemeIcon.fromCodicon(defaultViewIcon) : undefined, + icon: location === ViewContainerLocation.Sidebar ? defaultViewIcon : undefined, storageId: getViewContainerStorageId(id), hideIfEmpty: true }, location); diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index d736bc82ff0..811fd8dbc30 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -348,7 +348,7 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode titleChanged = true; } - const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); + const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || defaultViewIcon; let iconChanged: boolean = false; if (!this.isEqualIcon(icon)) { this._icon = icon; From 5a04894296ef7103cef20586324d58985a1c5b1c Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 24 Nov 2020 14:08:55 -0800 Subject: [PATCH 0228/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aa1dbada1d9..2468a6dbbde 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "e5fdc430f3622754e5b5838e4c4a93751b6f3ed7", + "distro": "4efc01d229d8c6ca0a14e80b89c7587fcb6cb59b", "author": { "name": "Microsoft Corporation" }, From 093acbdcbfdb2da891b139e99bcffc8013c71453 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2020 23:31:27 +0100 Subject: [PATCH 0229/1837] timeline icons: use codicon registry for now --- .../contrib/timeline/browser/timeline.contribution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts index 212f827bfee..33be689a140 100644 --- a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts +++ b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts @@ -18,8 +18,7 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ResourceContextKey } from 'vs/workbench/common/resources'; -import { Codicon } from 'vs/base/common/codicons'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; const timelineViewIcon = registerIcon('timeline-view-icon', Codicon.history, localize('timelineViewIcon', 'View icon of the timeline view.')); From 8c9dfcbcb44e514da39b2e8034abb1a943faaa02 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 24 Nov 2020 14:43:58 -0800 Subject: [PATCH 0230/1837] fix: appName in upload-vscode-configuration task --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 6c51051b765..6e556444fe1 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -458,7 +458,7 @@ const generateVSCodeConfigurationTask = task.define('generate-vscode-configurati const extensionsDir = path.join(os.tmpdir(), 'tmpextdir'); const arch = process.env['VSCODE_ARCH']; const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`); - const appName = product.nameLong + '.app'; + const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app'; const appPath = path.join(appRoot, appName, 'Contents', 'Resources', 'app', 'bin', 'code'); const codeProc = cp.exec( `${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`, From 3898e2ced36a1391dae55ba64dedeb26191e711f Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 24 Nov 2020 15:17:34 -0800 Subject: [PATCH 0231/1837] Update extension install button to match default button style --- .../contrib/extensions/browser/extensionsActions.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 5fbd09c9a4d..079ea8e7f6c 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -32,7 +32,6 @@ import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/c import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, registerColor, foreground } from 'vs/platform/theme/common/colorRegistry'; -import { Color } from 'vs/base/common/color'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -3219,20 +3218,20 @@ CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsWith }); export const extensionButtonProminentBackground = registerColor('extensionButton.prominentBackground', { - dark: '#327e36', - light: '#327e36', + dark: buttonBackground, + light: buttonBackground, hc: null }, localize('extensionButtonProminentBackground', "Button background color for actions extension that stand out (e.g. install button).")); export const extensionButtonProminentForeground = registerColor('extensionButton.prominentForeground', { - dark: Color.white, - light: Color.white, + dark: buttonForeground, + light: buttonForeground, hc: null }, localize('extensionButtonProminentForeground', "Button foreground color for actions extension that stand out (e.g. install button).")); export const extensionButtonProminentHoverBackground = registerColor('extensionButton.prominentHoverBackground', { - dark: '#28632b', - light: '#28632b', + dark: buttonHoverBackground, + light: buttonHoverBackground, hc: null }, localize('extensionButtonProminentHoverBackground', "Button background hover color for actions extension that stand out (e.g. install button).")); From 614a865d1d25037e076245ec2fdf16b71fcf9cac Mon Sep 17 00:00:00 2001 From: David Sanders Date: Tue, 24 Nov 2020 20:17:01 -0800 Subject: [PATCH 0232/1837] Fix error message --- src/vs/base/common/uri.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 5ac44dc8426..8111602efc5 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -345,7 +345,7 @@ export class URI implements UriComponents { */ static joinPath(uri: URI, ...pathFragment: string[]): URI { if (!uri.path) { - throw new Error(`[UriError]: cannot call joinPaths on URI without path`); + throw new Error(`[UriError]: cannot call joinPath on URI without path`); } let newPath: string; if (isWindows && uri.scheme === 'file') { From c6e908997b91e92b7287eba2504d0b50a27a05ba Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 08:04:01 +0100 Subject: [PATCH 0233/1837] jsdoc :lipstick: for relative pattern --- src/vs/vscode.d.ts | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0c8d499f1ba..7a98e9bc3eb 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1878,8 +1878,9 @@ declare module 'vscode' { /** * A relative pattern is a helper to construct glob patterns that are matched - * relatively to a base path. The base path can either be an absolute file path - * or a [workspace folder](#WorkspaceFolder). + * relatively to a base file path. The base path can either be an absolute file + * path as string or uri or a [workspace folder](#WorkspaceFolder), which is the + * preferred way of creating the relative pattern. */ export class RelativePattern { @@ -1898,15 +1899,28 @@ declare module 'vscode' { pattern: string; /** - * Creates a new relative pattern object with a base and pattern to match. This pattern - * will be matched on paths relative to the base path. + * Creates a new relative pattern object with a base file path and pattern to match. This pattern + * will be matched on file paths relative to the base. + * + * Example: + * ```ts + * const folder = vscode.workspace.workspaceFolders?.[0]; + * if (folder) { + * + * // Match any TypeScript file in the root of this workspace folder + * const pattern1 = new vscode.RelativePattern(folder, '*.ts'); + * + * // Match any TypeScript file in `someFolder` inside this workspace folder + * const pattern2 = new vscode.RelativePattern(folder, 'someFolder/*.ts'); + * } + * ``` * * @param base A base to which this pattern will be matched against relatively. It is recommended * to pass in a [workspace folder](#WorkspaceFolder) if the pattern should match inside the workspace. - * Otherwise, a uri or string should only be used if the pattern is for a path outside the workspace. + * Otherwise, a uri or string should only be used if the pattern is for a file path outside the workspace. * @param pattern A file glob pattern like `*.{ts,js}` that will be matched on paths relative to the base. */ - constructor(base: Uri | WorkspaceFolder | string, pattern: string) + constructor(base: WorkspaceFolder | Uri | string, pattern: string) } /** From ec5da2bdc1c58c229cbc6a6749be53fb3e5a5fe1 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 24 Nov 2020 23:03:26 -0800 Subject: [PATCH 0234/1837] build: rebuild keytar for arm64 Fixes https://github.com/microsoft/vscode/issues/111271 --- build/azure-pipelines/darwin/product-build-darwin.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 478365c7bbd..24d0611c76c 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -114,9 +114,14 @@ steps: - script: | set -e + export npm_config_arch=$(VSCODE_ARCH) + export npm_config_node_gyp=$(which node-gyp) + export npm_config_build_from_source=true export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ yarn electron-rebuild + cd ./node_modules/keytar + node-gyp rebuild displayName: Rebuild native modules for ARM64 condition: eq(variables['VSCODE_ARCH'], 'arm64') From 2433e2938303617190a9b44971c89d478e133aba Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 08:16:33 +0100 Subject: [PATCH 0235/1837] sandbox - use IPC communication to read bundles --- src/bootstrap.js | 75 ++++++++++++++++--- .../parts/sandbox/electron-browser/preload.js | 59 ++++++++------- src/vs/code/electron-main/app.ts | 65 +++++++++++++--- .../electron-main/environmentMainService.ts | 6 ++ 4 files changed, 157 insertions(+), 48 deletions(-) diff --git a/src/bootstrap.js b/src/bootstrap.js index 250ac23b987..b25b34cc330 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -127,14 +127,11 @@ * @returns {{locale?: string, availableLanguages: {[lang: string]: string;}, pseudo?: boolean } | undefined} */ function setupNLS() { - if (!path || !fs || typeof process === 'undefined') { - console.warn('setupNLS() is only available in node.js environments'); - return { availableLanguages: {} }; // TODO@sandbox NLS is currently non-sandboxed only - } - // Get the nls configuration into the process.env as early as possible. + // Get the nls configuration as early as possible. + const process = safeProcess(); let nlsConfig = { availableLanguages: {} }; - if (process.env['VSCODE_NLS_CONFIG']) { + if (process && process.env['VSCODE_NLS_CONFIG']) { try { nlsConfig = JSON.parse(process.env['VSCODE_NLS_CONFIG']); } catch (e) { @@ -153,8 +150,7 @@ return; } - const bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, `${bundle.replace(/\//g, '!')}.nls.json`); - fs.promises.readFile(bundleFile, 'utf8').then(function (content) { + safeReadNlsFile(nlsConfig._resolvedLanguagePackCoreLocation, `${bundle.replace(/\//g, '!')}.nls.json`).then(function (content) { const json = JSON.parse(content); bundles[bundle] = json; @@ -162,7 +158,7 @@ }).catch((error) => { try { if (nlsConfig._corruptedFile) { - fs.promises.writeFile(nlsConfig._corruptedFile, 'corrupted', 'utf8').catch(function (error) { console.error(error); }); + safeWriteNlsFile(nlsConfig._corruptedFile, 'corrupted').catch(function (error) { console.error(error); }); } } finally { cb(error, undefined); @@ -267,14 +263,69 @@ global['diagnosticsSource'] = {}; // Prevents diagnostic channel (which patches "require") from initializing entirely } - function safeProcess() { + function safeGlobals() { const globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {}); + return globals.vscode; + } + + /** + * @returns {NodeJS.Process | undefined} + */ + function safeProcess() { if (typeof process !== 'undefined') { return process; // Native environment (non-sandboxed) - } else if (typeof globals.vscode !== 'undefined') { - return globals.vscode.process; // Native environment (sandboxed) } + + const globals = safeGlobals(); + if (globals) { + return globals.process; // Native environment (sandboxed) + } + } + + /** + * @returns {Electron.IpcRenderer | undefined} + */ + function safeIpcRenderer() { + const globals = safeGlobals(); + if (globals) { + return globals.ipcRenderer; + } + } + + /** + * @param {string[]} pathSegments + * @returns {Promise} + */ + async function safeReadNlsFile(...pathSegments) { + const ipcRenderer = safeIpcRenderer(); + if (ipcRenderer) { + return ipcRenderer.invoke('vscode:readNlsFile', ...pathSegments); + } + + if (fs && path) { + return (await fs.promises.readFile(path.join(...pathSegments))).toString(); + } + + throw new Error('Unsupported operation (read NLS files)'); + } + + /** + * @param {string} path + * @param {string} content + * @returns {Promise} + */ + function safeWriteNlsFile(path, content) { + const ipcRenderer = safeIpcRenderer(); + if (ipcRenderer) { + return ipcRenderer.invoke('vscode:writeNlsFile', path, content); + } + + if (fs) { + return fs.promises.writeFile(path, content); + } + + throw new Error('Unsupported operation (write NLS files)'); } //#endregion diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index 3ee0b2ca853..a1aa638f825 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -35,6 +35,17 @@ } }, + /** + * @param {string} channel + * @param {any[]} args + * @returns {Promise | undefined} + */ + invoke(channel, ...args) { + if (validateIPC(channel)) { + return ipcRenderer.invoke(channel, ...args); + } + }, + /** * @param {string} channel * @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener @@ -108,33 +119,30 @@ get type() { return 'renderer'; }, get execPath() { return process.execPath; }, - resolveEnv: - /** - * @param userEnv {{[key: string]: string}} - * @returns {Promise} - */ - function (userEnv) { - return resolveEnv(userEnv); - }, + /** + * @param {{[key: string]: string}} userEnv + * @returns {Promise} + */ + resolveEnv(userEnv) { + return resolveEnv(userEnv); + }, - getProcessMemoryInfo: - /** - * @returns {Promise} - */ - function () { - return process.getProcessMemoryInfo(); - }, + /** + * @returns {Promise} + */ + getProcessMemoryInfo() { + return process.getProcessMemoryInfo(); + }, - on: - /** - * @param {string} type - * @param {() => void} callback - */ - function (type, callback) { - if (validateProcessEventType(type)) { - process.on(type, callback); - } + /** + * @param {string} type + * @param {() => void} callback + */ + on(type, callback) { + if (validateProcessEventType(type)) { + process.on(type, callback); } + } }, /** @@ -168,6 +176,7 @@ /** * @param {string} channel + * @returns {true | never} */ function validateIPC(channel) { if (!channel || !channel.startsWith('vscode:')) { @@ -198,7 +207,7 @@ * all development related environment variables. We do this from the * main process because it may involve spawning a shell. * - * @param userEnv {{[key: string]: string}} + * @param {{[key: string]: string}} userEnv * @returns {Promise} */ function resolveEnv(userEnv) { diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 5f91f3fd6d7..9525b29bcfa 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app, ipcMain as ipc, systemPreferences, contentTracing, protocol, IpcMainEvent, BrowserWindow, dialog, session } from 'electron'; -import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform'; +import { app, ipcMain as ipc, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session } from 'electron'; +import { IProcessEnvironment, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; @@ -52,7 +52,7 @@ import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver'; import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService'; import { RunOnceScheduler } from 'vs/base/common/async'; import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu'; -import { sep, posix } from 'vs/base/common/path'; +import { sep, posix, join, isAbsolute } from 'vs/base/common/path'; import { joinPath } from 'vs/base/common/resources'; import { localize } from 'vs/nls'; import { Schemas } from 'vs/base/common/network'; @@ -86,6 +86,7 @@ import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platfo import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; +import { isEqualOrParent } from 'vs/base/common/extpath'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -100,7 +101,8 @@ export class CodeApplication extends Disposable { @IEnvironmentMainService private readonly environmentService: IEnvironmentMainService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @IConfigurationService private readonly configurationService: IConfigurationService, - @IStateService private readonly stateService: IStateService + @IStateService private readonly stateService: IStateService, + @IFileService private readonly fileService: IFileService ) { super(); @@ -264,7 +266,9 @@ export class CodeApplication extends Disposable { this.windowsMainService?.openEmptyWindow({ context: OpenContext.DESKTOP }); //macOS native tab "+" button }); - ipc.on('vscode:fetchShellEnv', async (event: IpcMainEvent) => { + //#region Bootstrap IPC Handlers + + ipc.on('vscode:fetchShellEnv', async event => { const webContents = event.sender; const window = this.windowsMainService?.getWindowByWebContents(event.sender); @@ -312,10 +316,50 @@ export class CodeApplication extends Disposable { acceptShellEnv(shellEnv); }); - ipc.on('vscode:toggleDevTools', (event: IpcMainEvent) => event.sender.toggleDevTools()); - ipc.on('vscode:openDevTools', (event: IpcMainEvent) => event.sender.openDevTools()); + ipc.handle('vscode:writeNlsFile', (event, path: unknown, data: unknown) => { + const uri = this.validateNlsPath([path]); + if (!uri || typeof data !== 'string') { + return Promise.reject('Invalid operation (vscode:writeNlsFile)'); + } - ipc.on('vscode:reloadWindow', (event: IpcMainEvent) => event.sender.reload()); + return this.fileService.writeFile(uri, VSBuffer.fromString(data)); + }); + + ipc.handle('vscode:readNlsFile', async (event, ...paths: unknown[]) => { + const uri = this.validateNlsPath(paths); + if (!uri) { + return Promise.reject('Invalid operation (vscode:readNlsFile)'); + } + + return (await this.fileService.readFile(uri)).value.toString(); + }); + + ipc.on('vscode:toggleDevTools', event => event.sender.toggleDevTools()); + ipc.on('vscode:openDevTools', event => event.sender.openDevTools()); + + ipc.on('vscode:reloadWindow', event => event.sender.reload()); + + //#endregion + } + + private validateNlsPath(pathSegments: unknown[]): URI | undefined { + let path: string | undefined = undefined; + + for (const pathSegment of pathSegments) { + if (typeof pathSegment === 'string') { + if (typeof path !== 'string') { + path = pathSegment; + } else { + path = join(path, pathSegment); + } + } + } + + if (typeof path !== 'string' || !isAbsolute(path) || !isEqualOrParent(path, this.environmentService.cachedLanguagesPath, !isLinux)) { + return undefined; + } + + return URI.file(path); } private onUnexpectedError(err: Error): void { @@ -856,8 +900,7 @@ export class CodeApplication extends Disposable { // based on telemetry.enableCrashreporter settings, generate a UUID which // will be used as crash reporter id and also update the json file. try { - const fileService = accessor.get(IFileService); - const argvContent = await fileService.readFile(this.environmentService.argvResource); + const argvContent = await this.fileService.readFile(this.environmentService.argvResource); const argvString = argvContent.value.toString(); const argvJSON = JSON.parse(stripComments(argvString)); if (argvJSON['enable-crash-reporter'] === undefined) { @@ -874,7 +917,7 @@ export class CodeApplication extends Disposable { '}' ]; const newArgvString = argvString.substring(0, argvString.length - 2).concat(',\n', additionalArgvContent.join('\n')); - await fileService.writeFile(this.environmentService.argvResource, VSBuffer.fromString(newArgvString)); + await this.fileService.writeFile(this.environmentService.argvResource, VSBuffer.fromString(newArgvString)); } } catch (error) { this.logService.error(error); diff --git a/src/vs/platform/environment/electron-main/environmentMainService.ts b/src/vs/platform/environment/electron-main/environmentMainService.ts index 178b9ee68d3..35b09d89d39 100644 --- a/src/vs/platform/environment/electron-main/environmentMainService.ts +++ b/src/vs/platform/environment/electron-main/environmentMainService.ts @@ -19,6 +19,9 @@ export const IEnvironmentMainService = createDecorator( */ export interface IEnvironmentMainService extends INativeEnvironmentService { + // --- NLS cache path + cachedLanguagesPath: string; + // --- backup paths backupHome: string; backupWorkspacesPath: string; @@ -37,6 +40,9 @@ export interface IEnvironmentMainService extends INativeEnvironmentService { export class EnvironmentMainService extends NativeEnvironmentService implements IEnvironmentMainService { + @memoize + get cachedLanguagesPath(): string { return join(this.userDataPath, 'clp'); } + @memoize get backupHome(): string { return join(this.userDataPath, 'Backups'); } From 1460908e187f3ffcdbd0b9d5b15077d775bd8e5a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 08:46:40 +0100 Subject: [PATCH 0236/1837] bootstrap - move portable mode into bootstrap-node --- src/bootstrap-node.js | 70 ++++++++++++++++++++++++++ src/bootstrap.js | 112 +++++++----------------------------------- src/cli.js | 3 +- src/main.js | 3 +- 4 files changed, 92 insertions(+), 96 deletions(-) diff --git a/src/bootstrap-node.js b/src/bootstrap-node.js index 2686249978d..161d68d5941 100644 --- a/src/bootstrap-node.js +++ b/src/bootstrap-node.js @@ -58,3 +58,73 @@ exports.removeGlobalNodeModuleLookupPaths = function () { return paths.slice(0, paths.length - commonSuffixLength); }; }; + +/** + * Helper to enable portable mode. + * + * @param {{ portable?: string; applicationName: string; }} product + * @returns {{ portableDataPath: string; isPortable: boolean; }} + */ +exports.configurePortable = function (product) { + const fs = require('fs'); + const path = require('path'); + + const appRoot = path.dirname(__dirname); + + /** + * @param {import('path')} path + */ + function getApplicationPath(path) { + if (process.env['VSCODE_DEV']) { + return appRoot; + } + + if (process.platform === 'darwin') { + return path.dirname(path.dirname(path.dirname(appRoot))); + } + + return path.dirname(path.dirname(appRoot)); + } + + /** + * @param {import('path')} path + */ + function getPortableDataPath(path) { + if (process.env['VSCODE_PORTABLE']) { + return process.env['VSCODE_PORTABLE']; + } + + if (process.platform === 'win32' || process.platform === 'linux') { + return path.join(getApplicationPath(path), 'data'); + } + + // @ts-ignore + const portableDataName = product.portable || `${product.applicationName}-portable-data`; + return path.join(path.dirname(getApplicationPath(path)), portableDataName); + } + + const portableDataPath = getPortableDataPath(path); + const isPortable = !('target' in product) && fs.existsSync(portableDataPath); + const portableTempPath = path.join(portableDataPath, 'tmp'); + const isTempPortable = isPortable && fs.existsSync(portableTempPath); + + if (isPortable) { + process.env['VSCODE_PORTABLE'] = portableDataPath; + } else { + delete process.env['VSCODE_PORTABLE']; + } + + if (isTempPortable) { + if (process.platform === 'win32') { + process.env['TMP'] = portableTempPath; + process.env['TEMP'] = portableTempPath; + } else { + process.env['TMPDIR'] = portableTempPath; + } + } + + return { + portableDataPath, + isPortable + }; +}; diff --git a/src/bootstrap.js b/src/bootstrap.js index b25b34cc330..5392a5602cf 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -170,99 +170,6 @@ return nlsConfig; } - //#endregion - - - //#region Portable helpers - - /** - * @param {{ portable: string | undefined; applicationName: string; }} product - * @returns {{ portableDataPath: string; isPortable: boolean; } | undefined} - */ - function configurePortable(product) { - if (!path || !fs || typeof process === 'undefined') { - console.warn('configurePortable() is only available in node.js environments'); // TODO@sandbox Portable is currently non-sandboxed only - return; - } - - const appRoot = path.dirname(__dirname); - - /** - * @param {import('path')} path - */ - function getApplicationPath(path) { - if (process.env['VSCODE_DEV']) { - return appRoot; - } - - if (process.platform === 'darwin') { - return path.dirname(path.dirname(path.dirname(appRoot))); - } - - return path.dirname(path.dirname(appRoot)); - } - - /** - * @param {import('path')} path - */ - function getPortableDataPath(path) { - if (process.env['VSCODE_PORTABLE']) { - return process.env['VSCODE_PORTABLE']; - } - - if (process.platform === 'win32' || process.platform === 'linux') { - return path.join(getApplicationPath(path), 'data'); - } - - // @ts-ignore - const portableDataName = product.portable || `${product.applicationName}-portable-data`; - return path.join(path.dirname(getApplicationPath(path)), portableDataName); - } - - const portableDataPath = getPortableDataPath(path); - const isPortable = !('target' in product) && fs.existsSync(portableDataPath); - const portableTempPath = path.join(portableDataPath, 'tmp'); - const isTempPortable = isPortable && fs.existsSync(portableTempPath); - - if (isPortable) { - process.env['VSCODE_PORTABLE'] = portableDataPath; - } else { - delete process.env['VSCODE_PORTABLE']; - } - - if (isTempPortable) { - if (process.platform === 'win32') { - process.env['TMP'] = portableTempPath; - process.env['TEMP'] = portableTempPath; - } else { - process.env['TMPDIR'] = portableTempPath; - } - } - - return { - portableDataPath, - isPortable - }; - } - - //#endregion - - - //#region ApplicationInsights - - // Prevents appinsights from monkey patching modules. - // This should be called before importing the applicationinsights module - function avoidMonkeyPatchFromAppInsights() { - if (typeof process === 'undefined') { - console.warn('avoidMonkeyPatchFromAppInsights() is only available in node.js environments'); - return; - } - - // @ts-ignore - process.env['APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL'] = true; // Skip monkey patching of 3rd party modules by appinsights - global['diagnosticsSource'] = {}; // Prevents diagnostic channel (which patches "require") from initializing entirely - } - function safeGlobals() { const globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {}); @@ -329,12 +236,29 @@ } //#endregion + + + //#region ApplicationInsights + + // Prevents appinsights from monkey patching modules. + // This should be called before importing the applicationinsights module + function avoidMonkeyPatchFromAppInsights() { + if (typeof process === 'undefined') { + console.warn('avoidMonkeyPatchFromAppInsights() is only available in node.js environments'); + return; + } + + // @ts-ignore + process.env['APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL'] = true; // Skip monkey patching of 3rd party modules by appinsights + global['diagnosticsSource'] = {}; // Prevents diagnostic channel (which patches "require") from initializing entirely + } + + //#endregion return { enableASARSupport, avoidMonkeyPatchFromAppInsights, - configurePortable, setupNLS, fileUriFromPath }; diff --git a/src/cli.js b/src/cli.js index c59d5ae2f6d..5624cb93bb5 100644 --- a/src/cli.js +++ b/src/cli.js @@ -7,13 +7,14 @@ 'use strict'; const bootstrap = require('./bootstrap'); +const bootstrapNode = require('./bootstrap-node'); const product = require('../product.json'); // Avoid Monkey Patches from Application Insights bootstrap.avoidMonkeyPatchFromAppInsights(); // Enable portable support -bootstrap.configurePortable(product); +bootstrapNode.configurePortable(product); // Enable ASAR support bootstrap.enableASARSupport(undefined); diff --git a/src/main.js b/src/main.js index 699ccb5b1ab..8ec0aa74c39 100644 --- a/src/main.js +++ b/src/main.js @@ -15,6 +15,7 @@ const path = require('path'); const fs = require('fs'); const os = require('os'); const bootstrap = require('./bootstrap'); +const bootstrapNode = require('./bootstrap-node'); const paths = require('./paths'); /** @type {any} */ const product = require('../product.json'); @@ -25,7 +26,7 @@ const { app, protocol, crashReporter } = require('electron'); app.allowRendererProcessReuse = false; // Enable portable support -const portable = bootstrap.configurePortable(product); +const portable = bootstrapNode.configurePortable(product); // Enable ASAR support bootstrap.enableASARSupport(undefined); From 41ef01de561118d96432cc2447dfb9dae15f81b0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 25 Nov 2020 09:02:42 +0100 Subject: [PATCH 0237/1837] Fix #111212 --- .../contrib/output/browser/outputView.ts | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 7e86eb96f38..a01c54ae7e8 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -11,7 +11,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; @@ -164,11 +163,6 @@ export class OutputViewPane extends ViewPane { export class OutputEditor extends AbstractTextResourceEditor { - // Override the instantiation service to use to be the scoped one - private scopedInstantiationService: IInstantiationService; - protected get instantiationService(): IInstantiationService { return this.scopedInstantiationService; } - protected set instantiationService(instantiationService: IInstantiationService) { } - constructor( @ITelemetryService telemetryService: ITelemetryService, @IInstantiationService instantiationService: IInstantiationService, @@ -177,15 +171,10 @@ export class OutputEditor extends AbstractTextResourceEditor { @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService, @IThemeService themeService: IThemeService, @IOutputService private readonly outputService: IOutputService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, @IEditorGroupsService editorGroupService: IEditorGroupsService, @IEditorService editorService: IEditorService ) { super(OUTPUT_VIEW_ID, telemetryService, instantiationService, storageService, textResourceConfigurationService, themeService, editorGroupService, editorService); - - // Initially, the scoped instantiation service is the global - // one until the editor is created later on - this.scopedInstantiationService = instantiationService; } getId(): string { @@ -258,13 +247,12 @@ export class OutputEditor extends AbstractTextResourceEditor { parent.setAttribute('role', 'document'); - // First create the scoped instantiation service and only then construct the editor using the scoped service - const scopedContextKeyService = this._register(this.contextKeyService.createScoped(parent)); - this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, scopedContextKeyService])); - super.createEditor(parent); - CONTEXT_IN_OUTPUT.bindTo(scopedContextKeyService).set(true); + const scopedContextKeyService = this.scopedContextKeyService; + if (scopedContextKeyService) { + CONTEXT_IN_OUTPUT.bindTo(scopedContextKeyService).set(true); + } } } From 00eea33b237d874aa68b56fc831613d9031ed97a Mon Sep 17 00:00:00 2001 From: Pablo Sebastian Greco Date: Wed, 25 Nov 2020 05:14:38 -0300 Subject: [PATCH 0238/1837] More cleanup for armhfp and aarch64 rpm hardcoded dependencies (#111253) * Adjust hardcoded rpm dependecies for aarch64 to what is minimally available in CentOS7 and CentOS8 * Cleanup some hardcoded rpm dependecies for armv7hl to what is minimally available in CentOS7 and CentOS8, may need more work Co-authored-by: Pablo Greco --- resources/linux/rpm/dependencies.json | 29 ++++++++------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/resources/linux/rpm/dependencies.json b/resources/linux/rpm/dependencies.json index dec9b480689..8a055565b64 100644 --- a/resources/linux/rpm/dependencies.json +++ b/resources/linux/rpm/dependencies.json @@ -67,9 +67,7 @@ ], "aarch64": [ "libpthread.so.0()(64bit)", - "libpthread.so.0(GLIBC_2.2.5)(64bit)", - "libpthread.so.0(GLIBC_2.3.2)(64bit)", - "libpthread.so.0(GLIBC_2.3.3)(64bit)", + "libpthread.so.0(GLIBC_2.17)(64bit)", "libgtk-3.so.0()(64bit)", "libgdk-x11-2.0.so.0()(64bit)", "libatk-1.0.so.0()(64bit)", @@ -112,29 +110,21 @@ "libstdc++.so.6(GLIBCXX_3.4.15)(64bit)", "libstdc++.so.6(GLIBCXX_3.4.9)(64bit)", "libm.so.6()(64bit)", - "libm.so.6(GLIBC_2.2.5)(64bit)", + "libm.so.6(GLIBC_2.17)(64bit)", "libgcc_s.so.1()(64bit)", "libgcc_s.so.1(GCC_3.0)(64bit)", "libgcc_s.so.1(GCC_4.0.0)(64bit)", "libc.so.6()(64bit)", - "libc.so.6(GLIBC_2.11)(64bit)", - "libc.so.6(GLIBC_2.2.5)(64bit)", - "libc.so.6(GLIBC_2.3)(64bit)", - "libc.so.6(GLIBC_2.3.2)(64bit)", - "libc.so.6(GLIBC_2.3.4)(64bit)", - "libc.so.6(GLIBC_2.4)(64bit)", - "libc.so.6(GLIBC_2.6)(64bit)", - "libc.so.6(GLIBC_2.7)(64bit)", - "libc.so.6(GLIBC_2.9)(64bit)", + "libc.so.6(GLIBC_2.17)(64bit)", "libxcb.so.1()(64bit)", "libxkbfile.so.1()(64bit)", "libsecret-1.so.0()(64bit)" ], "armv7hl": [ "libpthread.so.0()", - "libpthread.so.0(GLIBC_2.2.5)", - "libpthread.so.0(GLIBC_2.3.2)", - "libpthread.so.0(GLIBC_2.3.3)", + "libpthread.so.0(GLIBC_2.4)", + "libpthread.so.0(GLIBC_2.11)", + "libpthread.so.0(GLIBC_2.12)", "libgtk-3.so.0()", "libgdk-x11-2.0.so.0()", "libatk-1.0.so.0()", @@ -177,16 +167,13 @@ "libstdc++.so.6(GLIBCXX_3.4.15)", "libstdc++.so.6(GLIBCXX_3.4.9)", "libm.so.6()", - "libm.so.6(GLIBC_2.2.5)", + "libm.so.6(GLIBC_2.4)", + "libm.so.6(GLIBC_2.15)", "libgcc_s.so.1()", "libgcc_s.so.1(GCC_3.0)", "libgcc_s.so.1(GCC_4.0.0)", "libc.so.6()", "libc.so.6(GLIBC_2.11)", - "libc.so.6(GLIBC_2.2.5)", - "libc.so.6(GLIBC_2.3)", - "libc.so.6(GLIBC_2.3.2)", - "libc.so.6(GLIBC_2.3.4)", "libc.so.6(GLIBC_2.4)", "libc.so.6(GLIBC_2.6)", "libc.so.6(GLIBC_2.7)", From 2ea9ecd6da760369af5259e0fac29124316830de Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 09:23:49 +0100 Subject: [PATCH 0239/1837] increate file participant default time to 1 minute, show notification progress which allows for cancellation, https://github.com/microsoft/vscode/issues/111208 --- .../mainThreadFileSystemEventService.ts | 2 +- .../workingCopyFileOperationParticipant.ts | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index b6e0a210a30..81905c6b1d0 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -77,7 +77,7 @@ Registry.as(Extensions.Configuration).registerConfigurat properties: { 'files.participants.timeout': { type: 'number', - default: 5000, + default: 60000, markdownDescription: localize('files.participants.timeout', "Timeout in milliseconds after which file participants for create, rename, and delete are cancelled. Use `0` to disable participants."), } } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index d7723c151a4..185f3546b45 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { raceTimeout } from 'vs/base/common/async'; +import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; @@ -40,10 +40,13 @@ export class WorkingCopyFileOperationParticipant extends Disposable { } const cts = new CancellationTokenSource(); + const timer = setTimeout(() => cts.cancel(), timeout); return this.progressService.withProgress({ - location: ProgressLocation.Window, - title: this.progressLabel(operation) + location: ProgressLocation.Notification, + title: this.progressLabel(operation), + cancellable: true, + delay: Math.min(timeout / 2, 3000) }, async progress => { // For each participant @@ -51,14 +54,21 @@ export class WorkingCopyFileOperationParticipant extends Disposable { if (cts.token.isCancellationRequested) { break; } - try { const promise = participant.participate(files, operation, undoRedoGroupId, isUndoing, progress, timeout, cts.token); - await raceTimeout(promise, timeout, () => cts.dispose(true /* cancel */)); + await raceCancellation(promise, cts.token); } catch (err) { this.logService.warn(err); } } + }, () => { + // user cancel + cts.cancel(); + + }).finally(() => { + // cleanup + cts.dispose(); + clearTimeout(timer); }); } From 236298851a5af1305a0e741871a5fed31847708b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 09:26:24 +0100 Subject: [PATCH 0240/1837] :lipstick: use linked list instead of array-remove gymnastics, fyi @bpasero --- .../common/workingCopyFileOperationParticipant.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index 185f3546b45..c1b2b911baf 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -13,11 +13,11 @@ import { IWorkingCopyFileOperationParticipant } from 'vs/workbench/services/work import { URI } from 'vs/base/common/uri'; import { FileOperation } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { insert } from 'vs/base/common/arrays'; +import { LinkedList } from 'vs/base/common/linkedList'; export class WorkingCopyFileOperationParticipant extends Disposable { - private readonly participants: IWorkingCopyFileOperationParticipant[] = []; + private readonly participants = new LinkedList(); constructor( @IProgressService private readonly progressService: IProgressService, @@ -28,8 +28,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { } addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { - const remove = insert(this.participants, participant); - + const remove = this.participants.push(participant); return toDisposable(() => remove()); } @@ -86,6 +85,6 @@ export class WorkingCopyFileOperationParticipant extends Disposable { } dispose(): void { - this.participants.splice(0, this.participants.length); + this.participants.clear(); } } From ffec932655b672f1b11f6db1696c9460d1f92eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 09:37:56 +0100 Subject: [PATCH 0241/1837] add timeout to terrapin step --- build/azure-pipelines/darwin/product-build-darwin.yml | 1 + build/azure-pipelines/linux/product-build-alpine.yml | 1 + build/azure-pipelines/linux/product-build-linux.yml | 1 + build/azure-pipelines/product-compile.yml | 1 + build/azure-pipelines/web/product-build-web.yml | 1 + build/azure-pipelines/win32/product-build-win32-arm64.yml | 1 + build/azure-pipelines/win32/product-build-win32.yml | 1 + 7 files changed, 7 insertions(+) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 24d0611c76c..8f63b6f1684 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -60,6 +60,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index b489de4a97e..01e209626bd 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -65,6 +65,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index f1f5b9173ac..6aaad7fc958 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -55,6 +55,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 - script: | echo -n $VSCODE_ARCH > .build/arch diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index a975e8a9fb7..62fac4de703 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -55,6 +55,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index d6c48fb1b9b..ee2e85e25d6 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -55,6 +55,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 # - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 # inputs: diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index 7c75bace832..a56b4aa3cd9 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -61,6 +61,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 01310e32544..608adccf384 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -61,6 +61,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages + timeoutInMinutes: 5 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: From 96b2c670d7e484ab860fa9dde8e042b4ad83687b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 09:59:49 +0100 Subject: [PATCH 0242/1837] debt - extensions path is always defined --- .../sharedProcess/sharedProcessMain.ts | 2 +- src/vs/code/electron-main/app.ts | 6 ++--- src/vs/code/electron-main/main.ts | 10 +-------- src/vs/code/node/cliProcessMain.ts | 4 ++-- .../environment/common/environment.ts | 2 +- .../node/extensionsScanner.ts | 2 +- .../platform/windows/electron-main/windows.ts | 5 +++++ .../extensions.contribution.ts | 6 ++--- .../electron-sandbox/extensionsActions.ts | 22 +++++++++---------- .../sandbox.simpleservices.ts | 2 +- .../cachedExtensionScanner.ts | 20 +++++++---------- .../electron-browser/telemetryService.ts | 2 +- 12 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index e0da67e1091..3dcc360b59e 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -187,7 +187,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat appender: telemetryAppender, commonProperties: resolveCommonProperties(product.commit, product.version, configuration.machineId, product.msftInternalDomains, installSourcePath), sendErrorTelemetry: true, - piiPaths: extensionsPath ? [appRoot, extensionsPath] : [appRoot] + piiPaths: [appRoot, extensionsPath] }; telemetryService = new TelemetryService(config, configurationService); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 9525b29bcfa..7175b7a17ea 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -531,7 +531,7 @@ export class CodeApplication extends Disposable { const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender'))); const appender = new TelemetryAppenderClient(channel); const commonProperties = resolveCommonProperties(product.commit, product.version, machineId, product.msftInternalDomains, this.environmentService.installSourcePath); - const piiPaths = this.environmentService.extensionsPath ? [this.environmentService.appRoot, this.environmentService.extensionsPath] : [this.environmentService.appRoot]; + const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath]; const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true }; services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config])); @@ -731,11 +731,11 @@ export class CodeApplication extends Disposable { }); // Create a URL handler which forwards to the last active window - const activeWindowManager = new ActiveWindowManager({ + const activeWindowManager = this._register(new ActiveWindowManager({ onDidOpenWindow: nativeHostMainService.onDidOpenWindow, onDidFocusWindow: nativeHostMainService.onDidFocusWindow, getActiveWindowId: () => nativeHostMainService.getActiveWindowId(-1) - }); + })); const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id)); const urlHandlerRouter = new URLHandlerRouter(activeWindowRouter); const urlHandlerChannel = electronIpcServer.getChannel('urlHandler', urlHandlerRouter); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 1b6ce0e6802..783ac6fb565 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -343,15 +343,7 @@ class CodeMain { private handleStartupDataDirError(environmentService: IEnvironmentMainService, error: NodeJS.ErrnoException): void { if (error.code === 'EACCES' || error.code === 'EPERM') { - const directories = [environmentService.userDataPath]; - - if (environmentService.extensionsPath) { - directories.push(environmentService.extensionsPath); - } - - if (XDG_RUNTIME_DIR) { - directories.push(XDG_RUNTIME_DIR); - } + const directories = coalesce([environmentService.userDataPath, environmentService.extensionsPath, XDG_RUNTIME_DIR]); this.showStartupWarningDialog( localize('startupDataDirError', "Unable to write program user data."), diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 985d9a3d33b..817f3f1ecd6 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -93,7 +93,7 @@ export class Main { } else if (argv['locate-extension']) { await this.locateExtension(argv['locate-extension']); } else if (argv['telemetry']) { - console.log(buildTelemetryMessage(this.environmentService.appRoot, this.environmentService.extensionsPath ? this.environmentService.extensionsPath : undefined)); + console.log(buildTelemetryMessage(this.environmentService.appRoot, this.environmentService.extensionsPath)); } } @@ -425,7 +425,7 @@ export async function main(argv: NativeParsedArgs): Promise { appender: combinedAppender(...appenders), sendErrorTelemetry: false, commonProperties: resolveCommonProperties(product.commit, product.version, stateService.getItem('telemetry.machineId'), product.msftInternalDomains, installSourcePath), - piiPaths: extensionsPath ? [appRoot, extensionsPath] : [appRoot] + piiPaths: [appRoot, extensionsPath] }; services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config])); diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 21b4d719cec..f4b34454238 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -119,7 +119,7 @@ export interface INativeEnvironmentService extends IEnvironmentService { sharedIPCHandle: string; // --- Extensions - extensionsPath?: string; + extensionsPath: string; extensionsDownloadPath: string; builtinExtensionsPath: string; diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index aee65f8eddb..adce023b961 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -49,7 +49,7 @@ export class ExtensionsScanner extends Disposable { ) { super(); this.systemExtensionsPath = environmentService.builtinExtensionsPath; - this.extensionsPath = environmentService.extensionsPath!; + this.extensionsPath = environmentService.extensionsPath; this.uninstalledPath = path.join(this.extensionsPath, '.obsolete'); this.uninstalledFileLimiter = new Queue(); } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 801435cf777..6359b340711 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -33,6 +33,11 @@ export const enum WindowMode { export interface ICodeWindow extends IDisposable { + readonly onLoad: Event; + readonly onReady: Event; + readonly onClose: Event; + readonly onDestroy: Event; + readonly whenClosedOrLoaded: Promise; readonly id: number; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 8d8712ac3c6..bf55d0c1c1e 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -73,10 +73,8 @@ class ExtensionsContributions implements IWorkbenchContribution { @ISharedProcessService sharedProcessService: ISharedProcessService, ) { sharedProcessService.registerChannel('IExtensionRecommendationNotificationService', new ExtensionRecommendationNotificationServiceChannel(extensionRecommendationNotificationService)); - if (environmentService.extensionsPath) { - const openExtensionsFolderActionDescriptor = SyncActionDescriptor.from(OpenExtensionsFolderAction); - actionRegistry.registerWorkbenchAction(openExtensionsFolderActionDescriptor, 'Extensions: Open Extensions Folder', ExtensionsLabel); - } + const openExtensionsFolderActionDescriptor = SyncActionDescriptor.from(OpenExtensionsFolderAction); + actionRegistry.registerWorkbenchAction(openExtensionsFolderActionDescriptor, 'Extensions: Open Extensions Folder', ExtensionsLabel); } } diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsActions.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsActions.ts index 369d6a1bf0b..99cd8d052d8 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsActions.ts @@ -27,20 +27,18 @@ export class OpenExtensionsFolderAction extends Action { } async run(): Promise { - if (this.environmentService.extensionsPath) { - const extensionsHome = URI.file(this.environmentService.extensionsPath); - const file = await this.fileService.resolve(extensionsHome); + const extensionsHome = URI.file(this.environmentService.extensionsPath); + const file = await this.fileService.resolve(extensionsHome); - let itemToShow: URI; - if (file.children && file.children.length > 0) { - itemToShow = file.children[0].resource; - } else { - itemToShow = extensionsHome; - } + let itemToShow: URI; + if (file.children && file.children.length > 0) { + itemToShow = file.children[0].resource; + } else { + itemToShow = extensionsHome; + } - if (itemToShow.scheme === Schemas.file) { - return this.nativeHostService.showItemInFolder(itemToShow.fsPath); - } + if (itemToShow.scheme === Schemas.file) { + return this.nativeHostService.showItemInFolder(itemToShow.fsPath); } } } diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index 8efc2ba91e0..d2ce5a454f8 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -121,7 +121,7 @@ export class SimpleNativeWorkbenchEnvironmentService implements INativeWorkbench sharedIPCHandle: string = undefined!; - extensionsPath?: string | undefined; + extensionsPath: string = undefined!; extensionsDownloadPath: string = undefined!; builtinExtensionsPath: string = undefined!; diff --git a/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts b/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts index a68c61147e1..f974db68e45 100644 --- a/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts +++ b/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts @@ -273,18 +273,14 @@ export class CachedExtensionScanner { finalBuiltinExtensions = ExtensionScanner.mergeBuiltinExtensions(builtinExtensions, extraBuiltinExtensions); } - const userExtensions = ( - !environmentService.extensionsPath - ? Promise.resolve([]) - : this._scanExtensionsWithCache( - hostService, - notificationService, - environmentService, - USER_MANIFEST_CACHE_FILE, - new ExtensionScannerInput(version, commit, locale, devMode, environmentService.extensionsPath, false, false, translations), - log - ) - ); + const userExtensions = (this._scanExtensionsWithCache( + hostService, + notificationService, + environmentService, + USER_MANIFEST_CACHE_FILE, + new ExtensionScannerInput(version, commit, locale, devMode, environmentService.extensionsPath, false, false, translations), + log + )); // Always load developed extensions while extensions development let developedExtensions: Promise = Promise.resolve([]); diff --git a/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts b/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts index 0724f0e7972..acabe9e4dc5 100644 --- a/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts +++ b/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts @@ -38,7 +38,7 @@ export class TelemetryService extends Disposable implements ITelemetryService { const config: ITelemetryServiceConfig = { appender: new TelemetryAppenderClient(channel), commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.machineId, productService.msftInternalDomains, environmentService.installSourcePath, environmentService.remoteAuthority), - piiPaths: environmentService.extensionsPath ? [environmentService.appRoot, environmentService.extensionsPath] : [environmentService.appRoot], + piiPaths: [environmentService.appRoot, environmentService.extensionsPath], sendErrorTelemetry: true }; From 927290270acbd00a2fdf8634a51118a7c1d97295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 10:02:40 +0100 Subject: [PATCH 0243/1837] build: - ENABLE_TERRAPIN env - .build/terrapin cache flag - fix alpine cache - enable web cache --- .../darwin/product-build-darwin.yml | 31 +++++++------- .../linux/product-build-alpine.yml | 19 +++++---- .../linux/product-build-linux.yml | 23 +++++------ build/azure-pipelines/product-compile.yml | 17 ++++---- .../azure-pipelines/web/product-build-web.yml | 40 ++++++++++--------- .../win32/product-build-win32-arm64.yml | 18 +++++---- .../win32/product-build-win32.yml | 18 +++++---- 7 files changed, 86 insertions(+), 80 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 8f63b6f1684..7bf941f8887 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -3,11 +3,13 @@ steps: mkdir -p .build echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n $VSCODE_ARCH > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -54,25 +56,22 @@ steps: displayName: Merge distro - script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag + set -e + sudo xcode-select -s /Applications/Xcode_12.2.app + displayName: Switch to Xcode 12 + condition: eq(variables['VSCODE_ARCH'], 'arm64') + + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - - - script: | - set -e - sudo xcode-select -s /Applications/Xcode_12.2.app - displayName: Switch to Xcode 12 - condition: eq(variables['VSCODE_ARCH'], 'arm64') + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | set -e @@ -98,7 +97,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 01e209626bd..ffbe5b6c1bc 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -3,11 +3,13 @@ steps: mkdir -p .build echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n "alpine" > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -62,16 +64,17 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | set -e @@ -86,7 +89,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: "build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 6aaad7fc958..6485554efd5 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -3,11 +3,13 @@ steps: mkdir -p .build echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n $VSCODE_ARCH > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -52,20 +54,17 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - - - script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | set -e @@ -81,7 +80,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 62fac4de703..a8985ab34a1 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -3,11 +3,13 @@ steps: mkdir -p .build echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n $VSCODE_ARCH > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -56,16 +58,11 @@ steps: npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - script: | - echo -n $VSCODE_ARCH > .build/arch - displayName: Prepare arch cache flag - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true'), ne(variables['CacheExists-Compilation'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) @@ -83,7 +80,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: ".build/arch, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) @@ -150,7 +147,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index ee2e85e25d6..dc8eed5a45f 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -3,11 +3,13 @@ steps: mkdir -p .build echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n "web" > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -52,16 +54,18 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - # - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - # inputs: - # keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - # targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - # vstsFeed: 'npm-vscode' - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin @@ -71,20 +75,20 @@ steps: env: CHILD_CONCURRENCY: 1 displayName: Install dependencies - # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - # - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - # inputs: - # keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' - # targetfolder: '**/node_modules, !**/node_modules/**/node_modules' - # vstsFeed: 'npm-vscode' - # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - # - script: | - # set -e - # yarn postinstall - # displayName: Run postinstall scripts - # condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - script: | set -e diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml index a56b4aa3cd9..add2487aa9c 100644 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ b/build/azure-pipelines/win32/product-build-win32-arm64.yml @@ -3,11 +3,12 @@ steps: mkdir .build -ea 0 "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality + "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -58,16 +59,17 @@ steps: exec { git merge $(node -p "require('./package.json').distro") } displayName: Merge distro + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - powershell: | . build/azure-pipelines/win32/exec.ps1 @@ -82,7 +84,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 608adccf384..6c85805f49a 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -3,11 +3,12 @@ steps: mkdir .build -ea 0 "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality + "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" platformIndependent: true @@ -58,16 +59,17 @@ steps: exec { git merge $(node -p "require('./package.json').distro") } displayName: Merge distro + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - powershell: | . build/azure-pipelines/win32/exec.ps1 @@ -82,7 +84,7 @@ steps: - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: - keyfile: "build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) From 7b1da3a3d95cd8e915896a2ff27adb299c5a0560 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 10:14:04 +0100 Subject: [PATCH 0244/1837] add IBulkEditOptions#token, https://github.com/microsoft/vscode/issues/111281 --- src/vs/editor/browser/services/bulkEditService.ts | 2 ++ .../contrib/bulkEdit/browser/bulkCellEdits.ts | 5 +++++ .../contrib/bulkEdit/browser/bulkEditService.ts | 12 ++++++++---- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 7 +++++++ .../contrib/bulkEdit/browser/bulkTextEdits.ts | 5 +++++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts index 62deab309e2..6b0867d496c 100644 --- a/src/vs/editor/browser/services/bulkEditService.ts +++ b/src/vs/editor/browser/services/bulkEditService.ts @@ -11,6 +11,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { isObject } from 'vs/base/common/types'; import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; +import { CancellationToken } from 'vs/base/common/cancellation'; export const IBulkEditService = createDecorator('IWorkspaceEditService'); @@ -66,6 +67,7 @@ export class ResourceFileEdit extends ResourceEdit { export interface IBulkEditOptions { editor?: ICodeEditor; progress?: IProgress; + token?: CancellationToken; showPreview?: boolean; label?: string; quotableLabel?: string; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts index ff0d2ce11ad..714e459272b 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { groupBy } from 'vs/base/common/arrays'; +import { CancellationToken } from 'vs/base/common/cancellation'; import { compare } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { ResourceEdit } from 'vs/editor/browser/services/bulkEditService'; @@ -31,6 +32,7 @@ export class BulkCellEdits { private readonly _undoRedoGroup: UndoRedoGroup, undoRedoSource: UndoRedoSource | undefined, private readonly _progress: IProgress, + private readonly _token: CancellationToken, private readonly _edits: ResourceNotebookCellEdit[], @INotebookEditorModelResolverService private readonly _notebookModelService: INotebookEditorModelResolverService, ) { } @@ -40,6 +42,9 @@ export class BulkCellEdits { const editsByNotebook = groupBy(this._edits, (a, b) => compare(a.resource.toString(), b.resource.toString())); for (let group of editsByNotebook) { + if (this._token.isCancellationRequested) { + break; + } const [first] = group; const ref = await this._notebookModelService.resolve(first.resource); diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index 100a96523e2..5081e9c0587 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -18,6 +18,7 @@ import { BulkFileEdits } from 'vs/workbench/contrib/bulkEdit/browser/bulkFileEdi import { BulkCellEdits, ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; import { UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; import { LinkedList } from 'vs/base/common/linkedList'; +import { CancellationToken } from 'vs/base/common/cancellation'; class BulkEdit { @@ -25,6 +26,7 @@ class BulkEdit { private readonly _label: string | undefined, private readonly _editor: ICodeEditor | undefined, private readonly _progress: IProgress, + private readonly _token: CancellationToken, private readonly _edits: ResourceEdit[], private readonly _undoRedoGroup: UndoRedoGroup, private readonly _undoRedoSource: UndoRedoSource | undefined, @@ -82,19 +84,19 @@ class BulkEdit { private async _performFileEdits(edits: ResourceFileEdit[], undoRedoGroup: UndoRedoGroup, undoRedoSource: UndoRedoSource | undefined, progress: IProgress) { this._logService.debug('_performFileEdits', JSON.stringify(edits)); - const model = this._instaService.createInstance(BulkFileEdits, this._label || localize('workspaceEdit', "Workspace Edit"), undoRedoGroup, undoRedoSource, progress, edits); + const model = this._instaService.createInstance(BulkFileEdits, this._label || localize('workspaceEdit', "Workspace Edit"), undoRedoGroup, undoRedoSource, progress, this._token, edits); await model.apply(); } private async _performTextEdits(edits: ResourceTextEdit[], undoRedoGroup: UndoRedoGroup, undoRedoSource: UndoRedoSource | undefined, progress: IProgress): Promise { this._logService.debug('_performTextEdits', JSON.stringify(edits)); - const model = this._instaService.createInstance(BulkTextEdits, this._label || localize('workspaceEdit', "Workspace Edit"), this._editor, undoRedoGroup, undoRedoSource, progress, edits); + const model = this._instaService.createInstance(BulkTextEdits, this._label || localize('workspaceEdit', "Workspace Edit"), this._editor, undoRedoGroup, undoRedoSource, progress, this._token, edits); await model.apply(); } private async _performCellEdits(edits: ResourceNotebookCellEdit[], undoRedoGroup: UndoRedoGroup, undoRedoSource: UndoRedoSource | undefined, progress: IProgress): Promise { this._logService.debug('_performCellEdits', JSON.stringify(edits)); - const model = this._instaService.createInstance(BulkCellEdits, undoRedoGroup, undoRedoSource, progress, edits); + const model = this._instaService.createInstance(BulkCellEdits, undoRedoGroup, undoRedoSource, progress, this._token, edits); await model.apply(); } } @@ -170,7 +172,9 @@ export class BulkEditService implements IBulkEditService { const bulkEdit = this._instaService.createInstance( BulkEdit, options?.quotableLabel || options?.label, - codeEditor, options?.progress ?? Progress.None, + codeEditor, + options?.progress ?? Progress.None, + options?.token ?? CancellationToken.None, edits, undoRedoGroup, options?.undoRedoSource diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index c1fbb07562e..b9b6516e62b 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -16,6 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { VSBuffer } from 'vs/base/common/buffer'; import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import * as resources from 'vs/base/common/resources'; +import { CancellationToken } from 'vs/base/common/cancellation'; interface IFileOperationUndoRedoInfo { undoRedoGroupId?: number; @@ -227,6 +228,7 @@ export class BulkFileEdits { private readonly _undoRedoGroup: UndoRedoGroup, private readonly _undoRedoSource: UndoRedoSource | undefined, private readonly _progress: IProgress, + private readonly _token: CancellationToken, private readonly _edits: ResourceFileEdit[], @IInstantiationService private readonly _instaService: IInstantiationService, @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, @@ -236,6 +238,11 @@ export class BulkFileEdits { const undoOperations: IFileOperation[] = []; const undoRedoInfo = { undoRedoGroupId: this._undoRedoGroup.id }; for (const edit of this._edits) { + + if (this._token.isCancellationRequested) { + break; + } + this._progress.report(undefined); const options = edit.options || {}; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts index 0dbc9ca3571..852da604343 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts @@ -19,6 +19,7 @@ import { SingleModelEditStackElement, MultiModelEditStackElement } from 'vs/edit import { ResourceMap } from 'vs/base/common/map'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; +import { CancellationToken } from 'vs/base/common/cancellation'; type ValidationResult = { canApply: true } | { canApply: false, reason: URI }; @@ -136,6 +137,7 @@ export class BulkTextEdits { private readonly _undoRedoGroup: UndoRedoGroup, private readonly _undoRedoSource: UndoRedoSource | undefined, private readonly _progress: IProgress, + private readonly _token: CancellationToken, edits: ResourceTextEdit[], @IEditorWorkerService private readonly _editorWorker: IEditorWorkerService, @IModelService private readonly _modelService: IModelService, @@ -223,6 +225,9 @@ export class BulkTextEdits { this._validateBeforePrepare(); const tasks = await this._createEditsTasks(); + if (this._token.isCancellationRequested) { + return; + } try { const validation = this._validateTasks(tasks); From 97a7e63de83fcfd0a13576af88fdb80df4c9debf Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 10:20:03 +0100 Subject: [PATCH 0245/1837] also check cancellation token in outer perform function, https://github.com/microsoft/vscode/issues/111281 --- src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index 5081e9c0587..2c0386f8ad7 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -68,6 +68,9 @@ class BulkEdit { let index = 0; for (let range of ranges) { + if (this._token.isCancellationRequested) { + break; + } const group = this._edits.slice(index, index + range); if (group[0] instanceof ResourceFileEdit) { await this._performFileEdits(group, this._undoRedoGroup, this._undoRedoSource, progress); From e6d2bd326d6ae783598e08e462862f8f1f82c7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 10:11:35 +0100 Subject: [PATCH 0246/1837] fix darwin build --- .../azure-pipelines/darwin/product-build-darwin.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 7bf941f8887..c46273cbe58 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -48,6 +48,12 @@ steps: git config user.name "VSCode" displayName: Prepare tooling + - script: | + set -e + sudo xcode-select -s /Applications/Xcode_12.2.app + displayName: Switch to Xcode 12 + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'arm64')) + - script: | set -e git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" @@ -55,12 +61,6 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro - - script: | - set -e - sudo xcode-select -s /Applications/Xcode_12.2.app - displayName: Switch to Xcode 12 - condition: eq(variables['VSCODE_ARCH'], 'arm64') - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" From 48f4109f3db1a661138c3844ca3eda8e75517732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 10:23:09 +0100 Subject: [PATCH 0247/1837] unify win32 build templates --- build/azure-pipelines/product-build.yml | 2 +- .../win32/product-build-win32-arm64.yml | 201 ------------------ .../win32/product-build-win32.yml | 27 ++- 3 files changed, 17 insertions(+), 213 deletions(-) delete mode 100644 build/azure-pipelines/win32/product-build-win32-arm64.yml diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 57c0fac5d4e..8072dc4d143 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -62,7 +62,7 @@ stages: variables: VSCODE_ARCH: arm64 steps: - - template: win32/product-build-win32-arm64.yml + - template: win32/product-build-win32.yml - stage: Linux dependsOn: diff --git a/build/azure-pipelines/win32/product-build-win32-arm64.yml b/build/azure-pipelines/win32/product-build-win32-arm64.yml deleted file mode 100644 index add2487aa9c..00000000000 --- a/build/azure-pipelines/win32/product-build-win32-arm64.yml +++ /dev/null @@ -1,201 +0,0 @@ -steps: - - powershell: | - mkdir .build -ea 0 - "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit - "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality - "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin - displayName: Prepare cache flag - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" - vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" - - - powershell: | - $ErrorActionPreference = "Stop" - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) - - - task: NodeTool@0 - inputs: - versionSpec: "12.18.3" - - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" - - - task: UsePythonVersion@0 - inputs: - versionSpec: "2.x" - addToPath: true - - - task: AzureKeyVault@1 - displayName: "Azure Key Vault: Get Secrets" - inputs: - azureSubscription: "vscode-builds-subscription" - KeyVaultName: vscode - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII - - exec { git config user.email "vscode@microsoft.com" } - exec { git config user.name "VSCode" } - - mkdir .build -ea 0 - "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch - displayName: Prepare tooling - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } - exec { git fetch distro } - exec { git merge $(node -p "require('./package.json').distro") } - displayName: Merge distro - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - . build/azure-pipelines/win32/retry.ps1 - $ErrorActionPreference = "Stop" - retry { exec { yarn --frozen-lockfile } } - env: - npm_config_arch: $(VSCODE_ARCH) - CHILD_CONCURRENCY: 1 - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn postinstall } - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { node build/azure-pipelines/mixin } - displayName: Mix in quality - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } - displayName: Build - - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - inputs: - ConnectedServiceName: "ESRP CodeSign" - FolderPath: "$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" - Pattern: "*.dll,*.exe,*.node" - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolSign", - "parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "VS Code" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "https://code.visualstudio.com/" - }, - { - "parameterName": "Append", - "parameterValue": "/as" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd \"SHA256\"" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - }, - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolVerify", - "parameters": [ - { - "parameterName": "VerifyAll", - "parameterValue": "/all" - } - ], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 120 - - - task: NuGetCommand@2 - displayName: Install ESRPClient.exe - inputs: - restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config' - feedsToUse: config - nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' - externalFeedCredentials: 3fc0b7f7-da09-4ae7-a9c8-d69824b1819b - restoreDirectory: packages - - - task: ESRPImportCertTask@1 - displayName: Import ESRP Request Signing Certificate - inputs: - ESRP: "ESRP CodeSign" - - - task: PowerShell@2 - inputs: - targetType: filePath - filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 - arguments: "$(ESRP-SSL-AADAuth)" - displayName: Import ESRP Auth Certificate - - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" - $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" - $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - .\build\azure-pipelines\win32\publish.ps1 - displayName: Publish - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: "Component Detection" - continueOnError: true diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 6c85805f49a..b6385a43b50 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -4,6 +4,7 @@ steps: "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin + "$env:VSCODE_ARCH" | Out-File -Encoding ascii -NoNewLine .build\arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -46,9 +47,6 @@ steps: exec { git config user.email "vscode@microsoft.com" } exec { git config user.name "VSCode" } - - mkdir .build -ea 0 - "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch displayName: Prepare tooling - powershell: | @@ -107,26 +105,33 @@ steps: $ErrorActionPreference = "Stop" $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } displayName: Build + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + displayName: Build Server + condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64')) + - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" exec { yarn electron $(VSCODE_ARCH) } exec { .\scripts\test.bat --build --tfs "Unit Tests" } displayName: Run unit tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" exec { yarn test-browser --build --browser chromium --browser firefox --tfs "Browser Unit Tests" } displayName: Run unit tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | # Figure out the full absolute path of the product we just built @@ -139,14 +144,14 @@ steps: $AppNameShort = $AppProductJson.nameShort exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\scripts\test-integration.bat --build --tfs "Integration Tests" } displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" exec { $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-web-integration.bat --browser firefox } displayName: Run integration tests (Browser) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | . build/azure-pipelines/win32/exec.ps1 @@ -156,7 +161,7 @@ steps: $AppNameShort = $AppProductJson.nameShort exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-remote-integration.bat } displayName: Run remote integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - task: PublishPipelineArtifact@0 inputs: @@ -171,7 +176,7 @@ steps: inputs: testResultsFiles: "*-results.xml" searchFolder: "$(Build.ArtifactStagingDirectory)/test-results" - condition: succeededOrFailed() + condition: and(succeededOrFailed(), ne(variables['VSCODE_ARCH'], 'arm64')) - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: From 9abd43315c0cf9e141f6f093ee11e89d7bcb7301 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 10:51:22 +0100 Subject: [PATCH 0248/1837] Manually release reference to piece tree when disposing (#107999) --- src/vs/editor/common/model.ts | 2 +- .../pieceTreeTextBuffer/pieceTreeTextBuffer.ts | 14 +++++++++----- src/vs/editor/common/model/textModel.ts | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 98ce23d7b0e..e41f1fdbcba 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -1327,7 +1327,7 @@ export interface IReadonlyTextBuffer { /** * @internal */ -export interface ITextBuffer extends IReadonlyTextBuffer { +export interface ITextBuffer extends IReadonlyTextBuffer, IDisposable { setEOL(newEOL: '\r\n' | '\n'): void; applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult; } diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index 62ab2929910..2401eba3b3c 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -12,7 +12,7 @@ import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTex import { SearchData } from 'vs/editor/common/model/textModelSearch'; import { countEOL, StringEOL } from 'vs/editor/common/model/tokensStore'; import { TextChange } from 'vs/editor/common/model/textChange'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; export interface IValidatedEditOperation { sortIndex: number; @@ -32,25 +32,29 @@ export interface IReverseSingleEditOperation extends IValidEditOperation { sortIndex: number; } -export class PieceTreeTextBuffer implements ITextBuffer, IDisposable { - private readonly _pieceTree: PieceTreeBase; +export class PieceTreeTextBuffer extends Disposable implements ITextBuffer { + private _pieceTree: PieceTreeBase; private readonly _BOM: string; private _mightContainRTL: boolean; private _mightContainUnusualLineTerminators: boolean; private _mightContainNonBasicASCII: boolean; - private readonly _onDidChangeContent: Emitter = new Emitter(); + private readonly _onDidChangeContent: Emitter = this._register(new Emitter()); public readonly onDidChangeContent: Event = this._onDidChangeContent.event; constructor(chunks: StringBuffer[], BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, containsUnusualLineTerminators: boolean, isBasicASCII: boolean, eolNormalized: boolean) { + super(); this._BOM = BOM; this._mightContainNonBasicASCII = !isBasicASCII; this._mightContainRTL = containsRTL; this._mightContainUnusualLineTerminators = containsUnusualLineTerminators; this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized); } + dispose(): void { - this._onDidChangeContent.dispose(); + super.dispose(); + // Manually release reference to previous piece tree to avoid large leaks + this._pieceTree = new PieceTreeBase([], '\n', true); } // #region TextBuffer diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 7c8ca731d0f..9b161cb202a 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -328,7 +328,7 @@ export class TextModel extends Disposable implements model.ITextModel { this._undoRedoService = undoRedoService; this._attachedEditorCount = 0; - this._buffer = createTextBuffer(source, creationOptions.defaultEOL); + this._buffer = this._register(createTextBuffer(source, creationOptions.defaultEOL)); this._options = TextModel.resolveOptions(this._buffer, creationOptions); From fb54cd1cd704c1c5a7427b18c0642e2dc60dd864 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 25 Nov 2020 11:18:21 +0100 Subject: [PATCH 0249/1837] Move inline actions when ports view is in the panel Part of microsoft/vscode-remote-release#4021 --- .../remote/browser/media/tunnelView.css | 26 ++++++++++++++++++- .../contrib/remote/browser/tunnelView.ts | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/media/tunnelView.css b/src/vs/workbench/contrib/remote/browser/media/tunnelView.css index 659c875492f..55776ca9962 100644 --- a/src/vs/workbench/contrib/remote/browser/media/tunnelView.css +++ b/src/vs/workbench/contrib/remote/browser/media/tunnelView.css @@ -3,6 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.customview-tree .tunnel-view-label { +.pane-body:not(.wide) .ports-view .monaco-icon-label, +.pane-body:not(.wide) .ports-view .monaco-icon-label { flex: 1; } + +.pane-body:not(.wide) .ports-view .monaco-list .monaco-list-row:hover:not(.highlighted) .monaco-icon-label, +.pane-body:not(.wide) .ports-view .monaco-list .monaco-list-row.focused .monaco-icon-label { + flex: 1; +} + +.pane-body.wide .ports-view .monaco-list .monaco-list-row .actionBarContainer, +.ports-view .monaco-list .monaco-list-row .actionBarContainer { + flex: 1 0 auto; +} + +.pane-body:not(.wide) .ports-view .monaco-list .monaco-list-row .actionBarContainer { + flex: 0 0 auto; +} + +.ports-view.actions-right .monaco-list .monaco-list-row .actionBarContainer, +.pane-body:not(.wide) .ports-view .monaco-list .monaco-list-row .actionBarContainer { + text-align: right; +} + +.pane-body.wide .ports-view .monaco-action-bar { + margin-left: 10px; +} diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index c54d3fccb2a..c1e1ae26e8a 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -518,6 +518,7 @@ export class TunnelPanel extends ViewPane { const panelContainer = dom.append(container, dom.$('.tree-explorer-viewlet-tree-view')); const treeContainer = dom.append(panelContainer, dom.$('.customview-tree')); + treeContainer.classList.add('ports-view'); treeContainer.classList.add('file-icon-themable-tree', 'show-file-icons'); const renderer = new TunnelTreeRenderer(TunnelPanel.ID, this.menuService, this.contextKeyService, this.instantiationService, this.contextViewService, this.themeService, this.remoteExplorerService); From 6e631518ab7a6555d927e3541da3dc77c9e7ce6c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 11:24:27 +0100 Subject: [PATCH 0250/1837] Extract `ReportExtensionIssueAction` to a separate file --- .../reportExtensionIssueAction.ts | 79 +++++++++++++++++++ .../runtimeExtensionsEditor.ts | 75 +----------------- 2 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts new file mode 100644 index 00000000000..3e80e98f1dd --- /dev/null +++ b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/runtimeExtensionsEditor'; +import * as nls from 'vs/nls'; +import { IProductService } from 'vs/platform/product/common/productService'; +import { Action } from 'vs/base/common/actions'; +import { IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtensionsStatus, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; +import { ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { URI } from 'vs/base/common/uri'; + +export class ReportExtensionIssueAction extends Action { + + private static readonly _id = 'workbench.extensions.action.reportExtensionIssue'; + private static readonly _label = nls.localize('reportExtensionIssue', "Report Issue"); + + private _url: string | undefined; + + constructor( + private extension: { + description: IExtensionDescription; + marketplaceInfo: IExtension; + status?: IExtensionsStatus; + unresponsiveProfile?: IExtensionHostProfile + }, + @IOpenerService private readonly openerService: IOpenerService, + @IClipboardService private readonly clipboardService: IClipboardService, + @IProductService private readonly productService: IProductService, + @INativeHostService private readonly nativeHostService: INativeHostService + ) { + super(ReportExtensionIssueAction._id, ReportExtensionIssueAction._label, 'extension-action report-issue'); + this.enabled = !!extension.description.repository && !!extension.description.repository.url; + } + + async run(): Promise { + if (!this._url) { + this._url = await this._generateNewIssueUrl(this.extension); + } + this.openerService.open(URI.parse(this._url)); + } + + private async _generateNewIssueUrl(extension: { + description: IExtensionDescription; + marketplaceInfo: IExtension; + status?: IExtensionsStatus; + unresponsiveProfile?: IExtensionHostProfile + }): Promise { + let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined; + if (!!baseUrl) { + baseUrl = `${baseUrl.indexOf('.git') !== -1 ? baseUrl.substr(0, baseUrl.length - 4) : baseUrl}/issues/new/`; + } else { + baseUrl = this.productService.reportIssueUrl!; + } + + let reason = 'Bug'; + let title = 'Extension issue'; + let message = ':warning: We have written the needed data into your clipboard. Please paste! :warning:'; + this.clipboardService.writeText('```json \n' + JSON.stringify(extension.status, null, '\t') + '\n```'); + + const os = await this.nativeHostService.getOSProperties(); + const osVersion = `${os.type} ${os.arch} ${os.release}`; + const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&'; + const body = encodeURIComponent( + `- Issue Type: \`${reason}\` +- Extension Name: \`${extension.description.name}\` +- Extension Version: \`${extension.description.version}\` +- OS Version: \`${osVersion}\` +- VSCode version: \`${this.productService.version}\`\n\n${message}` + ); + + return `${baseUrl}${queryStringPrefix}body=${body}&title=${encodeURIComponent(title)}`; + } +} diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index c775e9d0042..7061df39d4b 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -20,7 +20,6 @@ import { append, $, reset, Dimension, clearNode } from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; @@ -36,17 +35,17 @@ import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/cont import { IStorageService } from 'vs/platform/storage/common/storage'; import { ILabelService } from 'vs/platform/label/common/label'; import { renderCodicons } from 'vs/base/browser/codicons'; -import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { Schemas } from 'vs/base/common/network'; import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { domEvent } from 'vs/base/browser/event'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; +import { ReportExtensionIssueAction } from 'vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -122,10 +121,6 @@ export class RuntimeExtensionsEditor extends EditorPane { @IStorageService storageService: IStorageService, @ILabelService private readonly _labelService: ILabelService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, - @IOpenerService private readonly _openerService: IOpenerService, - @IClipboardService private readonly _clipboardService: IClipboardService, - @IProductService private readonly _productService: IProductService, - @INativeHostService private readonly _nativeHostService: INativeHostService ) { super(RuntimeExtensionsEditor.ID, telemetryService, themeService, storageService); @@ -344,7 +339,7 @@ export class RuntimeExtensionsEditor extends EditorPane { data.actionbar.push(this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile), { icon: true, label: true }); } if (isNonEmptyArray(element.status.runtimeErrors)) { - data.actionbar.push(new ReportExtensionIssueAction(element, this._openerService, this._clipboardService, this._productService, this._nativeHostService), { icon: true, label: true }); + data.actionbar.push(this._instantiationService.createInstance(ReportExtensionIssueAction, element), { icon: true, label: true }); } let title: string; @@ -459,7 +454,7 @@ export class RuntimeExtensionsEditor extends EditorPane { const actions: IAction[] = []; - actions.push(new ReportExtensionIssueAction(e.element, this._openerService, this._clipboardService, this._productService, this._nativeHostService)); + actions.push(this._instantiationService.createInstance(ReportExtensionIssueAction, e.element)); actions.push(new Separator()); actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace))); @@ -509,68 +504,6 @@ export class ShowRuntimeExtensionsAction extends Action { } } -export class ReportExtensionIssueAction extends Action { - - private static readonly _id = 'workbench.extensions.action.reportExtensionIssue'; - private static readonly _label = nls.localize('reportExtensionIssue', "Report Issue"); - - private _url: string | undefined; - - constructor( - private extension: { - description: IExtensionDescription; - marketplaceInfo: IExtension; - status?: IExtensionsStatus; - unresponsiveProfile?: IExtensionHostProfile - }, - @IOpenerService private readonly openerService: IOpenerService, - @IClipboardService private readonly clipboardService: IClipboardService, - @IProductService private readonly productService: IProductService, - @INativeHostService private readonly nativeHostService: INativeHostService - ) { - super(ReportExtensionIssueAction._id, ReportExtensionIssueAction._label, 'extension-action report-issue'); - this.enabled = !!extension.description.repository && !!extension.description.repository.url; - } - - async run(): Promise { - if (!this._url) { - this._url = await this._generateNewIssueUrl(this.extension); - } - this.openerService.open(URI.parse(this._url)); - } - - private async _generateNewIssueUrl(extension: { - description: IExtensionDescription; - marketplaceInfo: IExtension; - status?: IExtensionsStatus; - unresponsiveProfile?: IExtensionHostProfile - }): Promise { - let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined; - if (!!baseUrl) { - baseUrl = `${baseUrl.indexOf('.git') !== -1 ? baseUrl.substr(0, baseUrl.length - 4) : baseUrl}/issues/new/`; - } else { - baseUrl = this.productService.reportIssueUrl!; - } - - let reason = 'Bug'; - let title = 'Extension issue'; - let message = ':warning: We have written the needed data into your clipboard. Please paste! :warning:'; - this.clipboardService.writeText('```json \n' + JSON.stringify(extension.status, null, '\t') + '\n```'); - - const os = await this.nativeHostService.getOSProperties(); - const osVersion = `${os.type} ${os.arch} ${os.release}`; - const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&'; - const body = encodeURIComponent( - `- Issue Type: \`${reason}\` -- Extension Name: \`${extension.description.name}\` -- Extension Version: \`${extension.description.version}\` -- OS Version: \`${osVersion}\` -- VSCode version: \`${this.productService.version}\`\n\n${message}` - ); - - return `${baseUrl}${queryStringPrefix}body=${body}&title=${encodeURIComponent(title)}`; - } -} export class DebugExtensionHostAction extends Action { static readonly ID = 'workbench.extensions.action.debugExtensionHost'; From ce6f5e0f8fd7f680b7a6aa88d782715f8abf23bf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 25 Nov 2020 11:33:39 +0100 Subject: [PATCH 0251/1837] Make ports view flat when there're only forwarded ports Part of microsoft/vscode-remote-release#4021 --- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index c1e1ae26e8a..7c00838aaa8 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -368,9 +368,16 @@ class TunnelDataSource implements IAsyncDataSource 0) && (items[0].tunnelType === TunnelType.Forwarded)) { + return items; + } + } + return groups; } else if (element instanceof TunnelItem) { return []; } else if ((element).items) { From 7bbf45c14e8058fd8bedcd14ff6bb727e44db8a7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 11:38:15 +0100 Subject: [PATCH 0252/1837] env - only show one notifications not two (fix #111246) --- src/vs/code/electron-main/app.ts | 7 +++++-- src/vs/code/electron-main/auth2.ts | 3 ++- src/vs/code/electron-main/window.ts | 17 +++++++++++------ .../launch/electron-main/launchMainService.ts | 3 ++- .../platform/menubar/electron-main/menubar.ts | 5 +++-- .../platform/windows/electron-main/windows.ts | 3 ++- .../windows/electron-main/windowsMainService.ts | 9 +++++---- 7 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 7175b7a17ea..2a74fe4ed76 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -87,6 +87,7 @@ import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { isEqualOrParent } from 'vs/base/common/extpath'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -290,9 +291,11 @@ export class CodeApplication extends Disposable { // Handle slow shell environment resolve calls: // - a warning after 3s but continue to resolve // - an error after 10s and stop trying to resolve - const shellEnvSlowWarningHandle = setTimeout(() => window?.sendWhenReady('vscode:showShellEnvSlowWarning'), 3000); + const cts = new CancellationTokenSource(); + const shellEnvSlowWarningHandle = setTimeout(() => window?.sendWhenReady('vscode:showShellEnvSlowWarning', cts.token), 3000); const shellEnvTimeoutErrorHandle = setTimeout(function () { - window?.sendWhenReady('vscode:showShellEnvTimeoutError'); + cts.dispose(true); + window?.sendWhenReady('vscode:showShellEnvTimeoutError', CancellationToken.None); acceptShellEnv({}); }, 10000); diff --git a/src/vs/code/electron-main/auth2.ts b/src/vs/code/electron-main/auth2.ts index 1bce044577e..1b84d4bc4d9 100644 --- a/src/vs/code/electron-main/auth2.ts +++ b/src/vs/code/electron-main/auth2.ts @@ -13,6 +13,7 @@ import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeH import { IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService'; import { generateUuid } from 'vs/base/common/uuid'; import product from 'vs/platform/product/common/product'; +import { CancellationToken } from 'vs/base/common/cancellation'; interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails { firstAuthAttempt?: boolean; // https://github.com/electron/electron/blob/84a42a050e7d45225e69df5bd2d2bf9f1037ea41/shell/browser/login_handler.cc#L70 @@ -192,7 +193,7 @@ export class ProxyAuthHandler2 extends Disposable { password: this.sessionCredentials?.password ?? storedPassword, // prefer to show already used password (if any) over stored replyChannel: `vscode:proxyAuthResponse:${generateUuid()}` }; - window.sendWhenReady('vscode:openProxyAuthenticationDialog', payload); + window.sendWhenReady('vscode:openProxyAuthenticationDialog', CancellationToken.None, payload); this.state = ProxyAuthState.LoginDialogShown; // Handle reply diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 5b0fe508826..1968e72b9c7 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -36,6 +36,7 @@ import { IStorageMainService } from 'vs/platform/storage/node/storageMainService import { ByteSize, IFileService } from 'vs/platform/files/common/files'; import { FileAccess, Schemas } from 'vs/base/common/network'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; +import { CancellationToken } from 'vs/base/common/cancellation'; export interface IWindowCreationOptions { state: IWindowState; @@ -518,11 +519,11 @@ export class CodeWindow extends Disposable implements ICodeWindow { // Window Fullscreen this._win.on('enter-full-screen', () => { - this.sendWhenReady('vscode:enterFullScreen'); + this.sendWhenReady('vscode:enterFullScreen', CancellationToken.None); }); this._win.on('leave-full-screen', () => { - this.sendWhenReady('vscode:leaveFullScreen'); + this.sendWhenReady('vscode:leaveFullScreen', CancellationToken.None); }); // Window Failed to load @@ -1100,7 +1101,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } // Events - this.sendWhenReady(fullscreen ? 'vscode:enterFullScreen' : 'vscode:leaveFullScreen'); + this.sendWhenReady(fullscreen ? 'vscode:enterFullScreen' : 'vscode:leaveFullScreen', CancellationToken.None); // Respect configured menu bar visibility or default to toggle if not set if (this.currentMenuBarVisibility) { @@ -1241,11 +1242,15 @@ export class CodeWindow extends Disposable implements ICodeWindow { } } - sendWhenReady(channel: string, ...args: any[]): void { + sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void { if (this.isReady) { this.send(channel, ...args); } else { - this.ready().then(() => this.send(channel, ...args)); + this.ready().then(() => { + if (!token.isCancellationRequested) { + this.send(channel, ...args); + } + }); } } @@ -1295,7 +1300,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { mode: 'buttons', segmentStyle: 'automatic', change: (selectedIndex) => { - this.sendWhenReady('vscode:runAction', { id: (control.segments[selectedIndex] as ITouchBarSegment).id, from: 'touchbar' }); + this.sendWhenReady('vscode:runAction', CancellationToken.None, { id: (control.segments[selectedIndex] as ITouchBarSegment).id, from: 'touchbar' }); } }); diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 069bb585c19..2e48223e568 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -20,6 +20,7 @@ import { coalesce } from 'vs/base/common/arrays'; import { IDiagnosticInfoOptions, IDiagnosticInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { IMainProcessInfo, IWindowInfo } from 'vs/platform/launch/node/launch'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; +import { CancellationToken } from 'vs/base/common/cancellation'; export const ID = 'launchMainService'; export const ILaunchMainService = createDecorator(ID); @@ -248,7 +249,7 @@ export class LaunchMainService implements ILaunchMainService { folders: options.includeWorkspaceMetadata ? this.getFolderURIs(window) : undefined }; - window.sendWhenReady('vscode:getDiagnosticInfo', { replyChannel, args }); + window.sendWhenReady('vscode:getDiagnosticInfo', CancellationToken.None, { replyChannel, args }); ipcMain.once(replyChannel, (_: IpcEvent, data: IRemoteDiagnosticInfo) => { // No data is returned if getting the connection fails. diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index e2a0efb0bd5..90fba9c3fb1 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -24,6 +24,7 @@ import { IStateService } from 'vs/platform/state/node/state'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService'; +import { CancellationToken } from 'vs/base/common/cancellation'; const telemetryFrom = 'menu'; @@ -754,10 +755,10 @@ export class Menubar { if (invocation.type === 'commandId') { const runActionPayload: INativeRunActionInWindowRequest = { id: invocation.commandId, from: 'menu' }; - activeWindow.sendWhenReady('vscode:runAction', runActionPayload); + activeWindow.sendWhenReady('vscode:runAction', CancellationToken.None, runActionPayload); } else { const runKeybindingPayload: INativeRunKeybindingInWindowRequest = { userSettingsLabel: invocation.userSettingsLabel }; - activeWindow.sendWhenReady('vscode:runKeybinding', runKeybindingPayload); + activeWindow.sendWhenReady('vscode:runKeybinding', CancellationToken.None, runKeybindingPayload); } } else { this.logService.trace('menubar#runActionInRenderer: no active window found', invocation); diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 6359b340711..83eccca73c4 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -14,6 +14,7 @@ import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { URI } from 'vs/base/common/uri'; import { Rectangle, BrowserWindow, WebContents } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { CancellationToken } from 'vs/base/common/cancellation'; export interface IWindowState { width?: number; @@ -72,7 +73,7 @@ export interface ICodeWindow extends IDisposable { getBounds(): Rectangle; send(channel: string, ...args: any[]): void; - sendWhenReady(channel: string, ...args: any[]): void; + sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void; readonly isFullScreen: boolean; toggleFullScreen(): void; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 30f5d85c93e..74beab39da6 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -39,6 +39,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware } from 'vs/base/common/extpath'; import { CharCode } from 'vs/base/common/charCode'; import { getPathLabel } from 'vs/base/common/labels'; +import { CancellationToken } from 'vs/base/common/cancellation'; export interface IWindowState { workspace?: IWorkspaceIdentifier; @@ -758,7 +759,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic params.termProgram = configuration.userEnv['TERM_PROGRAM']; } - window.sendWhenReady('vscode:openFiles', params); + window.sendWhenReady('vscode:openFiles', CancellationToken.None, params); return window; } @@ -767,7 +768,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic window.focus(); // make sure window has focus const request: IAddFoldersRequest = { foldersToAdd }; - window.sendWhenReady('vscode:addFolders', request); + window.sendWhenReady('vscode:addFolders', CancellationToken.None, request); return window; } @@ -1679,7 +1680,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow(); if (focusedWindow) { - focusedWindow.sendWhenReady(channel, ...args); + focusedWindow.sendWhenReady(channel, CancellationToken.None, ...args); } } @@ -1689,7 +1690,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic continue; // do not send if we are instructed to ignore it } - window.sendWhenReady(channel, payload); + window.sendWhenReady(channel, CancellationToken.None, payload); } } From 221a5570b613dd610607c4c6fc5bdbd7f1b770e7 Mon Sep 17 00:00:00 2001 From: Aasim Khan Date: Wed, 25 Nov 2020 02:42:04 -0800 Subject: [PATCH 0253/1837] Fixing how escape key works in listWidget (#110760) --- src/vs/base/browser/ui/list/listWidget.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index ed8ecbed669..e530b43d36f 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -318,10 +318,12 @@ class KeyboardController implements IDisposable { } private onEscape(e: StandardKeyboardEvent): void { - e.preventDefault(); - e.stopPropagation(); - this.list.setSelection([], e.browserEvent); - this.view.domNode.focus(); + if (this.list.getSelection().length) { + e.preventDefault(); + e.stopPropagation(); + this.list.setSelection([], e.browserEvent); + this.view.domNode.focus(); + } } dispose() { From 799e72cc2fc1b0cfd1172b671fb049ccecd8a653 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 25 Nov 2020 11:44:58 +0100 Subject: [PATCH 0254/1837] Add tunnel creation options to web api --- src/vs/workbench/contrib/remote/common/tunnelFactory.ts | 6 +++--- src/vs/workbench/workbench.web.api.ts | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/remote/common/tunnelFactory.ts b/src/vs/workbench/contrib/remote/common/tunnelFactory.ts index be2b914af6f..2fab1543dfc 100644 --- a/src/vs/workbench/contrib/remote/common/tunnelFactory.ts +++ b/src/vs/workbench/contrib/remote/common/tunnelFactory.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITunnelService, TunnelOptions, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; +import { ITunnelService, TunnelOptions, RemoteTunnel, TunnelCreationOptions } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -20,8 +20,8 @@ export class TunnelFactoryContribution extends Disposable implements IWorkbenchC const tunnelFactory = environmentService.options?.tunnelProvider?.tunnelFactory; if (tunnelFactory) { this._register(tunnelService.setTunnelProvider({ - forwardPort: (tunnelOptions: TunnelOptions): Promise | undefined => { - const tunnelPromise = tunnelFactory(tunnelOptions); + forwardPort: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined => { + const tunnelPromise = tunnelFactory(tunnelOptions, tunnelCreationOptions); if (!tunnelPromise) { return undefined; } diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index fa41ddb1337..d68ec392cca 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -52,7 +52,7 @@ interface ITunnelProvider { } interface ITunnelFactory { - (tunnelOptions: ITunnelOptions, elevate?: boolean): Promise | undefined; + (tunnelOptions: ITunnelOptions, tunnelCreationOptions: TunnelCreationOptions): Promise | undefined; } interface ITunnelOptions { @@ -66,6 +66,13 @@ interface ITunnelOptions { label?: string; } +export interface TunnelCreationOptions { + /** + * True when the local operating system will require elevation to use the requested local port. + */ + elevationRequired?: boolean; +} + interface ITunnel extends IDisposable { remoteAddress: { port: number, host: string }; From bb60e21a36d0e7675b260eddee86c498162abe1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 11:47:43 +0100 Subject: [PATCH 0255/1837] fix esrp for arm64 --- build/azure-pipelines/win32/product-build-win32.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index b6385a43b50..b9fe926f1da 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -107,6 +107,7 @@ steps: exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } + echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" displayName: Build - powershell: | @@ -115,6 +116,7 @@ steps: $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(CodeSigningFolderPath),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)" displayName: Build Server condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64')) @@ -181,7 +183,7 @@ steps: - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: ConnectedServiceName: "ESRP CodeSign" - FolderPath: "$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)" + FolderPath: "$(CodeSigningFolderPath)" Pattern: "*.dll,*.exe,*.node" signConfigType: inlineSignParams inlineOperation: | From 84ce1317819a05f87e7d57cd27dbbc910b063383 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 11:52:31 +0100 Subject: [PATCH 0256/1837] Emoji characters in col 40 of an empty file causes crash (fix #111235) --- .../untitled/common/untitledTextEditorModel.ts | 10 +++++++--- .../test/browser/untitledTextEditor.test.ts | 14 +++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts index 92efe2cac0c..630443962d1 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts @@ -22,6 +22,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { getCharContainingOffset } from 'vs/base/common/strings'; export interface IUntitledTextEditorModel extends ITextEditorModel, IModeSupport, IEncodingSupport, IWorkingCopy { @@ -362,15 +363,18 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IUnt let modelFirstWordsCandidate: string | undefined = undefined; - const firstLineText = textEditorModel + let firstLineText = textEditorModel .getValueInRange({ startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: UntitledTextEditorModel.FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH + 1 // first cap at FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH }) - .trim().replace(/\s+/g, ' ') // normalize whitespaces - .substr(0, UntitledTextEditorModel.FIRST_LINE_NAME_MAX_LENGTH); // finally cap at FIRST_LINE_NAME_MAX_LENGTH + .trim().replace(/\s+/g, ' '); // normalize whitespaces + firstLineText = firstLineText.substr(0, getCharContainingOffset( // finally cap at FIRST_LINE_NAME_MAX_LENGTH (grapheme aware #111235) + firstLineText, + UntitledTextEditorModel.FIRST_LINE_NAME_MAX_LENGTH)[0] + ); if (firstLineText && ensureValidWordDefinition().exec(firstLineText)) { modelFirstWordsCandidate = firstLineText; diff --git a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts index 6e0820a85d7..2048b160bf7 100644 --- a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts +++ b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts @@ -446,10 +446,18 @@ suite('Untitled text editors', () => { assert.equal(input.getName(), '([]}hello'); assert.equal(model.name, '([]}hello'); - assert.equal(counter, 4); + model.textEditorModel.setValue('12345678901234567890123456789012345678901234567890'); // trimmed at 40chars max + assert.equal(input.getName(), '1234567890123456789012345678901234567890'); + assert.equal(model.name, '1234567890123456789012345678901234567890'); + + model.textEditorModel.setValue('123456789012345678901234567890123456789🌞'); // do not break grapehems (#111235) + assert.equal(input.getName(), '123456789012345678901234567890123456789'); + assert.equal(model.name, '123456789012345678901234567890123456789'); + + assert.equal(counter, 6); model.textEditorModel.setValue('Hello\nWorld'); - assert.equal(counter, 5); + assert.equal(counter, 7); function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation { let range = new Range( @@ -468,7 +476,7 @@ suite('Untitled text editors', () => { } model.textEditorModel.applyEdits([createSingleEditOp('hello', 2, 2)]); - assert.equal(counter, 5); // change was not on first line + assert.equal(counter, 7); // change was not on first line input.dispose(); model.dispose(); From 3ceea1784692dc6cb859c7c03883e938f4a97d4d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2020 11:53:09 +0100 Subject: [PATCH 0257/1837] npm: use project dir when using npm --- .../npm/src/features/bowerJSONContribution.ts | 12 ++++---- .../npm/src/features/jsonContributions.ts | 28 +++++++++---------- .../src/features/packageJSONContribution.ts | 28 ++++++++++--------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/extensions/npm/src/features/bowerJSONContribution.ts b/extensions/npm/src/features/bowerJSONContribution.ts index c3a827fd1e1..4fb0f0633b4 100644 --- a/extensions/npm/src/features/bowerJSONContribution.ts +++ b/extensions/npm/src/features/bowerJSONContribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MarkdownString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace } from 'vscode'; +import { MarkdownString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, Uri } from 'vscode'; import { IJSONContribution, ISuggestionsCollector } from './jsonContributions'; import { XHRRequest } from 'request-light'; import { Location } from 'jsonc-parser'; @@ -37,7 +37,7 @@ export class BowerJSONContribution implements IJSONContribution { return !!workspace.getConfiguration('npm').get('fetchOnlinePackageInfo'); } - public collectDefaultSuggestions(_resource: string, collector: ISuggestionsCollector): Thenable { + public collectDefaultSuggestions(_resource: Uri, collector: ISuggestionsCollector): Thenable { const defaultValue = { 'name': '${1:name}', 'description': '${2:description}', @@ -53,7 +53,7 @@ export class BowerJSONContribution implements IJSONContribution { return Promise.resolve(null); } - public collectPropertySuggestions(_resource: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable | null { + public collectPropertySuggestions(_resource: Uri, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable | null { if (!this.isEnabled()) { return null; } @@ -125,7 +125,7 @@ export class BowerJSONContribution implements IJSONContribution { return null; } - public collectValueSuggestions(_resource: string, location: Location, collector: ISuggestionsCollector): Promise | null { + public collectValueSuggestions(_resource: Uri, location: Location, collector: ISuggestionsCollector): Promise | null { if (!this.isEnabled()) { return null; } @@ -141,7 +141,7 @@ export class BowerJSONContribution implements IJSONContribution { return null; } - public resolveSuggestion(item: CompletionItem): Thenable | null { + public resolveSuggestion(_resource: Uri | undefined, item: CompletionItem): Thenable | null { if (item.kind === CompletionItemKind.Property && item.documentation === '') { return this.getInfo(item.label).then(documentation => { if (documentation) { @@ -182,7 +182,7 @@ export class BowerJSONContribution implements IJSONContribution { }); } - public getInfoContribution(_resource: string, location: Location): Thenable | null { + public getInfoContribution(_resource: Uri, location: Location): Thenable | null { if (!this.isEnabled()) { return null; } diff --git a/extensions/npm/src/features/jsonContributions.ts b/extensions/npm/src/features/jsonContributions.ts index 071d57b3348..3954c235168 100644 --- a/extensions/npm/src/features/jsonContributions.ts +++ b/extensions/npm/src/features/jsonContributions.ts @@ -4,14 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { Location, getLocation, createScanner, SyntaxKind, ScanError, JSONScanner } from 'jsonc-parser'; -import { basename } from 'path'; import { BowerJSONContribution } from './bowerJSONContribution'; import { PackageJSONContribution } from './packageJSONContribution'; import { XHRRequest } from 'request-light'; import { CompletionItem, CompletionItemProvider, CompletionList, TextDocument, Position, Hover, HoverProvider, - CancellationToken, Range, MarkedString, DocumentSelector, languages, Disposable + CancellationToken, Range, MarkedString, DocumentSelector, languages, Disposable, Uri } from 'vscode'; export interface ISuggestionsCollector { @@ -23,11 +22,11 @@ export interface ISuggestionsCollector { export interface IJSONContribution { getDocumentSelector(): DocumentSelector; - getInfoContribution(fileName: string, location: Location): Thenable | null; - collectPropertySuggestions(fileName: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable | null; - collectValueSuggestions(fileName: string, location: Location, result: ISuggestionsCollector): Thenable | null; - collectDefaultSuggestions(fileName: string, result: ISuggestionsCollector): Thenable; - resolveSuggestion?(item: CompletionItem): Thenable | null; + getInfoContribution(resourceUri: Uri, location: Location): Thenable | null; + collectPropertySuggestions(resourceUri: Uri, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable | null; + collectValueSuggestions(resourceUri: Uri, location: Location, result: ISuggestionsCollector): Thenable | null; + collectDefaultSuggestions(resourceUri: Uri, result: ISuggestionsCollector): Thenable; + resolveSuggestion?(resourceUri: Uri | undefined, item: CompletionItem): Thenable | null; } export function addJSONProviders(xhr: XHRRequest, canRunNPM: boolean): Disposable { @@ -47,7 +46,6 @@ export class JSONHoverProvider implements HoverProvider { } public provideHover(document: TextDocument, position: Position, _token: CancellationToken): Thenable | null { - const fileName = basename(document.fileName); const offset = document.offsetAt(position); const location = getLocation(document.getText(), offset); if (!location.previousNode) { @@ -55,7 +53,7 @@ export class JSONHoverProvider implements HoverProvider { } const node = location.previousNode; if (node && node.offset <= offset && offset <= node.offset + node.length) { - const promise = this.jsonContribution.getInfoContribution(fileName, location); + const promise = this.jsonContribution.getInfoContribution(document.uri, location); if (promise) { return promise.then(htmlContent => { const range = new Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length)); @@ -73,12 +71,14 @@ export class JSONHoverProvider implements HoverProvider { export class JSONCompletionItemProvider implements CompletionItemProvider { + private lastResource: Uri | undefined; + constructor(private jsonContribution: IJSONContribution) { } public resolveCompletionItem(item: CompletionItem, _token: CancellationToken): Thenable { if (this.jsonContribution.resolveSuggestion) { - const resolver = this.jsonContribution.resolveSuggestion(item); + const resolver = this.jsonContribution.resolveSuggestion(this.lastResource, item); if (resolver) { return resolver; } @@ -87,8 +87,8 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { } public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): Thenable | null { + this.lastResource = document.uri; - const fileName = basename(document.fileName); const currentWord = this.getCurrentWord(document, position); let overwriteRange: Range; @@ -126,12 +126,12 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { const scanner = createScanner(document.getText(), true); const addValue = !location.previousNode || !this.hasColonAfter(scanner, location.previousNode.offset + location.previousNode.length); const isLast = this.isLast(scanner, document.offsetAt(position)); - collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector); + collectPromise = this.jsonContribution.collectPropertySuggestions(document.uri, location, currentWord, addValue, isLast, collector); } else { if (location.path.length === 0) { - collectPromise = this.jsonContribution.collectDefaultSuggestions(fileName, collector); + collectPromise = this.jsonContribution.collectDefaultSuggestions(document.uri, collector); } else { - collectPromise = this.jsonContribution.collectValueSuggestions(fileName, location, collector); + collectPromise = this.jsonContribution.collectValueSuggestions(document.uri, location, collector); } } if (collectPromise) { diff --git a/extensions/npm/src/features/packageJSONContribution.ts b/extensions/npm/src/features/packageJSONContribution.ts index 7fc5475abcc..3249cb7655a 100644 --- a/extensions/npm/src/features/packageJSONContribution.ts +++ b/extensions/npm/src/features/packageJSONContribution.ts @@ -3,13 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MarkedString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, MarkdownString } from 'vscode'; +import { MarkedString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, MarkdownString, Uri } from 'vscode'; import { IJSONContribution, ISuggestionsCollector } from './jsonContributions'; import { XHRRequest } from 'request-light'; import { Location } from 'jsonc-parser'; import * as cp from 'child_process'; import * as nls from 'vscode-nls'; +import { dirname } from 'path'; const localize = nls.loadMessageBundle(); const LIMIT = 40; @@ -35,7 +36,7 @@ export class PackageJSONContribution implements IJSONContribution { public constructor(private xhr: XHRRequest, private canRunNPM: boolean) { } - public collectDefaultSuggestions(_fileName: string, result: ISuggestionsCollector): Thenable { + public collectDefaultSuggestions(_resource: Uri, result: ISuggestionsCollector): Thenable { const defaultValue = { 'name': '${1:name}', 'description': '${2:description}', @@ -60,7 +61,7 @@ export class PackageJSONContribution implements IJSONContribution { } public collectPropertySuggestions( - _resource: string, + _resource: Uri, location: Location, currentWord: string, addValue: boolean, @@ -183,7 +184,7 @@ export class PackageJSONContribution implements IJSONContribution { return Promise.resolve(null); } - public async collectValueSuggestions(_fileName: string, location: Location, result: ISuggestionsCollector): Promise { + public async collectValueSuggestions(resource: Uri, location: Location, result: ISuggestionsCollector): Promise { if (!this.isEnabled()) { return null; } @@ -191,7 +192,7 @@ export class PackageJSONContribution implements IJSONContribution { if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const currentKey = location.path[location.path.length - 1]; if (typeof currentKey === 'string') { - const info = await this.fetchPackageInfo(currentKey); + const info = await this.fetchPackageInfo(currentKey, resource); if (info && info.version) { let name = JSON.stringify(info.version); @@ -236,9 +237,9 @@ export class PackageJSONContribution implements IJSONContribution { return str; } - public resolveSuggestion(item: CompletionItem): Thenable | null { + public resolveSuggestion(resource: Uri | undefined, item: CompletionItem): Thenable | null { if (item.kind === CompletionItemKind.Property && !item.documentation) { - return this.fetchPackageInfo(item.label).then(info => { + return this.fetchPackageInfo(item.label, resource).then(info => { if (info) { item.documentation = this.getDocumentation(info.description, info.version, info.homepage); return item; @@ -266,13 +267,13 @@ export class PackageJSONContribution implements IJSONContribution { return false; } - private async fetchPackageInfo(pack: string): Promise { + private async fetchPackageInfo(pack: string, resource: Uri | undefined): Promise { if (!this.isValidNPMName(pack)) { return undefined; // avoid unnecessary lookups } let info: ViewPackageInfo | undefined; if (this.canRunNPM) { - info = await this.npmView(pack); + info = await this.npmView(pack, resource); } if (!info && this.onlineEnabled()) { info = await this.npmjsView(pack); @@ -280,10 +281,11 @@ export class PackageJSONContribution implements IJSONContribution { return info; } - private npmView(pack: string): Promise { + private npmView(pack: string, resource: Uri | undefined): Promise { return new Promise((resolve, _reject) => { const args = ['view', '--json', pack, 'description', 'dist-tags.latest', 'homepage', 'version']; - cp.execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, (error, stdout) => { + let cwd = resource && resource.scheme === 'file' ? dirname(resource.fsPath) : undefined; + cp.execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, { cwd }, (error, stdout) => { if (!error) { try { const content = JSON.parse(stdout); @@ -325,14 +327,14 @@ export class PackageJSONContribution implements IJSONContribution { return undefined; } - public getInfoContribution(_fileName: string, location: Location): Thenable | null { + public getInfoContribution(resource: Uri, location: Location): Thenable | null { if (!this.isEnabled()) { return null; } if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const pack = location.path[location.path.length - 1]; if (typeof pack === 'string') { - return this.fetchPackageInfo(pack).then(info => { + return this.fetchPackageInfo(pack, resource).then(info => { if (info) { return [this.getDocumentation(info.description, info.version, info.homepage)]; } From a15493cf905ee271761646ea81cdf59e6537ca97 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 11:51:06 +0100 Subject: [PATCH 0258/1837] Extract `DebugExtensionHostAction` to its own file --- .../debugExtensionHostAction.ts | 55 +++++++++++++++++++ .../extensions.contribution.ts | 3 +- .../runtimeExtensionsEditor.ts | 47 ---------------- 3 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts new file mode 100644 index 00000000000..bd3ea4886c1 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.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. + *--------------------------------------------------------------------------------------------*/ + +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 { 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'; +import { randomPort } from 'vs/base/node/ports'; + +export class DebugExtensionHostAction extends Action { + static readonly ID = 'workbench.extensions.action.debugExtensionHost'; + static readonly LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); + static readonly CSS_CLASS = 'debug-extension-host'; + + constructor( + @IDebugService private readonly _debugService: IDebugService, + @INativeHostService private readonly _nativeHostService: INativeHostService, + @IDialogService private readonly _dialogService: IDialogService, + @IExtensionService private readonly _extensionService: IExtensionService, + @IProductService private readonly productService: IProductService + ) { + super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS); + } + + async run(): Promise { + + const inspectPort = await this._extensionService.getInspectPort(false); + if (!inspectPort) { + const res = await this._dialogService.confirm({ + type: 'info', + message: nls.localize('restart1', "Profile Extensions"), + detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", this.productService.nameLong), + primaryButton: nls.localize('restart3', "&&Restart"), + secondaryButton: nls.localize('cancel', "&&Cancel") + }); + if (res.confirmed) { + await this._nativeHostService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] }); + } + + return; + } + + return this._debugService.startDebugging(undefined, { + type: 'node', + name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), + request: 'attach', + port: inspectPort + }); + } +} diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index bf55d0c1c1e..4af05bb491b 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -14,7 +14,8 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, DebugExtensionHostAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { DebugExtensionHostAction } from 'vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction'; import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 7061df39d4b..18c99c8c187 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -5,7 +5,6 @@ import 'vs/css!./media/runtimeExtensionsEditor'; import * as nls from 'vs/nls'; -import { IProductService } from 'vs/platform/product/common/productService'; import { Action, IAction, Separator } from 'vs/base/common/actions'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -28,9 +27,6 @@ import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; -import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; -import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { randomPort } from 'vs/base/node/ports'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ILabelService } from 'vs/platform/label/common/label'; @@ -504,49 +500,6 @@ export class ShowRuntimeExtensionsAction extends Action { } } - -export class DebugExtensionHostAction extends Action { - static readonly ID = 'workbench.extensions.action.debugExtensionHost'; - static readonly LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); - static readonly CSS_CLASS = 'debug-extension-host'; - - constructor( - @IDebugService private readonly _debugService: IDebugService, - @INativeHostService private readonly _nativeHostService: INativeHostService, - @IDialogService private readonly _dialogService: IDialogService, - @IExtensionService private readonly _extensionService: IExtensionService, - @IProductService private readonly productService: IProductService - ) { - super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS); - } - - async run(): Promise { - - const inspectPort = await this._extensionService.getInspectPort(false); - if (!inspectPort) { - const res = await this._dialogService.confirm({ - type: 'info', - message: nls.localize('restart1', "Profile Extensions"), - detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", this.productService.nameLong), - primaryButton: nls.localize('restart3', "&&Restart"), - secondaryButton: nls.localize('cancel', "&&Cancel") - }); - if (res.confirmed) { - await this._nativeHostService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] }); - } - - return; - } - - return this._debugService.startDebugging(undefined, { - type: 'node', - name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), - request: 'attach', - port: inspectPort - }); - } -} - export class StartExtensionHostProfileAction extends Action { static readonly ID = 'workbench.extensions.action.extensionHostProfile'; static readonly LABEL = nls.localize('extensionHostProfileStart', "Start Extension Host Profile"); From 72f4a2a7deec61c8c7439ed8db1155b2c1a4551c Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Wed, 25 Nov 2020 12:00:19 +0100 Subject: [PATCH 0259/1837] Fixed $REPOS macro --- .vscode/notebooks/endgame.github-issues | 2 +- .vscode/notebooks/my-endgame.github-issues | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 605197ab069..cc35e93f06e 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -8,7 +8,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/vscode \n\t repo:microsoft/vscode-internalbacklog\n\t repo:microsoft/vscode-js-debug\n\t repo:microsoft/vscode-remote-release\n\t repo:microsoft/vscode-pull-request-github\n\t repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"", + "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"", "editable": false }, { diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 7793fb88d32..5a6ae7cc7d6 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -8,7 +8,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/vscode \n\t repo:microsoft/vscode-internalbacklog\n\t repo:microsoft/vscode-js-debug\n\t repo:microsoft/vscode-remote-release\n\t repo:microsoft/vscode-pull-request-github\n\t repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"\n\n$MINE=assignee:@me", + "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server\n\n$MILESTONE=milestone:\"November 2020\"\n\n$MINE=assignee:@me", "editable": false }, { From 6dc1a9540c8fa5768b48c3355e00c7c6bba74606 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 12:15:47 +0100 Subject: [PATCH 0260/1837] "undo delete" operation recreates file contents when intital create had contents, fixes https://github.com/microsoft/vscode/issues/111162 --- src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index b9b6516e62b..285cfe309a1 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -128,7 +128,7 @@ class CreateOperation implements IFileOperation { } else { await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }); } - return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder); + return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder && !this.contents); } toString(): string { From ad8b6baef6c2da167d3a75b69576acc48352c452 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 11:57:58 +0100 Subject: [PATCH 0261/1837] Extract `SaveExtensionHostProfileAction` to a separate file --- .../extensions.contribution.ts | 3 +- .../runtimeExtensionsEditor.ts | 64 +---------------- .../saveExtensionHostProfileAction.ts | 71 +++++++++++++++++++ 3 files changed, 74 insertions(+), 64 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 4af05bb491b..0668716a02c 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -14,7 +14,8 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction'; import { DebugExtensionHostAction } from 'vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction'; import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 18c99c8c187..db07c072db1 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -21,7 +21,6 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { memoize } from 'vs/base/common/decorators'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; @@ -35,13 +34,11 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio import { Schemas } from 'vs/base/common/network'; import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { URI } from 'vs/base/common/uri'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { domEvent } from 'vs/base/browser/event'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { IFileService } from 'vs/platform/files/common/files'; -import { VSBuffer } from 'vs/base/common/buffer'; import { ReportExtensionIssueAction } from 'vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction'; +import { SaveExtensionHostProfileAction } from './saveExtensionHostProfileAction'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -534,65 +531,6 @@ export class StopExtensionHostProfileAction extends Action { } } -export class SaveExtensionHostProfileAction extends Action { - - static readonly LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); - static readonly ID = 'workbench.extensions.action.saveExtensionHostProfile'; - - constructor( - id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL, - @INativeHostService private readonly _nativeHostService: INativeHostService, - @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, - @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, - @IFileService private readonly _fileService: IFileService - ) { - super(id, label, undefined, false); - this._extensionHostProfileService.onDidChangeLastProfile(() => { - this.enabled = (this._extensionHostProfileService.lastProfile !== null); - }); - } - - run(): Promise { - return Promise.resolve(this._asyncRun()); - } - - private async _asyncRun(): Promise { - let picked = await this._nativeHostService.showSaveDialog({ - title: 'Save Extension Host Profile', - buttonLabel: 'Save', - defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`, - filters: [{ - name: 'CPU Profiles', - extensions: ['cpuprofile', 'txt'] - }] - }); - - if (!picked || !picked.filePath || picked.canceled) { - return; - } - - const profileInfo = this._extensionHostProfileService.lastProfile; - let dataToWrite: object = profileInfo ? profileInfo.data : {}; - - let savePath = picked.filePath; - - if (this._environmentService.isBuilt) { - const profiler = await import('v8-inspect-profiler'); - // when running from a not-development-build we remove - // absolute filenames because we don't want to reveal anything - // about users. We also append the `.txt` suffix to make it - // easier to attach these files to GH issues - - let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved'); - dataToWrite = tmp.profile; - - savePath = savePath + '.txt'; - } - - return this._fileService.writeFile(URI.file(savePath), VSBuffer.fromString(JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'))); - } -} - class RuntimeExtensionsEditorAccessibilityProvider implements IListAccessibilityProvider { getWidgetAriaLabel(): string { return nls.localize('runtimeExtensions', "Runtime Extensions"); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts new file mode 100644 index 00000000000..4bc156cdcf9 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts @@ -0,0 +1,71 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { Action } from 'vs/base/common/actions'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { URI } from 'vs/base/common/uri'; +import { IFileService } from 'vs/platform/files/common/files'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { IExtensionHostProfileService } from './runtimeExtensionsEditor'; + +export class SaveExtensionHostProfileAction extends Action { + + static readonly LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); + static readonly ID = 'workbench.extensions.action.saveExtensionHostProfile'; + + constructor( + id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL, + @INativeHostService private readonly _nativeHostService: INativeHostService, + @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, + @IFileService private readonly _fileService: IFileService + ) { + super(id, label, undefined, false); + this._extensionHostProfileService.onDidChangeLastProfile(() => { + this.enabled = (this._extensionHostProfileService.lastProfile !== null); + }); + } + + run(): Promise { + return Promise.resolve(this._asyncRun()); + } + + private async _asyncRun(): Promise { + let picked = await this._nativeHostService.showSaveDialog({ + title: 'Save Extension Host Profile', + buttonLabel: 'Save', + defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`, + filters: [{ + name: 'CPU Profiles', + extensions: ['cpuprofile', 'txt'] + }] + }); + + if (!picked || !picked.filePath || picked.canceled) { + return; + } + + const profileInfo = this._extensionHostProfileService.lastProfile; + let dataToWrite: object = profileInfo ? profileInfo.data : {}; + + let savePath = picked.filePath; + + if (this._environmentService.isBuilt) { + const profiler = await import('v8-inspect-profiler'); + // when running from a not-development-build we remove + // absolute filenames because we don't want to reveal anything + // about users. We also append the `.txt` suffix to make it + // easier to attach these files to GH issues + let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved'); + dataToWrite = tmp.profile; + + savePath = savePath + '.txt'; + } + + return this._fileService.writeFile(URI.file(savePath), VSBuffer.fromString(JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'))); + } +} From 2864ebf134292240da2a1457b9545e85409aa109 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Wed, 25 Nov 2020 12:08:06 +0100 Subject: [PATCH 0262/1837] Do not include iteration plans into the open issues --- .vscode/notebooks/endgame.github-issues | 2 +- .vscode/notebooks/my-endgame.github-issues | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index cc35e93f06e..fbcd551c806 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -26,7 +26,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:open", + "value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan", "editable": true }, { diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 5a6ae7cc7d6..0e8db03775c 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -26,7 +26,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:issue is:open", + "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan", "editable": true }, { From d63fee4308e1396c41b42869da1367307485f376 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 25 Nov 2020 12:40:48 +0100 Subject: [PATCH 0263/1837] Fix #111291 --- .../userDataSync/common/globalStateMerge.ts | 22 +++++++++++++++---- .../test/common/globalStateMerge.test.ts | 20 ++++++++--------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/userDataSync/common/globalStateMerge.ts b/src/vs/platform/userDataSync/common/globalStateMerge.ts index f71e40ca610..e519854a95b 100644 --- a/src/vs/platform/userDataSync/common/globalStateMerge.ts +++ b/src/vs/platform/userDataSync/common/globalStateMerge.ts @@ -32,7 +32,13 @@ export function merge(localStorage: IStringDictionary, remoteStor // Added in local for (const key of baseToLocal.added.values()) { - remote[key] = localStorage[key]; + // Skip if local was not synced before and remote also has the key + // In this case, remote gets precedence + if (!baseStorage && baseToRemote.added.has(key)) { + continue; + } else { + remote[key] = localStorage[key]; + } } // Updated in local @@ -56,11 +62,19 @@ export function merge(localStorage: IStringDictionary, remoteStor logService.info(`GlobalState: Skipped adding ${key} in local storage because it is declared as machine scoped.`); continue; } - // Skip if the value is also added in local - if (baseToLocal.added.has(key)) { + // Skip if the value is also added in local from the time it is last synced + if (baseStorage && baseToLocal.added.has(key)) { continue; } - local.added[key] = remoteValue; + const localValue = localStorage[key]; + if (localValue && localValue.value === remoteValue.value) { + continue; + } + if (localValue) { + local.updated[key] = remoteValue; + } else { + local.added[key] = remoteValue; + } } // Updated in Remote diff --git a/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts b/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts index 45230ee1929..27fb0a2353d 100644 --- a/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts +++ b/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts @@ -9,7 +9,7 @@ import { NullLogService } from 'vs/platform/log/common/log'; suite('GlobalStateMerge', () => { - test('merge when local and remote are same with one value', async () => { + test('merge when local and remote are same with one value and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'a' } }; @@ -21,7 +21,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when local and remote are same with multiple entries', async () => { + test('merge when local and remote are same with multiple entries and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; @@ -33,7 +33,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when local and remote are same with multiple entries in different order', async () => { + test('merge when local and remote are same with multiple entries in different order and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; @@ -58,7 +58,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when a new entry is added to remote', async () => { + test('merge when a new entry is added to remote and local has not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; @@ -70,7 +70,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when multiple new entries are added to remote', async () => { + test('merge when multiple new entries are added to remote and local is not synced yet', async () => { const local = {}; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; @@ -142,7 +142,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when new entries are added to local', async () => { + test('merge when new entries are added to local and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' } }; @@ -202,16 +202,16 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, local); }); - test('merge when local and remote with one entry but different value', async () => { + test('merge when local and remote with one entry but different value and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'b' } }; const actual = merge(local, remote, null, { machine: [], unregistered: [] }, new NullLogService()); assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); + assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'b' } }); assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, local); + assert.deepEqual(actual.remote, null); }); test('merge when the entry is removed in remote but updated in local and a new entry is added in remote', async () => { @@ -253,7 +253,7 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, local); }); - test('merge when a new entry is added to remote but scoped to machine locally', async () => { + test('merge when a new entry is added to remote but scoped to machine locally and local is not synced yet', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; From 182fe687b7bb4d6b11f1b162a8560c1a7c2659f7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 25 Nov 2020 12:45:53 +0100 Subject: [PATCH 0264/1837] #111291 fix tests --- .../userDataSync/test/common/userDataSyncService.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts b/src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts index 386650d6c9b..768592a3ec5 100644 --- a/src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts +++ b/src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts @@ -136,7 +136,6 @@ suite('UserDataSyncService', () => { { type: 'GET', url: `${target.url}/v1/resource/snippets/latest`, headers: {} }, { type: 'POST', url: `${target.url}/v1/resource/snippets`, headers: { 'If-Match': '1' } }, { type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} }, - { type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '1' } }, { type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} }, ]); From cda7b564e88b56c7c4c538322821e6ebb59cbdc7 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2020 13:05:31 +0100 Subject: [PATCH 0265/1837] fixes #111191 --- .../contrib/debug/browser/debugANSIHandling.ts | 12 ++++++------ src/vs/workbench/contrib/debug/browser/replViewer.ts | 12 ++++++------ .../test/electron-browser/debugANSIHandling.test.ts | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugANSIHandling.ts b/src/vs/workbench/contrib/debug/browser/debugANSIHandling.ts index 47356271445..d3cef4bbadd 100644 --- a/src/vs/workbench/contrib/debug/browser/debugANSIHandling.ts +++ b/src/vs/workbench/contrib/debug/browser/debugANSIHandling.ts @@ -7,13 +7,13 @@ import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector'; import { RGBA, Color } from 'vs/base/common/color'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ansiColorIdentifiers } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; -import { IDebugSession } from 'vs/workbench/contrib/debug/common/debug'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; /** * @param text The content to stylize. * @returns An {@link HTMLSpanElement} that contains the potentially stylized text. */ -export function handleANSIOutput(text: string, linkDetector: LinkDetector, themeService: IThemeService, debugSession: IDebugSession): HTMLSpanElement { +export function handleANSIOutput(text: string, linkDetector: LinkDetector, themeService: IThemeService, workspaceFolder: IWorkspaceFolder | undefined): HTMLSpanElement { const root: HTMLSpanElement = document.createElement('span'); const textLength: number = text.length; @@ -54,7 +54,7 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector, theme if (sequenceFound) { // Flush buffer with previous styles. - appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, debugSession, customFgColor, customBgColor); + appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, workspaceFolder, customFgColor, customBgColor); buffer = ''; @@ -100,7 +100,7 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector, theme // Flush remaining text buffer if not empty. if (buffer) { - appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, debugSession, customFgColor, customBgColor); + appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, workspaceFolder, customFgColor, customBgColor); } return root; @@ -268,7 +268,7 @@ export function appendStylizedStringToContainer( stringContent: string, cssClasses: string[], linkDetector: LinkDetector, - debugSession: IDebugSession, + workspaceFolder: IWorkspaceFolder | undefined, customTextColor?: RGBA, customBackgroundColor?: RGBA ): void { @@ -276,7 +276,7 @@ export function appendStylizedStringToContainer( return; } - const container = linkDetector.linkify(stringContent, true, debugSession.root); + const container = linkDetector.linkify(stringContent, true, workspaceFolder); container.className = cssClasses.join(' '); if (customTextColor) { diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts index 07302918462..3e1c3884994 100644 --- a/src/vs/workbench/contrib/debug/browser/replViewer.ts +++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts @@ -107,7 +107,7 @@ export class ReplGroupRenderer implements ITreeRenderer { +export class ReplEvaluationResultsRenderer implements ITreeRenderer { static readonly ID = 'replEvaluationResult'; get templateId(): string { @@ -123,7 +123,7 @@ export class ReplEvaluationResultsRenderer implements ITreeRenderer, index: number, templateData: IReplEvaluationResultTemplateData): void { + renderElement(element: ITreeNode, index: number, templateData: IReplEvaluationResultTemplateData): void { const expression = element.element; renderExpressionValue(expression, templateData.value, { showHover: false, @@ -187,7 +187,7 @@ export class ReplSimpleElementsRenderer implements ITreeRenderer { if (element instanceof Variable && element.name) { return ReplVariablesRenderer.ID; } - if (element instanceof ReplEvaluationResult) { + if (element instanceof ReplEvaluationResult || (element instanceof Variable && !element.name)) { + // Variable with no name is a top level variable which should be rendered like a repl element #17404 return ReplEvaluationResultsRenderer.ID; } if (element instanceof ReplEvaluationInput) { return ReplEvaluationInputsRenderer.ID; } - if (element instanceof SimpleReplElement || (element instanceof Variable && !element.name)) { - // Variable with no name is a top level variable which should be rendered like a repl element #17404 + if (element instanceof SimpleReplElement) { return ReplSimpleElementsRenderer.ID; } if (element instanceof ReplGroup) { diff --git a/src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts b/src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts index b56194b265d..2a915d52409 100644 --- a/src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts +++ b/src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts @@ -49,8 +49,8 @@ suite('Debug - ANSI Handling', () => { assert.equal(0, root.children.length); - appendStylizedStringToContainer(root, 'content1', ['class1', 'class2'], linkDetector, session); - appendStylizedStringToContainer(root, 'content2', ['class2', 'class3'], linkDetector, session); + appendStylizedStringToContainer(root, 'content1', ['class1', 'class2'], linkDetector, session.root); + appendStylizedStringToContainer(root, 'content2', ['class2', 'class3'], linkDetector, session.root); assert.equal(2, root.children.length); @@ -80,7 +80,7 @@ suite('Debug - ANSI Handling', () => { * @returns An {@link HTMLSpanElement} that contains the stylized text. */ function getSequenceOutput(sequence: string): HTMLSpanElement { - const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector, themeService, session); + const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector, themeService, session.root); assert.equal(1, root.children.length); const child: Node = root.lastChild!; if (child instanceof HTMLSpanElement) { @@ -320,7 +320,7 @@ suite('Debug - ANSI Handling', () => { if (elementsExpected === undefined) { elementsExpected = assertions.length; } - const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector, themeService, session); + const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector, themeService, session.root); assert.equal(elementsExpected, root.children.length); for (let i = 0; i < elementsExpected; i++) { const child: Node = root.children[i]; From d189ecf9366dd373bf27ec96e220222a48c78765 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 13:32:29 +0100 Subject: [PATCH 0266/1837] issues - check for sender being destroyed before reply --- .../issue/electron-main/issueMainService.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index ca72fa628be..f7c4d8dbc3d 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -55,7 +55,7 @@ export class IssueMainService implements ICommonIssueService { .then(result => { const [info, remoteData] = result; this.diagnosticsService.getSystemInfo(info, remoteData).then(msg => { - event.sender.send('vscode:issueSystemInfoResponse', msg); + this.safeSend(event, 'vscode:issueSystemInfoResponse', msg); }); }); }); @@ -86,7 +86,7 @@ export class IssueMainService implements ICommonIssueService { this.logService.error(`Listing processes failed: ${e}`); } - event.sender.send('vscode:listProcessesResponse', processes); + this.safeSend(event, 'vscode:listProcessesResponse', processes); }); ipcMain.on('vscode:issueReporterClipboard', (event: IpcMainEvent) => { @@ -102,14 +102,14 @@ export class IssueMainService implements ICommonIssueService { if (this._issueWindow) { this.dialogMainService.showMessageBox(messageOptions, this._issueWindow) .then(result => { - event.sender.send('vscode:issueReporterClipboardResponse', result.response === 0); + this.safeSend(event, 'vscode:issueReporterClipboardResponse', result.response === 0); }); } }); ipcMain.on('vscode:issuePerformanceInfoRequest', (event: IpcMainEvent) => { this.getPerformanceInfo().then(msg => { - event.sender.send('vscode:issuePerformanceInfoResponse', msg); + this.safeSend(event, 'vscode:issuePerformanceInfoResponse', msg); }); }); @@ -174,11 +174,17 @@ export class IssueMainService implements ICommonIssueService { ipcMain.on('vscode:windowsInfoRequest', (event: IpcMainEvent) => { this.launchMainService.getMainProcessInfo().then(info => { - event.sender.send('vscode:windowsInfoResponse', info.windows); + this.safeSend(event, 'vscode:windowsInfoResponse', info.windows); }); }); } + private safeSend(event: IpcMainEvent, channel: string, ...args: unknown[]): void { + if (!event.sender.isDestroyed()) { + event.sender.send(channel, ...args); + } + } + openReporter(data: IssueReporterData): Promise { return new Promise(_ => { if (!this._issueWindow) { From a8b6afefabde81faf16c6d39568e1f0918874673 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 13:56:49 +0100 Subject: [PATCH 0267/1837] process explorer - prevent process loops --- .../processExplorer/processExplorerMain.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts index b1883c720ec..ef93a1c528d 100644 --- a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts @@ -68,17 +68,20 @@ class ProcessExplorer { private getProcessList(rootProcess: ProcessItem, isLocal: boolean, totalMem: number): FormattedProcessItem[] { const processes: FormattedProcessItem[] = []; + const handledProcesses = new Set(); if (rootProcess) { - this.getProcessItem(processes, rootProcess, 0, isLocal, totalMem); + this.getProcessItem(processes, rootProcess, 0, isLocal, totalMem, handledProcesses); } return processes; } - private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean, totalMem: number): void { + private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean, totalMem: number, handledProcesses: Set): void { const isRoot = (indent === 0); + handledProcesses.add(item.pid); + let name = item.name; if (isRoot) { name = isLocal ? `${this.data.applicationName} main` : 'remote agent'; @@ -104,9 +107,11 @@ class ProcessExplorer { // Recurse into children if any if (Array.isArray(item.children)) { item.children.forEach(child => { - if (child) { - this.getProcessItem(processes, child, indent + 1, isLocal, totalMem); + if (!child || handledProcesses.has(child.pid)) { + return; // prevent loops } + + this.getProcessItem(processes, child, indent + 1, isLocal, totalMem, handledProcesses); }); } } From 97a896091dcc7614a98d9f9baddf40a234bfb33b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 14:00:18 +0100 Subject: [PATCH 0268/1837] remove startupPerf experiement, https://github.com/microsoft/vscode-internalbacklog/issues/1620 --- src/vs/base/node/startupPerf.d.ts | 17 ---------- src/vs/base/node/startupPerf.js | 53 ------------------------------- 2 files changed, 70 deletions(-) delete mode 100644 src/vs/base/node/startupPerf.d.ts delete mode 100644 src/vs/base/node/startupPerf.js diff --git a/src/vs/base/node/startupPerf.d.ts b/src/vs/base/node/startupPerf.d.ts deleted file mode 100644 index 18ad7e11ba3..00000000000 --- a/src/vs/base/node/startupPerf.d.ts +++ /dev/null @@ -1,17 +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 { PerformanceEntry } from 'perf_hooks'; - -/** - * Start the startup performace observer - */ -export function start(): void; - -/** - * Return all performance entries captured so far and stop startup - * performance recording. - */ -export function consumeAndStop(): PerformanceEntry[]; diff --git a/src/vs/base/node/startupPerf.js b/src/vs/base/node/startupPerf.js deleted file mode 100644 index 964d01b75c5..00000000000 --- a/src/vs/base/node/startupPerf.js +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -//@ts-check - -function _factory(sharedObj, nodeRequire) { - - let _data = sharedObj.MonacoStartupPerformanceMarks; - - if (!_data) { - _data = sharedObj.MonacoStartupPerformanceMarks = { - startupEntries: [], - observer: undefined, - }; - } - - return { - start() { - if (!_data.observer) { - const { PerformanceObserver } = nodeRequire('perf_hooks'); - const observer = new PerformanceObserver(list => { - _data.startupEntries.push(list.getEntries()); - }); - observer.observe({ buffered: true, entryTypes: ['mark'] }); - _data.observer = observer; - } - }, - consumeAndStop() { - if (_data.observer) { - const entries = [].concat(..._data.startupEntries); - _data.observer.disconnect(); - _data.startupEntries.length = 0; - return entries; - } - return []; // never started - } - }; -} - -// This module can be loaded in an amd and commonjs-context. -// Because we want both instances to use the same perf-data -// we store them globally -if (typeof define === 'function') { - // amd - define([], function () { return _factory(global, require.__$__nodeRequire); }); -} else if (typeof module === 'object' && typeof module.exports === 'object') { - // commonjs - module.exports = _factory(global, require); -} From ba867135c5faead575ec10a62ca1a9b226cba93f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 13:39:42 +0100 Subject: [PATCH 0269/1837] Extract `AbstractRuntimeExtensionsEditor` --- .../runtimeExtensionsEditor.ts | 91 +++++++++++++------ 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index db07c072db1..d822b1de660 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -38,7 +38,7 @@ import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { domEvent } from 'vs/base/browser/event'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { ReportExtensionIssueAction } from 'vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction'; -import { SaveExtensionHostProfileAction } from './saveExtensionHostProfileAction'; +import { SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -90,7 +90,7 @@ interface IRuntimeExtension { unresponsiveProfile?: IExtensionHostProfile; } -export class RuntimeExtensionsEditor extends EditorPane { +export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { public static readonly ID: string = 'workbench.editor.runtimeExtensions'; @@ -109,7 +109,7 @@ export class RuntimeExtensionsEditor extends EditorPane { @IExtensionService private readonly _extensionService: IExtensionService, @INotificationService private readonly _notificationService: INotificationService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, - @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IInstantiationService protected readonly _instantiationService: IInstantiationService, @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, @IStorageService storageService: IStorageService, @ILabelService private readonly _labelService: ILabelService, @@ -328,11 +328,15 @@ export class RuntimeExtensionsEditor extends EditorPane { data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`; data.actionbar.clear(); - if (element.unresponsiveProfile) { - data.actionbar.push(this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile), { icon: true, label: true }); + const slowExtensionAction = this._createSlowExtensionAction(element); + if (slowExtensionAction) { + data.actionbar.push(slowExtensionAction, { icon: true, label: true }); } if (isNonEmptyArray(element.status.runtimeErrors)) { - data.actionbar.push(this._instantiationService.createInstance(ReportExtensionIssueAction, element), { icon: true, label: true }); + const reportExtensionIssueAction = this._createReportExtensionIssueAction(element); + if (reportExtensionIssueAction) { + data.actionbar.push(reportExtensionIssueAction, { icon: true, label: true }); + } } let title: string; @@ -435,7 +439,14 @@ export class RuntimeExtensionsEditor extends EditorPane { overrideStyles: { listBackground: editorBackground }, - accessibilityProvider: new RuntimeExtensionsEditorAccessibilityProvider() + accessibilityProvider: new class implements IListAccessibilityProvider { + getWidgetAriaLabel(): string { + return nls.localize('runtimeExtensions', "Runtime Extensions"); + } + getAriaLabel(element: IRuntimeExtension): string | null { + return element.description.name; + } + } }); this._list.splice(0, this._list.length, this._elements || undefined); @@ -447,20 +458,25 @@ export class RuntimeExtensionsEditor extends EditorPane { const actions: IAction[] = []; - actions.push(this._instantiationService.createInstance(ReportExtensionIssueAction, e.element)); - actions.push(new Separator()); + const reportExtensionIssueAction = this._createReportExtensionIssueAction(e.element); + if (reportExtensionIssueAction) { + actions.push(reportExtensionIssueAction); + actions.push(new Separator()); + } actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace))); actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally))); actions.push(new Separator()); const state = this._extensionHostProfileService.state; - if (state === ProfileSessionState.Running) { - actions.push(this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL)); - } else { - actions.push(this._instantiationService.createInstance(StartExtensionHostProfileAction, StartExtensionHostProfileAction.ID, StartExtensionHostProfileAction.LABEL)); + const profileAction = (state === ProfileSessionState.Running ? this._createStopExtensionHostProfileAction() : this._createStartExtensionHostProfileAction()); + if (profileAction) { + actions.push(profileAction); + } + const saveExtensionHostProfileAction = this.saveExtensionHostProfileAction; + if (saveExtensionHostProfileAction) { + actions.push(saveExtensionHostProfileAction); } - actions.push(this.saveExtensionHostProfileAction); this._contextMenuService.showContextMenu({ getAnchor: () => e.anchor, @@ -470,8 +486,8 @@ export class RuntimeExtensionsEditor extends EditorPane { } @memoize - private get saveExtensionHostProfileAction(): IAction { - return this._instantiationService.createInstance(SaveExtensionHostProfileAction, SaveExtensionHostProfileAction.ID, SaveExtensionHostProfileAction.LABEL); + private get saveExtensionHostProfileAction(): IAction | null { + return this._createSaveExtensionHostProfileAction(); } public layout(dimension: Dimension): void { @@ -479,6 +495,39 @@ export class RuntimeExtensionsEditor extends EditorPane { this._list.layout(dimension.height); } } + + protected abstract _createSlowExtensionAction(element: IRuntimeExtension): Action | null; + protected abstract _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null; + protected abstract _createSaveExtensionHostProfileAction(): Action | null; + protected abstract _createStartExtensionHostProfileAction(): Action | null; + protected abstract _createStopExtensionHostProfileAction(): Action | null; +} + +export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { + + protected _createSlowExtensionAction(element: IRuntimeExtension): Action | null { + if (element.unresponsiveProfile) { + return this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile); + } + return null; + } + + protected _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null { + return this._instantiationService.createInstance(ReportExtensionIssueAction, element); + } + + protected _createSaveExtensionHostProfileAction(): Action | null { + return this._instantiationService.createInstance(SaveExtensionHostProfileAction, SaveExtensionHostProfileAction.ID, SaveExtensionHostProfileAction.LABEL); + } + + protected _createStartExtensionHostProfileAction(): Action | null { + return this._instantiationService.createInstance(StartExtensionHostProfileAction, StartExtensionHostProfileAction.ID, StartExtensionHostProfileAction.LABEL); + } + + protected _createStopExtensionHostProfileAction(): Action | null { + return this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL); + } + } export class ShowRuntimeExtensionsAction extends Action { @@ -530,13 +579,3 @@ export class StopExtensionHostProfileAction extends Action { return Promise.resolve(); } } - -class RuntimeExtensionsEditorAccessibilityProvider implements IListAccessibilityProvider { - getWidgetAriaLabel(): string { - return nls.localize('runtimeExtensions', "Runtime Extensions"); - } - - getAriaLabel(element: IRuntimeExtension): string | null { - return element.description.name; - } -} From 97f01b33e961def5b7e0d2417b7b3dae42dcf682 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 13:56:33 +0100 Subject: [PATCH 0270/1837] Move profiling related state down from `AbstractRuntimeExtensionsEditor` --- .../runtimeExtensionsEditor.ts | 105 +++++++++++------- 1 file changed, 66 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index d822b1de660..8b9093cf8df 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -95,11 +95,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { public static readonly ID: string = 'workbench.editor.runtimeExtensions'; private _list: WorkbenchList | null; - private _profileInfo: IExtensionHostProfile | null; private _elements: IRuntimeExtension[] | null; private _updateSoon: RunOnceScheduler; - private _profileSessionState: IContextKey; - private _extensionsHostRecorded: IContextKey; constructor( @ITelemetryService telemetryService: ITelemetryService, @@ -110,7 +107,6 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { @INotificationService private readonly _notificationService: INotificationService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, @IInstantiationService protected readonly _instantiationService: IInstantiationService, - @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, @IStorageService storageService: IStorageService, @ILabelService private readonly _labelService: ILabelService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, @@ -118,27 +114,14 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { super(RuntimeExtensionsEditor.ID, telemetryService, themeService, storageService); this._list = null; - this._profileInfo = this._extensionHostProfileService.lastProfile; this._elements = null; this._updateSoon = this._register(new RunOnceScheduler(() => this._updateExtensions(), 200)); - this._profileSessionState = CONTEXT_PROFILE_SESSION_STATE.bindTo(contextKeyService); - this._extensionsHostRecorded = CONTEXT_EXTENSION_HOST_PROFILE_RECORDED.bindTo(contextKeyService); - this._register(this._extensionHostProfileService.onDidChangeLastProfile(() => { - this._profileInfo = this._extensionHostProfileService.lastProfile; - this._extensionsHostRecorded.set(!!this._profileInfo); - this._updateExtensions(); - })); - this._register(this._extensionHostProfileService.onDidChangeState(() => { - const state = this._extensionHostProfileService.state; - this._profileSessionState.set(ProfileSessionState[state].toLowerCase()); - })); this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule())); - this._updateExtensions(); } - private async _updateExtensions(): Promise { + protected async _updateExtensions(): Promise { this._elements = await this._resolveExtensions(); if (this._list) { this._list.splice(0, this._list.length, this._elements); @@ -161,11 +144,12 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { // group profile segments by extension let segments: { [id: string]: number[]; } = Object.create(null); - if (this._profileInfo) { - let currentStartTime = this._profileInfo.startTime; - for (let i = 0, len = this._profileInfo.deltas.length; i < len; i++) { - const id = this._profileInfo.ids[i]; - const delta = this._profileInfo.deltas[i]; + const profileInfo = this._getProfileInfo(); + if (profileInfo) { + let currentStartTime = profileInfo.startTime; + for (let i = 0, len = profileInfo.deltas.length; i < len; i++) { + const id = profileInfo.ids[i]; + const delta = profileInfo.deltas[i]; let extensionSegments = segments[ExtensionIdentifier.toKey(id)]; if (!extensionSegments) { @@ -184,7 +168,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { const extensionDescription = extensionsDescriptions[i]; let profileInfo: IExtensionProfileInformation | null = null; - if (this._profileInfo) { + if (profileInfo) { let extensionSegments = segments[ExtensionIdentifier.toKey(extensionDescription.identifier)] || []; let extensionTotalTime = 0; for (let j = 0, lenJ = extensionSegments.length / 2; j < lenJ; j++) { @@ -204,7 +188,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { marketplaceInfo: marketplaceMap[ExtensionIdentifier.toKey(extensionDescription.identifier)], status: statusMap[extensionDescription.identifier.value], profileInfo: profileInfo || undefined, - unresponsiveProfile: this._extensionHostProfileService.getUnresponsiveProfile(extensionDescription.identifier) + unresponsiveProfile: this._getUnresponsiveProfile(extensionDescription.identifier) }; } @@ -213,7 +197,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { // bubble up extensions that have caused slowness const isUnresponsive = (extension: IRuntimeExtension): boolean => - extension.unresponsiveProfile === this._profileInfo; + extension.unresponsiveProfile === profileInfo; const profileTime = (extension: IRuntimeExtension): number => extension.profileInfo?.totalTime ?? 0; @@ -391,7 +375,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { clearNode(data.msgContainer); - if (this._extensionHostProfileService.getUnresponsiveProfile(element.description.identifier)) { + if (this._getUnresponsiveProfile(element.description.identifier)) { const el = $('span', undefined, ...renderCodicons(` $(alert) Unresponsive`)); el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze."); data.msgContainer.appendChild(el); @@ -417,7 +401,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } } - if (this._profileInfo && element.profileInfo) { + if (element.profileInfo) { data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`; } else { data.profileTime.textContent = ''; @@ -468,8 +452,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally))); actions.push(new Separator()); - const state = this._extensionHostProfileService.state; - const profileAction = (state === ProfileSessionState.Running ? this._createStopExtensionHostProfileAction() : this._createStartExtensionHostProfileAction()); + const profileAction = this._createProfileAction(); if (profileAction) { actions.push(profileAction); } @@ -496,15 +479,58 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } } + protected abstract _getProfileInfo(): IExtensionHostProfile | null; + protected abstract _getUnresponsiveProfile(extensionId: ExtensionIdentifier): IExtensionHostProfile | undefined; protected abstract _createSlowExtensionAction(element: IRuntimeExtension): Action | null; protected abstract _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null; protected abstract _createSaveExtensionHostProfileAction(): Action | null; - protected abstract _createStartExtensionHostProfileAction(): Action | null; - protected abstract _createStopExtensionHostProfileAction(): Action | null; + protected abstract _createProfileAction(): Action | null; } export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { + private _profileInfo: IExtensionHostProfile | null; + private _extensionsHostRecorded: IContextKey; + private _profileSessionState: IContextKey; + + 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, + @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, + ) { + super(telemetryService, themeService, contextKeyService, extensionsWorkbenchService, extensionService, notificationService, contextMenuService, instantiationService, storageService, labelService, environmentService); + this._profileInfo = this._extensionHostProfileService.lastProfile; + this._extensionsHostRecorded = CONTEXT_EXTENSION_HOST_PROFILE_RECORDED.bindTo(contextKeyService); + this._profileSessionState = CONTEXT_PROFILE_SESSION_STATE.bindTo(contextKeyService); + + this._register(this._extensionHostProfileService.onDidChangeLastProfile(() => { + this._profileInfo = this._extensionHostProfileService.lastProfile; + this._extensionsHostRecorded.set(!!this._profileInfo); + this._updateExtensions(); + })); + this._register(this._extensionHostProfileService.onDidChangeState(() => { + const state = this._extensionHostProfileService.state; + this._profileSessionState.set(ProfileSessionState[state].toLowerCase()); + })); + } + + protected _getProfileInfo(): IExtensionHostProfile | null { + return this._profileInfo; + } + + protected _getUnresponsiveProfile(extensionId: ExtensionIdentifier): IExtensionHostProfile | undefined { + return this._extensionHostProfileService.getUnresponsiveProfile(extensionId); + } + protected _createSlowExtensionAction(element: IRuntimeExtension): Action | null { if (element.unresponsiveProfile) { return this._instantiationService.createInstance(SlowExtensionAction, element.description, element.unresponsiveProfile); @@ -520,14 +546,15 @@ export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { return this._instantiationService.createInstance(SaveExtensionHostProfileAction, SaveExtensionHostProfileAction.ID, SaveExtensionHostProfileAction.LABEL); } - protected _createStartExtensionHostProfileAction(): Action | null { - return this._instantiationService.createInstance(StartExtensionHostProfileAction, StartExtensionHostProfileAction.ID, StartExtensionHostProfileAction.LABEL); + protected _createProfileAction(): Action | null { + const state = this._extensionHostProfileService.state; + const profileAction = ( + state === ProfileSessionState.Running + ? this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL) + : this._instantiationService.createInstance(StartExtensionHostProfileAction, StartExtensionHostProfileAction.ID, StartExtensionHostProfileAction.LABEL) + ); + return profileAction; } - - protected _createStopExtensionHostProfileAction(): Action | null { - return this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL); - } - } export class ShowRuntimeExtensionsAction extends Action { From d387fa978afced5a4b12fc7412061a52e799526b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 14:01:27 +0100 Subject: [PATCH 0271/1837] Extract `AbstractRuntimeExtensionsEditor` to separate file --- .../abstractRuntimeExtensionsEditor.ts | 456 ++++++++++++++++++ .../media/runtimeExtensionsEditor.css | 0 .../runtimeExtensionsEditor.ts | 445 +---------------- 3 files changed, 461 insertions(+), 440 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts rename src/vs/workbench/contrib/extensions/{electron-browser => browser}/media/runtimeExtensionsEditor.css (100%) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts new file mode 100644 index 00000000000..8ef5a6a5c41 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -0,0 +1,456 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/runtimeExtensionsEditor'; +import * as nls from 'vs/nls'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IInstantiationService } 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 } 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, $, reset, Dimension, clearNode } from 'vs/base/browser/dom'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { memoize } from 'vs/base/common/decorators'; +import { isNonEmptyArray } from 'vs/base/common/arrays'; +import { Event } from 'vs/base/common/event'; +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 { renderCodicons } from 'vs/base/browser/codicons'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { Schemas } from 'vs/base/common/network'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; +import { domEvent } from 'vs/base/browser/event'; +import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; + +interface IExtensionProfileInformation { + /** + * segment when the extension was running. + * 2*i = segment start time + * 2*i+1 = segment end time + */ + segments: number[]; + /** + * total time when the extension was running. + * (sum of all segment lengths). + */ + totalTime: number; +} + +export interface IRuntimeExtension { + originalIndex: number; + description: IExtensionDescription; + marketplaceInfo: IExtension; + status: IExtensionsStatus; + profileInfo?: IExtensionProfileInformation; + unresponsiveProfile?: IExtensionHostProfile; +} + +export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { + + public static readonly ID: string = 'workbench.editor.runtimeExtensions'; + + private _list: WorkbenchList | null; + private _elements: IRuntimeExtension[] | null; + private _updateSoon: RunOnceScheduler; + + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IThemeService themeService: IThemeService, + @IContextKeyService contextKeyService: IContextKeyService, + @IExtensionsWorkbenchService private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService, + @IExtensionService private readonly _extensionService: IExtensionService, + @INotificationService private readonly _notificationService: INotificationService, + @IContextMenuService private readonly _contextMenuService: IContextMenuService, + @IInstantiationService protected readonly _instantiationService: IInstantiationService, + @IStorageService storageService: IStorageService, + @ILabelService private readonly _labelService: ILabelService, + @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + ) { + super(AbstractRuntimeExtensionsEditor.ID, telemetryService, themeService, storageService); + + this._list = null; + this._elements = null; + this._updateSoon = this._register(new RunOnceScheduler(() => this._updateExtensions(), 200)); + + this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule())); + this._updateExtensions(); + } + + protected async _updateExtensions(): Promise { + this._elements = await this._resolveExtensions(); + if (this._list) { + this._list.splice(0, this._list.length, this._elements); + } + } + + private async _resolveExtensions(): Promise { + // We only deal with extensions with source code! + const extensionsDescriptions = (await this._extensionService.getExtensions()).filter((extension) => { + return Boolean(extension.main) || Boolean(extension.browser); + }); + let marketplaceMap: { [id: string]: IExtension; } = Object.create(null); + const marketPlaceExtensions = await this._extensionsWorkbenchService.queryLocal(); + for (let extension of marketPlaceExtensions) { + marketplaceMap[ExtensionIdentifier.toKey(extension.identifier.id)] = extension; + } + + let statusMap = this._extensionService.getExtensionsStatus(); + + // group profile segments by extension + let segments: { [id: string]: number[]; } = Object.create(null); + + const profileInfo = this._getProfileInfo(); + if (profileInfo) { + let currentStartTime = profileInfo.startTime; + for (let i = 0, len = profileInfo.deltas.length; i < len; i++) { + const id = profileInfo.ids[i]; + const delta = profileInfo.deltas[i]; + + let extensionSegments = segments[ExtensionIdentifier.toKey(id)]; + if (!extensionSegments) { + extensionSegments = []; + segments[ExtensionIdentifier.toKey(id)] = extensionSegments; + } + + extensionSegments.push(currentStartTime); + currentStartTime = currentStartTime + delta; + extensionSegments.push(currentStartTime); + } + } + + let result: IRuntimeExtension[] = []; + for (let i = 0, len = extensionsDescriptions.length; i < len; i++) { + const extensionDescription = extensionsDescriptions[i]; + + let profileInfo: IExtensionProfileInformation | null = null; + if (profileInfo) { + let extensionSegments = segments[ExtensionIdentifier.toKey(extensionDescription.identifier)] || []; + let extensionTotalTime = 0; + for (let j = 0, lenJ = extensionSegments.length / 2; j < lenJ; j++) { + const startTime = extensionSegments[2 * j]; + const endTime = extensionSegments[2 * j + 1]; + extensionTotalTime += (endTime - startTime); + } + profileInfo = { + segments: extensionSegments, + totalTime: extensionTotalTime + }; + } + + result[i] = { + originalIndex: i, + description: extensionDescription, + marketplaceInfo: marketplaceMap[ExtensionIdentifier.toKey(extensionDescription.identifier)], + status: statusMap[extensionDescription.identifier.value], + profileInfo: profileInfo || undefined, + unresponsiveProfile: this._getUnresponsiveProfile(extensionDescription.identifier) + }; + } + + result = result.filter(element => element.status.activationTimes); + + // bubble up extensions that have caused slowness + + const isUnresponsive = (extension: IRuntimeExtension): boolean => + extension.unresponsiveProfile === profileInfo; + + const profileTime = (extension: IRuntimeExtension): number => + extension.profileInfo?.totalTime ?? 0; + + const activationTime = (extension: IRuntimeExtension): number => + (extension.status.activationTimes?.codeLoadingTime ?? 0) + + (extension.status.activationTimes?.activateCallTime ?? 0); + + result = result.sort((a, b) => { + if (isUnresponsive(a) || isUnresponsive(b)) { + return +isUnresponsive(b) - +isUnresponsive(a); + } else if (profileTime(a) || profileTime(b)) { + return profileTime(b) - profileTime(a); + } else if (activationTime(a) || activationTime(b)) { + return activationTime(b) - activationTime(a); + } + return a.originalIndex - b.originalIndex; + }); + + return result; + } + + protected createEditor(parent: HTMLElement): void { + parent.classList.add('runtime-extensions-editor'); + + const TEMPLATE_ID = 'runtimeExtensionElementTemplate'; + + const delegate = new class implements IListVirtualDelegate{ + getHeight(element: IRuntimeExtension): number { + return 62; + } + getTemplateId(element: IRuntimeExtension): string { + return TEMPLATE_ID; + } + }; + + interface IRuntimeExtensionTemplateData { + root: HTMLElement; + element: HTMLElement; + icon: HTMLImageElement; + name: HTMLElement; + version: HTMLElement; + msgContainer: HTMLElement; + actionbar: ActionBar; + activationTime: HTMLElement; + profileTime: HTMLElement; + disposables: IDisposable[]; + elementDisposables: IDisposable[]; + } + + const renderer: IListRenderer = { + templateId: TEMPLATE_ID, + renderTemplate: (root: HTMLElement): IRuntimeExtensionTemplateData => { + const element = append(root, $('.extension')); + const iconContainer = append(element, $('.icon-container')); + const icon = append(iconContainer, $('img.icon')); + + const desc = append(element, $('div.desc')); + const headerContainer = append(desc, $('.header-container')); + const header = append(headerContainer, $('.header')); + const name = append(header, $('div.name')); + const version = append(header, $('span.version')); + + const msgContainer = append(desc, $('div.msg')); + + const actionbar = new ActionBar(desc, { animated: false }); + actionbar.onDidRun(({ error }) => error && this._notificationService.error(error)); + + + const timeContainer = append(element, $('.time')); + const activationTime = append(timeContainer, $('div.activation-time')); + const profileTime = append(timeContainer, $('div.profile-time')); + + const disposables = [actionbar]; + + return { + root, + element, + icon, + name, + version, + actionbar, + activationTime, + profileTime, + msgContainer, + disposables, + elementDisposables: [], + }; + }, + + renderElement: (element: IRuntimeExtension, index: number, data: IRuntimeExtensionTemplateData): void => { + + data.elementDisposables = dispose(data.elementDisposables); + + data.root.classList.toggle('odd', index % 2 === 1); + + const onError = Event.once(domEvent(data.icon, 'error')); + onError(() => data.icon.src = element.marketplaceInfo.iconUrlFallback, null, data.elementDisposables); + data.icon.src = element.marketplaceInfo.iconUrl; + + if (!data.icon.complete) { + data.icon.style.visibility = 'hidden'; + data.icon.onload = () => data.icon.style.visibility = 'inherit'; + } else { + data.icon.style.visibility = 'inherit'; + } + data.name.textContent = element.marketplaceInfo.displayName; + data.version.textContent = element.description.version; + + const activationTimes = element.status.activationTimes!; + let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime; + data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`; + + data.actionbar.clear(); + const slowExtensionAction = this._createSlowExtensionAction(element); + if (slowExtensionAction) { + data.actionbar.push(slowExtensionAction, { icon: true, label: true }); + } + if (isNonEmptyArray(element.status.runtimeErrors)) { + const reportExtensionIssueAction = this._createReportExtensionIssueAction(element); + if (reportExtensionIssueAction) { + data.actionbar.push(reportExtensionIssueAction, { icon: true, label: true }); + } + } + + let title: string; + const activationId = activationTimes.activationReason.extensionId.value; + const activationEvent = activationTimes.activationReason.activationEvent; + if (activationEvent === '*') { + title = nls.localize('starActivation', "Activated by {0} on start-up", activationId); + } else if (/^workspaceContains:/.test(activationEvent)) { + let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length); + if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) { + title = nls.localize({ + key: 'workspaceContainsGlobActivation', + comment: [ + '{0} will be a glob pattern' + ] + }, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId); + } else { + title = nls.localize({ + key: 'workspaceContainsFileActivation', + comment: [ + '{0} will be a file name' + ] + }, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId); + } + } else if (/^workspaceContainsTimeout:/.test(activationEvent)) { + const glob = activationEvent.substr('workspaceContainsTimeout:'.length); + title = nls.localize({ + key: 'workspaceContainsTimeout', + comment: [ + '{0} will be a glob pattern' + ] + }, "Activated by {1} because searching for {0} took too long", glob, activationId); + } else if (activationEvent === 'onStartupFinished') { + title = nls.localize({ + key: 'startupFinishedActivation', + comment: [ + 'This refers to an extension. {0} will be an activation event.' + ] + }, "Activated by {0} after start-up finished", activationId); + } else if (/^onLanguage:/.test(activationEvent)) { + let language = activationEvent.substr('onLanguage:'.length); + title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId); + } else { + title = nls.localize({ + key: 'workspaceGenericActivation', + comment: [ + 'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.' + ] + }, "Activated by {1} on {0}", activationEvent, activationId); + } + data.activationTime.title = title; + + clearNode(data.msgContainer); + + if (this._getUnresponsiveProfile(element.description.identifier)) { + const el = $('span', undefined, ...renderCodicons(` $(alert) Unresponsive`)); + el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze."); + data.msgContainer.appendChild(el); + } + + if (isNonEmptyArray(element.status.runtimeErrors)) { + const el = $('span', undefined, ...renderCodicons(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`)); + data.msgContainer.appendChild(el); + } + + if (element.status.messages && element.status.messages.length > 0) { + const el = $('span', undefined, ...renderCodicons(`$(alert) ${element.status.messages[0].message}`)); + data.msgContainer.appendChild(el); + } + + if (element.description.extensionLocation.scheme !== Schemas.file) { + const el = $('span', undefined, ...renderCodicons(`$(remote) ${element.description.extensionLocation.authority}`)); + data.msgContainer.appendChild(el); + + const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); + if (hostLabel) { + reset(el, ...renderCodicons(`$(remote) ${hostLabel}`)); + } + } + + if (element.profileInfo) { + data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`; + } else { + data.profileTime.textContent = ''; + } + + }, + + disposeTemplate: (data: IRuntimeExtensionTemplateData): void => { + data.disposables = dispose(data.disposables); + } + }; + + this._list = >this._instantiationService.createInstance(WorkbenchList, + 'RuntimeExtensions', + parent, delegate, [renderer], { + multipleSelectionSupport: false, + setRowLineHeight: false, + horizontalScrolling: false, + overrideStyles: { + listBackground: editorBackground + }, + accessibilityProvider: new class implements IListAccessibilityProvider { + getWidgetAriaLabel(): string { + return nls.localize('runtimeExtensions', "Runtime Extensions"); + } + getAriaLabel(element: IRuntimeExtension): string | null { + return element.description.name; + } + } + }); + + this._list.splice(0, this._list.length, this._elements || undefined); + + this._list.onContextMenu((e) => { + if (!e.element) { + return; + } + + const actions: IAction[] = []; + + const reportExtensionIssueAction = this._createReportExtensionIssueAction(e.element); + if (reportExtensionIssueAction) { + actions.push(reportExtensionIssueAction); + actions.push(new Separator()); + } + + actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace))); + actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally))); + actions.push(new Separator()); + + const profileAction = this._createProfileAction(); + if (profileAction) { + actions.push(profileAction); + } + const saveExtensionHostProfileAction = this.saveExtensionHostProfileAction; + if (saveExtensionHostProfileAction) { + actions.push(saveExtensionHostProfileAction); + } + + this._contextMenuService.showContextMenu({ + getAnchor: () => e.anchor, + getActions: () => actions + }); + }); + } + + @memoize + private get saveExtensionHostProfileAction(): IAction | null { + return this._createSaveExtensionHostProfileAction(); + } + + public layout(dimension: Dimension): void { + if (this._list) { + this._list.layout(dimension.height); + } + } + + protected abstract _getProfileInfo(): IExtensionHostProfile | null; + protected abstract _getUnresponsiveProfile(extensionId: ExtensionIdentifier): IExtensionHostProfile | undefined; + protected abstract _createSlowExtensionAction(element: IRuntimeExtension): Action | null; + protected abstract _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null; + protected abstract _createSaveExtensionHostProfileAction(): Action | null; + protected abstract _createProfileAction(): Action | null; +} diff --git a/src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css b/src/vs/workbench/contrib/extensions/browser/media/runtimeExtensionsEditor.css similarity index 100% rename from src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css rename to src/vs/workbench/contrib/extensions/browser/media/runtimeExtensionsEditor.css diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 8b9093cf8df..2780857cd97 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -3,42 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/runtimeExtensionsEditor'; import * as nls from 'vs/nls'; -import { Action, IAction, Separator } from 'vs/base/common/actions'; -import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; +import { Action } from 'vs/base/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IExtensionService, IExtensionsStatus, IExtensionHostProfile } 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, $, reset, Dimension, clearNode } from 'vs/base/browser/dom'; -import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { RunOnceScheduler } from 'vs/base/common/async'; -import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; +import { IExtensionService, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { memoize } from 'vs/base/common/decorators'; -import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ILabelService } from 'vs/platform/label/common/label'; -import { renderCodicons } from 'vs/base/browser/codicons'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { Schemas } from 'vs/base/common/network'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; -import { domEvent } from 'vs/base/browser/event'; -import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { ReportExtensionIssueAction } from 'vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction'; import { SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction'; +import { AbstractRuntimeExtensionsEditor, IRuntimeExtension } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -67,426 +52,6 @@ export interface IExtensionHostProfileService { setUnresponsiveProfile(extensionId: ExtensionIdentifier, profile: IExtensionHostProfile): void; } -interface IExtensionProfileInformation { - /** - * segment when the extension was running. - * 2*i = segment start time - * 2*i+1 = segment end time - */ - segments: number[]; - /** - * total time when the extension was running. - * (sum of all segment lengths). - */ - totalTime: number; -} - -interface IRuntimeExtension { - originalIndex: number; - description: IExtensionDescription; - marketplaceInfo: IExtension; - status: IExtensionsStatus; - profileInfo?: IExtensionProfileInformation; - unresponsiveProfile?: IExtensionHostProfile; -} - -export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { - - public static readonly ID: string = 'workbench.editor.runtimeExtensions'; - - private _list: WorkbenchList | null; - private _elements: IRuntimeExtension[] | null; - private _updateSoon: RunOnceScheduler; - - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IThemeService themeService: IThemeService, - @IContextKeyService contextKeyService: IContextKeyService, - @IExtensionsWorkbenchService private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService, - @IExtensionService private readonly _extensionService: IExtensionService, - @INotificationService private readonly _notificationService: INotificationService, - @IContextMenuService private readonly _contextMenuService: IContextMenuService, - @IInstantiationService protected readonly _instantiationService: IInstantiationService, - @IStorageService storageService: IStorageService, - @ILabelService private readonly _labelService: ILabelService, - @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, - ) { - super(RuntimeExtensionsEditor.ID, telemetryService, themeService, storageService); - - this._list = null; - this._elements = null; - this._updateSoon = this._register(new RunOnceScheduler(() => this._updateExtensions(), 200)); - - this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule())); - this._updateExtensions(); - } - - protected async _updateExtensions(): Promise { - this._elements = await this._resolveExtensions(); - if (this._list) { - this._list.splice(0, this._list.length, this._elements); - } - } - - private async _resolveExtensions(): Promise { - // We only deal with extensions with source code! - const extensionsDescriptions = (await this._extensionService.getExtensions()).filter((extension) => { - return Boolean(extension.main) || Boolean(extension.browser); - }); - let marketplaceMap: { [id: string]: IExtension; } = Object.create(null); - const marketPlaceExtensions = await this._extensionsWorkbenchService.queryLocal(); - for (let extension of marketPlaceExtensions) { - marketplaceMap[ExtensionIdentifier.toKey(extension.identifier.id)] = extension; - } - - let statusMap = this._extensionService.getExtensionsStatus(); - - // group profile segments by extension - let segments: { [id: string]: number[]; } = Object.create(null); - - const profileInfo = this._getProfileInfo(); - if (profileInfo) { - let currentStartTime = profileInfo.startTime; - for (let i = 0, len = profileInfo.deltas.length; i < len; i++) { - const id = profileInfo.ids[i]; - const delta = profileInfo.deltas[i]; - - let extensionSegments = segments[ExtensionIdentifier.toKey(id)]; - if (!extensionSegments) { - extensionSegments = []; - segments[ExtensionIdentifier.toKey(id)] = extensionSegments; - } - - extensionSegments.push(currentStartTime); - currentStartTime = currentStartTime + delta; - extensionSegments.push(currentStartTime); - } - } - - let result: IRuntimeExtension[] = []; - for (let i = 0, len = extensionsDescriptions.length; i < len; i++) { - const extensionDescription = extensionsDescriptions[i]; - - let profileInfo: IExtensionProfileInformation | null = null; - if (profileInfo) { - let extensionSegments = segments[ExtensionIdentifier.toKey(extensionDescription.identifier)] || []; - let extensionTotalTime = 0; - for (let j = 0, lenJ = extensionSegments.length / 2; j < lenJ; j++) { - const startTime = extensionSegments[2 * j]; - const endTime = extensionSegments[2 * j + 1]; - extensionTotalTime += (endTime - startTime); - } - profileInfo = { - segments: extensionSegments, - totalTime: extensionTotalTime - }; - } - - result[i] = { - originalIndex: i, - description: extensionDescription, - marketplaceInfo: marketplaceMap[ExtensionIdentifier.toKey(extensionDescription.identifier)], - status: statusMap[extensionDescription.identifier.value], - profileInfo: profileInfo || undefined, - unresponsiveProfile: this._getUnresponsiveProfile(extensionDescription.identifier) - }; - } - - result = result.filter(element => element.status.activationTimes); - - // bubble up extensions that have caused slowness - - const isUnresponsive = (extension: IRuntimeExtension): boolean => - extension.unresponsiveProfile === profileInfo; - - const profileTime = (extension: IRuntimeExtension): number => - extension.profileInfo?.totalTime ?? 0; - - const activationTime = (extension: IRuntimeExtension): number => - (extension.status.activationTimes?.codeLoadingTime ?? 0) + - (extension.status.activationTimes?.activateCallTime ?? 0); - - result = result.sort((a, b) => { - if (isUnresponsive(a) || isUnresponsive(b)) { - return +isUnresponsive(b) - +isUnresponsive(a); - } else if (profileTime(a) || profileTime(b)) { - return profileTime(b) - profileTime(a); - } else if (activationTime(a) || activationTime(b)) { - return activationTime(b) - activationTime(a); - } - return a.originalIndex - b.originalIndex; - }); - - return result; - } - - protected createEditor(parent: HTMLElement): void { - parent.classList.add('runtime-extensions-editor'); - - const TEMPLATE_ID = 'runtimeExtensionElementTemplate'; - - const delegate = new class implements IListVirtualDelegate{ - getHeight(element: IRuntimeExtension): number { - return 62; - } - getTemplateId(element: IRuntimeExtension): string { - return TEMPLATE_ID; - } - }; - - interface IRuntimeExtensionTemplateData { - root: HTMLElement; - element: HTMLElement; - icon: HTMLImageElement; - name: HTMLElement; - version: HTMLElement; - msgContainer: HTMLElement; - actionbar: ActionBar; - activationTime: HTMLElement; - profileTime: HTMLElement; - disposables: IDisposable[]; - elementDisposables: IDisposable[]; - } - - const renderer: IListRenderer = { - templateId: TEMPLATE_ID, - renderTemplate: (root: HTMLElement): IRuntimeExtensionTemplateData => { - const element = append(root, $('.extension')); - const iconContainer = append(element, $('.icon-container')); - const icon = append(iconContainer, $('img.icon')); - - const desc = append(element, $('div.desc')); - const headerContainer = append(desc, $('.header-container')); - const header = append(headerContainer, $('.header')); - const name = append(header, $('div.name')); - const version = append(header, $('span.version')); - - const msgContainer = append(desc, $('div.msg')); - - const actionbar = new ActionBar(desc, { animated: false }); - actionbar.onDidRun(({ error }) => error && this._notificationService.error(error)); - - - const timeContainer = append(element, $('.time')); - const activationTime = append(timeContainer, $('div.activation-time')); - const profileTime = append(timeContainer, $('div.profile-time')); - - const disposables = [actionbar]; - - return { - root, - element, - icon, - name, - version, - actionbar, - activationTime, - profileTime, - msgContainer, - disposables, - elementDisposables: [], - }; - }, - - renderElement: (element: IRuntimeExtension, index: number, data: IRuntimeExtensionTemplateData): void => { - - data.elementDisposables = dispose(data.elementDisposables); - - data.root.classList.toggle('odd', index % 2 === 1); - - const onError = Event.once(domEvent(data.icon, 'error')); - onError(() => data.icon.src = element.marketplaceInfo.iconUrlFallback, null, data.elementDisposables); - data.icon.src = element.marketplaceInfo.iconUrl; - - if (!data.icon.complete) { - data.icon.style.visibility = 'hidden'; - data.icon.onload = () => data.icon.style.visibility = 'inherit'; - } else { - data.icon.style.visibility = 'inherit'; - } - data.name.textContent = element.marketplaceInfo.displayName; - data.version.textContent = element.description.version; - - const activationTimes = element.status.activationTimes!; - let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime; - data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`; - - data.actionbar.clear(); - const slowExtensionAction = this._createSlowExtensionAction(element); - if (slowExtensionAction) { - data.actionbar.push(slowExtensionAction, { icon: true, label: true }); - } - if (isNonEmptyArray(element.status.runtimeErrors)) { - const reportExtensionIssueAction = this._createReportExtensionIssueAction(element); - if (reportExtensionIssueAction) { - data.actionbar.push(reportExtensionIssueAction, { icon: true, label: true }); - } - } - - let title: string; - const activationId = activationTimes.activationReason.extensionId.value; - const activationEvent = activationTimes.activationReason.activationEvent; - if (activationEvent === '*') { - title = nls.localize('starActivation', "Activated by {0} on start-up", activationId); - } else if (/^workspaceContains:/.test(activationEvent)) { - let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length); - if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) { - title = nls.localize({ - key: 'workspaceContainsGlobActivation', - comment: [ - '{0} will be a glob pattern' - ] - }, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId); - } else { - title = nls.localize({ - key: 'workspaceContainsFileActivation', - comment: [ - '{0} will be a file name' - ] - }, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId); - } - } else if (/^workspaceContainsTimeout:/.test(activationEvent)) { - const glob = activationEvent.substr('workspaceContainsTimeout:'.length); - title = nls.localize({ - key: 'workspaceContainsTimeout', - comment: [ - '{0} will be a glob pattern' - ] - }, "Activated by {1} because searching for {0} took too long", glob, activationId); - } else if (activationEvent === 'onStartupFinished') { - title = nls.localize({ - key: 'startupFinishedActivation', - comment: [ - 'This refers to an extension. {0} will be an activation event.' - ] - }, "Activated by {0} after start-up finished", activationId); - } else if (/^onLanguage:/.test(activationEvent)) { - let language = activationEvent.substr('onLanguage:'.length); - title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId); - } else { - title = nls.localize({ - key: 'workspaceGenericActivation', - comment: [ - 'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.' - ] - }, "Activated by {1} on {0}", activationEvent, activationId); - } - data.activationTime.title = title; - - clearNode(data.msgContainer); - - if (this._getUnresponsiveProfile(element.description.identifier)) { - const el = $('span', undefined, ...renderCodicons(` $(alert) Unresponsive`)); - el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze."); - data.msgContainer.appendChild(el); - } - - if (isNonEmptyArray(element.status.runtimeErrors)) { - const el = $('span', undefined, ...renderCodicons(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`)); - data.msgContainer.appendChild(el); - } - - if (element.status.messages && element.status.messages.length > 0) { - const el = $('span', undefined, ...renderCodicons(`$(alert) ${element.status.messages[0].message}`)); - data.msgContainer.appendChild(el); - } - - if (element.description.extensionLocation.scheme !== Schemas.file) { - const el = $('span', undefined, ...renderCodicons(`$(remote) ${element.description.extensionLocation.authority}`)); - data.msgContainer.appendChild(el); - - const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); - if (hostLabel) { - reset(el, ...renderCodicons(`$(remote) ${hostLabel}`)); - } - } - - if (element.profileInfo) { - data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`; - } else { - data.profileTime.textContent = ''; - } - - }, - - disposeTemplate: (data: IRuntimeExtensionTemplateData): void => { - data.disposables = dispose(data.disposables); - } - }; - - this._list = >this._instantiationService.createInstance(WorkbenchList, - 'RuntimeExtensions', - parent, delegate, [renderer], { - multipleSelectionSupport: false, - setRowLineHeight: false, - horizontalScrolling: false, - overrideStyles: { - listBackground: editorBackground - }, - accessibilityProvider: new class implements IListAccessibilityProvider { - getWidgetAriaLabel(): string { - return nls.localize('runtimeExtensions', "Runtime Extensions"); - } - getAriaLabel(element: IRuntimeExtension): string | null { - return element.description.name; - } - } - }); - - this._list.splice(0, this._list.length, this._elements || undefined); - - this._list.onContextMenu((e) => { - if (!e.element) { - return; - } - - const actions: IAction[] = []; - - const reportExtensionIssueAction = this._createReportExtensionIssueAction(e.element); - if (reportExtensionIssueAction) { - actions.push(reportExtensionIssueAction); - actions.push(new Separator()); - } - - actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace))); - actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally))); - actions.push(new Separator()); - - const profileAction = this._createProfileAction(); - if (profileAction) { - actions.push(profileAction); - } - const saveExtensionHostProfileAction = this.saveExtensionHostProfileAction; - if (saveExtensionHostProfileAction) { - actions.push(saveExtensionHostProfileAction); - } - - this._contextMenuService.showContextMenu({ - getAnchor: () => e.anchor, - getActions: () => actions - }); - }); - } - - @memoize - private get saveExtensionHostProfileAction(): IAction | null { - return this._createSaveExtensionHostProfileAction(); - } - - public layout(dimension: Dimension): void { - if (this._list) { - this._list.layout(dimension.height); - } - } - - protected abstract _getProfileInfo(): IExtensionHostProfile | null; - protected abstract _getUnresponsiveProfile(extensionId: ExtensionIdentifier): IExtensionHostProfile | undefined; - protected abstract _createSlowExtensionAction(element: IRuntimeExtension): Action | null; - protected abstract _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null; - protected abstract _createSaveExtensionHostProfileAction(): Action | null; - protected abstract _createProfileAction(): Action | null; -} - export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { private _profileInfo: IExtensionHostProfile | null; From 043c17ef7d320a47ef22ec80ca34e5b5afe1b75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 14:03:30 +0100 Subject: [PATCH 0272/1837] update azure cosmos :shrug: --- build/package.json | 2 +- build/yarn.lock | 198 +++++++++++---------------------------------- 2 files changed, 49 insertions(+), 151 deletions(-) diff --git a/build/package.json b/build/package.json index 188bcf0c2f4..20fc702f97d 100644 --- a/build/package.json +++ b/build/package.json @@ -60,6 +60,6 @@ "npmCheckJs": "tsc --noEmit" }, "dependencies": { - "@azure/cosmos": "^3.4.0" + "@azure/cosmos": "^3.9.3" } } diff --git a/build/yarn.lock b/build/yarn.lock index 96d7054300f..17c5c201d57 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -2,21 +2,22 @@ # yarn lockfile v1 -"@azure/cosmos@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.4.0.tgz#96f36a4522be23e1389d0516ea4d77e5fc153221" - integrity sha512-4ym+ezk7qBe4s7/tb6IJ5kmXE4xgEbAPbraT3382oeCRlYpGrblIZIDoWbthMCJfLyLBDX5T05Fhm18QeY1R/w== +"@azure/cosmos@^3.9.3": + version "3.9.3" + resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.9.3.tgz#7e95ff92e5c3e9da7e8316bc50c9cc928be6c1d6" + integrity sha512-1mh8a6LAIykz24tJvQpafXiABUfq+HSAZBFJVZXea0Rd0qG8Ia9z8AK9FtPbC1nPvDC2RID2mRIjJvYbxRM/BA== dependencies: "@types/debug" "^4.1.4" debug "^4.1.1" fast-json-stable-stringify "^2.0.0" + jsbi "^3.1.3" node-abort-controller "^1.0.4" node-fetch "^2.6.0" - os-name "^3.1.0" priorityqueuejs "^1.0.0" semaphore "^1.0.5" - tslib "^1.9.3" - uuid "^3.3.2" + tslib "^2.0.0" + universal-user-agent "^6.0.0" + uuid "^8.3.0" "@dsherret/to-absolute-glob@^2.0.2": version "2.0.2" @@ -926,17 +927,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1004,13 +994,20 @@ debug@2.X, debug@^2.6.8: dependencies: ms "2.0.0" -debug@4, debug@^4.1.1: +debug@4: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" +debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1241,19 +1238,6 @@ event-stream@3.3.4: stream-combiner "~0.0.4" through "~2.3.1" -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" @@ -1324,9 +1308,9 @@ fast-glob@^3.0.3: micromatch "^4.0.2" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fastq@^1.6.0: version "1.6.0" @@ -1441,13 +1425,6 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1922,11 +1899,6 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -1978,11 +1950,6 @@ isbinaryfile@^3.0.2: dependencies: buffer-alloc "^1.2.0" -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" @@ -1993,6 +1960,11 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +jsbi@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.4.tgz#9654dd02207a66a4911b4e4bb74265bc2cbc9dd0" + integrity sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -2216,11 +2188,6 @@ lodash@^4.15.0, lodash@^4.17.10: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== -macos-release@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" - integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== - make-error-cause@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" @@ -2338,7 +2305,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -2366,20 +2333,15 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - node-abort-controller@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.0.4.tgz#4095e41d58b2fae169d2f9892904d603e11c7a39" - integrity sha512-7cNtLKTAg0LrW3ViS2C7UfIzbL3rZd8L0++5MidbKqQVJ8yrH6+1VRSHl33P0ZjBTbOJd37d9EYekvHyKkB0QQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.1.0.tgz#8a734a631b022af29963be7245c1483cbb9e070d" + integrity sha512-dEYmUqjtbivotqjraOe8UvhT/poFfog1BQRNsZm/MSEDDESk2cQ1tvD8kGyuN07TM/zoW+n42odL8zTeJupYdQ== node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" @@ -2395,13 +2357,6 @@ now-and-later@^2.0.0: dependencies: once "^1.3.2" -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -2476,14 +2431,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-name@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" - integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== - dependencies: - macos-release "^2.2.0" - windows-release "^3.1.0" - os-tmpdir@^1.0.0, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -2497,11 +2444,6 @@ osenv@^0.1.3: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -2555,11 +2497,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -2662,14 +2599,6 @@ pump@^2.0.0: end-of-stream "^1.1.0" once "^1.3.1" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pumpify@^1.3.5: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" @@ -2971,11 +2900,6 @@ semver@^5.1.0, semver@^5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== -semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -2986,23 +2910,6 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3175,11 +3082,6 @@ strip-bom@2.X: dependencies: is-utf8 "^0.2.0" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -3307,10 +3209,10 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslib@^1.9.3: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== tsutils@^3.17.1: version "3.17.1" @@ -3395,6 +3297,11 @@ unique-stream@^2.0.2: json-stable-stringify-without-jsonify "^1.0.1" through2-filter "^3.0.0" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -3433,9 +3340,14 @@ uuid@^3.1.0: integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" + integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== validator@~3.35.0: version "3.35.0" @@ -3589,20 +3501,6 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -windows-release@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" - integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA== - dependencies: - execa "^1.0.0" - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" From 37274abda92637865331f089313e79c421bec223 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 14:47:56 +0100 Subject: [PATCH 0273/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2468a6dbbde..482ac3072d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "4efc01d229d8c6ca0a14e80b89c7587fcb6cb59b", + "distro": "7acf21eaff37c77f31a9174a64954ef71b484f1e", "author": { "name": "Microsoft Corporation" }, From a59aa579b6be7e03c87be56c67a040699704291d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2020 14:52:07 +0100 Subject: [PATCH 0274/1837] fix debug toolbar colors --- .../contrib/debug/browser/debugToolBar.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 539e95ceb4f..5caea036d1b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -367,36 +367,36 @@ registerThemingParticipant((theme, collector) => { const debugIconDisconnectColor = theme.getColor(debugIconDisconnectForeground); if (debugIconDisconnectColor) { - collector.addRule(`.monaco-workbench .debug-view-content ${icons.debugDisconnect.cssSelector}, .monaco-workbench .debug-toolbar ${icons.debugDisconnect.cssSelector}, { color: ${debugIconDisconnectColor} !important; }`); + collector.addRule(`.monaco-workbench .debug-view-content ${icons.debugDisconnect.cssSelector}, .monaco-workbench .debug-toolbar ${icons.debugDisconnect.cssSelector} { color: ${debugIconDisconnectColor} !important; }`); } const debugIconRestartColor = theme.getColor(debugIconRestartForeground); if (debugIconRestartColor) { - collector.addRule(`.monaco-workbench ${icons.debugRestart.cssSelector},, .monaco-workbench ${icons.debugRestartFrame.cssSelector}, { color: ${debugIconRestartColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugRestart.cssSelector}, .monaco-workbench ${icons.debugRestartFrame.cssSelector} { color: ${debugIconRestartColor} !important; }`); } const debugIconStepOverColor = theme.getColor(debugIconStepOverForeground); if (debugIconStepOverColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepOver.cssSelector}, { color: ${debugIconStepOverColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepOver.cssSelector} { color: ${debugIconStepOverColor} !important; }`); } const debugIconStepIntoColor = theme.getColor(debugIconStepIntoForeground); if (debugIconStepIntoColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepInto.cssSelector}, { color: ${debugIconStepIntoColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepInto.cssSelector} { color: ${debugIconStepIntoColor} !important; }`); } const debugIconStepOutColor = theme.getColor(debugIconStepOutForeground); if (debugIconStepOutColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepOut.cssSelector}, { color: ${debugIconStepOutColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepOut.cssSelector} { color: ${debugIconStepOutColor} !important; }`); } const debugIconContinueColor = theme.getColor(debugIconContinueForeground); if (debugIconContinueColor) { - collector.addRule(`.monaco-workbench ${icons.debugContinue.cssSelector},,.monaco-workbench ${icons.debugReverseContinue.cssSelector}, { color: ${debugIconContinueColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugContinue.cssSelector}, .monaco-workbench ${icons.debugReverseContinue.cssSelector} { color: ${debugIconContinueColor} !important; }`); } const debugIconStepBackColor = theme.getColor(debugIconStepBackForeground); if (debugIconStepBackColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepBack.cssSelector}, { color: ${debugIconStepBackColor} !important; }`); + collector.addRule(`.monaco-workbench ${icons.debugStepBack.cssSelector} { color: ${debugIconStepBackColor} !important; }`); } }); From a500715422eef4eb63a7b384f0424e542aadc24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 14:56:13 +0100 Subject: [PATCH 0275/1837] fix terrapin order --- .../azure-pipelines/darwin/product-build-darwin.yml | 12 ++++++------ build/azure-pipelines/linux/product-build-alpine.yml | 12 ++++++------ build/azure-pipelines/linux/product-build-linux.yml | 12 ++++++------ build/azure-pipelines/product-compile.yml | 2 +- build/azure-pipelines/web/product-build-web.yml | 12 ++++++------ build/azure-pipelines/win32/product-build-win32.yml | 6 ------ 6 files changed, 25 insertions(+), 31 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index c46273cbe58..3da70b5e6ae 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -61,18 +61,18 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - script: | set -e npm install -g node-gyp@7.1.0 diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index ffbe5b6c1bc..e24b479c648 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -64,18 +64,18 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index f0738e1b6f5..ed048f0693d 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -54,18 +54,18 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index a8985ab34a1..8995a5f6031 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -58,7 +58,7 @@ steps: npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true'), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index dc8eed5a45f..7afbb85952b 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -54,18 +54,18 @@ steps: git merge $(node -p "require('./package.json').distro") displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index b9fe926f1da..280da3224e1 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -63,12 +63,6 @@ steps: targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheRestored'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - powershell: | . build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/retry.ps1 From aa91d0455227746297f6df2c7ba631efab662a3b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 15:20:05 +0100 Subject: [PATCH 0276/1837] add cancellation token to working copy service and hook it up with file operation participants --- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 24 +++++------ .../workingCopyFileOperationParticipant.ts | 6 +-- .../common/workingCopyFileService.ts | 42 +++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 285cfe309a1..d197df7f654 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -25,7 +25,7 @@ interface IFileOperationUndoRedoInfo { interface IFileOperation { uris: URI[]; - perform(): Promise; + perform(token: CancellationToken): Promise; } class Noop implements IFileOperation { @@ -51,13 +51,13 @@ class RenameOperation implements IFileOperation { return [this.newUri, this.oldUri]; } - async perform(): Promise { + async perform(token: CancellationToken): Promise { // rename if (this.options.overwrite === undefined && this.options.ignoreIfExists && await this._fileService.exists(this.newUri)) { return new Noop(); // not overwriting, but ignoring, and the target file exists } - await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }); + await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token); return new RenameOperation(this.oldUri, this.newUri, this.options, { isUndoing: true }, this._workingCopyFileService, this._fileService); } @@ -87,13 +87,13 @@ class CopyOperation implements IFileOperation { return [this.newUri, this.oldUri]; } - async perform(): Promise { + async perform(token: CancellationToken): Promise { // copy if (this.options.overwrite === undefined && this.options.ignoreIfExists && await this._fileService.exists(this.newUri)) { return new Noop(); // not overwriting, but ignoring, and the target file exists } - await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }); + await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token); return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, true); } @@ -118,15 +118,15 @@ class CreateOperation implements IFileOperation { return [this.newUri]; } - async perform(): Promise { + async perform(token: CancellationToken): Promise { // create file if (this.options.overwrite === undefined && this.options.ignoreIfExists && await this._fileService.exists(this.newUri)) { return new Noop(); // not overwriting, but ignoring, and the target file exists } if (this.options.folder) { - await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo }); + await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo }, token); } else { - await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }); + await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token); } return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder && !this.contents); } @@ -155,7 +155,7 @@ class DeleteOperation implements IFileOperation { return [this.oldUri]; } - async perform(): Promise { + async perform(token: CancellationToken): Promise { // delete file if (!await this._fileService.exists(this.oldUri)) { if (!this.options.ignoreIfNotExists) { @@ -174,7 +174,7 @@ class DeleteOperation implements IFileOperation { } const useTrash = !this.options.skipTrashBin && this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); - await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }); + await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }, token); if (typeof this.options.maxSize === 'number' && fileContent && (fileContent?.size > this.options.maxSize)) { return new Noop(); @@ -211,7 +211,7 @@ class FileUndoRedoElement implements IWorkspaceUndoRedoElement { private async _reverse() { for (let i = 0; i < this.operations.length; i++) { const op = this.operations[i]; - const undo = await op.perform(); + const undo = await op.perform(CancellationToken.None); this.operations[i] = undo; } } @@ -260,7 +260,7 @@ export class BulkFileEdits { op = this._instaService.createInstance(CreateOperation, edit.newResource, options, undoRedoInfo, undefined); } if (op) { - const undoOp = await op.perform(); + const undoOp = await op.perform(this._token); undoOperations.push(undoOp); } } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index c1b2b911baf..f4b04294ed3 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { raceCancellation } from 'vs/base/common/async'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -32,13 +32,13 @@ export class WorkingCopyFileOperationParticipant extends Disposable { return toDisposable(() => remove()); } - async participate(files: { source?: URI, target: URI }[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise { + async participate(files: { source?: URI, target: URI }[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, token: CancellationToken | undefined): Promise { const timeout = this.configurationService.getValue('files.participants.timeout'); if (timeout <= 0) { return; // disabled } - const cts = new CancellationTokenSource(); + const cts = new CancellationTokenSource(token); const timer = setTimeout(() => cts.cancel(), timeout); return this.progressService.withProgress({ diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 568268969e1..0e78557503d 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -132,7 +132,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; + create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; /** * Will create a folder and any parent folder that needs to be created. @@ -143,7 +143,7 @@ export interface IWorkingCopyFileService { * Note: events will only be emitted for the provided resource, but not any * parent folders that are being created as part of the operation. */ - createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }): Promise; + createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; /** * Will move working copies matching the provided resources and corresponding children @@ -152,7 +152,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; + move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; /** * Will copy working copies matching the provided resources and corresponding children @@ -161,7 +161,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; + copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; /** * Will delete working copies matching the provided resources and children @@ -170,7 +170,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise; + delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; //#endregion @@ -239,15 +239,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi //#region File operations - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { - return this.doCreateFileOrFolder(resource, true, contents, options); + create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { + return this.doCreateFileOrFolder(resource, true, contents, options, token); } - createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { - return this.doCreateFileOrFolder(resource, false, undefined, options); + createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { + return this.doCreateFileOrFolder(resource, false, undefined, options, token); } - async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { + async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { // validate create operation before starting if (isFile) { @@ -258,7 +258,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi } // file operation participant - await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options?.undoRedoGroupId, options?.isUndoing); + await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options?.undoRedoGroupId, options?.isUndoing, token); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] }; @@ -286,15 +286,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stat; } - async move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { - return this.doMoveOrCopy(files, true, options); + async move(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { + return this.doMoveOrCopy(files, true, options, token); } - async copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { - return this.doMoveOrCopy(files, false, options); + async copy(files: Required[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { + return this.doMoveOrCopy(files, false, options, token); } - private async doMoveOrCopy(files: Required[], move: boolean, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { + private async doMoveOrCopy(files: Required[], move: boolean, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { const overwrite = options?.overwrite; const stats: IFileStatWithMetadata[] = []; @@ -307,7 +307,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi } // file operation participant - await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, options?.undoRedoGroupId, options?.isUndoing); + await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, options?.undoRedoGroupId, options?.isUndoing, token); // before event const event = { correlationId: this.correlationIds++, operation: move ? FileOperation.MOVE : FileOperation.COPY, files }; @@ -346,7 +346,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stats; } - async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise { + async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { // validate delete operation before starting for (const resource of resources) { @@ -358,7 +358,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi // file operation participant const files = resources.map(target => ({ target })); - await this.runFileOperationParticipants(files, FileOperation.DELETE, options?.undoRedoGroupId, options?.isUndoing); + await this.runFileOperationParticipants(files, FileOperation.DELETE, options?.undoRedoGroupId, options?.isUndoing, token); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.DELETE, files }; @@ -400,8 +400,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return this.fileOperationParticipants.addFileOperationParticipant(participant); } - private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise { - return this.fileOperationParticipants.participate(files, operation, undoRedoGroupId, isUndoing); + private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, token: CancellationToken | undefined): Promise { + return this.fileOperationParticipants.participate(files, operation, undoRedoGroupId, isUndoing, token); } //#endregion From e3e2837476ef5570e6e3f1aeee66e6b1fd8d126f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 15:24:26 +0100 Subject: [PATCH 0277/1837] Bring Running Extensions to the web --- .../abstractRuntimeExtensionsEditor.ts | 18 +++++ .../browser/browserRuntimeExtensionsEditor.ts | 62 ++++++++++++++ .../browser/extensions.contribution.ts | 9 ++- .../browser/extensions.web.contribution.ts | 17 ++++ .../extensions.contribution.ts | 18 ++--- .../reportExtensionIssueAction.ts | 1 - .../runtimeExtensionsEditor.ts | 81 ++++++++++++++----- .../saveExtensionHostProfileAction.ts | 71 ---------------- src/vs/workbench/workbench.web.main.ts | 3 + 9 files changed, 174 insertions(+), 106 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts create mode 100644 src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.ts delete mode 100644 src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index 8ef5a6a5c41..a00d0ce22bb 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -34,6 +34,8 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { domEvent } from 'vs/base/browser/event'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; interface IExtensionProfileInformation { /** @@ -454,3 +456,19 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { protected abstract _createSaveExtensionHostProfileAction(): Action | null; protected abstract _createProfileAction(): Action | null; } + +export class ShowRuntimeExtensionsAction extends Action { + static readonly ID = 'workbench.action.showRuntimeExtensions'; + static readonly LABEL = nls.localize('showRuntimeExtensions', "Show Running Extensions"); + + constructor( + id: string, label: string, + @IEditorService private readonly _editorService: IEditorService + ) { + super(id, label); + } + + public async run(e?: any): Promise { + await this._editorService.openEditor(RuntimeExtensionsInput.instance, { revealIfOpened: true, pinned: true }); + } +} diff --git a/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts new file mode 100644 index 00000000000..a3b1e809050 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +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 { 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; + } + + protected _getUnresponsiveProfile(extensionId: ExtensionIdentifier): IExtensionHostProfile | undefined { + return undefined; + } + + protected _createSlowExtensionAction(element: IRuntimeExtension): Action | null { + return null; + } + + protected _createReportExtensionIssueAction(element: IRuntimeExtension): Action | null { + return null; + } + + protected _createSaveExtensionHostProfileAction(): Action | null { + return null; + } + + protected _createProfileAction(): Action | null { + return null; + } +} diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 0435d1b1325..36676ca8bb2 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { Registry } from 'vs/platform/registry/common/platform'; -import { MenuRegistry, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; +import { MenuRegistry, MenuId, registerAction2, Action2, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionsLabel, ExtensionsLocalizedLabel, ExtensionsChannelId, IExtensionManagementService, IExtensionGalleryService, PreferencesLocalizedLabel } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -54,7 +54,7 @@ import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys'; -import { CATEGORIES } from 'vs/workbench/common/actions'; +import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; import { IExtensionRecommendationNotificationService } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { ExtensionRecommendationNotificationService } from 'vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService'; import { IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; @@ -65,6 +65,7 @@ import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ShowRuntimeExtensionsAction } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -1176,3 +1177,7 @@ workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContributi workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInstaller, LifecyclePhase.Eventually); + +// Running Extensions +const actionRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); +actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ShowRuntimeExtensionsAction), 'Show Running Extensions', CATEGORIES.Developer.value); diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.ts new file mode 100644 index 00000000000..f5d4587b748 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; +import { RuntimeExtensionsEditor } from 'vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor'; +import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; + +// Running Extensions +Registry.as(EditorExtensions.Editors).registerEditor( + EditorDescriptor.create(RuntimeExtensionsEditor, RuntimeExtensionsEditor.ID, localize('runtimeExtension', "Running Extensions")), + [new SyncDescriptor(RuntimeExtensionsInput)] +); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 0668716a02c..a472654f086 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -7,15 +7,14 @@ import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; +import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; -import { SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction'; +import { RuntimeExtensionsEditor, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED, SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; import { DebugExtensionHostAction } from 'vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction'; import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; @@ -37,16 +36,11 @@ const workbenchRegistry = Registry.as(Workbench workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, LifecyclePhase.Eventually); // Running Extensions Editor - -const runtimeExtensionsEditorDescriptor = EditorDescriptor.create( - RuntimeExtensionsEditor, - RuntimeExtensionsEditor.ID, - localize('runtimeExtension', "Running Extensions") +Registry.as(EditorExtensions.Editors).registerEditor( + EditorDescriptor.create(RuntimeExtensionsEditor, RuntimeExtensionsEditor.ID, localize('runtimeExtension', "Running Extensions")), + [new SyncDescriptor(RuntimeExtensionsInput)] ); -Registry.as(EditorExtensions.Editors) - .registerEditor(runtimeExtensionsEditorDescriptor, [new SyncDescriptor(RuntimeExtensionsInput)]); - class RuntimeExtensionsInputFactory implements IEditorInputFactory { canSerialize(editorInput: EditorInput): boolean { return true; @@ -65,8 +59,6 @@ Registry.as(EditorInputExtensions.EditorInputFactor // Global actions const actionRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); -actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ShowRuntimeExtensionsAction), 'Show Running Extensions', CATEGORIES.Developer.value); - class ExtensionsContributions implements IWorkbenchContribution { constructor( diff --git a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts index 3e80e98f1dd..faf606a75e0 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/runtimeExtensionsEditor'; import * as nls from 'vs/nls'; import { IProductService } from 'vs/platform/product/common/productService'; import { Action } from 'vs/base/common/actions'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 2780857cd97..8aba9dd18a1 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -9,12 +9,10 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IExtensionService, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ILabelService } from 'vs/platform/label/common/label'; @@ -22,8 +20,11 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ReportExtensionIssueAction } from 'vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction'; -import { SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction'; import { AbstractRuntimeExtensionsEditor, IRuntimeExtension } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { URI } from 'vs/base/common/uri'; +import { IFileService } from 'vs/platform/files/common/files'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -122,22 +123,6 @@ export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { } } -export class ShowRuntimeExtensionsAction extends Action { - static readonly ID = 'workbench.action.showRuntimeExtensions'; - static readonly LABEL = nls.localize('showRuntimeExtensions', "Show Running Extensions"); - - constructor( - id: string, label: string, - @IEditorService private readonly _editorService: IEditorService - ) { - super(id, label); - } - - public async run(e?: any): Promise { - await this._editorService.openEditor(RuntimeExtensionsInput.instance, { revealIfOpened: true, pinned: true }); - } -} - export class StartExtensionHostProfileAction extends Action { static readonly ID = 'workbench.extensions.action.extensionHostProfile'; static readonly LABEL = nls.localize('extensionHostProfileStart', "Start Extension Host Profile"); @@ -171,3 +156,61 @@ export class StopExtensionHostProfileAction extends Action { return Promise.resolve(); } } + +export class SaveExtensionHostProfileAction extends Action { + + static readonly LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); + static readonly ID = 'workbench.extensions.action.saveExtensionHostProfile'; + + constructor( + id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL, + @INativeHostService private readonly _nativeHostService: INativeHostService, + @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, + @IFileService private readonly _fileService: IFileService + ) { + super(id, label, undefined, false); + this._extensionHostProfileService.onDidChangeLastProfile(() => { + this.enabled = (this._extensionHostProfileService.lastProfile !== null); + }); + } + + run(): Promise { + return Promise.resolve(this._asyncRun()); + } + + private async _asyncRun(): Promise { + let picked = await this._nativeHostService.showSaveDialog({ + title: 'Save Extension Host Profile', + buttonLabel: 'Save', + defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`, + filters: [{ + name: 'CPU Profiles', + extensions: ['cpuprofile', 'txt'] + }] + }); + + if (!picked || !picked.filePath || picked.canceled) { + return; + } + + const profileInfo = this._extensionHostProfileService.lastProfile; + let dataToWrite: object = profileInfo ? profileInfo.data : {}; + + let savePath = picked.filePath; + + if (this._environmentService.isBuilt) { + const profiler = await import('v8-inspect-profiler'); + // when running from a not-development-build we remove + // absolute filenames because we don't want to reveal anything + // about users. We also append the `.txt` suffix to make it + // easier to attach these files to GH issues + let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved'); + dataToWrite = tmp.profile; + + savePath = savePath + '.txt'; + } + + return this._fileService.writeFile(URI.file(savePath), VSBuffer.fromString(JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'))); + } +} diff --git a/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts deleted file mode 100644 index 4bc156cdcf9..00000000000 --- a/src/vs/workbench/contrib/extensions/electron-browser/saveExtensionHostProfileAction.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vs/nls'; -import { Action } from 'vs/base/common/actions'; -import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { URI } from 'vs/base/common/uri'; -import { IFileService } from 'vs/platform/files/common/files'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { IExtensionHostProfileService } from './runtimeExtensionsEditor'; - -export class SaveExtensionHostProfileAction extends Action { - - static readonly LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); - static readonly ID = 'workbench.extensions.action.saveExtensionHostProfile'; - - constructor( - id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL, - @INativeHostService private readonly _nativeHostService: INativeHostService, - @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, - @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, - @IFileService private readonly _fileService: IFileService - ) { - super(id, label, undefined, false); - this._extensionHostProfileService.onDidChangeLastProfile(() => { - this.enabled = (this._extensionHostProfileService.lastProfile !== null); - }); - } - - run(): Promise { - return Promise.resolve(this._asyncRun()); - } - - private async _asyncRun(): Promise { - let picked = await this._nativeHostService.showSaveDialog({ - title: 'Save Extension Host Profile', - buttonLabel: 'Save', - defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`, - filters: [{ - name: 'CPU Profiles', - extensions: ['cpuprofile', 'txt'] - }] - }); - - if (!picked || !picked.filePath || picked.canceled) { - return; - } - - const profileInfo = this._extensionHostProfileService.lastProfile; - let dataToWrite: object = profileInfo ? profileInfo.data : {}; - - let savePath = picked.filePath; - - if (this._environmentService.isBuilt) { - const profiler = await import('v8-inspect-profiler'); - // when running from a not-development-build we remove - // absolute filenames because we don't want to reveal anything - // about users. We also append the `.txt` suffix to make it - // easier to attach these files to GH issues - let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved'); - dataToWrite = tmp.profile; - - savePath = savePath + '.txt'; - } - - return this._fileService.writeFile(URI.file(savePath), VSBuffer.fromString(JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'))); - } -} diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 2a04a94091f..1746e7929ef 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -123,6 +123,9 @@ import 'vs/workbench/contrib/debug/browser/extensionHostDebugService'; // Webview import 'vs/workbench/contrib/webview/browser/webview.web.contribution'; +// Extensions Management +import 'vs/workbench/contrib/extensions/browser/extensions.web.contribution'; + // Terminal import 'vs/workbench/contrib/terminal/browser/terminal.web.contribution'; import 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; From 5a0ab56492d0c99f08028ca62ac3d59edb37f30f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 15:38:42 +0100 Subject: [PATCH 0278/1837] use native performance.mark when avialable --- src/vs/base/common/performance.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 5893db44495..b10f9b1d68c 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -12,7 +12,7 @@ function _factory(sharedObj) { sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || []; const _dataLen = 2; - const _timeStamp = typeof console.timeStamp === 'function' ? console.timeStamp.bind(console) : () => { }; + const _nativeMark = typeof performance === 'object' && typeof performance.mark === 'function' ? performance.mark.bind(performance) : () => { }; function importEntries(entries) { sharedObj.MonacoPerformanceMarks.splice(0, 0, ...entries); @@ -55,7 +55,7 @@ function _factory(sharedObj) { function mark(name) { sharedObj.MonacoPerformanceMarks.push(name, Date.now()); - _timeStamp(name); + _nativeMark(name); } const exports = { From b909e2051342707d91a7da452187c324bdc6b0dd Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2020 16:06:30 +0100 Subject: [PATCH 0279/1837] progress: Increment by percentage points since progress API expects that --- src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts | 5 +++-- src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index 2c0386f8ad7..137b4c92f99 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -63,8 +63,9 @@ class BulkEdit { } } - this._progress.report({ total: this._edits.length }); - const progress: IProgress = { report: _ => this._progress.report({ increment: 1 }) }; + this._progress.report({ total: 100 }); + // Increment by percentage points since progress API expects that + const progress: IProgress = { report: _ => this._progress.report({ increment: 100 / this._edits.length }) }; let index = 0; for (let range of ranges) { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index d197df7f654..e2e5a774dc2 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -243,8 +243,6 @@ export class BulkFileEdits { break; } - this._progress.report(undefined); - const options = edit.options || {}; let op: IFileOperation | undefined; if (edit.newResource && edit.oldResource && !options.copy) { @@ -263,6 +261,8 @@ export class BulkFileEdits { const undoOp = await op.perform(this._token); undoOperations.push(undoOp); } + + this._progress.report(undefined); } this._undoRedoService.pushElement(new FileUndoRedoElement(this._label, undoOperations), this._undoRedoGroup, this._undoRedoSource); From cab737e707e98cdef35e51e893240f62b79a1b0c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 16:22:35 +0100 Subject: [PATCH 0280/1837] Make `extensionKind: ['ui', 'web', 'workspace']` pick the web worker extension host if possible --- .../extensions/browser/extensionService.ts | 11 +-- .../electron-browser/extensionService.test.ts | 88 +++++++++++++++++++ 2 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 1dff19bf177..c6eb782943a 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -54,7 +54,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten new ExtensionRunningLocationClassifier( productService, configurationService, - (extensionKinds, isInstalledLocally, isInstalledRemotely) => this._pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely) + (extensionKinds, isInstalledLocally, isInstalledRemotely) => ExtensionService.pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely) ), instantiationService, notificationService, @@ -137,11 +137,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten }; } - private _pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean): ExtensionRunningLocation { + public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean): ExtensionRunningLocation { + let canRunRemotely = false; for (const extensionKind of extensionKinds) { if (extensionKind === 'ui' && isInstalledRemotely) { - // ui extensions run remotely if possible - return ExtensionRunningLocation.Remote; + // ui extensions run remotely if possible (but only as a last resort) + canRunRemotely = true; } if (extensionKind === 'workspace' && isInstalledRemotely) { // workspace extensions run remotely if possible @@ -152,7 +153,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten return ExtensionRunningLocation.LocalWebWorker; } } - return ExtensionRunningLocation.None; + return (canRunRemotely ? ExtensionRunningLocation.Remote : ExtensionRunningLocation.None); } protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] { diff --git a/src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts b/src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts new file mode 100644 index 00000000000..77a803dfa60 --- /dev/null +++ b/src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts @@ -0,0 +1,88 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { ExtensionService as BrowserExtensionService } from 'vs/workbench/services/extensions/browser/extensionService'; +import { ExtensionRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; + +suite('BrowserExtensionService', () => { + test('pickRunningLocation', () => { + assert.deepEqual(BrowserExtensionService.pickRunningLocation([], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation([], false, true), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation([], true, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation([], true, true), ExtensionRunningLocation.None); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true), ExtensionRunningLocation.Remote); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true), ExtensionRunningLocation.Remote); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true), ExtensionRunningLocation.LocalWebWorker); + + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true), ExtensionRunningLocation.Remote); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true), ExtensionRunningLocation.Remote); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); + + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true), ExtensionRunningLocation.Remote); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); + + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true), ExtensionRunningLocation.Remote); + }); +}); From 5cb2ee7b8b4c09678711eb10242ffaaa31bb0e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 16:07:31 +0100 Subject: [PATCH 0281/1837] confirmed extension -> user trusted extension --- .../extensions/browser/extensionUrlHandler.ts | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 5ef04b5f571..57dc911b054 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -30,20 +30,20 @@ import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; const FIVE_MINUTES = 5 * 60 * 1000; const THIRTY_SECONDS = 30 * 1000; const URL_TO_HANDLE = 'extensionUrlHandler.urlToHandle'; -const CONFIRMED_EXTENSIONS_CONFIGURATION_KEY = 'extensions.confirmedUriHandlerExtensionIds'; -const CONFIRMED_EXTENSIONS_STORAGE_KEY = 'extensionUrlHandler.confirmedExtensions'; +const USER_TRUSTED_EXTENSIONS_CONFIGURATION_KEY = 'extensions.confirmedUriHandlerExtensionIds'; +const USER_TRUSTED_EXTENSIONS_STORAGE_KEY = 'extensionUrlHandler.confirmedExtensions'; function isExtensionId(value: string): boolean { return /^[a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*$/i.test(value); } -class ConfirmedExtensionIdStorage { +class UserTrustedExtensionIdStorage { get extensions(): string[] { - const confirmedExtensionIdsJson = this.storageService.get(CONFIRMED_EXTENSIONS_STORAGE_KEY, StorageScope.GLOBAL, '[]'); + const userTrustedExtensionIdsJson = this.storageService.get(USER_TRUSTED_EXTENSIONS_STORAGE_KEY, StorageScope.GLOBAL, '[]'); try { - return JSON.parse(confirmedExtensionIdsJson); + return JSON.parse(userTrustedExtensionIdsJson); } catch { return []; } @@ -60,7 +60,7 @@ class ConfirmedExtensionIdStorage { } set(ids: string[]): void { - this.storageService.store(CONFIRMED_EXTENSIONS_STORAGE_KEY, JSON.stringify(ids), StorageScope.GLOBAL, StorageTarget.MACHINE); + this.storageService.store(USER_TRUSTED_EXTENSIONS_STORAGE_KEY, JSON.stringify(ids), StorageScope.GLOBAL, StorageTarget.MACHINE); } } @@ -87,7 +87,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { private extensionHandlers = new Map(); private uriBuffer = new Map(); - private storage: ConfirmedExtensionIdStorage; + private userTrustedExtensionsStorage: UserTrustedExtensionIdStorage; private disposable: IDisposable; constructor( @@ -103,7 +103,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { @IConfigurationService private readonly configurationService: IConfigurationService, @IProgressService private readonly progressService: IProgressService ) { - this.storage = new ConfirmedExtensionIdStorage(storageService); + this.userTrustedExtensionsStorage = new UserTrustedExtensionIdStorage(storageService); const interval = setInterval(() => this.garbageCollect(), THIRTY_SECONDS); const urlToHandleValue = this.storageService.get(URL_TO_HANDLE, StorageScope.WORKSPACE); @@ -135,14 +135,13 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { return true; } - let showConfirm: boolean; - if (options && options.trusted) { - showConfirm = false; - } else { - showConfirm = !this.isConfirmed(ExtensionIdentifier.toKey(extensionId)); + let trusted = options?.trusted; + + if (!trusted) { + trusted = this.didUserTrustExtension(ExtensionIdentifier.toKey(extensionId)); } - if (showConfirm) { + if (!trusted) { let uriString = uri.toString(false); if (uriString.length > 40) { @@ -164,7 +163,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { } if (result.checkboxChecked) { - this.storage.add(ExtensionIdentifier.toKey(extensionId)); + this.userTrustedExtensionsStorage.add(ExtensionIdentifier.toKey(extensionId)); } } @@ -313,22 +312,22 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { this.uriBuffer = uriBuffer; } - private isConfirmed(id: string): boolean { - if (this.storage.has(id)) { + private didUserTrustExtension(id: string): boolean { + if (this.userTrustedExtensionsStorage.has(id)) { return true; } - return this.getConfirmedExtensionIdsFromConfiguration().indexOf(id) > -1; + return this.getConfirmedTrustedExtensionIdsFromConfiguration().indexOf(id) > -1; } - private getConfirmedExtensionIdsFromConfiguration(): Array { - const confirmedExtensionIds = this.configurationService.getValue>(CONFIRMED_EXTENSIONS_CONFIGURATION_KEY); + private getConfirmedTrustedExtensionIdsFromConfiguration(): Array { + const trustedExtensionIds = this.configurationService.getValue>(USER_TRUSTED_EXTENSIONS_CONFIGURATION_KEY); - if (!Array.isArray(confirmedExtensionIds)) { + if (!Array.isArray(trustedExtensionIds)) { return []; } - return confirmedExtensionIds; + return trustedExtensionIds; } dispose(): void { @@ -391,7 +390,7 @@ class ManageAuthorizedExtensionURIsAction extends Action2 { async run(accessor: ServicesAccessor): Promise { const storageService = accessor.get(IStorageService); const quickInputService = accessor.get(IQuickInputService); - const storage = new ConfirmedExtensionIdStorage(storageService); + const storage = new UserTrustedExtensionIdStorage(storageService); const items = storage.extensions.map(label => ({ label, picked: true } as IQuickPickItem)); if (items.length === 0) { From bef58ff84aebe3637e39b512938bcd43155f4b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2020 16:23:30 +0100 Subject: [PATCH 0282/1837] forgot! --- build/azure-pipelines/win32/product-build-win32.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 280da3224e1..11881b353b2 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -57,6 +57,12 @@ steps: exec { git merge $(node -p "require('./package.json').distro") } displayName: Merge distro + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" From e287b8c9d3859d5a8bd434a4a3970087b16e13f6 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2020 16:25:46 +0100 Subject: [PATCH 0283/1837] explorer: hook in cancellation #111281 --- .../contrib/files/browser/explorerService.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index 70b1b8f59e8..fabc636c569 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -20,6 +20,7 @@ import { IBulkEditService, ResourceFileEdit } from 'vs/editor/browser/services/b import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; import { IExplorerView, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; export const UNDO_REDO_SOURCE = new UndoRedoSource(); @@ -93,21 +94,22 @@ export class ExplorerService implements IExplorerService { } async applyBulkEdit(edit: ResourceFileEdit[], options: { undoLabel: string, progressLabel: string }): Promise { + const cancellationTokenSource = new CancellationTokenSource(); const promise = this.progressService.withProgress({ location: ProgressLocation.Window, delay: 500, - title: options.progressLabel + title: options.progressLabel, + cancellable: true }, async progress => { - await this.bulkEditService.apply(edit, { undoRedoSource: UNDO_REDO_SOURCE, label: options.undoLabel, - progress + progress, + token: cancellationTokenSource.token }); - }); - this.progressService.withProgress({ location: ProgressLocation.Explorer, delay: 500 }, () => promise); - - return promise; + }, () => cancellationTokenSource.cancel()); + await this.progressService.withProgress({ location: ProgressLocation.Explorer, delay: 500 }, () => promise); + cancellationTokenSource.dispose(); } hasViewFocus(): boolean { From 545332f7939e8b53bb59f75966e43eeab47d0e85 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2020 16:43:32 +0100 Subject: [PATCH 0284/1837] explorer: polish progress --- src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts | 2 +- src/vs/workbench/contrib/files/browser/explorerService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index 137b4c92f99..558b4a0f90a 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -63,7 +63,7 @@ class BulkEdit { } } - this._progress.report({ total: 100 }); + this._progress.report({ increment: 0, total: 100 }); // Increment by percentage points since progress API expects that const progress: IProgress = { report: _ => this._progress.report({ increment: 100 / this._edits.length }) }; diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index fabc636c569..6398736b046 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -99,7 +99,7 @@ export class ExplorerService implements IExplorerService { location: ProgressLocation.Window, delay: 500, title: options.progressLabel, - cancellable: true + cancellable: edit.length > 1 // Only allow cancellation when there is more than one edit. Since cancelling will not actually stop the current edit that is in progress. }, async progress => { await this.bulkEditService.apply(edit, { undoRedoSource: UNDO_REDO_SOURCE, From 37e9cceddc5f8e8fe504378b04ebd7388beb6601 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 16:46:03 +0100 Subject: [PATCH 0285/1837] Enable sandbox, contextIsolation and vscode-file for process explorer and issue reporter (#111304) * Enable sandbox for issue reporter and process explorer (fix #101834) * sandbox - enable vscode-file protocol for sandboxed renderers * issues - stop setting nodeCachedDataDir * address feedback and also use vscode-file for shared process if sandbox is on --- src/bootstrap-window.js | 9 +- src/main.js | 9 ++ src/vs/base/common/network.ts | 51 ++++++++++ src/vs/base/common/platform.ts | 2 + src/vs/base/test/common/network.test.ts | 70 ++++++++++++++ src/vs/code/electron-main/app.ts | 12 ++- src/vs/code/electron-main/protocol.ts | 93 +++++++++++++++++++ src/vs/code/electron-main/sharedProcess.ts | 5 +- src/vs/code/electron-main/window.ts | 9 +- .../issue/electron-main/issueMainService.ts | 32 +------ 10 files changed, 254 insertions(+), 38 deletions(-) create mode 100644 src/vs/base/test/common/network.test.ts create mode 100644 src/vs/code/electron-main/protocol.ts diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index fcd68b1f309..8edd1780ff6 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -88,9 +88,14 @@ window['MonacoEnvironment'] = {}; + const baseUrl = sandbox ? + `${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out` : + `${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32' })}/out`; + const loaderConfig = { - baseUrl: `${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32' })}/out`, - 'vs/nls': nlsConfig + baseUrl, + 'vs/nls': nlsConfig, + preferScriptTags: sandbox }; // Enable loading of node modules: diff --git a/src/main.js b/src/main.js index 8ec0aa74c39..0bc566099a2 100644 --- a/src/main.js +++ b/src/main.js @@ -134,6 +134,15 @@ protocol.registerSchemesAsPrivileged([ corsEnabled: true, } }, + { + scheme: 'vscode-file', + privileges: { + secure: true, + standard: true, + supportFetchAPI: true, + corsEnabled: true + } + } ]); // Global app listeners diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index f475b10e5e8..4e12b577e22 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts @@ -78,6 +78,12 @@ export namespace Schemas { * Scheme used for extension pages */ export const extension = 'extension'; + + /** + * Scheme used as a replacement of `file` scheme to load + * files with our custom protocol handler (desktop only). + */ + export const vscodeFileResource = 'vscode-file'; } class RemoteAuthoritiesImpl { @@ -132,6 +138,8 @@ export const RemoteAuthorities = new RemoteAuthoritiesImpl(); class FileAccessImpl { + private readonly FALLBACK_AUTHORITY = 'vscode-app'; + /** * Returns a URI to use in contexts where the browser is responsible * for loading (e.g. fetch()) or when used within the DOM. @@ -143,13 +151,43 @@ class FileAccessImpl { asBrowserUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI { const uri = this.toUri(uriOrModule, moduleIdToUrl); + // Handle remote URIs via `RemoteAuthorities` if (uri.scheme === Schemas.vscodeRemote) { return RemoteAuthorities.rewrite(uri); } + // Only convert the URI if we are in a native context and it has `file:` scheme + if (platform.isElectronSandboxed && platform.isNative && uri.scheme === Schemas.file) { + return this.toCodeFileUri(uri); + } + return uri; } + /** + * TODO@bpasero remove me eventually when vscode-file is adopted everywhere + */ + _asCodeFileUri(uri: URI): URI; + _asCodeFileUri(moduleId: string, moduleIdToUrl: { toUrl(moduleId: string): string }): URI; + _asCodeFileUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI { + const uri = this.toUri(uriOrModule, moduleIdToUrl); + + return this.toCodeFileUri(uri); + } + + private toCodeFileUri(uri: URI): URI { + return uri.with({ + scheme: Schemas.vscodeFileResource, + // We need to provide an authority here so that it can serve + // as origin for network and loading matters in chromium. + // If the URI is not coming with an authority already, we + // add our own + authority: uri.authority || this.FALLBACK_AUTHORITY, + query: null, + fragment: null + }); + } + /** * Returns the `file` URI to use in contexts where node.js * is responsible for loading. @@ -159,6 +197,19 @@ class FileAccessImpl { asFileUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI { const uri = this.toUri(uriOrModule, moduleIdToUrl); + // Only convert the URI if it is `vscode-file:` scheme + if (uri.scheme === Schemas.vscodeFileResource) { + return uri.with({ + scheme: Schemas.file, + // Only preserve the `authority` if it is different from + // our fallback authority. This ensures we properly preserve + // Windows UNC paths that come with their own authority. + authority: uri.authority !== this.FALLBACK_AUTHORITY ? uri.authority : null, + query: null, + fragment: null + }); + } + return uri; } diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index c03aef236d8..61fa4d71ff1 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -33,6 +33,7 @@ export interface INodeProcess { versions?: { electron?: string; }; + sandboxed?: boolean; // Electron type?: string; cwd(): string; } @@ -59,6 +60,7 @@ if (typeof process !== 'undefined') { } const isElectronRenderer = typeof nodeProcess?.versions?.electron === 'string' && nodeProcess.type === 'renderer'; +export const isElectronSandboxed = isElectronRenderer && nodeProcess?.sandboxed; // Web environment if (typeof navigator === 'object' && !isElectronRenderer) { diff --git a/src/vs/base/test/common/network.test.ts b/src/vs/base/test/common/network.test.ts new file mode 100644 index 00000000000..1729d4b1c12 --- /dev/null +++ b/src/vs/base/test/common/network.test.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { URI } from 'vs/base/common/uri'; +import { FileAccess, Schemas } from 'vs/base/common/network'; +import { isEqual } from 'vs/base/common/resources'; +import { isElectronSandboxed } from 'vs/base/common/platform'; + +suite('network', () => { + const enableTest = isElectronSandboxed; + + (!enableTest ? test.skip : test)('FileAccess: URI (native)', () => { + + // asCodeUri() & asFileUri(): simple, without authority + let originalFileUri = URI.file('network.test.ts'); + let browserUri = FileAccess.asBrowserUri(originalFileUri); + assert.ok(browserUri.authority.length > 0); + let fileUri = FileAccess.asFileUri(browserUri); + assert.equal(fileUri.authority.length, 0); + assert(isEqual(originalFileUri, fileUri)); + + // asCodeUri() & asFileUri(): with authority + originalFileUri = URI.file('network.test.ts').with({ authority: 'test-authority' }); + browserUri = FileAccess.asBrowserUri(originalFileUri); + assert.equal(browserUri.authority, originalFileUri.authority); + fileUri = FileAccess.asFileUri(browserUri); + assert(isEqual(originalFileUri, fileUri)); + }); + + (!enableTest ? test.skip : test)('FileAccess: moduleId (native)', () => { + const browserUri = FileAccess.asBrowserUri('vs/base/test/node/network.test', require); + assert.equal(browserUri.scheme, Schemas.vscodeFileResource); + + const fileUri = FileAccess.asFileUri('vs/base/test/node/network.test', require); + assert.equal(fileUri.scheme, Schemas.file); + }); + + (!enableTest ? test.skip : test)('FileAccess: query and fragment is dropped (native)', () => { + let originalFileUri = URI.file('network.test.ts').with({ query: 'foo=bar', fragment: 'something' }); + let browserUri = FileAccess.asBrowserUri(originalFileUri); + assert.equal(browserUri.query, ''); + assert.equal(browserUri.fragment, ''); + }); + + (!enableTest ? test.skip : test)('FileAccess: query and fragment is kept if URI is already of same scheme (native)', () => { + let originalFileUri = URI.file('network.test.ts').with({ query: 'foo=bar', fragment: 'something' }); + let browserUri = FileAccess.asBrowserUri(originalFileUri.with({ scheme: Schemas.vscodeFileResource })); + assert.equal(browserUri.query, 'foo=bar'); + assert.equal(browserUri.fragment, 'something'); + + let fileUri = FileAccess.asFileUri(originalFileUri); + assert.equal(fileUri.query, 'foo=bar'); + assert.equal(fileUri.fragment, 'something'); + }); + + (!enableTest ? test.skip : test)('FileAccess: web', () => { + const originalHttpsUri = URI.file('network.test.ts').with({ scheme: 'https' }); + const browserUri = FileAccess.asBrowserUri(originalHttpsUri); + assert.equal(originalHttpsUri.toString(), browserUri.toString()); + }); + + test('FileAccess: remote URIs', () => { + const originalRemoteUri = URI.file('network.test.ts').with({ scheme: Schemas.vscodeRemote }); + const browserUri = FileAccess.asBrowserUri(originalRemoteUri); + assert.notEqual(originalRemoteUri.scheme, browserUri.scheme); + }); +}); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 2a74fe4ed76..87fddedeba9 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -35,6 +35,7 @@ import { getDelayedChannel, StaticRouter, createChannelReceiver, createChannelSe import product from 'vs/platform/product/common/product'; import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { ProxyAuthHandler2 } from 'vs/code/electron-main/auth2'; +import { FileProtocolHandler } from 'vs/code/electron-main/protocol'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { URI } from 'vs/base/common/uri'; @@ -412,6 +413,9 @@ export class CodeApplication extends Disposable { this.logService.error(error); } + // Setup Protocol Handler + const fileProtocolHandler = this._register(this.instantiationService.createInstance(FileProtocolHandler)); + // Create Electron IPC Server const electronIpcServer = new ElectronIPCServer(); @@ -457,7 +461,7 @@ export class CodeApplication extends Disposable { } // Open Windows - const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient)); + const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient, fileProtocolHandler)); // Post Open Windows Tasks appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor)); @@ -583,7 +587,7 @@ export class CodeApplication extends Disposable { }); } - private openFirstWindow(accessor: ServicesAccessor, electronIpcServer: ElectronIPCServer, sharedProcessClient: Promise>): ICodeWindow[] { + private openFirstWindow(accessor: ServicesAccessor, electronIpcServer: ElectronIPCServer, sharedProcessClient: Promise>, fileProtocolHandler: FileProtocolHandler): ICodeWindow[] { // Register more Main IPC services const launchMainService = accessor.get(ILaunchMainService); @@ -645,8 +649,10 @@ export class CodeApplication extends Disposable { electronIpcServer.registerChannel('logger', loggerChannel); sharedProcessClient.then(client => client.registerChannel('logger', loggerChannel)); - // ExtensionHost Debug broadcast service const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); + fileProtocolHandler.injectWindowsMainService(windowsMainService); + + // ExtensionHost Debug broadcast service electronIpcServer.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ElectronExtensionHostDebugBroadcastChannel(windowsMainService)); // Signal phase: ready (services set) diff --git a/src/vs/code/electron-main/protocol.ts b/src/vs/code/electron-main/protocol.ts new file mode 100644 index 00000000000..41a241ac602 --- /dev/null +++ b/src/vs/code/electron-main/protocol.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { FileAccess, Schemas } from 'vs/base/common/network'; +import { URI } from 'vs/base/common/uri'; +import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; +import { session } from 'electron'; +import { ILogService } from 'vs/platform/log/common/log'; +import { TernarySearchTree } from 'vs/base/common/map'; +import { isLinux } from 'vs/base/common/platform'; +import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; + +type ProtocolCallback = { (result: string | Electron.FilePathWithHeaders | { error: number }): void }; + +export class FileProtocolHandler extends Disposable { + + private readonly validRoots = TernarySearchTree.forUris(() => !isLinux); + + constructor( + @INativeEnvironmentService environmentService: INativeEnvironmentService, + @ILogService private readonly logService: ILogService + ) { + super(); + + const { defaultSession } = session; + + // Define an initial set of roots we allow loading from + // - appRoot : all files installed as part of the app + // - extensions : all files shipped from extensions + this.validRoots.set(URI.file(environmentService.appRoot), true); + this.validRoots.set(URI.file(environmentService.extensionsPath), true); + + // Register vscode-file:// handler + defaultSession.protocol.registerFileProtocol(Schemas.vscodeFileResource, (request, callback) => this.handleResourceRequest(request, callback as unknown as ProtocolCallback)); + + // Cleanup + this._register(toDisposable(() => { + defaultSession.protocol.unregisterProtocol(Schemas.vscodeFileResource); + })); + } + + injectWindowsMainService(windowsMainService: IWindowsMainService): void { + this._register(windowsMainService.onWindowReady(window => { + if (window.config?.extensionDevelopmentPath || window.config?.extensionTestsPath) { + const disposables = new DisposableStore(); + disposables.add(Event.any(window.onClose, window.onDestroy)(() => disposables.dispose())); + + // Allow access to extension development path + if (window.config.extensionDevelopmentPath) { + for (const extensionDevelopmentPath of window.config.extensionDevelopmentPath) { + disposables.add(this.addValidRoot(URI.file(extensionDevelopmentPath))); + } + } + + // Allow access to extension tests path + if (window.config.extensionTestsPath) { + disposables.add(this.addValidRoot(URI.file(window.config.extensionTestsPath))); + } + } + })); + } + + private addValidRoot(root: URI): IDisposable { + if (!this.validRoots.get(root)) { + this.validRoots.set(root, true); + + return toDisposable(() => this.validRoots.delete(root)); + } + + return Disposable.None; + } + + private async handleResourceRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback) { + const uri = URI.parse(request.url); + + // Restore the `vscode-file` URI to a `file` URI so that we can + // ensure the root is valid and properly tell Chrome where the + // resource is at. + const fileUri = FileAccess.asFileUri(uri); + if (this.validRoots.findSubstr(fileUri)) { + return callback({ + path: fileUri.fsPath + }); + } + + this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath}}`); + callback({ error: -3 /* ABORTED */ }); + } +} diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index c513c3c6c4b..dd721db92ad 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -60,8 +60,9 @@ export class SharedProcess implements ISharedProcess { windowId: this.window.id }; - const windowUrl = FileAccess - .asBrowserUri('vs/code/electron-browser/sharedProcess/sharedProcess.html', require) + const windowUrl = (this.environmentService.sandbox ? + FileAccess._asCodeFileUri('vs/code/electron-browser/sharedProcess/sharedProcess.html', require) : + FileAccess.asBrowserUri('vs/code/electron-browser/sharedProcess/sharedProcess.html', require)) .with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }); this.window.loadURL(windowUrl.toString(true)); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 1968e72b9c7..39f1bc472ca 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -848,10 +848,11 @@ export class CodeWindow extends Disposable implements ICodeWindow { workbench = 'vs/code/electron-browser/workbench/workbench.html'; } - return FileAccess - .asBrowserUri(workbench, require) - .with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }) - .toString(true); + const browserUri = this.environmentService.sandbox ? + FileAccess._asCodeFileUri(workbench, require) : + FileAccess.asBrowserUri(workbench, require); + + return browserUri.with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }).toString(true); } serializeWindowState(): IWindowState { diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index f7c4d8dbc3d..da98e2f94f6 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -209,18 +209,8 @@ export class IssueMainService implements ICommonIssueService { spellcheck: false, nativeWindowOpen: true, zoomFactor: zoomLevelToZoomFactor(data.zoomLevel), - ...this.environmentService.sandbox ? - - // Sandbox - { - sandbox: true, - contextIsolation: true - } : - - // No Sandbox - { - nodeIntegration: true - } + sandbox: true, + contextIsolation: true } }); @@ -275,18 +265,8 @@ export class IssueMainService implements ICommonIssueService { spellcheck: false, nativeWindowOpen: true, zoomFactor: zoomLevelToZoomFactor(data.zoomLevel), - ...this.environmentService.sandbox ? - - // Sandbox - { - sandbox: true, - contextIsolation: true - } : - - // No Sandbox - { - nodeIntegration: true - } + sandbox: true, + contextIsolation: true } }); @@ -294,7 +274,6 @@ export class IssueMainService implements ICommonIssueService { const windowConfiguration = { appRoot: this.environmentService.appRoot, - nodeCachedDataDir: this.environmentService.nodeCachedDataDir, windowId: this._processExplorerWindow.id, userEnv: this.userEnv, machineId: this.machineId, @@ -422,7 +401,6 @@ export class IssueMainService implements ICommonIssueService { const windowConfiguration = { appRoot: this.environmentService.appRoot, - nodeCachedDataDir: this.environmentService.nodeCachedDataDir, windowId: this._issueWindow.id, machineId: this.machineId, userEnv: this.userEnv, @@ -458,7 +436,7 @@ function toWindowUrl(modulePathToHtml: string, windowConfiguration: T): strin } return FileAccess - .asBrowserUri(modulePathToHtml, require) + ._asCodeFileUri(modulePathToHtml, require) .with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }) .toString(true); } From 0ab259ff278255793aec411cb12195e4b7b862d1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2020 16:48:30 +0100 Subject: [PATCH 0286/1837] remove unsued code, fyi @roblourens, https://github.com/microsoft/vscode/issues/106741 --- .../workbench/api/common/extHost.protocol.ts | 1 - .../workbench/api/common/extHostNotebook.ts | 23 ------------------- 2 files changed, 24 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index ac101e511bb..69f4f321c84 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1721,7 +1721,6 @@ export interface ExtHostNotebookShape { $resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise; $executeNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; $cancelNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; - $executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise; $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise; $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise; $backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 9cc0cf8d2c1..bb136d1c0bd 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -214,7 +214,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN private readonly _proxy: MainThreadNotebookShape; private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape; private readonly _notebookContentProviders = new Map(); - private readonly _notebookKernels = new Map(); private readonly _notebookKernelProviders = new Map(); private readonly _documents = new ResourceMap(); private readonly _editors = new Map(); @@ -516,28 +515,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN }); } - async $executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise { - const document = this._documents.get(URI.revive(uri)); - - if (!document || document.notebookDocument.viewType !== viewType) { - return; - } - - const kernelInfo = this._notebookKernels.get(kernelId); - - if (!kernelInfo) { - return; - } - - const cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined; - - if (cell) { - return withToken(token => (kernelInfo!.kernel.executeCell as any)(document.notebookDocument, cell.cell, token)); - } else { - return withToken(token => (kernelInfo!.kernel.executeAllCells as any)(document.notebookDocument, token)); - } - } - async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise { const document = this._documents.get(URI.revive(uri)); if (!document) { From 71462d03fe44673415310bc3aeeb7db188565a1b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 17:13:17 +0100 Subject: [PATCH 0287/1837] Fixes #111309 --- src/tsconfig.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/tsconfig.json b/src/tsconfig.json index 85e7f18d516..5e81e53802a 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -13,12 +13,6 @@ "sinon", "winreg", "trusted-types" - ], - "plugins": [ - { - // the path is relative to TS server, "../../" points to the root dir - "name": "../../node_modules/tsec/lib/tsec_lib/language_service_plugin.js" - } ] }, "include": [ From 89c255a52339127213bd767cd952ee3743ca3d5c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2020 17:17:16 +0100 Subject: [PATCH 0288/1837] generate icon-css from theme.comon.IconRegistry --- .../base/browser/ui/codicons/codiconStyles.ts | 13 +--- .../browser/standaloneThemeServiceImpl.ts | 11 ++-- src/vs/platform/theme/common/iconRegistry.ts | 63 +++++++++++++++---- src/vs/platform/theme/common/themeService.ts | 21 +++++-- .../browser/breakpointEditorContribution.ts | 30 ++++----- .../contrib/debug/browser/breakpointsView.ts | 13 ++-- .../browser/callStackEditorContribution.ts | 6 +- .../contrib/debug/browser/callStackView.ts | 24 +++---- .../debug/browser/debugActionViewItems.ts | 4 +- .../contrib/debug/browser/debugActions.ts | 15 ++--- .../browser/debugConfigurationManager.ts | 3 +- .../contrib/debug/browser/debugIcons.ts | 3 +- .../contrib/debug/browser/debugQuickAccess.ts | 3 +- .../contrib/debug/browser/debugToolBar.ts | 24 +++---- .../contrib/debug/browser/debugViewlet.ts | 4 +- .../workbench/contrib/debug/browser/repl.ts | 6 +- .../contrib/debug/browser/replViewer.ts | 4 +- .../contrib/debug/browser/variablesView.ts | 4 +- .../debug/browser/watchExpressionsView.ts | 4 +- .../debug/test/browser/callStack.test.ts | 7 ++- .../themes/browser/workbenchThemeService.ts | 7 ++- 21 files changed, 157 insertions(+), 112 deletions(-) diff --git a/src/vs/base/browser/ui/codicons/codiconStyles.ts b/src/vs/base/browser/ui/codicons/codiconStyles.ts index 8229f2f1cf1..44281196746 100644 --- a/src/vs/base/browser/ui/codicons/codiconStyles.ts +++ b/src/vs/base/browser/ui/codicons/codiconStyles.ts @@ -7,18 +7,7 @@ import 'vs/css!./codicon/codicon'; import 'vs/css!./codicon/codicon-modifications'; import 'vs/css!./codicon/codicon-animations'; -import { Codicon, iconRegistry } from 'vs/base/common/codicons'; - -export const CodiconStyles = new class { - onDidChange = iconRegistry.onDidRegister; - public getCSS(): string { - const rules = []; - for (let c of iconRegistry.all) { - rules.push(formatRule(c)); - } - return rules.join('\n'); - } -}; +import { Codicon } from 'vs/base/common/codicons'; export function formatRule(c: Codicon) { let def = c.definition; diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 54ca7023896..544d7b07af1 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -16,7 +16,7 @@ import { ColorIdentifier, Extensions, IColorRegistry } from 'vs/platform/theme/c import { Extensions as ThemingExtensions, ICssStyleCollector, IFileIconTheme, IThemingRegistry, ITokenStyle } from 'vs/platform/theme/common/themeService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { CodiconStyles } from 'vs/base/browser/ui/codicons/codiconStyles'; +import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry'; const VS_THEME_NAME = 'vs'; const VS_DARK_THEME_NAME = 'vs-dark'; @@ -208,15 +208,18 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon this._knownThemes.set(VS_THEME_NAME, newBuiltInTheme(VS_THEME_NAME)); this._knownThemes.set(VS_DARK_THEME_NAME, newBuiltInTheme(VS_DARK_THEME_NAME)); this._knownThemes.set(HC_BLACK_THEME_NAME, newBuiltInTheme(HC_BLACK_THEME_NAME)); - this._codiconCSS = CodiconStyles.getCSS(); + + const iconRegistry = getIconRegistry(); + + this._codiconCSS = iconRegistry.getCSS(); this._themeCSS = ''; this._allCSS = `${this._codiconCSS}\n${this._themeCSS}`; this._globalStyleElement = null; this._styleElements = []; this.setTheme(VS_THEME_NAME); - CodiconStyles.onDidChange(() => { - this._codiconCSS = CodiconStyles.getCSS(); + iconRegistry.onDidChange(() => { + this._codiconCSS = iconRegistry.getCSS(); this._updateCSS(); }); } diff --git a/src/vs/platform/theme/common/iconRegistry.ts b/src/vs/platform/theme/common/iconRegistry.ts index 63fcc3787de..79ae6dffdc1 100644 --- a/src/vs/platform/theme/common/iconRegistry.ts +++ b/src/vs/platform/theme/common/iconRegistry.ts @@ -30,14 +30,14 @@ export interface IconDefinition { export interface IconContribution { id: string; - description: string; + description: string | undefined; deprecationMessage?: string; defaults: IconDefaults; } export interface IIconRegistry { - readonly onDidChangeSchema: Event; + readonly onDidChange: Event; /** * Register a icon to the registry. @@ -72,12 +72,17 @@ export interface IIconRegistry { */ getIconReferenceSchema(): IJSONSchema; + /** + * The CSS for all icons + */ + getCSS(): string; + } class IconRegistry implements IIconRegistry { - private readonly _onDidChangeSchema = new Emitter(); - readonly onDidChangeSchema: Event = this._onDidChangeSchema.event; + private readonly _onDidChange = new Emitter(); + readonly onDidChange: Event = this._onDidChange.event; private iconsById: { [key: string]: IconContribution }; private iconSchema: IJSONSchema & { properties: IJSONSchemaMap } = { @@ -102,8 +107,18 @@ class IconRegistry implements IIconRegistry { } public registerIcon(id: string, defaults: IconDefaults, description?: string, deprecationMessage?: string): ThemeIcon { - if (!description) { - description = localize('icon.defaultDescription', 'Icon with identifier \'{0}\'', id); + const existing = this.iconsById[id]; + if (existing) { + if (description && !existing.description) { + existing.description = description; + this.iconSchema.properties[id].markdownDescription = `${description}: $(${id})`; + const enumIndex = this.iconReferenceSchema.enum.indexOf(id); + if (enumIndex !== -1) { + this.iconReferenceSchema.enumDescriptions[enumIndex] = description; + } + this._onDidChange.fire(); + } + return existing; } let iconContribution: IconContribution = { id, description, defaults, deprecationMessage }; this.iconsById[id] = iconContribution; @@ -111,12 +126,14 @@ class IconRegistry implements IIconRegistry { if (deprecationMessage) { propertySchema.deprecationMessage = deprecationMessage; } - propertySchema.markdownDescription = `${description}: $(${id})`; + if (description) { + propertySchema.markdownDescription = `${description}: $(${id})`; + } this.iconSchema.properties[id] = propertySchema; this.iconReferenceSchema.enum.push(id); - this.iconReferenceSchema.enumDescriptions.push(description); + this.iconReferenceSchema.enumDescriptions.push(description || ''); - this._onDidChangeSchema.fire(); + this._onDidChange.fire(); return { id }; } @@ -129,7 +146,7 @@ class IconRegistry implements IIconRegistry { this.iconReferenceSchema.enum.splice(index, 1); this.iconReferenceSchema.enumDescriptions.splice(index, 1); } - this._onDidChangeSchema.fire(); + this._onDidChange.fire(); } public getIcons(): IconContribution[] { @@ -148,6 +165,29 @@ class IconRegistry implements IIconRegistry { return this.iconReferenceSchema; } + public getCSS() { + const rules = []; + for (let id in this.iconsById) { + const rule = this.formatRule(id); + if (rule) { + rules.push(rule); + } + } + return rules.join('\n'); + } + + private formatRule(id: string): string | undefined { + let definition = this.iconsById[id].defaults; + while (ThemeIcon.isThemeIcon(definition)) { + const c = this.iconsById[definition.id]; + if (!c) { + return undefined; + } + definition = c.defaults; + } + return `.codicon-${id}:before { content: '${definition.character}'; }`; + } + public toString() { const sorter = (i1: IconContribution, i2: IconContribution) => { const isThemeIcon1 = ThemeIcon.isThemeIcon(i1.defaults); @@ -200,14 +240,13 @@ function initialize() { } initialize(); - export const iconsSchemaId = 'vscode://schemas/icons'; let schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution); schemaRegistry.registerSchema(iconsSchemaId, iconRegistry.getIconSchema()); const delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(iconsSchemaId), 200); -iconRegistry.onDidChangeSchema(() => { +iconRegistry.onDidChange(() => { if (!delayer.isScheduled()) { delayer.schedule(); } diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 1632d1abc15..56ce464ca60 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -71,20 +71,29 @@ export namespace ThemeIcon { const _regexAsClassName = /^(codicon\/)?([a-z-]+)(~[a-z]+)?$/i; - export function asClassName(icon: ThemeIcon): string | undefined { - // todo@martin,joh -> this should go into the ThemeService + export function asClassNameArray(icon: ThemeIcon): string[] { const match = _regexAsClassName.exec(icon.id); if (!match) { - return undefined; + return ['codicon', 'codicon-error']; } let [, , name, modifier] = match; - let className = `codicon codicon-${name}`; + let className = `codicon-${name}`; if (modifier) { - className += ` ${modifier.substr(1)}`; + return ['codicon', className, modifier.substr(1)]; } - return className; + return ['codicon', className]; } + + export function asClassName(icon: ThemeIcon): string { + return asClassNameArray(icon).join(' '); + } + + export function asCSSSelector(icon: ThemeIcon): string { + return '.' + asClassNameArray(icon).join('.'); + } + + export function revive(icon: any): ThemeIcon | undefined { if (ThemeIcon.isThemeIcon(icon)) { return { id: icon.id, color: icon.color ? { id: icon.color.id } : undefined }; diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index e18f751b30f..966dc83e5da 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -32,7 +32,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; import { isSafari } from 'vs/base/browser/browser'; -import { registerThemingParticipant, themeColorFromId } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, themeColorFromId, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; @@ -47,7 +47,7 @@ interface IBreakpointDecoration { } const breakpointHelperDecoration: IModelDecorationOptions = { - glyphMarginClassName: icons.debugBreakpointHint.classNames, + glyphMarginClassName: ThemeIcon.asClassName(icons.debugBreakpointHint), stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }; @@ -95,7 +95,7 @@ function getBreakpointDecorationOptions(model: ITextModel, breakpoint: IBreakpoi const renderInline = breakpoint.column && (breakpoint.column > model.getLineFirstNonWhitespaceColumn(breakpoint.lineNumber)); return { - glyphMarginClassName: icon.classNames, + glyphMarginClassName: ThemeIcon.asClassName(icon), glyphMarginHoverMessage, stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, beforeContentClassName: renderInline ? `debug-breakpoint-placeholder` : undefined, @@ -456,7 +456,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi // We could have also rendered this first decoration as part of desiredBreakpointDecorations however at that moment we have no location information const icon = candidate.breakpoint ? getBreakpointMessageAndIcon(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).icon : icons.debugBreakpointDisabled; const contextMenuActions = () => this.getContextMenuActions(candidate.breakpoint ? [candidate.breakpoint] : [], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn); - const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, icon.classNames, candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions); + const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, ThemeIcon.asClassName(icon), candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions); return { decorationId, @@ -645,15 +645,15 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointColor = theme.getColor(debugIconBreakpointForeground); if (debugIconBreakpointColor) { collector.addRule(` - .monaco-workbench ${icons.debugBreakpoint.cssSelector}, - .monaco-workbench ${icons.debugBreakpointConditional.cssSelector}, - .monaco-workbench ${icons.debugBreakpointLog.cssSelector}, - .monaco-workbench ${icons.debugBreakpointFunction.cssSelector}, - .monaco-workbench ${icons.debugBreakpointData.cssSelector}, - .monaco-workbench ${icons.debugBreakpointUnsupported.cssSelector}, - .monaco-workbench ${icons.debugBreakpointHint.cssSelector}:not([class*='${icons.debugBreakpoint.classNameIdentifier}']):not([class*='${icons.debugStackframe.classNameIdentifier}']), - .monaco-workbench ${icons.debugBreakpoint.cssSelector}${icons.debugStackframeFocused.cssSelector}::after, - .monaco-workbench ${icons.debugBreakpoint.cssSelector}${icons.debugStackframe.cssSelector}::after { + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointConditional)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointLog)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointFunction)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointData)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointUnsupported)}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointHint)}:not([class*='codicon-debug-breakpoint']):not([class*='codicon-debug-stackframe']), + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}${ThemeIcon.asCSSSelector(icons.debugStackframeFocused)}::after, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}${ThemeIcon.asCSSSelector(icons.debugStackframe)}::after { color: ${debugIconBreakpointColor} !important; } `); @@ -680,7 +680,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointCurrentStackframeForegroundColor = theme.getColor(debugIconBreakpointCurrentStackframeForeground); if (debugIconBreakpointCurrentStackframeForegroundColor) { collector.addRule(` - .monaco-workbench ${icons.debugStackframe.cssSelector}, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStackframe)}, .monaco-editor .debug-top-stack-frame-column::before { color: ${debugIconBreakpointCurrentStackframeForegroundColor} !important; } @@ -690,7 +690,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeForeground); if (debugIconBreakpointStackframeFocusedColor) { collector.addRule(` - .monaco-workbench ${icons.debugStackframeFocused.cssSelector} { + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStackframeFocused)} { color: ${debugIconBreakpointStackframeFocusedColor} !important; } `); diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 8a449d87fde..22dcf505982 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -13,7 +13,7 @@ import { AddFunctionBreakpointAction, ToggleBreakpointsActivatedAction, RemoveAl import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { Constants } from 'vs/base/common/uint'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IListVirtualDelegate, IListContextMenuEvent, IListRenderer } from 'vs/base/browser/ui/list/list'; @@ -38,7 +38,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; -import { Codicon } from 'vs/base/common/codicons'; const $ = dom.$; @@ -382,7 +381,7 @@ class BreakpointsRenderer implements IListRenderer this.tree, true, 'explorer-action ' + icons.debugCollapseAll.classNames)]; + return [new CollapseAction(() => this.tree, true, 'explorer-action ' + ThemeIcon.asClassName(icons.debugCollapseAll))]; } return []; @@ -502,7 +502,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer { + const action = new Action('debug.callStack.restartFrame', nls.localize('restartFrame', "Restart Frame"), ThemeIcon.asClassName(icons.debugRestartFrame), true, async () => { try { await stackFrame.restart(); } catch (e) { @@ -995,7 +995,7 @@ class StopAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STOP_ID}`, STOP_LABEL, 'debug-action ' + icons.debugStop.classNames); + super(`action.${STOP_ID}`, STOP_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugStop)); } public run(): Promise { @@ -1009,7 +1009,7 @@ class DisconnectAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${DISCONNECT_ID}`, DISCONNECT_LABEL, 'debug-action ' + icons.debugDisconnect.classNames); + super(`action.${DISCONNECT_ID}`, DISCONNECT_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugDisconnect)); } public run(): Promise { @@ -1023,7 +1023,7 @@ class RestartAction extends Action { private readonly session: IDebugSession, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${RESTART_SESSION_ID}`, RESTART_LABEL, 'debug-action ' + icons.debugRestart.classNames); + super(`action.${RESTART_SESSION_ID}`, RESTART_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugRestart)); } public run(): Promise { @@ -1037,7 +1037,7 @@ class StepOverAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_OVER_ID}`, STEP_OVER_LABEL, 'debug-action ' + icons.debugStepOver.classNames, thread.stopped); + super(`action.${STEP_OVER_ID}`, STEP_OVER_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugStepOver), thread.stopped); } public run(): Promise { @@ -1051,7 +1051,7 @@ class StepIntoAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_INTO_ID}`, STEP_INTO_LABEL, 'debug-action ' + icons.debugStepInto.classNames, thread.stopped); + super(`action.${STEP_INTO_ID}`, STEP_INTO_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugStepInto), thread.stopped); } public run(): Promise { @@ -1065,7 +1065,7 @@ class StepOutAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${STEP_OUT_ID}`, STEP_OUT_LABEL, 'debug-action ' + icons.debugStepOut.classNames, thread.stopped); + super(`action.${STEP_OUT_ID}`, STEP_OUT_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugStepOut), thread.stopped); } public run(): Promise { @@ -1079,7 +1079,7 @@ class PauseAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${PAUSE_ID}`, PAUSE_LABEL, 'debug-action ' + icons.debugPause.classNames, !thread.stopped); + super(`action.${PAUSE_ID}`, PAUSE_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugPause), !thread.stopped); } public run(): Promise { @@ -1093,7 +1093,7 @@ class ContinueAction extends Action { private readonly thread: IThread, @ICommandService private readonly commandService: ICommandService ) { - super(`action.${CONTINUE_ID}`, CONTINUE_LABEL, 'debug-action ' + icons.debugContinue.classNames, thread.stopped); + super(`action.${CONTINUE_ID}`, CONTINUE_LABEL, 'debug-action ' + ThemeIcon.asClassName(icons.debugContinue), thread.stopped); } public run(): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts index 8e2acc29b6d..3ab90797656 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts @@ -12,7 +12,7 @@ import { SelectBox, ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selec import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch } from 'vs/workbench/contrib/debug/common/debug'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { selectBorder, selectBackground } from 'vs/platform/theme/common/colorRegistry'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; @@ -69,7 +69,7 @@ export class StartDebugActionViewItem implements IActionViewItem { render(container: HTMLElement): void { this.container = container; container.classList.add('start-debug-action-item'); - this.start = dom.append(container, $(debugStart.cssSelector)); + this.start = dom.append(container, $(ThemeIcon.asCSSSelector(debugStart))); this.start.title = this.action.label; this.start.setAttribute('role', 'button'); this.start.tabIndex = 0; diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 6d3eb9c3a56..9fae429ed01 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -15,6 +15,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { deepClone } from 'vs/base/common/objects'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export abstract class AbstractDebugAction extends Action { @@ -65,7 +66,7 @@ export class ConfigureAction extends AbstractDebugAction { @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IQuickInputService private readonly quickInputService: IQuickInputService ) { - super(id, label, 'debug-action ' + icons.debugConfigure.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.debugConfigure), debugService, keybindingService); this._register(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass())); this.updateClass(); } @@ -80,7 +81,7 @@ export class ConfigureAction extends AbstractDebugAction { private updateClass(): void { const configurationManager = this.debugService.getConfigurationManager(); - this.class = configurationManager.selectedConfiguration.name ? 'debug-action' + icons.debugConfigure.classNames : 'debug-action ' + icons.debugConfigure.classNames + ' notification'; + this.class = configurationManager.selectedConfiguration.name ? 'debug-action' + ThemeIcon.asClassName(icons.debugConfigure) : 'debug-action ' + ThemeIcon.asClassName(icons.debugConfigure) + ' notification'; } async run(): Promise { @@ -211,7 +212,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { static readonly LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + icons.breakpointsRemoveAll.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.breakpointsRemoveAll), debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } @@ -269,7 +270,7 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { static readonly DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + icons.breakpointsActivate.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.breakpointsActivate), debugService, keybindingService); this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => { @@ -312,7 +313,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { static readonly LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + icons.watchExpressionsAddFuncBreakpoint.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsAddFuncBreakpoint), debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } @@ -331,7 +332,7 @@ export class AddWatchExpressionAction extends AbstractDebugAction { static readonly LABEL = nls.localize('addWatchExpression', "Add Expression"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + icons.watchExpressionsAdd.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsAdd), debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); this._register(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement())); } @@ -351,7 +352,7 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { static readonly LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + icons.watchExpressionsRemoveAll.classNames, debugService, keybindingService); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsRemoveAll), debugService, keybindingService); this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); } diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index ba5b86f55e4..d7caaef4389 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -38,6 +38,7 @@ import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/e import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager'; import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); jsonRegistry.registerSchema(launchSchemaId, launchSchema); @@ -226,7 +227,7 @@ export class ConfigurationManager implements IConfigurationManager { description: launch.name, config, buttons: [{ - iconClass: debugConfigure.classNames, + iconClass: ThemeIcon.asClassName(debugConfigure), tooltip: nls.localize('editLaunchConfig', "Edit Debug Configuration in launch.json") }], launch diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts index bf6ee24f24a..b2203e38102 100644 --- a/src/vs/workbench/contrib/debug/browser/debugIcons.ts +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export const debugConsoleViewIcon = registerIcon('debug-console-view-icon', Codicon.debugConsole, localize('debugConsoleViewIcon', 'View icon of the debug console view.')); export const runViewIcon = registerIcon('run-view-icon', Codicon.debugAlt, localize('runViewIcon', 'View icon of the run view.')); diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts index 1ab4d8e9b99..2b6f530c48b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts @@ -14,6 +14,7 @@ import { matchesFuzzy } from 'vs/base/common/filters'; import { withNullAsUndefined } from 'vs/base/common/types'; import { ADD_CONFIGURATION_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { @@ -56,7 +57,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 5caea036d1b..8f62ac8d999 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -18,7 +18,7 @@ import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/d import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { registerThemingParticipant, IThemeService, Themable } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { registerColor, contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; import { localize } from 'vs/nls'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -65,7 +65,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { this.$el = dom.$('div.debug-toolbar'); this.$el.style.top = `${layoutService.offset?.top ?? 0}px`; - this.dragArea = dom.append(this.$el, dom.$('div.drag-area' + icons.debugGripper.cssSelector)); + this.dragArea = dom.append(this.$el, dom.$('div.drag-area' + ThemeIcon.asCSSSelector(icons.debugGripper))); const actionBarContainer = dom.append(this.$el, dom.$('div.action-bar-container')); this.debugToolBarMenu = menuService.createMenu(MenuId.DebugToolBar, contextKeyService); @@ -352,51 +352,51 @@ registerThemingParticipant((theme, collector) => { const debugIconStartColor = theme.getColor(debugIconStartForeground); if (debugIconStartColor) { - collector.addRule(`.monaco-workbench ${icons.debugStart.cssSelector} { color: ${debugIconStartColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStart)} { color: ${debugIconStartColor} !important; }`); } const debugIconPauseColor = theme.getColor(debugIconPauseForeground); if (debugIconPauseColor) { - collector.addRule(`.monaco-workbench ${icons.debugPause.cssSelector} { color: ${debugIconPauseColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugPause)} { color: ${debugIconPauseColor} !important; }`); } const debugIconStopColor = theme.getColor(debugIconStopForeground); if (debugIconStopColor) { - collector.addRule(`.monaco-workbench ${icons.debugStop.cssSelector} { color: ${debugIconStopColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStop)} { color: ${debugIconStopColor} !important; }`); } const debugIconDisconnectColor = theme.getColor(debugIconDisconnectForeground); if (debugIconDisconnectColor) { - collector.addRule(`.monaco-workbench .debug-view-content ${icons.debugDisconnect.cssSelector}, .monaco-workbench .debug-toolbar ${icons.debugDisconnect.cssSelector} { color: ${debugIconDisconnectColor} !important; }`); + collector.addRule(`.monaco-workbench .debug-view-content ${ThemeIcon.asCSSSelector(icons.debugDisconnect)}, .monaco-workbench .debug-toolbar ${ThemeIcon.asCSSSelector(icons.debugDisconnect)} { color: ${debugIconDisconnectColor} !important; }`); } const debugIconRestartColor = theme.getColor(debugIconRestartForeground); if (debugIconRestartColor) { - collector.addRule(`.monaco-workbench ${icons.debugRestart.cssSelector}, .monaco-workbench ${icons.debugRestartFrame.cssSelector} { color: ${debugIconRestartColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestart)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestartFrame)} { color: ${debugIconRestartColor} !important; }`); } const debugIconStepOverColor = theme.getColor(debugIconStepOverForeground); if (debugIconStepOverColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepOver.cssSelector} { color: ${debugIconStepOverColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOver)} { color: ${debugIconStepOverColor} !important; }`); } const debugIconStepIntoColor = theme.getColor(debugIconStepIntoForeground); if (debugIconStepIntoColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepInto.cssSelector} { color: ${debugIconStepIntoColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepInto)} { color: ${debugIconStepIntoColor} !important; }`); } const debugIconStepOutColor = theme.getColor(debugIconStepOutForeground); if (debugIconStepOutColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepOut.cssSelector} { color: ${debugIconStepOutColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOut)} { color: ${debugIconStepOutColor} !important; }`); } const debugIconContinueColor = theme.getColor(debugIconContinueForeground); if (debugIconContinueColor) { - collector.addRule(`.monaco-workbench ${icons.debugContinue.cssSelector}, .monaco-workbench ${icons.debugReverseContinue.cssSelector} { color: ${debugIconContinueColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugContinue)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugReverseContinue)} { color: ${debugIconContinueColor} !important; }`); } const debugIconStepBackColor = theme.getColor(debugIconStepBackForeground); if (debugIconStepBackColor) { - collector.addRule(`.monaco-workbench ${icons.debugStepBack.cssSelector} { color: ${debugIconStepBackColor} !important; }`); + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepBack)} { color: ${debugIconStepBackColor} !important; }`); } }); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 3182a136f9e..91187dd3a53 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -15,7 +15,7 @@ import { IProgressService } from 'vs/platform/progress/common/progress'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -248,7 +248,7 @@ export class OpenDebugConsoleAction extends ToggleViewAction { @IContextKeyService contextKeyService: IContextKeyService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, debugConsole.classNames); + super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, ThemeIcon.asClassName(debugConsole)); } } diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 88a38e6ce16..16593506851 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -20,7 +20,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { memoize } from 'vs/base/common/decorators'; import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle'; @@ -596,7 +596,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { private createReplInput(container: HTMLElement): void { this.replInputContainer = dom.append(container, $('.repl-input-wrapper')); - dom.append(this.replInputContainer, $('.repl-input-chevron' + debugConsoleEvaluationPrompt.cssSelector)); + dom.append(this.replInputContainer, $('.repl-input-chevron' + ThemeIcon.asCSSSelector(debugConsoleEvaluationPrompt))); const { scopedContextKeyService, historyNavigationEnablement } = createAndBindHistoryNavigationWidgetScopedContextKeyService(this.contextKeyService, { target: this.replInputContainer, historyNavigator: this }); this.historyNavigationEnablement = historyNavigationEnablement; @@ -857,7 +857,7 @@ export class ClearReplAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'debug-action ' + debugConsoleClearAll.classNames); + super(id, label, 'debug-action ' + ThemeIcon.asClassName(debugConsoleClearAll)); } async run(): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts index 3e1c3884994..0d432417fcf 100644 --- a/src/vs/workbench/contrib/debug/browser/replViewer.ts +++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts @@ -21,7 +21,7 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters'; import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IReplElementSource, IDebugService, IExpression, IReplElement, IDebugConfiguration, IDebugSession, IExpressionContainer } from 'vs/workbench/contrib/debug/common/debug'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { localize } from 'vs/nls'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; @@ -68,7 +68,7 @@ export class ReplEvaluationInputsRenderer implements ITreeRenderer this.tree, true, 'explorer-action ' + debugCollapseAll.classNames)]; + return [new CollapseAction(() => this.tree, true, 'explorer-action ' + ThemeIcon.asClassName(debugCollapseAll))]; } layoutBody(width: number, height: number): void { diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index 65806b518a2..2e18414c9db 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -30,7 +30,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { dispose } from 'vs/base/common/lifecycle'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { debugCollapseAll } from 'vs/workbench/contrib/debug/browser/debugIcons'; @@ -161,7 +161,7 @@ export class WatchExpressionsView extends ViewPane { getActions(): IAction[] { return [ new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService), - new CollapseAction(() => this.tree, true, 'explorer-action ' + debugCollapseAll.classNames), + new CollapseAction(() => this.tree, true, 'explorer-action ' + ThemeIcon.asClassName(debugCollapseAll)), new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService) ]; } diff --git a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts index 4ccc9771607..ca7c0db5020 100644 --- a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts @@ -18,6 +18,7 @@ import { getContext, getContextForContributedActions, getSpecificSourceName } fr import { getStackFrameThreadAndSessionToFocus } from 'vs/workbench/contrib/debug/browser/debugService'; import { generateUuid } from 'vs/base/common/uuid'; import { debugStackframe, debugStackframeFocused } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession { return new DebugSession(generateUuid(), { resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, { @@ -309,7 +310,7 @@ suite('Debug - CallStack', () => { let decorations = createDecorationsForStackFrame(firstStackFrame, firstStackFrame.range, true); assert.equal(decorations.length, 2); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, debugStackframe.classNames); + assert.equal(decorations[0].options.glyphMarginClassName, ThemeIcon.asClassName(debugStackframe)); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-top-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); @@ -317,7 +318,7 @@ suite('Debug - CallStack', () => { decorations = createDecorationsForStackFrame(secondStackFrame, firstStackFrame.range, true); assert.equal(decorations.length, 2); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, debugStackframeFocused.classNames); + assert.equal(decorations[0].options.glyphMarginClassName, ThemeIcon.asClassName(debugStackframeFocused)); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-focused-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); @@ -325,7 +326,7 @@ suite('Debug - CallStack', () => { decorations = createDecorationsForStackFrame(firstStackFrame, new Range(1, 5, 1, 6), true); assert.equal(decorations.length, 3); assert.deepEqual(decorations[0].range, new Range(1, 2, 1, 1)); - assert.equal(decorations[0].options.glyphMarginClassName, debugStackframe.classNames); + assert.equal(decorations[0].options.glyphMarginClassName, ThemeIcon.asClassName(debugStackframe)); assert.deepEqual(decorations[1].range, new Range(1, Constants.MAX_SAFE_SMALL_INTEGER, 1, 1)); assert.equal(decorations[1].options.className, 'debug-top-stack-frame-line'); assert.equal(decorations[1].options.isWholeLine, true); diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index a97100a720f..a19c6fb877c 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -36,9 +36,9 @@ import { ILogService } from 'vs/platform/log/common/log'; import { isWeb } from 'vs/base/common/platform'; import { ColorScheme } from 'vs/platform/theme/common/theme'; import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; -import { CodiconStyles } from 'vs/base/browser/ui/codicons/codiconStyles'; import { RunOnceScheduler, Sequencer } from 'vs/base/common/async'; import { IUserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit'; +import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry'; // implementation @@ -179,12 +179,13 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { const codiconStyleSheet = createStyleSheet(); codiconStyleSheet.id = 'codiconStyles'; + const iconRegistry = getIconRegistry(); function updateAll() { - codiconStyleSheet.textContent = CodiconStyles.getCSS(); + codiconStyleSheet.textContent = iconRegistry.getCSS(); } const delayer = new RunOnceScheduler(updateAll, 0); - CodiconStyles.onDidChange(() => delayer.schedule()); + iconRegistry.onDidChange(() => delayer.schedule()); delayer.schedule(); } From 84cf12f40be434b836363f6c2a4e270d0470d9d0 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 17:42:07 +0100 Subject: [PATCH 0289/1837] Add trusted types policies where `.innerHTML` needs to be used (#108400) --- src/vs/editor/browser/view/domLineBreaksComputer.ts | 6 +++++- src/vs/editor/browser/widget/diffEditorWidget.ts | 5 ++++- src/vs/editor/standalone/browser/colorizer.ts | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/browser/view/domLineBreaksComputer.ts b/src/vs/editor/browser/view/domLineBreaksComputer.ts index 926d162f460..87c6461d54a 100644 --- a/src/vs/editor/browser/view/domLineBreaksComputer.ts +++ b/src/vs/editor/browser/view/domLineBreaksComputer.ts @@ -12,6 +12,8 @@ import * as strings from 'vs/base/common/strings'; import { Configuration } from 'vs/editor/browser/config/configuration'; import { ILineBreaksComputer, LineBreakData } from 'vs/editor/common/viewModel/viewModel'; +const ttPolicy = window.trustedTypes?.createPolicy('domLineBreaksComputer', { createHTML: value => value }); + export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory { public static create(): DOMLineBreaksComputerFactory { @@ -108,7 +110,9 @@ function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: numbe allCharOffsets[i] = tmp[0]; allVisibleColumns[i] = tmp[1]; } - containerDomNode.innerHTML = sb.build(); + const html = sb.build(); + const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html; + containerDomNode.innerHTML = trustedhtml as unknown as string; containerDomNode.style.position = 'absolute'; containerDomNode.style.top = '10000'; diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 31b375893d8..619ddfba0a3 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -156,6 +156,7 @@ let DIFF_EDITOR_ID = 0; const diffInsertIcon = registerIcon('diff-insert', Codicon.add); const diffRemoveIcon = registerIcon('diff-remove', Codicon.remove); +const ttPolicy = window.trustedTypes?.createPolicy('diffEditorWidget', { createHTML: value => value }); export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffEditor { @@ -2383,7 +2384,9 @@ class InlineViewZonesComputer extends ViewZonesComputer { } maxCharsPerLine += scrollBeyondLastColumn; - domNode.innerHTML = sb.build(); + const html = sb.build(); + const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html; + domNode.innerHTML = trustedhtml as unknown as string; viewZone.minWidthInPx = (maxCharsPerLine * typicalHalfwidthCharacterWidth); if (viewLineCounts) { diff --git a/src/vs/editor/standalone/browser/colorizer.ts b/src/vs/editor/standalone/browser/colorizer.ts index a45712fa85d..22bad13e9ef 100644 --- a/src/vs/editor/standalone/browser/colorizer.ts +++ b/src/vs/editor/standalone/browser/colorizer.ts @@ -15,6 +15,8 @@ import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import { MonarchTokenizer } from 'vs/editor/standalone/common/monarch/monarchLexer'; +const ttPolicy = window.trustedTypes?.createPolicy('standaloneColorizer', { createHTML: value => value }); + export interface IColorizerOptions { tabSize?: number; } @@ -40,7 +42,8 @@ export class Colorizer { let text = domNode.firstChild ? domNode.firstChild.nodeValue : ''; domNode.className += ' ' + theme; let render = (str: string) => { - domNode.innerHTML = str; + const trustedhtml = ttPolicy ? ttPolicy.createHTML(str) : str; + domNode.innerHTML = trustedhtml as unknown as string; }; return this.colorize(modeService, text || '', mimeType, options).then(render, (err) => console.error(err)); } From d7bdbe118ecd27812791f3e17a62c0eb723bbd0f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 17:42:27 +0100 Subject: [PATCH 0290/1837] Allow running `yarn tsec-compile-check` also on Windows --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 482ac3072d1..0f2e9b503ee 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "smoketest": "cd test/smoke && node test/index.js", "download-builtin-extensions": "node build/lib/builtInExtensions.js", "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", - "tsec-compile-check": "node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit", + "tsec-compile-check": "node node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit", "valid-layers-check": "node build/lib/layersChecker.js", "strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes", "update-distro": "node build/npm/update-distro.js", From e2c9d1a7a380e25d4d97a1ba86da37984c0bfb61 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 17:54:13 +0100 Subject: [PATCH 0291/1837] Avoid using `innerHTML` (#108400) --- .../test/browser/controller/imeTester.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/test/browser/controller/imeTester.ts b/src/vs/editor/test/browser/controller/imeTester.ts index 4a3f4e196df..eb0958400c4 100644 --- a/src/vs/editor/test/browser/controller/imeTester.ts +++ b/src/vs/editor/test/browser/controller/imeTester.ts @@ -9,6 +9,7 @@ import { ISimpleModel, PagedScreenReaderStrategy, TextAreaState } from 'vs/edito import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { EndOfLinePreference } from 'vs/editor/common/model'; +import * as dom from 'vs/base/browser/dom'; // To run this test, open imeTester.html @@ -50,12 +51,13 @@ class TestView { } public paint(output: HTMLElement) { - let r = ''; + dom.clearNode(output); for (let i = 1; i <= this._model.getLineCount(); i++) { - let content = this._model.getModelLineContent(i); - r += content + '
'; + const textNode = document.createTextNode(this._model.getModelLineContent(i)); + output.appendChild(textNode); + const br = document.createElement('br'); + output.appendChild(br); } - output.innerHTML = r; } } @@ -69,7 +71,12 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string let title = document.createElement('div'); title.className = 'title'; - title.innerHTML = description + '. Type ' + inputStr + ''; + const inputStrStrong = document.createElement('strong'); + inputStrStrong.innerText = inputStr; + + title.innerText = description + '. Type '; + title.appendChild(inputStrStrong); + container.appendChild(title); let startBtn = document.createElement('button'); @@ -140,7 +147,7 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string check.innerText = '[BAD]'; check.className = 'check bad'; } - check.innerHTML += expected; + check.appendChild(document.createTextNode(expected)); }; handler.onType((e) => { From b51a171a752b40963f79341963d1d4685b5fdab2 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 25 Nov 2020 09:55:35 -0800 Subject: [PATCH 0292/1837] Update codicons https://github.com/microsoft/vscode-codicons/commit/cbe2a17f2965d0f3ff363830fee4ebae5fee7c4d --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 62836 -> 62836 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 7b9d1812e32e9543c5b16ce115e96ed34453f264..7fdf6ed7b9db8580b4a762998936d06b55c37b51 100644 GIT binary patch delta 259 zcmezJiuubc<_Qi)t4i7?F)+x^VPH7okdd00B6a0v3j+hg10Xib01B{QXEg@0_W-d< zMs7)k#D0M#e8T76pst1>|L|lMM^X z3X%e>G)GyDja?aJiXk7Ph#c!=S3^4{H~-14 nhAQ%9mSB^Z6?quBxkR}g Date: Wed, 25 Nov 2020 19:18:58 +0100 Subject: [PATCH 0293/1837] don't leak env vars into process.env; fixes #83187 --- src/vs/workbench/contrib/debug/browser/rawDebugSession.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index dce391245dc..b93c12a826b 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -620,10 +620,10 @@ export class RawDebugSession implements IDisposable { } } - let env: IProcessEnvironment = {}; - if (vscodeArgs.env) { + let env: IProcessEnvironment = processEnv; + if (vscodeArgs.env && Object.keys(vscodeArgs.env).length > 0) { // merge environment variables into a copy of the process.env - env = objects.mixin(processEnv, vscodeArgs.env); + env = objects.mixin(objects.deepClone(process.env), vscodeArgs.env); // and delete some if necessary Object.keys(env).filter(k => env[k] === null).forEach(key => delete env[key]); } From 8dce3899da00b0c5ac10013f4327d01cf6f45003 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 25 Nov 2020 19:20:21 +0100 Subject: [PATCH 0294/1837] avoid unnecessary deepclone --- src/vs/workbench/contrib/debug/node/debugAdapter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index f9208710bfa..d8ba9f71e2c 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -199,9 +199,9 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { "Cannot determine executable for debug adapter '{0}'.", this.debugType)); } - let env = objects.mixin({}, process.env); - if (options.env) { - env = objects.mixin(env, options.env); + let env = process.env; + if (options.env && Object.keys(options.env).length > 0) { + env = objects.mixin(objects.deepClone(process.env), options.env); } if (command === 'node') { From af52f2cb8c7060749c6184f8bb91ce3bc7f046a9 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 20:23:04 +0100 Subject: [PATCH 0295/1837] `TextModel` should not dispose its `TextBuffer` --- src/vs/editor/common/model.ts | 2 +- .../common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts | 6 ------ src/vs/editor/common/model/textModel.ts | 5 ++++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index e41f1fdbcba..98ce23d7b0e 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -1327,7 +1327,7 @@ export interface IReadonlyTextBuffer { /** * @internal */ -export interface ITextBuffer extends IReadonlyTextBuffer, IDisposable { +export interface ITextBuffer extends IReadonlyTextBuffer { setEOL(newEOL: '\r\n' | '\n'): void; applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult; } diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index 2401eba3b3c..2b73835b2f4 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -51,12 +51,6 @@ export class PieceTreeTextBuffer extends Disposable implements ITextBuffer { this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized); } - dispose(): void { - super.dispose(); - // Manually release reference to previous piece tree to avoid large leaks - this._pieceTree = new PieceTreeBase([], '\n', true); - } - // #region TextBuffer public equals(other: ITextBuffer): boolean { if (!(other instanceof PieceTreeTextBuffer)) { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 9b161cb202a..2ba7cb4ee89 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -328,7 +328,7 @@ export class TextModel extends Disposable implements model.ITextModel { this._undoRedoService = undoRedoService; this._attachedEditorCount = 0; - this._buffer = this._register(createTextBuffer(source, creationOptions.defaultEOL)); + this._buffer = createTextBuffer(source, creationOptions.defaultEOL); this._options = TextModel.resolveOptions(this._buffer, creationOptions); @@ -387,6 +387,9 @@ export class TextModel extends Disposable implements model.ITextModel { this._isDisposed = true; super.dispose(); this._isDisposing = false; + // Manually release reference to previous text buffer to avoid large leaks + // in case someone leaks a TextModel reference + this._buffer = createTextBuffer('', this._options.defaultEOL); } private _assertNotDisposed(): void { From 3cd515d33e26b30d5dfb47a1b470d4efa18b035a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 25 Nov 2020 20:26:01 +0100 Subject: [PATCH 0296/1837] support installing web preferred extensions on web server --- .../extensions/browser/extensionsActions.ts | 24 ++++------ .../common/extensionManagement.ts | 3 +- .../common/extensionManagementService.ts | 46 ++++++------------- 3 files changed, 26 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 079ea8e7f6c..17b2a03b755 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -15,7 +15,7 @@ import { dispose } from 'vs/base/common/lifecycle'; import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, AutoUpdateConfigurationKey, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID } from 'vs/workbench/contrib/extensions/common/extensions'; import { ExtensionsConfigurationInitialContent } from 'vs/workbench/contrib/extensions/common/extensionsFileTemplate'; import { IGalleryExtension, IExtensionGalleryService, INSTALL_ERROR_MALICIOUS, INSTALL_ERROR_INCOMPATIBLE, IGalleryExtensionVersion, ILocalExtension, INSTALL_ERROR_NOT_SUPPORTED, InstallOptions, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; +import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensioManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionRecommendationReason, IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, ExtensionIdentifier, IExtensionDescription, IExtensionManifest, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions'; @@ -50,7 +50,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria'; import { coalesce } from 'vs/base/common/arrays'; import { IWorkbenchThemeService, IWorkbenchTheme, IWorkbenchColorTheme, IWorkbenchFileIconTheme, IWorkbenchProductIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { ILabelService } from 'vs/platform/label/common/label'; -import { prefersExecuteOnUI, prefersExecuteOnWorkspace, canExecuteOnUI, canExecuteOnWorkspace, prefersExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil'; +import { prefersExecuteOnUI, prefersExecuteOnWorkspace, canExecuteOnUI, canExecuteOnWorkspace } from 'vs/workbench/services/extensions/common/extensionsUtil'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IProductService } from 'vs/platform/product/common/productService'; import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -319,9 +319,8 @@ export class InstallAction extends AbstractInstallAction { @IExtensionService runtimeExtensionService: IExtensionService, @IWorkbenchThemeService workbenchThemeService: IWorkbenchThemeService, @ILabelService labelService: ILabelService, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IProductService private readonly productService: IProductService, @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, + @IWorkbenchExtensioManagementService private readonly workbenchExtensioManagementService: IWorkbenchExtensioManagementService, @IUserDataAutoSyncEnablementService protected readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService, @IUserDataSyncResourceEnablementService protected readonly userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService, ) { @@ -344,20 +343,15 @@ export class InstallAction extends AbstractInstallAction { // When remote connection exists if (this._manifest && this.extensionManagementServerService.remoteExtensionManagementServer) { - // On Desktop and UI Extension - if (this.extensionManagementServerService.localExtensionManagementServer && prefersExecuteOnUI(this._manifest, this.productService, this.configurationService)) { - this.label = isMachineScoped ? localize('install locally and do not sync', "Install Locally (Do not sync)") : localize('install locally', "Install Locally"); + const server = this.workbenchExtensioManagementService.getExtensionManagementServerToInstall(this._manifest); + + if (server === this.extensionManagementServerService.remoteExtensionManagementServer) { + const host = this.extensionManagementServerService.remoteExtensionManagementServer.label; + this.label = isMachineScoped ? localize('install on remote and do not sync', "Install on {0} (Do not sync)", host) : localize('install on remote', "Install on {0}", host); return; } - // On Web and Web Extension - if (this.extensionManagementServerService.webExtensionManagementServer && prefersExecuteOnWeb(this._manifest, this.productService, this.configurationService)) { - this.label = isMachineScoped ? localize('install locally and do not sync', "Install Locally (Do not sync)") : localize('install locally', "Install Locally"); - return; - } - - const host = this.extensionManagementServerService.remoteExtensionManagementServer.label; - this.label = isMachineScoped ? localize('install on remote and do not sync', "Install on {0} (Do not sync)", host) : localize('install on remote', "Install on {0}", host); + this.label = isMachineScoped ? localize('install locally and do not sync', "Install Locally (Do not sync)") : localize('install locally', "Install Locally"); return; } } diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts index e51b2217962..7f6e33de946 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts @@ -5,7 +5,7 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IExtension, IScannedExtension, ExtensionType, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions'; +import { IExtension, IScannedExtension, ExtensionType, ITranslatedScannedExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { IExtensionManagementService, IGalleryExtension, IExtensionIdentifier, ILocalExtension, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { URI } from 'vs/base/common/uri'; @@ -29,6 +29,7 @@ export interface IWorkbenchExtensioManagementService extends IExtensionManagemen readonly _serviceBrand: undefined; installExtensions(extensions: IGalleryExtension[], installOptions?: InstallOptions): Promise; updateFromGallery(gallery: IGalleryExtension, extension: ILocalExtension): Promise; + getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | null } export const enum EnablementState { diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index 3dd806177f7..f8f2a470fb8 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -15,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { CancellationToken } from 'vs/base/common/cancellation'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localize } from 'vs/nls'; -import { prefersExecuteOnUI, canExecuteOnWorkspace, prefersExecuteOnWorkspace, canExecuteOnUI, prefersExecuteOnWeb, canExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil'; +import { prefersExecuteOnUI, getExtensionKind } from 'vs/workbench/services/extensions/common/extensionsUtil'; import { IProductService } from 'vs/platform/product/common/productService'; import { Schemas } from 'vs/base/common/network'; import { IDownloadService } from 'vs/platform/download/common/download'; @@ -282,44 +282,28 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return Promise.reject(error); } - private getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | undefined { + getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | null { // Only local server if (this.servers.length === 1 && this.extensionManagementServerService.localExtensionManagementServer) { return this.extensionManagementServerService.localExtensionManagementServer; } - // 1. Install on preferred location - - // Install UI preferred extension on local server - if (prefersExecuteOnUI(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.localExtensionManagementServer) { - return this.extensionManagementServerService.localExtensionManagementServer; - } - // Install Workspace preferred extension on remote server - if (prefersExecuteOnWorkspace(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.remoteExtensionManagementServer) { - return this.extensionManagementServerService.remoteExtensionManagementServer; - } - // Install Web preferred extension on web server - if (prefersExecuteOnWeb(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.webExtensionManagementServer) { - return this.extensionManagementServerService.webExtensionManagementServer; + const extensionKind = getExtensionKind(manifest, this.productService, this.configurationService); + for (const kind of extensionKind) { + if (kind === 'ui' && this.extensionManagementServerService.localExtensionManagementServer) { + return this.extensionManagementServerService.localExtensionManagementServer; + } + if (kind === 'workspace' && this.extensionManagementServerService.remoteExtensionManagementServer) { + return this.extensionManagementServerService.remoteExtensionManagementServer; + } + if (kind === 'web' && this.extensionManagementServerService.webExtensionManagementServer) { + return this.extensionManagementServerService.webExtensionManagementServer; + } } - // 2. Install on supported location - - // Install UI supported extension on local server - if (canExecuteOnUI(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.localExtensionManagementServer) { - return this.extensionManagementServerService.localExtensionManagementServer; - } - // Install Workspace supported extension on remote server - if (canExecuteOnWorkspace(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.remoteExtensionManagementServer) { - return this.extensionManagementServerService.remoteExtensionManagementServer; - } - // Install Web supported extension on web server - if (canExecuteOnWeb(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.webExtensionManagementServer) { - return this.extensionManagementServerService.webExtensionManagementServer; - } - - return undefined; + // Local server can accept any extension. So return local server if not compatible server found. + return this.extensionManagementServerService.localExtensionManagementServer; } private async hasToFlagExtensionsMachineScoped(extensions: IGalleryExtension[]): Promise { From 6edf58b9ae517719bdf914a6e623b1d9958c2ec1 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 20:43:50 +0100 Subject: [PATCH 0297/1837] Avoid layer breaker (using `process` from `/browser/`) --- src/vs/workbench/contrib/debug/browser/rawDebugSession.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index b93c12a826b..a70036599d9 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -623,7 +623,7 @@ export class RawDebugSession implements IDisposable { let env: IProcessEnvironment = processEnv; if (vscodeArgs.env && Object.keys(vscodeArgs.env).length > 0) { // merge environment variables into a copy of the process.env - env = objects.mixin(objects.deepClone(process.env), vscodeArgs.env); + env = objects.mixin(objects.deepClone(processEnv), vscodeArgs.env); // and delete some if necessary Object.keys(env).filter(k => env[k] === null).forEach(key => delete env[key]); } From cad45e538a80f96e13b3b69809b6db0269d90e87 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 22:40:26 +0100 Subject: [PATCH 0298/1837] Add `ProtocolMessageType.ReplayRequest` such that missing messages can be requested again --- src/vs/base/parts/ipc/common/ipc.net.ts | 33 ++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts index bc8e97c269c..20a2ee63ce3 100644 --- a/src/vs/base/parts/ipc/common/ipc.net.ts +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -126,7 +126,8 @@ const enum ProtocolMessageType { Control = 2, Ack = 3, KeepAlive = 4, - Disconnect = 5 + Disconnect = 5, + ReplayRequest = 6 } export const enum ProtocolConstants { @@ -601,6 +602,8 @@ export class PersistentProtocol implements IMessagePassingProtocol { private _outgoingKeepAliveTimeout: any | null; private _incomingKeepAliveTimeout: any | null; + private _lastReplayRequestTime: number; + private _socket: ISocket; private _socketWriter: ProtocolWriter; private _socketReader: ProtocolReader; @@ -642,6 +645,8 @@ export class PersistentProtocol implements IMessagePassingProtocol { this._outgoingKeepAliveTimeout = null; this._incomingKeepAliveTimeout = null; + this._lastReplayRequestTime = 0; + this._socketDisposables = []; this._socket = socket; this._socketWriter = new ProtocolWriter(this._socket); @@ -747,6 +752,8 @@ export class PersistentProtocol implements IMessagePassingProtocol { this._onSocketTimeout.flushBuffer(); this._socket.dispose(); + this._lastReplayRequestTime = 0; + this._socket = socket; this._socketWriter = new ProtocolWriter(this._socket); this._socketDisposables.push(this._socketWriter); @@ -792,17 +799,31 @@ export class PersistentProtocol implements IMessagePassingProtocol { if (msg.type === ProtocolMessageType.Regular) { if (msg.id > this._incomingMsgId) { if (msg.id !== this._incomingMsgId + 1) { - console.error(`PROTOCOL CORRUPTION, LAST SAW MSG ${this._incomingMsgId} AND HAVE NOW RECEIVED MSG ${msg.id}`); + // in case we missed some messages we ask the other party to resend them + const now = Date.now(); + if (now - this._lastReplayRequestTime > 10000) { + // send a replay request at most once every 10s + this._lastReplayRequestTime = now; + this._socketWriter.write(new ProtocolMessage(ProtocolMessageType.ReplayRequest, 0, 0, getEmptyBuffer())); + } + } else { + this._incomingMsgId = msg.id; + this._incomingMsgLastTime = Date.now(); + this._sendAckCheck(); + this._onMessage.fire(msg.data); } - this._incomingMsgId = msg.id; - this._incomingMsgLastTime = Date.now(); - this._sendAckCheck(); - this._onMessage.fire(msg.data); } } else if (msg.type === ProtocolMessageType.Control) { this._onControlMessage.fire(msg.data); } else if (msg.type === ProtocolMessageType.Disconnect) { this._onClose.fire(); + } else if (msg.type === ProtocolMessageType.ReplayRequest) { + // Send again all unacknowledged messages + const toSend = this._outgoingUnackMsg.toArray(); + for (let i = 0, len = toSend.length; i < len; i++) { + this._socketWriter.write(toSend[i]); + } + this._recvAckCheck(); } } From c59ddc6a1fd855767db0cd1f17b6d65b520ae1f5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 22:51:05 +0100 Subject: [PATCH 0299/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f2e9b503ee..97613c38800 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "7acf21eaff37c77f31a9174a64954ef71b484f1e", + "distro": "52c70e96acffb178b85c6d50f6be99a1a261da42", "author": { "name": "Microsoft Corporation" }, From 2ecb47d4ecc46343c3ed64b92ca6c1be32725a34 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2020 22:49:18 +0100 Subject: [PATCH 0300/1837] Use ThemeIcon & IconRegistry for custom icons --- src/vs/base/browser/ui/checkbox/checkbox.ts | 4 +- src/vs/base/common/codicons.ts | 10 ++-- .../parts/quickinput/browser/quickInput.ts | 2 +- .../editor/browser/widget/diffEditorWidget.ts | 15 +++--- src/vs/editor/browser/widget/diffReview.ts | 17 +++--- src/vs/editor/contrib/find/findWidget.ts | 53 +++++++++++-------- src/vs/editor/contrib/folding/folding.ts | 6 +-- .../contrib/folding/foldingDecorations.ts | 18 ++++--- src/vs/editor/contrib/gotoError/gotoError.ts | 7 +-- .../parameterHints/parameterHintsWidget.ts | 13 ++--- .../contrib/suggest/suggestWidgetRenderer.ts | 9 ++-- src/vs/platform/theme/common/iconRegistry.ts | 8 +-- src/vs/platform/theme/common/themeService.ts | 7 +++ .../api/browser/mainThreadComments.ts | 3 +- .../parts/editor/editor.contribution.ts | 9 ++-- .../notifications/notificationsActions.ts | 28 +++++----- .../browser/parts/panel/panelActions.ts | 16 +++--- src/vs/workbench/common/views.ts | 3 +- .../browser/preview/bulkEdit.contribution.ts | 3 +- .../browser/callHierarchy.contribution.ts | 7 +-- .../browser/find/simpleFindReplaceWidget.ts | 13 ++--- .../browser/find/simpleFindWidget.ts | 9 ++-- .../browser/extensions.contribution.ts | 3 +- .../contrib/files/browser/explorerViewlet.ts | 3 +- .../markers/browser/markers.contribution.ts | 3 +- .../outline/browser/outline.contribution.ts | 3 +- .../output/browser/output.contribution.ts | 3 +- .../preferences/browser/keybindingsEditor.ts | 4 +- .../browser/preferencesRenderers.ts | 3 +- .../preferences/browser/preferencesWidgets.ts | 7 +-- .../preferences/browser/settingsWidgets.ts | 6 +-- .../contrib/remote/browser/remote.ts | 25 ++++----- .../contrib/scm/browser/scm.contribution.ts | 3 +- .../contrib/search/browser/searchActions.ts | 19 +++---- .../contrib/search/browser/searchIcons.ts | 31 ++++++----- .../contrib/search/browser/searchView.ts | 4 +- .../contrib/search/browser/searchWidget.ts | 16 +++--- .../searchEditor/browser/searchEditor.ts | 4 +- .../browser/searchEditorActions.ts | 3 +- .../terminal/browser/terminal.contribution.ts | 3 +- .../timeline/browser/timeline.contribution.ts | 3 +- .../contrib/timeline/browser/timelinePane.ts | 3 +- .../userDataSync/common/userDataSync.ts | 3 +- 43 files changed, 232 insertions(+), 180 deletions(-) diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index c3b0e243f91..932a28602da 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -11,12 +11,12 @@ import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, CSSIcon } from 'vs/base/common/codicons'; import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; export interface ICheckboxOpts extends ICheckboxStyles { readonly actionClassName?: string; - readonly icon?: Codicon; + readonly icon?: CSSIcon; readonly title: string; readonly isChecked: boolean; } diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index a9590734805..5448e242fe7 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -50,7 +50,7 @@ export function registerIcon(id: string, def: Codicon, description?: string) { return new Codicon(id, def, description); } -export class Codicon { +export class Codicon implements CSSIcon { constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition, public description?: string) { _registry.add(this); } @@ -58,10 +58,14 @@ export class Codicon { // classNamesArray is useful for migrating to ES6 classlist public get classNamesArray() { return ['codicon', 'codicon-' + this.id]; } public get cssSelector() { return '.codicon.codicon-' + this.id; } - - public get classNameIdentifier() { return 'codicon-' + this.id; } } +export interface CSSIcon { + readonly classNames: string; +} + + + interface IconDefinition { character: string; } diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 6c87b095b43..67542f72259 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -72,7 +72,7 @@ const $ = dom.$; type Writeable = { -readonly [P in keyof T]: T[P] }; -const backButtonIcon = registerIcon('quick-input-back', Codicon.arrowLeft); +const backButtonIcon = registerIcon('quick-input-back', Codicon.arrowLeft, localize('backButtonIcon', 'Icon for the back button in the quick input dialog.')); const backButton = { iconClass: backButtonIcon.classNames, diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 619ddfba0a3..9b5b41451f8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -39,7 +39,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { defaultInsertColor, defaultRemoveColor, diffBorder, diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, scrollbarShadow, scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground, diffDiagonalFill } from 'vs/platform/theme/common/colorRegistry'; -import { IColorTheme, IThemeService, getThemeTypeSelector, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, getThemeTypeSelector, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDiffLinesChange, InlineDiffMargin } from 'vs/editor/browser/widget/inlineDiffMargin'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -48,10 +48,11 @@ import { EditorExtensionsRegistry, IDiffEditorContributionDescription } from 'vs import { onUnexpectedError } from 'vs/base/common/errors'; import { IEditorProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor'; import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; interface IEditorDiffDecorations { decorations: IModelDeltaDecoration[]; @@ -154,8 +155,8 @@ class VisualEditorState { let DIFF_EDITOR_ID = 0; -const diffInsertIcon = registerIcon('diff-insert', Codicon.add); -const diffRemoveIcon = registerIcon('diff-remove', Codicon.remove); +const diffInsertIcon = registerIcon('diff-insert', Codicon.add, nls.localize('diffInsertIcon', 'Line decoration for inserts in the diff editor')); +const diffRemoveIcon = registerIcon('diff-remove', Codicon.remove, nls.localize('diffRemoveIcon', 'Line decoration for removals in the diff editor')); const ttPolicy = window.trustedTypes?.createPolicy('diffEditorWidget', { createHTML: value => value }); export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffEditor { @@ -1760,7 +1761,7 @@ const DECORATIONS = { }), lineInsertWithSign: ModelDecorationOptions.register({ className: 'line-insert', - linesDecorationsClassName: 'insert-sign ' + diffInsertIcon.classNames, + linesDecorationsClassName: 'insert-sign ' + ThemeIcon.asClassName(diffInsertIcon), marginClassName: 'line-insert', isWholeLine: true }), @@ -1772,7 +1773,7 @@ const DECORATIONS = { }), lineDeleteWithSign: ModelDecorationOptions.register({ className: 'line-delete', - linesDecorationsClassName: 'delete-sign ' + diffRemoveIcon.classNames, + linesDecorationsClassName: 'delete-sign ' + ThemeIcon.asClassName(diffRemoveIcon), marginClassName: 'line-delete', isWholeLine: true @@ -2462,7 +2463,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { if (this._renderIndicators) { const marginElement = document.createElement('div'); - marginElement.className = `delete-sign ${diffRemoveIcon.classNames}`; + marginElement.className = `delete-sign ${ThemeIcon.asClassName(diffRemoveIcon)}`; marginElement.setAttribute('style', `position:absolute;top:${renderedLineCount * lineHeight}px;width:${lineDecorationsWidth}px;height:${lineHeight}px;right:0;`); marginDomNode.appendChild(marginElement); } diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index 693261364d0..fd53314e1b7 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -29,9 +29,10 @@ import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { Constants } from 'vs/base/common/uint'; -import { registerIcon, Codicon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const DIFF_LINES_PADDING = 3; @@ -73,9 +74,9 @@ class Diff { } } -const diffReviewInsertIcon = registerIcon('diff-review-insert', Codicon.add); -const diffReviewRemoveIcon = registerIcon('diff-review-remove', Codicon.remove); -const diffReviewCloseIcon = registerIcon('diff-review-close', Codicon.close); +const diffReviewInsertIcon = registerIcon('diff-review-insert', Codicon.add, nls.localize('diffReviewInsertIcon', 'Icon for \'Insert\' in diff review.')); +const diffReviewRemoveIcon = registerIcon('diff-review-remove', Codicon.remove, nls.localize('diffReviewRemoveIcon', 'Icon for \'Remove\' in diff review.')); +const diffReviewCloseIcon = registerIcon('diff-review-close', Codicon.close, nls.localize('diffReviewCloseIcon', 'Icon for \'Close\' in diff review.')); export class DiffReview extends Disposable { @@ -104,7 +105,7 @@ export class DiffReview extends Disposable { this.actionBarContainer.domNode )); - this._actionBar.push(new Action('diffreview.close', nls.localize('label.close', "Close"), 'close-diff-review ' + diffReviewCloseIcon.classNames, true, () => { + this._actionBar.push(new Action('diffreview.close', nls.localize('label.close', "Close"), 'close-diff-review ' + ThemeIcon.asClassName(diffReviewCloseIcon), true, () => { this.hide(); return Promise.resolve(null); }), { label: false, icon: true }); @@ -647,7 +648,7 @@ export class DiffReview extends Disposable { let rowClassName: string = 'diff-review-row'; let lineNumbersExtraClassName: string = ''; const spacerClassName: string = 'diff-review-spacer'; - let spacerIcon: Codicon | null = null; + let spacerIcon: ThemeIcon | null = null; switch (type) { case DiffEntryType.Insert: rowClassName = 'diff-review-row line-insert'; @@ -723,7 +724,7 @@ export class DiffReview extends Disposable { if (spacerIcon) { const spacerCodicon = document.createElement('span'); - spacerCodicon.className = spacerIcon.classNames; + spacerCodicon.className = ThemeIcon.asClassName(spacerIcon); spacerCodicon.innerText = '\u00a0\u00a0'; spacer.appendChild(spacerCodicon); } else { diff --git a/src/vs/editor/contrib/find/findWidget.ts b/src/vs/editor/contrib/find/findWidget.ts index a429046dbb8..33944824331 100644 --- a/src/vs/editor/contrib/find/findWidget.ts +++ b/src/vs/editor/contrib/find/findWidget.ts @@ -31,22 +31,22 @@ import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contri import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { contrastBorder, editorFindMatch, editorFindMatchBorder, editorFindMatchHighlight, editorFindMatchHighlightBorder, editorFindRangeHighlight, editorFindRangeHighlightBorder, editorWidgetBackground, editorWidgetBorder, editorWidgetResizeBorder, errorForeground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground, focusBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput, ContextScopedReplaceInput } from 'vs/platform/browser/contextScopedHistoryWidget'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon, widgetClose } from 'vs/platform/theme/common/iconRegistry'; -const findSelectionIcon = registerIcon('find-selection', Codicon.selection); -const findCollapsedIcon = registerIcon('find-collapsed', Codicon.chevronRight); -const findExpandedIcon = registerIcon('find-expanded', Codicon.chevronDown); +const findSelectionIcon = registerIcon('find-selection', Codicon.selection, nls.localize('findSelectionIcon', 'Icon for \'Find in Selection\' in the editor find widget.')); +const findCollapsedIcon = registerIcon('find-collapsed', Codicon.chevronRight, nls.localize('findCollapsedIcon', 'Icon to indicate that the editor find widget is collapsed.')); +const findExpandedIcon = registerIcon('find-expanded', Codicon.chevronDown, nls.localize('findExpandedIcon', 'Icon to indicate that the editor find widget is expanded.')); -export const findCloseIcon = registerIcon('find-close', Codicon.close); -export const findReplaceIcon = registerIcon('find-replace', Codicon.replace); -export const findReplaceAllIcon = registerIcon('find-replace-all', Codicon.replaceAll); -export const findPreviousMatchIcon = registerIcon('find-previous-match', Codicon.arrowUp); -export const findNextMatchIcon = registerIcon('find-next-match', Codicon.arrowDown); +export const findReplaceIcon = registerIcon('find-replace', Codicon.replace, nls.localize('findReplaceIcon', 'Icon for \'Replace\' in the editor find widget.')); +export const findReplaceAllIcon = registerIcon('find-replace-all', Codicon.replaceAll, nls.localize('findReplaceAllIcon', 'Icon for \'Replace All\' in the editor find widget.')); +export const findPreviousMatchIcon = registerIcon('find-previous-match', Codicon.arrowUp, nls.localize('findPreviousMatchIcon', 'Icon for \'Find Previous\' in the editor find widget.')); +export const findNextMatchIcon = registerIcon('find-next-match', Codicon.arrowDown, nls.localize('findNextMatchIcon', 'Icon for \'Find Next\' in the editor find widget.')); export interface IFindController { replace(): void; @@ -1017,7 +1017,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Previous button this._prevBtn = this._register(new SimpleButton({ label: NLS_PREVIOUS_MATCH_BTN_LABEL + this._keybindingLabelFor(FIND_IDS.PreviousMatchFindAction), - className: findPreviousMatchIcon.classNames, + icon: findPreviousMatchIcon, onTrigger: () => { this._codeEditor.getAction(FIND_IDS.PreviousMatchFindAction).run().then(undefined, onUnexpectedError); } @@ -1026,7 +1026,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Next button this._nextBtn = this._register(new SimpleButton({ label: NLS_NEXT_MATCH_BTN_LABEL + this._keybindingLabelFor(FIND_IDS.NextMatchFindAction), - className: findNextMatchIcon.classNames, + icon: findNextMatchIcon, onTrigger: () => { this._codeEditor.getAction(FIND_IDS.NextMatchFindAction).run().then(undefined, onUnexpectedError); } @@ -1044,7 +1044,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Toggle selection button this._toggleSelectionFind = this._register(new Checkbox({ - icon: findSelectionIcon, + icon: ThemeIcon.asCSSIcon(findSelectionIcon), title: NLS_TOGGLE_SELECTION_FIND_TITLE + this._keybindingLabelFor(FIND_IDS.ToggleSearchScopeCommand), isChecked: false })); @@ -1077,7 +1077,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Close button this._closeBtn = this._register(new SimpleButton({ label: NLS_CLOSE_BTN_LABEL + this._keybindingLabelFor(FIND_IDS.CloseFindWidgetCommand), - className: findCloseIcon.classNames, + icon: widgetClose, onTrigger: () => { this._state.change({ isRevealed: false, searchScope: null }, false); }, @@ -1141,7 +1141,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Replace one button this._replaceBtn = this._register(new SimpleButton({ label: NLS_REPLACE_BTN_LABEL + this._keybindingLabelFor(FIND_IDS.ReplaceOneAction), - className: findReplaceIcon.classNames, + icon: findReplaceIcon, onTrigger: () => { this._controller.replace(); }, @@ -1156,7 +1156,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL // Replace all button this._replaceAllBtn = this._register(new SimpleButton({ label: NLS_REPLACE_ALL_BTN_LABEL + this._keybindingLabelFor(FIND_IDS.ReplaceAllAction), - className: findReplaceAllIcon.classNames, + icon: findReplaceAllIcon, onTrigger: () => { this._controller.replaceAll(); } @@ -1293,7 +1293,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL export interface ISimpleButtonOpts { readonly label: string; - readonly className: string; + readonly className?: string; + readonly icon?: ThemeIcon; readonly onTrigger: () => void; readonly onKeyDown?: (e: IKeyboardEvent) => void; } @@ -1307,10 +1308,18 @@ export class SimpleButton extends Widget { super(); this._opts = opts; + let className = 'button'; + if (this._opts.className) { + className = className + ' ' + this._opts.className; + } + if (this._opts.icon) { + className = className + ' ' + ThemeIcon.asClassName(this._opts.icon); + } + this._domNode = document.createElement('div'); this._domNode.title = this._opts.label; this._domNode.tabIndex = 0; - this._domNode.className = 'button ' + this._opts.className; + this._domNode.className = className; this._domNode.setAttribute('role', 'button'); this._domNode.setAttribute('aria-label', this._opts.label); @@ -1352,11 +1361,11 @@ export class SimpleButton extends Widget { public setExpanded(expanded: boolean): void { this._domNode.setAttribute('aria-expanded', String(!!expanded)); if (expanded) { - this._domNode.classList.remove(...findCollapsedIcon.classNames.split(' ')); - this._domNode.classList.add(...findExpandedIcon.classNames.split(' ')); + this._domNode.classList.remove(...ThemeIcon.asClassNameArray(findCollapsedIcon)); + this._domNode.classList.add(...ThemeIcon.asClassNameArray(findExpandedIcon)); } else { - this._domNode.classList.remove(...findExpandedIcon.classNames.split(' ')); - this._domNode.classList.add(...findCollapsedIcon.classNames.split(' ')); + this._domNode.classList.remove(...ThemeIcon.asClassNameArray(findExpandedIcon)); + this._domNode.classList.add(...ThemeIcon.asClassNameArray(findCollapsedIcon)); } } } diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 0bfa5f68166..1d48e06119d 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -32,7 +32,7 @@ import { InitializingRangeProvider, ID_INIT_PROVIDER } from 'vs/editor/contrib/f import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { onUnexpectedError } from 'vs/base/common/errors'; import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { registerColor, editorSelectionBackground, transparent, iconForeground } from 'vs/platform/theme/common/colorRegistry'; const CONTEXT_FOLDING_ENABLED = new RawContextKey('foldingEnabled', false); @@ -916,8 +916,8 @@ registerThemingParticipant((theme, collector) => { const editorFoldColor = theme.getColor(editorFoldForeground); if (editorFoldColor) { collector.addRule(` - .monaco-editor .cldr${foldingExpandedIcon.cssSelector}, - .monaco-editor .cldr${foldingCollapsedIcon.cssSelector} { + .monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingExpandedIcon)}, + .monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingCollapsedIcon)} { color: ${editorFoldColor} !important; } `); diff --git a/src/vs/editor/contrib/folding/foldingDecorations.ts b/src/vs/editor/contrib/folding/foldingDecorations.ts index c34e2c2121c..22601d1298e 100644 --- a/src/vs/editor/contrib/folding/foldingDecorations.ts +++ b/src/vs/editor/contrib/folding/foldingDecorations.ts @@ -7,18 +7,20 @@ import { TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationsChangeA import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { IDecorationProvider } from 'vs/editor/contrib/folding/foldingModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; - -export const foldingExpandedIcon = registerIcon('folding-expanded', Codicon.chevronDown); -export const foldingCollapsedIcon = registerIcon('folding-collapsed', Codicon.chevronRight); +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +export const foldingExpandedIcon = registerIcon('folding-expanded', Codicon.chevronDown, localize('foldingExpandedIcon', 'Icon for expanded ranges in the editor glyph margin.')); +export const foldingCollapsedIcon = registerIcon('folding-collapsed', Codicon.chevronRight, localize('foldingCollapsedIcon', 'Icon for collapsed ranges in the editor glyph margin.')); export class FoldingDecorationProvider implements IDecorationProvider { private static readonly COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, afterContentClassName: 'inline-folded', isWholeLine: true, - firstLineDecorationClassName: foldingCollapsedIcon.classNames + firstLineDecorationClassName: ThemeIcon.asClassName(foldingCollapsedIcon) }); private static readonly COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION = ModelDecorationOptions.register({ @@ -26,19 +28,19 @@ export class FoldingDecorationProvider implements IDecorationProvider { afterContentClassName: 'inline-folded', className: 'folded-background', isWholeLine: true, - firstLineDecorationClassName: foldingCollapsedIcon.classNames + firstLineDecorationClassName: ThemeIcon.asClassName(foldingCollapsedIcon) }); private static readonly EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, isWholeLine: true, - firstLineDecorationClassName: foldingExpandedIcon.classNames + firstLineDecorationClassName: ThemeIcon.asClassName(foldingExpandedIcon) }); private static readonly EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, isWholeLine: true, - firstLineDecorationClassName: 'alwaysShowFoldIcons ' + foldingExpandedIcon.classNames + firstLineDecorationClassName: 'alwaysShowFoldIcons ' + ThemeIcon.asClassName(foldingExpandedIcon) }); private static readonly HIDDEN_RANGE_DECORATION = ModelDecorationOptions.register({ diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index 001ed3f273b..259773d9065 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -20,9 +20,10 @@ import { MarkerNavigationWidget } from './gotoErrorWidget'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { MenuId } from 'vs/platform/actions/common/actions'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMarkerNavigationService, MarkerList } from 'vs/editor/contrib/gotoError/markerNavigationService'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export class MarkerController implements IEditorContribution { @@ -199,7 +200,7 @@ export class NextMarkerAction extends MarkerNavigationAction { menuOpts: { menuId: MarkerNavigationWidget.TitleMenu, title: NextMarkerAction.LABEL, - icon: registerIcon('marker-navigation-next', Codicon.chevronDown), + icon: registerIcon('marker-navigation-next', Codicon.chevronDown, nls.localize('nextMarkerIcon', 'Icon for goto next marker.')), group: 'navigation', order: 1 } @@ -224,7 +225,7 @@ class PrevMarkerAction extends MarkerNavigationAction { menuOpts: { menuId: MarkerNavigationWidget.TitleMenu, title: NextMarkerAction.LABEL, - icon: registerIcon('marker-navigation-previous', Codicon.chevronUp), + icon: registerIcon('marker-navigation-previous', Codicon.chevronUp, nls.localize('previousMarkerIcon', 'Icon for goto previous marker.')), group: 'navigation', order: 2 } diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index 2d0d4bcd349..54b7a807b9c 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -20,17 +20,18 @@ import * as nls from 'vs/nls'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { editorHoverBackground, editorHoverBorder, textCodeBlockBackground, textLinkForeground, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ParameterHintsModel, TriggerContext } from 'vs/editor/contrib/parameterHints/parameterHintsModel'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; -import { registerIcon, Codicon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { assertIsDefined } from 'vs/base/common/types'; import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const $ = dom.$; -const parameterHintsNextIcon = registerIcon('parameter-hints-next', Codicon.chevronDown); -const parameterHintsPreviousIcon = registerIcon('parameter-hints-previous', Codicon.chevronUp); +const parameterHintsNextIcon = registerIcon('parameter-hints-next', Codicon.chevronDown, nls.localize('parameterHintsNextIcon', 'Icon for show next parameter hint.')); +const parameterHintsPreviousIcon = registerIcon('parameter-hints-previous', Codicon.chevronUp, nls.localize('parameterHintsPreviousIcon', 'Icon for show previous parameter hint.')); export class ParameterHintsWidget extends Disposable implements IContentWidget { @@ -84,9 +85,9 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget { wrapper.tabIndex = -1; const controls = dom.append(wrapper, $('.controls')); - const previous = dom.append(controls, $('.button' + parameterHintsPreviousIcon.cssSelector)); + const previous = dom.append(controls, $('.button' + ThemeIcon.asCSSSelector(parameterHintsPreviousIcon))); const overloads = dom.append(controls, $('.overloads')); - const next = dom.append(controls, $('.button' + parameterHintsNextIcon.cssSelector)); + const next = dom.append(controls, $('.button' + ThemeIcon.asCSSSelector(parameterHintsNextIcon))); const onPreviousClick = stop(domEvent(previous, 'click')); this._register(onPreviousClick(this.previous, this)); diff --git a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts index 01e42685a92..48fb74da03b 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts @@ -11,7 +11,7 @@ import { IListRenderer } from 'vs/base/browser/ui/list/list'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { CompletionItem } from './suggest'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { CompletionItemKind, completionKindToCssClass, CompletionItemTag } from 'vs/editor/common/modes'; import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; @@ -21,14 +21,15 @@ import { URI } from 'vs/base/common/uri'; import { FileKind } from 'vs/platform/files/common/files'; import { flatten } from 'vs/base/common/arrays'; import { canExpandCompletionItem } from './suggestWidgetDetails'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { Emitter, Event } from 'vs/base/common/event'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export function getAriaId(index: number): string { return `suggest-aria-id:${index}`; } -export const suggestMoreInfoIcon = registerIcon('suggest-more-info', Codicon.chevronRight); +export const suggestMoreInfoIcon = registerIcon('suggest-more-info', Codicon.chevronRight, nls.localize('suggestMoreInfoIcon', 'Icon for more information in the suggest widget.')); const colorRegExp = /^(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))$/i; @@ -116,7 +117,7 @@ export class ItemRenderer implements IListRenderer { diff --git a/src/vs/platform/theme/common/iconRegistry.ts b/src/vs/platform/theme/common/iconRegistry.ts index 79ae6dffdc1..a7474fc4a54 100644 --- a/src/vs/platform/theme/common/iconRegistry.ts +++ b/src/vs/platform/theme/common/iconRegistry.ts @@ -45,7 +45,7 @@ export interface IIconRegistry { * @param defaults The default values * @description the description */ - registerIcon(id: string, defaults: IconDefaults, description: string): ThemeIcon; + registerIcon(id: string, defaults: IconDefaults, description?: string): ThemeIcon; /** * Register a icon to the registry. @@ -224,7 +224,7 @@ class IconRegistry implements IIconRegistry { const iconRegistry = new IconRegistry(); platform.Registry.add(Extensions.IconContribution, iconRegistry); -export function registerIcon(id: string, defaults: IconDefaults, description?: string, deprecationMessage?: string): ThemeIcon { +export function registerIcon(id: string, defaults: IconDefaults, description: string, deprecationMessage?: string): ThemeIcon { return iconRegistry.registerIcon(id, defaults, description, deprecationMessage); } @@ -234,9 +234,9 @@ export function getIconRegistry(): IIconRegistry { function initialize() { for (const icon of Codicons.iconRegistry.all) { - registerIcon(icon.id, icon.definition); + iconRegistry.registerIcon(icon.id, icon.definition, icon.description); } - Codicons.iconRegistry.onDidRegister(icon => registerIcon(icon.id, icon.definition)); + Codicons.iconRegistry.onDidRegister(icon => iconRegistry.registerIcon(icon.id, icon.definition, icon.description)); } initialize(); diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 56ce464ca60..7650acb28d2 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -11,6 +11,7 @@ import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { CSSIcon } from 'vs/base/common/codicons'; export const IThemeService = createDecorator('themeService'); @@ -93,6 +94,12 @@ export namespace ThemeIcon { return '.' + asClassNameArray(icon).join('.'); } + export function asCSSIcon(icon: ThemeIcon): CSSIcon { + return { + classNames: asClassName(icon) + }; + } + export function revive(icon: any): ThemeIcon | undefined { if (ThemeIcon.isThemeIcon(icon)) { diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index d8aa4bfcda6..8dba884cb92 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -20,7 +20,8 @@ import { COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE } from 'vs/workbench/contrib/comm import { ViewContainer, IViewContainersRegistry, Extensions as ViewExtensions, ViewContainerLocation, IViewsRegistry, IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { localize } from 'vs/nls'; diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index bfae9f51f2a..67b1c29733b 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -55,7 +55,8 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess, AllEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { FileAccess } from 'vs/base/common/network'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; // Register String Editor Registry.as(EditorExtensions.Editors).registerEditor( @@ -586,9 +587,9 @@ appendEditorToolItem( } ); -const previousChangeIcon = registerIcon('diff-editor-previous-change', Codicon.arrowUp, nls.localize('previousChangeIcon', 'Icon for the previous change action in the diff editor')); -const nextChangeIcon = registerIcon('diff-editor-next-change', Codicon.arrowDown, nls.localize('nextChangeIcon', 'Icon for the next change action in the diff editor')); -const toggleWhitespace = registerIcon('diff-editor-toggle-whitespace', Codicon.whitespace, nls.localize('toggleWhitespace', 'Icon for the toggle whitespace action in the diff editor')); +const previousChangeIcon = registerIcon('diff-editor-previous-change', Codicon.arrowUp, nls.localize('previousChangeIcon', 'Icon for the previous change action in the diff editor.')); +const nextChangeIcon = registerIcon('diff-editor-next-change', Codicon.arrowDown, nls.localize('nextChangeIcon', 'Icon for the next change action in the diff editor.')); +const toggleWhitespace = registerIcon('diff-editor-toggle-whitespace', Codicon.whitespace, nls.localize('toggleWhitespace', 'Icon for the toggle whitespace action in the diff editor.')); // Diff Editor Title Menu: Previous Change diff --git a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts index 477b90cfc2a..7aaa25068fc 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts @@ -12,14 +12,16 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { CLEAR_NOTIFICATION, EXPAND_NOTIFICATION, COLLAPSE_NOTIFICATION, CLEAR_ALL_NOTIFICATIONS, HIDE_NOTIFICATIONS_CENTER } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -const clearIcon = registerIcon('notifications-clear', Codicon.close); -const clearAllIcon = registerIcon('notifications-clear-all', Codicon.clearAll); -const hideIcon = registerIcon('notifications-hide', Codicon.chevronDown); -const expandIcon = registerIcon('notifications-expand', Codicon.chevronUp); -const collapseIcon = registerIcon('notifications-collapse', Codicon.chevronDown); -const configureIcon = registerIcon('notifications-configure', Codicon.gear); +const clearIcon = registerIcon('notifications-clear', Codicon.close, localize('clearIcon', 'Icon for the clear action in notifications.')); +const clearAllIcon = registerIcon('notifications-clear-all', Codicon.clearAll, localize('clearAllIcon', 'Icon for the clear all action in notifications.')); +const hideIcon = registerIcon('notifications-hide', Codicon.chevronDown, localize('hideIcon', 'Icon for the hide action in notifications.')); +const expandIcon = registerIcon('notifications-expand', Codicon.chevronUp, localize('expandIcon', 'Icon for the expand action in notifications.')); +const collapseIcon = registerIcon('notifications-collapse', Codicon.chevronDown, localize('collapseIcon', 'Icon for the collapse action in notifications.')); +const configureIcon = registerIcon('notifications-configure', Codicon.gear, localize('configureIcon', 'Icon for the configure action in notifications.')); export class ClearNotificationAction extends Action { @@ -31,7 +33,7 @@ export class ClearNotificationAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, clearIcon.classNames); + super(id, label, ThemeIcon.asClassName(clearIcon)); } async run(notification: INotificationViewItem): Promise { @@ -49,7 +51,7 @@ export class ClearAllNotificationsAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, clearAllIcon.classNames); + super(id, label, ThemeIcon.asClassName(clearAllIcon)); } async run(): Promise { @@ -67,7 +69,7 @@ export class HideNotificationsCenterAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, hideIcon.classNames); + super(id, label, ThemeIcon.asClassName(hideIcon)); } async run(): Promise { @@ -85,7 +87,7 @@ export class ExpandNotificationAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, expandIcon.classNames); + super(id, label, ThemeIcon.asClassName(expandIcon)); } async run(notification: INotificationViewItem): Promise { @@ -103,7 +105,7 @@ export class CollapseNotificationAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, collapseIcon.classNames); + super(id, label, ThemeIcon.asClassName(collapseIcon)); } async run(notification: INotificationViewItem): Promise { @@ -121,7 +123,7 @@ export class ConfigureNotificationAction extends Action { label: string, public readonly configurationActions: ReadonlyArray ) { - super(id, label, configureIcon.classNames); + super(id, label, ThemeIcon.asClassName(configureIcon)); } } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 41674f53feb..74619ecec37 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -18,11 +18,13 @@ import { IActivity } from 'vs/workbench/common/activity'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ActivePanelContext, PanelPositionContext } from 'vs/workbench/common/panel'; import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -const maximizeIcon = registerIcon('panel-maximize', Codicon.chevronUp); -const restoreIcon = registerIcon('panel-restore', Codicon.chevronDown); -const closeIcon = registerIcon('panel-close', Codicon.close); +const maximizeIcon = registerIcon('panel-maximize', Codicon.chevronUp, nls.localize('maximizeIcon', 'Icon to maximize a panel.')); +const restoreIcon = registerIcon('panel-restore', Codicon.chevronDown, nls.localize('restoreIcon', 'Icon to restore a panel.')); +const closeIcon = registerIcon('panel-close', Codicon.close, nls.localize('closeIcon', 'Icon to close a panel.')); export class ClosePanelAction extends Action { @@ -34,7 +36,7 @@ export class ClosePanelAction extends Action { name: string, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService ) { - super(id, name, closeIcon.classNames); + super(id, name, ThemeIcon.asClassName(closeIcon)); } async run(): Promise { @@ -106,11 +108,11 @@ export class ToggleMaximizedPanelAction extends Action { @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IEditorGroupsService editorGroupsService: IEditorGroupsService ) { - super(id, label, layoutService.isPanelMaximized() ? restoreIcon.classNames : maximizeIcon.classNames); + super(id, label, layoutService.isPanelMaximized() ? ThemeIcon.asClassName(restoreIcon) : ThemeIcon.asClassName(maximizeIcon)); this.toDispose.add(editorGroupsService.onDidLayout(() => { const maximized = this.layoutService.isPanelMaximized(); - this.class = maximized ? restoreIcon.classNames : maximizeIcon.classNames; + this.class = maximized ? ThemeIcon.asClassName(restoreIcon) : ThemeIcon.asClassName(maximizeIcon); this.label = maximized ? ToggleMaximizedPanelAction.RESTORE_LABEL : ToggleMaximizedPanelAction.MAXIMIZE_LABEL; })); } diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 9205a76de48..08b11a95553 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -25,7 +25,8 @@ import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { mixin } from 'vs/base/common/objects'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test'; export const testViewIcon = registerIcon('test-view-icon', Codicon.beaker, localize('testViewIcon', 'View icon of the test view.')); diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts index eac6f2517d1..7a757cf09d7 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts @@ -27,7 +27,8 @@ import type { ServicesAccessor } from 'vs/platform/instantiation/common/instanti import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; async function getBulkEditPane(viewsService: IViewsService): Promise { const view = await viewsService.openView(BulkEditPane.ID, true); diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts index e3961eb12f6..85c2711cb46 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts @@ -23,7 +23,8 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService import { Range } from 'vs/editor/common/core/range'; import { IPosition } from 'vs/editor/common/core/position'; import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; -import { registerIcon, Codicon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const _ctxHasCallHierarchyProvider = new RawContextKey('editorHasCallHierarchyProvider', false); const _ctxCallHierarchyVisible = new RawContextKey('callHierarchyVisible', false); @@ -207,7 +208,7 @@ registerAction2(class extends EditorAction2 { super({ id: 'editor.showIncomingCalls', title: { value: localize('title.incoming', "Show Incoming Calls"), original: 'Show Incoming Calls' }, - icon: registerIcon('callhierarchy-incoming', Codicon.callIncoming), + icon: registerIcon('callhierarchy-incoming', Codicon.callIncoming, localize('showIncomingCallsIcons', 'Icon for incoming calls in the call hierarchy view.')), precondition: ContextKeyExpr.and(_ctxCallHierarchyVisible, _ctxCallHierarchyDirection.isEqualTo(CallHierarchyDirection.CallsFrom)), keybinding: { weight: KeybindingWeight.WorkbenchContrib, @@ -232,7 +233,7 @@ registerAction2(class extends EditorAction2 { super({ id: 'editor.showOutgoingCalls', title: { value: localize('title.outgoing', "Show Outgoing Calls"), original: 'Show Outgoing Calls' }, - icon: registerIcon('callhierarchy-outgoing', Codicon.callOutgoing), + icon: registerIcon('callhierarchy-outgoing', Codicon.callOutgoing, localize('showOutgoingCallsIcon', 'Icon for outgoing calls in the call hierarchy view.')), precondition: ContextKeyExpr.and(_ctxCallHierarchyVisible, _ctxCallHierarchyDirection.isEqualTo(CallHierarchyDirection.CallsTo)), keybinding: { weight: KeybindingWeight.WorkbenchContrib, diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts index 29ab04607d3..cb7b1e97b5c 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts @@ -12,7 +12,7 @@ import { Delayer } from 'vs/base/common/async'; import { KeyCode } from 'vs/base/common/keyCodes'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState'; import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox'; -import { SimpleButton, findCloseIcon, findNextMatchIcon, findPreviousMatchIcon, findReplaceIcon, findReplaceAllIcon } from 'vs/editor/contrib/find/findWidget'; +import { SimpleButton, findNextMatchIcon, findPreviousMatchIcon, findReplaceIcon, findReplaceAllIcon } from 'vs/editor/contrib/find/findWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground } from 'vs/platform/theme/common/colorRegistry'; @@ -21,6 +21,7 @@ import { ContextScopedFindInput, ContextScopedReplaceInput } from 'vs/platform/b import { ReplaceInput, IReplaceInputStyles } from 'vs/base/browser/ui/findinput/replaceInput'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; +import { widgetClose } from 'vs/platform/theme/common/iconRegistry'; const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find"); const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); @@ -146,7 +147,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { this.prevBtn = this._register(new SimpleButton({ label: NLS_PREVIOUS_MATCH_BTN_LABEL, - className: findPreviousMatchIcon.classNames, + icon: findPreviousMatchIcon, onTrigger: () => { this.find(true); } @@ -154,7 +155,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { this.nextBtn = this._register(new SimpleButton({ label: NLS_NEXT_MATCH_BTN_LABEL, - className: findNextMatchIcon.classNames, + icon: findNextMatchIcon, onTrigger: () => { this.find(false); } @@ -162,7 +163,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { const closeBtn = this._register(new SimpleButton({ label: NLS_CLOSE_BTN_LABEL, - className: findCloseIcon.classNames, + icon: widgetClose, onTrigger: () => { this.hide(); } @@ -220,7 +221,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._replaceBtn = this._register(new SimpleButton({ label: NLS_REPLACE_BTN_LABEL, - className: findReplaceIcon.classNames, + icon: findReplaceIcon, onTrigger: () => { this.replaceOne(); } @@ -229,7 +230,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { // Replace all button this._replaceAllBtn = this._register(new SimpleButton({ label: NLS_REPLACE_ALL_BTN_LABEL, - className: findReplaceAllIcon.classNames, + icon: findReplaceAllIcon, onTrigger: () => { this.replaceAll(); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 6d8aaf29c1a..6226e8fb848 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -12,12 +12,13 @@ import { Delayer } from 'vs/base/common/async'; import { KeyCode } from 'vs/base/common/keyCodes'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox'; -import { SimpleButton, findPreviousMatchIcon, findNextMatchIcon, findCloseIcon } from 'vs/editor/contrib/find/findWidget'; +import { SimpleButton, findPreviousMatchIcon, findNextMatchIcon } from 'vs/editor/contrib/find/findWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput } from 'vs/platform/browser/contextScopedHistoryWidget'; +import { widgetClose } from 'vs/platform/theme/common/iconRegistry'; const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find"); const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); @@ -94,7 +95,7 @@ export abstract class SimpleFindWidget extends Widget { this.prevBtn = this._register(new SimpleButton({ label: NLS_PREVIOUS_MATCH_BTN_LABEL, - className: findPreviousMatchIcon.classNames, + icon: findPreviousMatchIcon, onTrigger: () => { this.find(true); } @@ -102,7 +103,7 @@ export abstract class SimpleFindWidget extends Widget { this.nextBtn = this._register(new SimpleButton({ label: NLS_NEXT_MATCH_BTN_LABEL, - className: findNextMatchIcon.classNames, + icon: findNextMatchIcon, onTrigger: () => { this.find(false); } @@ -110,7 +111,7 @@ export abstract class SimpleFindWidget extends Widget { const closeBtn = this._register(new SimpleButton({ label: NLS_CLOSE_BTN_LABEL, - className: findCloseIcon.classNames, + icon: widgetClose, onTrigger: () => { this.hide(); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 36676ca8bb2..dba30cc4e53 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -64,7 +64,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { ShowRuntimeExtensionsAction } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; // Singletons diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 7e1a9520b46..9745ec52db6 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -37,7 +37,8 @@ import { WorkbenchStateContext, RemoteNameContext } from 'vs/workbench/browser/c import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { AddRootFolderAction, OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; import { isMacintosh } from 'vs/base/common/platform'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const explorerViewIcon = registerIcon('explorer-view-icon', Codicon.files, localize('explorerViewIcon', 'View icon of the explorer view.')); diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index 6951a95e8e8..b7fcb530df4 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -32,7 +32,8 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import type { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index f43351c42ce..01b5f2a9ecc 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -11,7 +11,8 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export const PANEL_ID = 'panel.view.outline'; diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index 59365a234a2..0b615745928 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -32,7 +32,8 @@ import { assertIsDefined } from 'vs/base/common/types'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { CATEGORIES } from 'vs/workbench/common/actions'; // Register Service diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index f70011ab386..af69f6a7450 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -26,7 +26,7 @@ import { CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDIN import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; import { IListVirtualDelegate, IListRenderer, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode, ResolvedKeybinding } from 'vs/base/common/keyCodes'; @@ -926,7 +926,7 @@ class ActionsColumn extends Column { private createEditAction(keybindingItemEntry: IKeybindingItemEntry): IAction { const keybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_DEFINE); return { - class: preferencesEditIcon.classNames, + class: ThemeIcon.asClassName(preferencesEditIcon), enabled: true, id: 'editKeybinding', tooltip: keybinding ? localize('editKeybindingLabelWithKey', "Change Keybinding {0}", `(${keybinding.getLabel()})`) : localize('editKeybindingLabel', "Change Keybinding"), diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts index 52629d75ea6..7c2bee4dc42 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts @@ -32,6 +32,7 @@ import { IMarkerService, IMarkerData, MarkerSeverity, MarkerTag } from 'vs/platf import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { FindDecorations } from 'vs/editor/contrib/find/findDecorations'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export interface IPreferencesRenderer extends IDisposable { readonly preferencesModel: IPreferencesEditorModel; @@ -737,7 +738,7 @@ class EditSettingRenderer extends Disposable { const decorations = this.editor.getLineDecorations(line); if (decorations) { for (const { options } of decorations) { - if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf(preferencesEditIcon.classNames) === -1) { + if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf(ThemeIcon.asClassName(preferencesEditIcon)) === -1) { return false; } } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index a736bea3081..d24ee483241 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -28,14 +28,15 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { Schemas } from 'vs/base/common/network'; import { activeContrastBorder, badgeBackground, badgeForeground, contrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { attachInputBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; -import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND } from 'vs/workbench/common/theme'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ISettingsGroup, IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { isEqual } from 'vs/base/common/resources'; -import { registerIcon, Codicon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; export class SettingsHeaderWidget extends Widget implements IViewZone { @@ -785,7 +786,7 @@ export class EditPreferenceWidget extends Disposable { this._line = line; newDecoration.push({ options: { - glyphMarginClassName: preferencesEditIcon.classNames, + glyphMarginClassName: ThemeIcon.asClassName(preferencesEditIcon), glyphMarginHoverMessage: new MarkdownString().appendText(hoverMessage), stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, }, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts index 944f05ef4d8..023052f548c 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts @@ -23,7 +23,7 @@ import { localize } from 'vs/nls'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { editorWidgetBorder, focusBorder, foreground, inputBackground, inputBorder, inputForeground, listActiveSelectionBackground, listActiveSelectionForeground, listFocusBackground, listHoverBackground, listHoverForeground, listInactiveSelectionBackground, listInactiveSelectionForeground, registerColor, selectBackground, selectBorder, selectForeground, simpleCheckboxBackground, simpleCheckboxBorder, simpleCheckboxForeground, textLinkActiveForeground, textLinkForeground, textPreformatForeground, transparent } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; -import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { preferencesEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; const $ = DOM.$; @@ -496,7 +496,7 @@ export class ListSettingWidget extends AbstractListSettingWidget protected getActionsForItem(item: IListDataItem, idx: number): IAction[] { return [ { - class: preferencesEditIcon.classNames, + class: ThemeIcon.asClassName(preferencesEditIcon), enabled: true, id: 'workbench.action.editListItem', tooltip: this.getLocalizedStrings().editActionTooltip, @@ -740,7 +740,7 @@ export class ObjectSettingWidget extends AbstractListSettingWidget { } } -const getStartedIcon = registerIcon('remote-explorer-get-started', Codicon.star); -const documentationIcon = registerIcon('remote-explorer-documentation', Codicon.book); -const feedbackIcon = registerIcon('remote-explorer-feedback', Codicon.twitter); -const reviewIssuesIcon = registerIcon('remote-explorer-review-issues', Codicon.issues); -const reportIssuesIcon = registerIcon('remote-explorer-report-issues', Codicon.comment); +const getStartedIcon = registerIcon('remote-explorer-get-started', Codicon.star, nls.localize('getStartedIcon', 'Getting started icon in the remote explorer view.')); +const documentationIcon = registerIcon('remote-explorer-documentation', Codicon.book, nls.localize('documentationIcon', 'Documentation icon in the remote explorer view.')); +const feedbackIcon = registerIcon('remote-explorer-feedback', Codicon.twitter, nls.localize('feedbackIcon', 'Feedback icon in the remote explorer view.')); +const reviewIssuesIcon = registerIcon('remote-explorer-review-issues', Codicon.issues, nls.localize('reviewIssuesIcon', 'Review issue icon in the remote explorer view.')); +const reportIssuesIcon = registerIcon('remote-explorer-report-issues', Codicon.comment, nls.localize('reportIssuesIcon', 'Report issue icon in the remote explorer view.')); const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); interface IHelpItem { - icon: Codicon, + icon: ThemeIcon, iconClasses: string[]; label: string; handleClick(): Promise; @@ -298,14 +299,14 @@ class HelpItemValue { abstract class HelpItemBase implements IHelpItem { public iconClasses: string[] = []; constructor( - public icon: Codicon, + public icon: ThemeIcon, public label: string, public values: HelpItemValue[], private quickInputService: IQuickInputService, private environmentService: IWorkbenchEnvironmentService, private remoteExplorerService: IRemoteExplorerService ) { - this.iconClasses.push(...icon.classNamesArray); + this.iconClasses.push(...ThemeIcon.asClassNameArray(icon)); this.iconClasses.push('remote-help-tree-node-item-icon'); } @@ -352,7 +353,7 @@ abstract class HelpItemBase implements IHelpItem { class HelpItem extends HelpItemBase { constructor( - icon: Codicon, + icon: ThemeIcon, label: string, values: HelpItemValue[], quickInputService: IQuickInputService, @@ -370,7 +371,7 @@ class HelpItem extends HelpItemBase { class IssueReporterItem extends HelpItemBase { constructor( - icon: Codicon, + icon: ThemeIcon, label: string, values: HelpItemValue[], quickInputService: IQuickInputService, diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index a7d173b5ec7..98a0f62f8fa 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -22,7 +22,8 @@ import { IViewContainersRegistry, ViewContainerLocation, Extensions as ViewConta import { SCMViewPaneContainer } from 'vs/workbench/contrib/scm/browser/scmViewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane'; import { SCMViewService } from 'vs/workbench/contrib/scm/browser/scmViewService'; import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRepositoriesViewPane'; diff --git a/src/vs/workbench/contrib/search/browser/searchActions.ts b/src/vs/workbench/contrib/search/browser/searchActions.ts index d8abe601bd5..4e136901b2b 100644 --- a/src/vs/workbench/contrib/search/browser/searchActions.ts +++ b/src/vs/workbench/contrib/search/browser/searchActions.ts @@ -29,6 +29,7 @@ import { SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/sea import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor'; import { searchRefreshIcon, searchCollapseAllIcon, searchExpandAllIcon, searchClearIcon, searchReplaceAllIcon, searchReplaceIcon, searchRemoveIcon, searchStopIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export function isSearchViewFocused(viewsService: IViewsService): boolean { const searchView = getSearchView(viewsService); @@ -279,7 +280,7 @@ export class RefreshAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'search-action ' + searchRefreshIcon.classNames); + super(id, label, 'search-action ' + ThemeIcon.asClassName(searchRefreshIcon)); } get enabled(): boolean { @@ -309,7 +310,7 @@ export class CollapseDeepestExpandedLevelAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'search-action ' + searchCollapseAllIcon.classNames); + super(id, label, 'search-action ' + ThemeIcon.asClassName(searchCollapseAllIcon)); this.update(); } @@ -365,7 +366,7 @@ export class ExpandAllAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'search-action ' + searchExpandAllIcon.classNames); + super(id, label, 'search-action ' + ThemeIcon.asClassName(searchExpandAllIcon)); this.update(); } @@ -449,7 +450,7 @@ export class ClearSearchResultsAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'search-action ' + searchClearIcon.classNames); + super(id, label, 'search-action ' + ThemeIcon.asClassName(searchClearIcon)); this.update(); } @@ -475,7 +476,7 @@ export class CancelSearchAction extends Action { constructor(id: string, label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'search-action ' + searchStopIcon.classNames); + super(id, label, 'search-action ' + ThemeIcon.asClassName(searchStopIcon)); this.update(); } @@ -610,7 +611,7 @@ export class RemoveAction extends AbstractSearchAndReplaceAction { private viewer: WorkbenchObjectTree, private element: RenderableMatch ) { - super('remove', RemoveAction.LABEL, searchRemoveIcon.classNames); + super('remove', RemoveAction.LABEL, ThemeIcon.asClassName(searchRemoveIcon)); } run(): Promise { @@ -650,7 +651,7 @@ export class ReplaceAllAction extends AbstractSearchAndReplaceAction { private fileMatch: FileMatch, @IKeybindingService keyBindingService: IKeybindingService ) { - super(Constants.ReplaceAllInFileActionId, appendKeyBindingLabel(ReplaceAllAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFileActionId), keyBindingService), searchReplaceAllIcon.classNames); + super(Constants.ReplaceAllInFileActionId, appendKeyBindingLabel(ReplaceAllAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFileActionId), keyBindingService), ThemeIcon.asClassName(searchReplaceAllIcon)); } run(): Promise { @@ -674,7 +675,7 @@ export class ReplaceAllInFolderAction extends AbstractSearchAndReplaceAction { constructor(private viewer: WorkbenchObjectTree, private folderMatch: FolderMatch, @IKeybindingService keyBindingService: IKeybindingService ) { - super(Constants.ReplaceAllInFolderActionId, appendKeyBindingLabel(ReplaceAllInFolderAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFolderActionId), keyBindingService), searchReplaceAllIcon.classNames); + super(Constants.ReplaceAllInFolderActionId, appendKeyBindingLabel(ReplaceAllInFolderAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFolderActionId), keyBindingService), ThemeIcon.asClassName(searchReplaceAllIcon)); } run(): Promise { @@ -701,7 +702,7 @@ export class ReplaceAction extends AbstractSearchAndReplaceAction { @IConfigurationService private readonly configurationService: IConfigurationService, @IUriIdentityService private readonly uriIdentityService: IUriIdentityService ) { - super(Constants.ReplaceActionId, appendKeyBindingLabel(ReplaceAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceActionId), keyBindingService), searchReplaceIcon.classNames); + super(Constants.ReplaceActionId, appendKeyBindingLabel(ReplaceAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceActionId), keyBindingService), ThemeIcon.asClassName(searchReplaceIcon)); } async run(): Promise { diff --git a/src/vs/workbench/contrib/search/browser/searchIcons.ts b/src/vs/workbench/contrib/search/browser/searchIcons.ts index 2c264dbf1e4..e556aa76df5 100644 --- a/src/vs/workbench/contrib/search/browser/searchIcons.ts +++ b/src/vs/workbench/contrib/search/browser/searchIcons.ts @@ -3,26 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -export const searchDetailsIcon = registerIcon('search-details', Codicon.ellipsis); +export const searchDetailsIcon = registerIcon('search-details', Codicon.ellipsis, localize('searchDetailsIcon', 'Icon to make search details visible.')); -export const searchShowContextIcon = registerIcon('search-show-context', Codicon.listSelection); -export const searchHideReplaceIcon = registerIcon('search-hide-replace', Codicon.chevronRight); -export const searchShowReplaceIcon = registerIcon('search-show-replace', Codicon.chevronDown); -export const searchReplaceAllIcon = registerIcon('search-replace-all', Codicon.replaceAll); -export const searchReplaceIcon = registerIcon('search-replace', Codicon.replace); -export const searchRemoveIcon = registerIcon('search-remove', Codicon.close); +export const searchShowContextIcon = registerIcon('search-show-context', Codicon.listSelection, localize('searchShowContextIcon', 'Icon for toggle the context in the search editor')); +export const searchHideReplaceIcon = registerIcon('search-hide-replace', Codicon.chevronRight, localize('searchHideReplaceIcon', 'Icon to collapse the replace section in the search view.')); +export const searchShowReplaceIcon = registerIcon('search-show-replace', Codicon.chevronDown, localize('searchShowReplaceIcon', 'Icon to expand the replace section in the search view.')); +export const searchReplaceAllIcon = registerIcon('search-replace-all', Codicon.replaceAll, localize('searchReplaceAllIcon', 'Icon for replace all in the search view.')); +export const searchReplaceIcon = registerIcon('search-replace', Codicon.replace, localize('searchReplaceIcon', 'Icon for replace in the search view.')); +export const searchRemoveIcon = registerIcon('search-remove', Codicon.close, localize('searchRemoveIcon', 'Icon to remove a search result')); -export const searchRefreshIcon = registerIcon('search-refresh', Codicon.refresh); -export const searchCollapseAllIcon = registerIcon('search-collapse-results', Codicon.collapseAll); -export const searchExpandAllIcon = registerIcon('search-expand-results', Codicon.expandAll); -export const searchClearIcon = registerIcon('search-clear-results', Codicon.clearAll); -export const searchStopIcon = Codicon.searchStop; +export const searchRefreshIcon = registerIcon('search-refresh', Codicon.refresh, localize('searchRefreshIcon', 'Icon for refresh in the search view.')); +export const searchCollapseAllIcon = registerIcon('search-collapse-results', Codicon.collapseAll, localize('searchCollapseAllIcon', 'Icon for collapse results in the search view.')); +export const searchExpandAllIcon = registerIcon('search-expand-results', Codicon.expandAll, localize('searchExpandAllIcon', 'Icon for expand results in the search view.')); +export const searchClearIcon = registerIcon('search-clear-results', Codicon.clearAll, localize('searchClearIcon', 'Icon for clear results in the search view.')); +export const searchStopIcon = registerIcon('search-stop', Codicon.searchStop, localize('searchStopIcon', 'Icon for stop in the search view.')); export const searchViewIcon = registerIcon('search-view-icon', Codicon.search, localize('searchViewIcon', 'View icon of the search view.')); -export const searchNewEditorIcon = registerIcon('search-new-editor', Codicon.newFile); -export const searchGotoFileIcon = registerIcon('search-goto-file', Codicon.goToFile); - +export const searchNewEditorIcon = registerIcon('search-new-editor', Codicon.newFile, localize('searchNewEditorIcon', 'Icon for the action to open a new search editor.')); diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index f55fe884760..5a42e7b884b 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -38,7 +38,7 @@ import { IProgressService, IProgressStep, IProgress } from 'vs/platform/progress import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, SearchSortOrder, SearchCompletionExitCode } from 'vs/workbench/services/search/common/search'; import { ISearchHistoryService, ISearchHistoryValues } from 'vs/workbench/contrib/search/common/searchHistoryService'; import { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, listActiveSelectionForeground, foreground } from 'vs/platform/theme/common/colorRegistry'; -import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { OpenFileFolderAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; import { ResourceLabels } from 'vs/workbench/browser/labels'; @@ -283,7 +283,7 @@ export class SearchView extends ViewPane { // Toggle query details button this.toggleQueryDetailsButton = dom.append(this.queryDetails, - $('.more' + searchDetailsIcon.cssSelector, { tabindex: 0, role: 'button', title: nls.localize('moreSearch', "Toggle Search Details") })); + $('.more' + ThemeIcon.asCSSSelector(searchDetailsIcon), { tabindex: 0, role: 'button', title: nls.localize('moreSearch', "Toggle Search Details") })); this._register(dom.addDisposableListener(this.toggleQueryDetailsButton, dom.EventType.CLICK, e => { dom.EventHelper.stop(e); diff --git a/src/vs/workbench/contrib/search/browser/searchWidget.ts b/src/vs/workbench/contrib/search/browser/searchWidget.ts index 4c8d69beb3e..4a8c7ebd8f3 100644 --- a/src/vs/workbench/contrib/search/browser/searchWidget.ts +++ b/src/vs/workbench/contrib/search/browser/searchWidget.ts @@ -25,7 +25,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search'; import { attachFindReplaceInputBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput, ContextScopedReplaceInput } from 'vs/platform/browser/contextScopedHistoryWidget'; import { appendKeyBindingLabel, isSearchViewFocused, getSearchView } from 'vs/workbench/contrib/search/browser/searchActions'; import * as Constants from 'vs/workbench/contrib/search/common/constants'; @@ -57,7 +57,7 @@ class ReplaceAllAction extends Action { static readonly ID: string = 'search.action.replaceAll'; constructor(private _searchWidget: SearchWidget) { - super(ReplaceAllAction.ID, '', searchReplaceAllIcon.classNames, false); + super(ReplaceAllAction.ID, '', ThemeIcon.asClassName(searchReplaceAllIcon), false); } set searchWidget(searchWidget: SearchWidget) { @@ -294,7 +294,7 @@ export class SearchWidget extends Widget { }; this.toggleReplaceButton = this._register(new Button(parent, opts)); this.toggleReplaceButton.element.setAttribute('aria-expanded', 'false'); - this.toggleReplaceButton.element.classList.add(...searchHideReplaceIcon.classNamesArray); + this.toggleReplaceButton.element.classList.add(...ThemeIcon.asClassNameArray(searchHideReplaceIcon)); this.toggleReplaceButton.icon = 'toggle-replace-button'; // TODO@joao need to dispose this listener eventually this.toggleReplaceButton.onDidClick(() => this.onToggleReplaceButton()); @@ -355,7 +355,7 @@ export class SearchWidget extends Widget { this.showContextCheckbox = new Checkbox({ isChecked: false, title: appendKeyBindingLabel(nls.localize('showContext', "Toggle Context Lines"), this.keyBindingService.lookupKeybinding(ToggleSearchEditorContextLinesCommandId), this.keyBindingService), - icon: searchShowContextIcon + icon: ThemeIcon.asCSSIcon(searchShowContextIcon) }); this._register(this.showContextCheckbox.onChange(() => this.onContextLinesChanged())); @@ -436,11 +436,11 @@ export class SearchWidget extends Widget { private onToggleReplaceButton(): void { this.replaceContainer.classList.toggle('disabled'); if (this.isReplaceShown()) { - this.toggleReplaceButton.element.classList.remove(...searchHideReplaceIcon.classNamesArray); - this.toggleReplaceButton.element.classList.add(...searchShowReplaceIcon.classNamesArray); + this.toggleReplaceButton.element.classList.remove(...ThemeIcon.asClassNameArray(searchHideReplaceIcon)); + this.toggleReplaceButton.element.classList.add(...ThemeIcon.asClassNameArray(searchShowReplaceIcon)); } else { - this.toggleReplaceButton.element.classList.remove(...searchShowReplaceIcon.classNamesArray); - this.toggleReplaceButton.element.classList.add(...searchHideReplaceIcon.classNamesArray); + this.toggleReplaceButton.element.classList.remove(...ThemeIcon.asClassNameArray(searchShowReplaceIcon)); + this.toggleReplaceButton.element.classList.add(...ThemeIcon.asClassNameArray(searchHideReplaceIcon)); } this.toggleReplaceButton.element.setAttribute('aria-expanded', this.isReplaceShown() ? 'true' : 'false'); this.updateReplaceActiveState(); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 7b7ddcc6e52..caf6d801243 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -34,7 +34,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { inputBorder, registerColor, searchEditorFindMatch, searchEditorFindMatchBorder } from 'vs/platform/theme/common/colorRegistry'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; -import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; @@ -139,7 +139,7 @@ export class SearchEditor extends BaseTextEditor { this.includesExcludesContainer = DOM.append(this.queryEditorContainer, DOM.$('.includes-excludes')); // // Toggle query details button - this.toggleQueryDetailsButton = DOM.append(this.includesExcludesContainer, DOM.$('.expand' + searchDetailsIcon.cssSelector, { tabindex: 0, role: 'button', title: localize('moreSearch', "Toggle Search Details") })); + this.toggleQueryDetailsButton = DOM.append(this.includesExcludesContainer, DOM.$('.expand' + ThemeIcon.asCSSSelector(searchDetailsIcon), { tabindex: 0, role: 'button', title: localize('moreSearch', "Toggle Search Details") })); this._register(DOM.addDisposableListener(this.toggleQueryDetailsButton, DOM.EventType.CLICK, e => { DOM.EventHelper.stop(e); this.toggleIncludesExcludes(); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index 0c124a1f06a..f1d1426f4b1 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -28,6 +28,7 @@ import { OpenNewEditorCommandId } from 'vs/workbench/contrib/searchEditor/browse import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/searchEditor.contribution'; import { EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const toggleSearchEditorCaseSensitiveCommand = (accessor: ServicesAccessor) => { const editorService = accessor.get(IEditorService); @@ -85,7 +86,7 @@ export class OpenSearchEditorAction extends Action { constructor(id: string, label: string, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { - super(id, label, searchNewEditorIcon.classNames); + super(id, label, ThemeIcon.asClassName(searchNewEditorIcon)); } update() { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index d0cab873588..d0f5208055b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -36,7 +36,8 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { terminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; // Register services registerSingleton(ITerminalService, TerminalService, true); diff --git a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts index 33be689a140..212f827bfee 100644 --- a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts +++ b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts @@ -18,7 +18,8 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ResourceContextKey } from 'vs/workbench/common/resources'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const timelineViewIcon = registerIcon('timeline-view-icon', Codicon.history, localize('timelineViewIcon', 'View icon of the timeline view.')); diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 05a0b4e0b23..64f30027e35 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -42,7 +42,8 @@ import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2, MenuReg import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; const ItemHeight = 22; diff --git a/src/vs/workbench/services/userDataSync/common/userDataSync.ts b/src/vs/workbench/services/userDataSync/common/userDataSync.ts index bf587f2544b..4d31065fc87 100644 --- a/src/vs/workbench/services/userDataSync/common/userDataSync.ts +++ b/src/vs/workbench/services/userDataSync/common/userDataSync.ts @@ -9,7 +9,8 @@ import { Event } from 'vs/base/common/event'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export interface IUserDataSyncAccount { readonly authenticationProviderId: string; From 2c20676f5c938710e3b6cc1118ce233bf04cb0d7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 22:59:04 +0100 Subject: [PATCH 0301/1837] update distro (and hopefully unstuck builds) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97613c38800..e38f77fcac9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "52c70e96acffb178b85c6d50f6be99a1a261da42", + "distro": "19950a29d290a699141f8328af0c457dc0a9f204", "author": { "name": "Microsoft Corporation" }, From 76882e4eb404408c156f23c62c9ca3cc25880735 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 25 Nov 2020 11:29:28 -0800 Subject: [PATCH 0302/1837] avoid memory leak of large text buffer from notebook cell text model. --- .../contrib/notebook/common/model/notebookCellTextModel.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index d46143ecbbc..709f0a4f72f 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -12,6 +12,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Disposable } from 'vs/base/common/lifecycle'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { hash } from 'vs/base/common/hash'; +import { createTextBuffer } from 'vs/editor/common/model/textModel'; export class NotebookCellTextModel extends Disposable implements ICell { private _onDidChangeOutputs = new Emitter(); @@ -171,6 +172,9 @@ export class NotebookCellTextModel extends Disposable implements ICell { } dispose() { + // Manually release reference to previous text buffer to avoid large leaks + // in case someone leaks a CellTextModel reference + this._textBuffer = createTextBuffer('', model.DefaultEndOfLine.LF); super.dispose(); } } From f24f7be7f05bc309ff7bc0486c9a2ec0fca487cf Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 25 Nov 2020 11:40:51 -0800 Subject: [PATCH 0303/1837] less non-null operator in notebookEditorWidget --- .../notebook/browser/notebookEditorWidget.ts | 156 +++++++++++++----- 1 file changed, 111 insertions(+), 45 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 598ea026676..32961c25b84 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -624,8 +624,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview?.focusWebview(); } else { const focus = this._list?.getFocus()[0]; - if (typeof focus === 'number') { - const element = this._notebookViewModel!.viewCells[focus]; + if (typeof focus === 'number' && this._notebookViewModel) { + const element = this._notebookViewModel.viewCells[focus]; if (element.focusMode === CellFocusMode.Editor) { element.editState = CellEditState.Editing; @@ -685,9 +685,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor async setOptions(options: NotebookEditorOptions | undefined) { // reveal cell if editor options tell to do so - if (options?.cellOptions) { + if (options?.cellOptions && this._notebookViewModel) { const cellOptions = options.cellOptions; - const cell = this._notebookViewModel!.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); + const cell = this._notebookViewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { this.selectElement(cell); await this.revealInCenterIfOutsideViewportAsync(cell); @@ -1099,8 +1099,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor state.cellTotalHeights = cellHeights; const focus = this._list.getFocus()[0]; - if (typeof focus === 'number') { - const element = this._notebookViewModel!.viewCells[focus]; + if (typeof focus === 'number' && this._notebookViewModel) { + const element = this._notebookViewModel.viewCells[focus]; if (element) { const itemDOM = this._list?.domElementOfElement(element); const editorFocused = !!(document.activeElement && itemDOM && itemDOM.contains(document.activeElement)); @@ -1355,11 +1355,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private _nearestCodeCellIndex(index: number /* exclusive */, direction: 'above' | 'below') { - const nearest = this._notebookViewModel!.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); + if (!this._notebookViewModel) { + return -1; + } + + const nearest = this._notebookViewModel.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); if (nearest > -1) { return index - nearest - 1; } else { - const nearestCellTheOtherDirection = this._notebookViewModel!.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); + const nearestCellTheOtherDirection = this._notebookViewModel.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); if (nearestCellTheOtherDirection > -1) { return index + nearestCellTheOtherDirection; } @@ -1368,12 +1372,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction: 'above' | 'below' = 'above', initialText: string = '', ui: boolean = false): CellViewModel | null { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { return null; } - const index = cell ? this._notebookViewModel!.getCellIndex(cell) : 0; - const nextIndex = ui ? this._notebookViewModel!.getNextVisibleCellIndex(index) : index + 1; + if (!this._notebookViewModel.metadata.editable) { + return null; + } + + const index = cell ? this._notebookViewModel.getCellIndex(cell) : 0; + const nextIndex = ui ? this._notebookViewModel.getNextVisibleCellIndex(index) : index + 1; let language; if (type === CellKind.Code) { if (cell?.cellKind === CellKind.Code) { @@ -1381,16 +1389,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } else if (cell?.cellKind === CellKind.Markdown) { const nearestCodeCellIndex = this._nearestCodeCellIndex(index, direction); if (nearestCodeCellIndex > -1) { - language = this._notebookViewModel!.viewCells[nearestCodeCellIndex].language; + language = this._notebookViewModel.viewCells[nearestCodeCellIndex].language; } else { - language = this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; } } else { if (cell === undefined && direction === 'above') { // insert cell at the very top - language = this._notebookViewModel!.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + language = this._notebookViewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; } else { - language = this._notebookViewModel!.resolvedLanguages[0] || 'plaintext'; + language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; } } } else { @@ -1401,27 +1409,35 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor (direction === 'above' ? index : nextIndex) : index; const focused = this._list?.getFocusedElements(); - const newCell = this._notebookViewModel!.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); + const newCell = this._notebookViewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); return newCell as CellViewModel; } async splitNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { return null; } - const index = this._notebookViewModel!.getCellIndex(cell); + if (!this._notebookViewModel.metadata.editable) { + return null; + } - return this._notebookViewModel!.splitNotebookCell(index); + const index = this._notebookViewModel.getCellIndex(cell); + + return this._notebookViewModel.splitNotebookCell(index); } async joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { return null; } - const index = this._notebookViewModel!.getCellIndex(cell); - const ret = await this._notebookViewModel!.joinNotebookCells(index, direction, constraint); + if (!this._notebookViewModel.metadata.editable) { + return null; + } + + const index = this._notebookViewModel.getCellIndex(cell); + const ret = await this._notebookViewModel.joinNotebookCells(index, direction, constraint); if (ret) { ret.deletedCells.forEach(cell => { @@ -1437,7 +1453,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async deleteNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { + return false; + } + + if (!this._notebookViewModel.metadata.editable) { return false; } @@ -1445,18 +1465,22 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.pendingLayouts.get(cell)!.dispose(); } - const index = this._notebookViewModel!.getCellIndex(cell); - this._notebookViewModel!.deleteCell(index, true); + const index = this._notebookViewModel.getCellIndex(cell); + this._notebookViewModel.deleteCell(index, true); return true; } async moveCellDown(cell: ICellViewModel): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { return null; } - const index = this._notebookViewModel!.getCellIndex(cell); - if (index === this._notebookViewModel!.length - 1) { + if (!this._notebookViewModel.metadata.editable) { + return null; + } + + const index = this._notebookViewModel.getCellIndex(cell); + if (index === this._notebookViewModel.length - 1) { return null; } @@ -1465,11 +1489,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCellUp(cell: ICellViewModel): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { return null; } - const index = this._notebookViewModel!.getCellIndex(cell); + if (!this._notebookViewModel.metadata.editable) { + return null; + } + + const index = this._notebookViewModel.getCellIndex(cell); if (index === 0) { return null; } @@ -1479,7 +1507,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCell(cell: ICellViewModel, relativeToCell: ICellViewModel, direction: 'above' | 'below'): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { + return null; + } + + if (!this._notebookViewModel.metadata.editable) { return null; } @@ -1487,15 +1519,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - const originalIdx = this._notebookViewModel!.getCellIndex(cell); - const relativeToIndex = this._notebookViewModel!.getCellIndex(relativeToCell); + const originalIdx = this._notebookViewModel.getCellIndex(cell); + const relativeToIndex = this._notebookViewModel.getCellIndex(relativeToCell); const newIdx = direction === 'above' ? relativeToIndex : relativeToIndex + 1; return this._moveCellToIndex(originalIdx, 1, newIdx); } async moveCellsToIdx(index: number, length: number, toIdx: number): Promise { - if (!this._notebookViewModel!.metadata.editable) { + if (!this._notebookViewModel) { + return null; + } + + if (!this._notebookViewModel.metadata.editable) { return null; } @@ -1508,6 +1544,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor * @example to move the cell from index 0 down one spot, call with (0, 2) */ private async _moveCellToIndex(index: number, length: number, desiredIndex: number): Promise { + if (!this._notebookViewModel) { + return null; + } + if (index < desiredIndex) { // The cell is moving "down", it will free up one index spot and consume a new one desiredIndex -= length; @@ -1517,7 +1557,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - if (!this._notebookViewModel!.moveCellToIdx(index, length, desiredIndex, true)) { + if (!this._notebookViewModel.moveCellToIdx(index, length, desiredIndex, true)) { throw new Error('Notebook Editor move cell, index out of range'); } @@ -1525,9 +1565,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor DOM.scheduleAtNextAnimationFrame(() => { if (this._isDisposed) { r(null); + return; } - const viewCell = this._notebookViewModel!.viewCells[desiredIndex]; + if (!this._notebookViewModel) { + r(null); + return; + } + + const viewCell = this._notebookViewModel.viewCells[desiredIndex]; this._list?.revealElementInView(viewCell); r(viewCell); }); @@ -1536,7 +1582,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } editNotebookCell(cell: CellViewModel): void { - if (!cell.getEvaluatedMetadata(this._notebookViewModel!.metadata).editable) { + if (!this._notebookViewModel) { + return; + } + + if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).editable) { return; } @@ -1644,29 +1694,41 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async cancelNotebookExecution(): Promise { - if (this._notebookViewModel?.metadata.runState !== NotebookRunState.Running) { + if (!this._notebookViewModel) { + return; + } + + if (this._notebookViewModel.metadata.runState !== NotebookRunState.Running) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, undefined); + await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, undefined); } async executeNotebook(): Promise { - if (!this._notebookViewModel!.runnable) { + if (!this._notebookViewModel) { + return; + } + + if (!this._notebookViewModel.runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, undefined); + await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, undefined); } async cancelNotebookCellExecution(cell: ICellViewModel): Promise { + if (!this._notebookViewModel) { + return; + } + if (cell.cellKind !== CellKind.Code) { return; } - const metadata = cell.getEvaluatedMetadata(this._notebookViewModel!.metadata); + const metadata = cell.getEvaluatedMetadata(this._notebookViewModel.metadata); if (!metadata.runnable) { return; } @@ -1676,21 +1738,25 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, cell.handle); + await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, cell.handle); } async executeNotebookCell(cell: ICellViewModel): Promise { + if (!this._notebookViewModel) { + return; + } + if (cell.cellKind === CellKind.Markdown) { this.focusNotebookCell(cell, 'container'); return; } - if (!cell.getEvaluatedMetadata(this._notebookViewModel!.metadata).runnable) { + if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, cell.handle); + await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, cell.handle); } focusNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output') { From 3f0ada11fd486aa49d8163067ce60be08bc8f388 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 25 Nov 2020 12:04:56 -0800 Subject: [PATCH 0304/1837] core action active editor context should always have a view model. --- .../api/browser/mainThreadNotebook.ts | 11 +- .../notebook/browser/contrib/coreActions.ts | 50 ++++--- .../notebook/browser/notebookBrowser.ts | 6 + .../notebook/browser/notebookEditorWidget.ts | 140 +++++++++--------- .../browser/view/renderers/cellWidgets.ts | 5 +- .../browser/viewModel/codeCellViewModel.ts | 2 +- .../contrib/notebook/common/notebookCommon.ts | 1 - 7 files changed, 117 insertions(+), 98 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index f98ed6bb833..61521a984a2 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -420,9 +420,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const editors = new Map(); this._notebookService.listNotebookEditors().forEach(editor => { - if (editor.hasModel()) { + if (editor.textModel) { editors.set(editor.getId(), editor); - documentEditorsMap.set(editor.textModel!.uri.toString(), editor); + documentEditorsMap.set(editor.textModel.uri.toString(), editor); } }); @@ -441,7 +441,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo documents.add(document); }); - if (!activeEditor && focusedNotebookEditor && focusedNotebookEditor.hasModel()) { + if (!activeEditor && focusedNotebookEditor && focusedNotebookEditor.textModel) { activeEditor = focusedNotebookEditor.getId(); } @@ -666,8 +666,11 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const editor = this._notebookService.listNotebookEditors().find(editor => editor.getId() === id); if (editor && editor.isNotebookEditor) { const notebookEditor = editor as INotebookEditor; + if (!notebookEditor.hasModel()) { + return; + } const viewModel = notebookEditor.viewModel; - const cell = viewModel?.viewCells[range.start]; + const cell = viewModel.viewCells[range.start]; if (!cell) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index ca084aea984..aaf6e480c55 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -22,7 +22,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, IActiveNotebookEditor, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -103,7 +103,7 @@ const enum CellOverflowToolbarGroups { export interface INotebookActionContext { readonly cellTemplate?: BaseCellRenderTemplate; readonly cell?: ICellViewModel; - readonly notebookEditor: INotebookEditor; + readonly notebookEditor: INotebookEditor & IActiveNotebookEditor; readonly ui?: boolean; } @@ -162,6 +162,10 @@ abstract class NotebookAction extends Action2 { return; } + if (!editor.hasModel()) { + return; + } + const activeCell = editor.getActiveCell(); return { cell: activeCell, @@ -385,7 +389,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - const idx = context.notebookEditor.viewModel?.getCellIndex(context.cell); + const idx = context.notebookEditor.viewModel.getCellIndex(context.cell); if (typeof idx !== 'number') { return; } @@ -393,7 +397,7 @@ registerAction2(class extends NotebookCellAction { const executionP = runCell(accessor, context); // Try to select below, fall back on inserting - const nextCell = context.notebookEditor.viewModel?.viewCells[idx + 1]; + const nextCell = context.notebookEditor.viewModel.viewCells[idx + 1]; if (nextCell) { context.notebookEditor.focusNotebookCell(nextCell, 'container'); } else { @@ -471,7 +475,7 @@ registerAction2(class extends NotebookAction { }); function renderAllMarkdownCells(context: INotebookActionContext): void { - context.notebookEditor.viewModel!.viewCells.forEach(cell => { + context.notebookEditor.viewModel.viewCells.forEach(cell => { if (cell.cellKind === CellKind.Markdown) { cell.editState = CellEditState.Preview; } @@ -907,14 +911,14 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext) { - const index = context.notebookEditor.viewModel!.getCellIndex(context.cell); + const index = context.notebookEditor.viewModel.getCellIndex(context.cell); const result = await context.notebookEditor.deleteNotebookCell(context.cell); if (result) { // deletion succeeds, move focus to the next cell - const nextCellIdx = index < context.notebookEditor.viewModel!.length ? index : context.notebookEditor.viewModel!.length - 1; + const nextCellIdx = index < context.notebookEditor.viewModel.length ? index : context.notebookEditor.viewModel.length - 1; if (nextCellIdx >= 0) { - context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel!.viewCells[nextCellIdx], 'container'); + context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel.viewCells[nextCellIdx], 'container'); } } } @@ -1141,7 +1145,7 @@ registerAction2(class extends NotebookCellAction { return; } - const currCellIndex = viewModel.getCellIndex(context!.cell); + const currCellIndex = viewModel.getCellIndex(context.cell); let topPastedCell: CellViewModel | undefined = undefined; pasteCells.items.reverse().map(cell => { @@ -1239,12 +1243,12 @@ registerAction2(class extends NotebookCellAction { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getCellIndex(activeCell); + const idx = editor.viewModel.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } - const newCell = editor.viewModel?.viewCells[idx + 1]; + const newCell = editor.viewModel.viewCells[idx + 1]; if (!newCell) { return; @@ -1278,7 +1282,7 @@ registerAction2(class extends NotebookCellAction { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getCellIndex(activeCell); + const idx = editor.viewModel.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -1288,7 +1292,7 @@ registerAction2(class extends NotebookCellAction { return; } - const newCell = editor.viewModel?.viewCells[idx - 1]; + const newCell = editor.viewModel.viewCells[idx - 1]; if (!newCell) { return; @@ -1429,7 +1433,7 @@ registerAction2(class extends NotebookCellAction { editor.viewModel.notebookDocument.applyEdits(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true, undefined, () => undefined, undefined); if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) { - context.notebookEditor.viewModel!.notebookDocument.applyEdits(context.notebookEditor.viewModel!.notebookDocument.versionId, [{ + context.notebookEditor.viewModel.notebookDocument.applyEdits(context.notebookEditor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Metadata, index, metadata: { ...context.cell.metadata, runState: NotebookCellRunState.Idle, @@ -1468,7 +1472,7 @@ export class ChangeCellLanguageAction extends NotebookCellAction { const modelService = accessor.get(IModelService); const quickInputService = accessor.get(IQuickInputService); - const providerLanguages = [...context.notebookEditor.viewModel!.notebookDocument.resolvedLanguages, 'markdown']; + const providerLanguages = [...context.notebookEditor.viewModel.notebookDocument.resolvedLanguages, 'markdown']; providerLanguages.forEach(languageId => { let description: string; if (context.cell.cellKind === CellKind.Markdown ? (languageId === 'markdown') : (languageId === context.cell.language)) { @@ -1517,9 +1521,9 @@ export class ChangeCellLanguageAction extends NotebookCellAction { } else if (selection.languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markdown) { await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, selection.languageId); } else { - const index = context.notebookEditor.viewModel!.notebookDocument.cells.indexOf(context.cell.model); - context.notebookEditor.viewModel!.notebookDocument.applyEdits( - context.notebookEditor.viewModel!.notebookDocument.versionId, + const index = context.notebookEditor.viewModel.notebookDocument.cells.indexOf(context.cell.model); + context.notebookEditor.viewModel.notebookDocument.applyEdits( + context.notebookEditor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.CellLanguage, index, language: selection.languageId }], true, undefined, () => undefined, undefined ); @@ -1591,7 +1595,7 @@ registerAction2(class extends NotebookAction { } }).filter(edit => !!edit) as ICellEditOperation[]; if (clearExecutionMetadataEdits.length) { - context.notebookEditor.viewModel!.notebookDocument.applyEdits(context.notebookEditor.viewModel!.notebookDocument.versionId, clearExecutionMetadataEdits, true, undefined, () => undefined, undefined); + context.notebookEditor.viewModel.notebookDocument.applyEdits(context.notebookEditor.viewModel.notebookDocument.versionId, clearExecutionMetadataEdits, true, undefined, () => undefined, undefined); } } }); @@ -1715,7 +1719,7 @@ registerAction2(class extends NotebookCellAction { abstract class ChangeNotebookCellMetadataAction extends NotebookCellAction { async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { const cell = context.cell; - const textModel = context.notebookEditor.viewModel?.notebookDocument; + const textModel = context.notebookEditor.viewModel.notebookDocument; if (!textModel) { return; } @@ -1842,6 +1846,10 @@ registerAction2(class extends Action2 { return; } + if (!editor.hasModel()) { + return; + } + const activeCell = editor.getActiveCell(); return { cell: activeCell, @@ -1853,7 +1861,7 @@ registerAction2(class extends Action2 { const activeEditorContext = this.getActiveEditorContext(accessor); if (activeEditorContext) { - const viewModel = activeEditorContext.notebookEditor.viewModel!; + const viewModel = activeEditorContext.notebookEditor.viewModel; console.log('--- notebook ---'); console.log(viewModel.layoutInfo); console.log('--- cells ---'); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 0a135c6fed9..7e79b196107 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -207,6 +207,11 @@ export interface INotebookEditorCreationOptions { readonly contributions?: INotebookEditorContributionDescription[]; } +export interface IActiveNotebookEditor { + viewModel: NotebookViewModel; + uri: URI; +} + export interface INotebookEditor extends IEditor { isEmbedded: boolean; @@ -216,6 +221,7 @@ export interface INotebookEditor extends IEditor { * Notebook view model attached to the current editor */ viewModel: NotebookViewModel | undefined; + hasModel(): this is IActiveNotebookEditor; /** * An event emitted when the model of this editor has changed. diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 32961c25b84..b6dd38b2980 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -42,7 +42,7 @@ import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, ICellViewModel, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellViewModel, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -288,7 +288,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return this.viewModel?.selectionHandles || []; } - hasModel() { + hasModel(): this is IActiveNotebookEditor { return !!this._notebookViewModel; } @@ -337,7 +337,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor // a descendent of the notebook editor root. const focused = DOM.isAncestor(document.activeElement, this._overlayContainer); this._editorFocus?.set(focused); - this._notebookViewModel?.setFocus(focused); + this.viewModel?.setFocus(focused); } hasFocus() { @@ -624,8 +624,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview?.focusWebview(); } else { const focus = this._list?.getFocus()[0]; - if (typeof focus === 'number' && this._notebookViewModel) { - const element = this._notebookViewModel.viewCells[focus]; + if (typeof focus === 'number' && this.viewModel) { + const element = this.viewModel.viewCells[focus]; if (element.focusMode === CellFocusMode.Editor) { element.editState = CellEditState.Editing; @@ -646,7 +646,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async setModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined): Promise { - if (this._notebookViewModel === undefined || !this._notebookViewModel.equal(textModel)) { + if (this.viewModel === undefined || !this.viewModel.equal(textModel)) { this._detachModel(); await this._attachModel(textModel, viewState); } else { @@ -685,9 +685,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor async setOptions(options: NotebookEditorOptions | undefined) { // reveal cell if editor options tell to do so - if (options?.cellOptions && this._notebookViewModel) { + if (options?.cellOptions && this.viewModel) { const cellOptions = options.cellOptions; - const cell = this._notebookViewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); + const cell = this.viewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { this.selectElement(cell); await this.revealInCenterIfOutsideViewportAsync(cell); @@ -719,7 +719,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._list?.detachViewModel(); this.viewModel?.dispose(); // avoid event - this._notebookViewModel = undefined; + this.viewModel = undefined; // this.webview?.clearInsets(); // this.webview?.clearPreloadsCache(); this._webview?.dispose(); @@ -1068,7 +1068,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } if (viewState?.editorFocused) { - const cell = this._notebookViewModel?.viewCells[focusIdx]; + const cell = this.viewModel?.viewCells[focusIdx]; if (cell) { cell.focusMode = CellFocusMode.Editor; } @@ -1076,7 +1076,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } getEditorViewState(): INotebookEditorViewState { - const state = this._notebookViewModel?.getEditorViewState(); + const state = this.viewModel?.getEditorViewState(); if (!state) { return { editingCells: {}, @@ -1099,8 +1099,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor state.cellTotalHeights = cellHeights; const focus = this._list.getFocus()[0]; - if (typeof focus === 'number' && this._notebookViewModel) { - const element = this._notebookViewModel.viewCells[focus]; + if (typeof focus === 'number' && this.viewModel) { + const element = this.viewModel.viewCells[focus]; if (element) { const itemDOM = this._list?.domElementOfElement(element); const editorFocused = !!(document.activeElement && itemDOM && itemDOM.contains(document.activeElement)); @@ -1237,7 +1237,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } changeModelDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null { - return this._notebookViewModel?.changeModelDecorations(callback) || null; + return this.viewModel?.changeModelDecorations(callback) || null; } setHiddenAreas(_ranges: ICellRange[]): boolean { @@ -1355,15 +1355,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private _nearestCodeCellIndex(index: number /* exclusive */, direction: 'above' | 'below') { - if (!this._notebookViewModel) { + if (!this.viewModel) { return -1; } - const nearest = this._notebookViewModel.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); + const nearest = this.viewModel.viewCells.slice(0, index).reverse().findIndex(cell => cell.cellKind === CellKind.Code); if (nearest > -1) { return index - nearest - 1; } else { - const nearestCellTheOtherDirection = this._notebookViewModel.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); + const nearestCellTheOtherDirection = this.viewModel.viewCells.slice(index + 1).findIndex(cell => cell.cellKind === CellKind.Code); if (nearestCellTheOtherDirection > -1) { return index + nearestCellTheOtherDirection; } @@ -1372,16 +1372,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction: 'above' | 'below' = 'above', initialText: string = '', ui: boolean = false): CellViewModel | null { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = cell ? this._notebookViewModel.getCellIndex(cell) : 0; - const nextIndex = ui ? this._notebookViewModel.getNextVisibleCellIndex(index) : index + 1; + const index = cell ? this.viewModel.getCellIndex(cell) : 0; + const nextIndex = ui ? this.viewModel.getNextVisibleCellIndex(index) : index + 1; let language; if (type === CellKind.Code) { if (cell?.cellKind === CellKind.Code) { @@ -1389,16 +1389,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } else if (cell?.cellKind === CellKind.Markdown) { const nearestCodeCellIndex = this._nearestCodeCellIndex(index, direction); if (nearestCodeCellIndex > -1) { - language = this._notebookViewModel.viewCells[nearestCodeCellIndex].language; + language = this.viewModel.viewCells[nearestCodeCellIndex].language; } else { - language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.resolvedLanguages[0] || 'plaintext'; } } else { if (cell === undefined && direction === 'above') { // insert cell at the very top - language = this._notebookViewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this.viewModel.resolvedLanguages[0] || 'plaintext'; } else { - language = this._notebookViewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.resolvedLanguages[0] || 'plaintext'; } } } else { @@ -1409,35 +1409,35 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor (direction === 'above' ? index : nextIndex) : index; const focused = this._list?.getFocusedElements(); - const newCell = this._notebookViewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); + const newCell = this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); return newCell as CellViewModel; } async splitNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); + const index = this.viewModel.getCellIndex(cell); - return this._notebookViewModel.splitNotebookCell(index); + return this.viewModel.splitNotebookCell(index); } async joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); - const ret = await this._notebookViewModel.joinNotebookCells(index, direction, constraint); + const index = this.viewModel.getCellIndex(cell); + const ret = await this.viewModel.joinNotebookCells(index, direction, constraint); if (ret) { ret.deletedCells.forEach(cell => { @@ -1453,11 +1453,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async deleteNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return false; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return false; } @@ -1465,22 +1465,22 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.pendingLayouts.get(cell)!.dispose(); } - const index = this._notebookViewModel.getCellIndex(cell); - this._notebookViewModel.deleteCell(index, true); + const index = this.viewModel.getCellIndex(cell); + this.viewModel.deleteCell(index, true); return true; } async moveCellDown(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); - if (index === this._notebookViewModel.length - 1) { + const index = this.viewModel.getCellIndex(cell); + if (index === this.viewModel.length - 1) { return null; } @@ -1489,15 +1489,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCellUp(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } - const index = this._notebookViewModel.getCellIndex(cell); + const index = this.viewModel.getCellIndex(cell); if (index === 0) { return null; } @@ -1507,11 +1507,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async moveCell(cell: ICellViewModel, relativeToCell: ICellViewModel, direction: 'above' | 'below'): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } @@ -1519,19 +1519,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - const originalIdx = this._notebookViewModel.getCellIndex(cell); - const relativeToIndex = this._notebookViewModel.getCellIndex(relativeToCell); + const originalIdx = this.viewModel.getCellIndex(cell); + const relativeToIndex = this.viewModel.getCellIndex(relativeToCell); const newIdx = direction === 'above' ? relativeToIndex : relativeToIndex + 1; return this._moveCellToIndex(originalIdx, 1, newIdx); } async moveCellsToIdx(index: number, length: number, toIdx: number): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } - if (!this._notebookViewModel.metadata.editable) { + if (!this.viewModel.metadata.editable) { return null; } @@ -1544,7 +1544,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor * @example to move the cell from index 0 down one spot, call with (0, 2) */ private async _moveCellToIndex(index: number, length: number, desiredIndex: number): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return null; } @@ -1557,7 +1557,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return null; } - if (!this._notebookViewModel.moveCellToIdx(index, length, desiredIndex, true)) { + if (!this.viewModel.moveCellToIdx(index, length, desiredIndex, true)) { throw new Error('Notebook Editor move cell, index out of range'); } @@ -1568,12 +1568,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - if (!this._notebookViewModel) { + if (!this.viewModel) { r(null); return; } - const viewCell = this._notebookViewModel.viewCells[desiredIndex]; + const viewCell = this.viewModel.viewCells[desiredIndex]; this._list?.revealElementInView(viewCell); r(viewCell); }); @@ -1582,11 +1582,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } editNotebookCell(cell: CellViewModel): void { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).editable) { + if (!cell.getEvaluatedMetadata(this.viewModel.metadata).editable) { return; } @@ -1694,33 +1694,33 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } async cancelNotebookExecution(): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (this._notebookViewModel.metadata.runState !== NotebookRunState.Running) { + if (this.viewModel.metadata.runState !== NotebookRunState.Running) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, undefined); + await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, undefined); } async executeNotebook(): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } - if (!this._notebookViewModel.runnable) { + if (!this.viewModel.runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, undefined); + await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, undefined); } async cancelNotebookCellExecution(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } @@ -1728,7 +1728,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - const metadata = cell.getEvaluatedMetadata(this._notebookViewModel.metadata); + const metadata = cell.getEvaluatedMetadata(this.viewModel.metadata); if (!metadata.runnable) { return; } @@ -1738,11 +1738,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } await this._ensureActiveKernel(); - await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel.uri, cell.handle); + await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, cell.handle); } async executeNotebookCell(cell: ICellViewModel): Promise { - if (!this._notebookViewModel) { + if (!this.viewModel) { return; } @@ -1751,12 +1751,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - if (!cell.getEvaluatedMetadata(this._notebookViewModel.metadata).runnable) { + if (!cell.getEvaluatedMetadata(this.viewModel.metadata).runnable) { return; } await this._ensureActiveKernel(); - await this._activeKernel?.executeNotebookCell!(this._notebookViewModel.uri, cell.handle); + await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, cell.handle); } focusNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output') { @@ -1803,7 +1803,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor //#region MISC deltaCellDecorations(oldDecorations: string[], newDecorations: INotebookDeltaDecoration[]): string[] { - return this._notebookViewModel?.deltaCellDecorations(oldDecorations, newDecorations) || []; + return this.viewModel?.deltaCellDecorations(oldDecorations, newDecorations) || []; } deltaCellOutputContainerClassNames(cellId: string, added: string[], removed: string[]) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index b8c2a1172b9..5560bbeb119 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -252,7 +252,10 @@ export class CellLanguageStatusBarItem extends Disposable { private run() { this.instantiationService.invokeFunction(accessor => { - new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor!, cell: this.cell! }); + if (!this.editor || !this.editor.hasModel() || !this.cell) { + return; + } + new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor, cell: this.cell }); }); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 0760fbf4d82..bbc8ee2374c 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -86,7 +86,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod this._layoutInfo = { fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorHeight: 0, - editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo!.width) : 0, + editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0, outputContainerOffset: 0, outputTotalHeight: 0, outputShowMoreContainerHeight: 0, diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 0a9b17b2139..941f4a479c4 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -748,7 +748,6 @@ export interface IEditor extends editorCommon.ICompositeCodeEditor { textModel?: NotebookTextModel; getId(): string; hasFocus(): boolean; - hasModel(): boolean; } export enum NotebookEditorPriority { From ef03adf3a0fef22d5384816d6b44a7d90c673d82 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 25 Nov 2020 14:01:10 -0800 Subject: [PATCH 0305/1837] notebook editor widget always creates list in ctor. --- .../browser/contrib/fold/foldingModel.ts | 6 +- .../notebook/browser/notebookEditorWidget.ts | 141 +++++++++--------- .../browser/notebookEditorWidgetService.ts | 1 - 3 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel.ts b/src/vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel.ts index 3675729c2dd..777b97b7de6 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel.ts @@ -48,7 +48,11 @@ export class FoldingModel extends Disposable { })); this._viewModelStore.add(this._viewModel.onDidChangeSelection(() => { - const selectionHandles = this._viewModel!.selectionHandles; + if (!this._viewModel) { + return; + } + + const selectionHandles = this._viewModel.selectionHandles; const indexes = selectionHandles.map(handle => this._viewModel!.getCellIndex(this._viewModel!.getCellByHandle(handle)!) ); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b6dd38b2980..29e3ca7840a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,7 +76,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _webviewResolved: boolean = false; private _webviewResolvePromise: Promise | null = null; private _webviewTransparentCover: HTMLElement | null = null; - private _list: INotebookCellList | undefined; + private _list!: INotebookCellList; private _dndController: CellDragAndDropController | null = null; private _listTopCellToolbar: ListTopCellToolbar | null = null; private _renderedEditors: Map = new Map(); @@ -108,9 +108,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private readonly _insetModifyQueueByOutputId = new SequencerByKey(); set scrollTop(top: number) { - if (this._list) { - this._list.scrollTop = top; - } + this._list.scrollTop = top; } private _cellContextKeyManager: CellContextKeyManager | null = null; @@ -164,6 +162,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } + if (!this.viewModel) { + return; + } + if (this._activeKernel === kernel) { return; } @@ -172,7 +174,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._activeKernelResolvePromise = undefined; const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE); - memento[this.viewModel!.viewType] = this._activeKernel?.id; + memento[this.viewModel.viewType] = this._activeKernel?.id; this._activeKernelMemento.saveMemento(); this._onDidChangeKernel.fire(); } @@ -199,7 +201,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - const [focused] = this._list!.getFocusedElements(); + const [focused] = this._list.getFocusedElements(); return this._renderedEditors.get(focused); } @@ -226,7 +228,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor onDidChangeVisibleRanges: Event = this._onDidChangeVisibleRanges.event; get visibleRanges() { - return this._list?.visibleRanges || []; + return this._list.visibleRanges || []; } readonly isEmbedded: boolean; @@ -275,6 +277,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor }); this.notebookService.addNotebookEditor(this); + this._createEditor(); } /** @@ -382,7 +385,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return false; } - createEditor(): void { + private _createEditor(): void { const id = generateUuid(); this._overlayContainer.id = `notebook-${id}`; this._overlayContainer.className = 'notebookOverlay'; @@ -442,7 +445,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._body.classList.add('cell-list-container'); this._dndController = this._register(new CellDragAndDropController(this, this._body)); - const getScopedContextKeyService = (container?: HTMLElement) => this._list!.contextKeyService.createScoped(container); + const getScopedContextKeyService = (container?: HTMLElement) => this._list.contextKeyService.createScoped(container); const renderers = [ this.instantiationService.createInstance(CodeCellRenderer, this, this._renderedEditors, this._dndController, getScopedContextKeyService), this.instantiationService.createInstance(MarkdownCellRenderer, this, this._dndController, this._renderedEditors, getScopedContextKeyService), @@ -467,7 +470,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor enableKeyboardNavigation: true, additionalScrollHeight: 0, transformOptimization: false, //(isMacintosh && isNative) || getTitleBarStyle(this.configurationService, this.environmentService) === 'native', - styleController: (_suffix: string) => { return this._list!; }, + styleController: (_suffix: string) => { return this._list; }, overrideStyles: { listBackground: editorBackground, listActiveSelectionBackground: editorBackground, @@ -585,7 +588,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor // Will fire onDidChangeFocus, resetting the state to Container applyFocusChange(); - const newFocusedCell = this._list!.getFocusedElements()[0]; + const newFocusedCell = this._list.getFocusedElements()[0]; if (newFocusedCell.cellKind === CellKind.Code || newFocusedCell.editState === CellEditState.Editing) { this.focusNotebookCell(newFocusedCell, 'editor'); } else { @@ -623,7 +626,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (this._webiewFocused) { this._webview?.focusWebview(); } else { - const focus = this._list?.getFocus()[0]; + const focus = this._list.getFocus()[0]; if (typeof focus === 'number' && this.viewModel) { const element = this.viewModel.viewCells[focus]; @@ -635,7 +638,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } - this._list?.domFocus(); + this._list.domFocus(); } this._onDidFocusEditorWidget.fire(); @@ -671,8 +674,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor await this._setKernels(textModel, this._currentKernelTokenSource); })); - this._localStore.add(this._list!.onDidChangeFocus(() => { - const focused = this._list!.getFocusedElements()[0]; + this._localStore.add(this._list.onDidChangeFocus(() => { + const focused = this._list.getFocusedElements()[0]; if (focused) { if (!this._cellContextKeyManager) { this._cellContextKeyManager = this._localStore.add(new CellContextKeyManager(this.scopedContextKeyService, this, textModel, focused as CellViewModel)); @@ -716,7 +719,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _detachModel() { this._localStore.clear(); - this._list?.detachViewModel(); + this._list.detachViewModel(); this.viewModel?.dispose(); // avoid event this.viewModel = undefined; @@ -725,7 +728,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview?.dispose(); this._webview?.element.remove(); this._webview = null; - this._list?.clear(); + this._list.clear(); } async beginComputeContributedKernels() { @@ -892,7 +895,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (!this._webview) { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, this.getId(), this.textModel!.uri); // attach the webview container to the DOM tree first - this._list?.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); + this._list.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); } this._webviewResolvePromise = new Promise(async resolve => { @@ -932,7 +935,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private async _createWebview(id: string, resource: URI): Promise { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource); // attach the webview container to the DOM tree first - this._list?.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); + this._list.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); } private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) { @@ -970,7 +973,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._onDidChangeSelection.fire(); })); - this._localStore.add(this._list!.onWillScroll(e => { + this._localStore.add(this._list.onWillScroll(e => { this._onWillScroll.fire(e); if (!this._webviewResolved) { return; @@ -980,14 +983,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webviewTransparentCover!.style.top = `${e.scrollTop}px`; })); - this._localStore.add(this._list!.onDidChangeContentHeight(() => { + this._localStore.add(this._list.onDidChangeContentHeight(() => { DOM.scheduleAtNextAnimationFrame(() => { if (this._isDisposed) { return; } - const scrollTop = this._list?.scrollTop || 0; - const scrollHeight = this._list?.scrollHeight || 0; + const scrollTop = this._list.scrollTop; + const scrollHeight = this._list.scrollHeight; if (!this._webviewResolved) { return; @@ -1000,7 +1003,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const removedItems: IProcessedOutput[] = []; this._webview?.insetMapping.forEach((value, key) => { const cell = value.cell; - const viewIndex = this._list?.getViewIndex(cell); + const viewIndex = this._list.getViewIndex(cell); if (viewIndex === undefined) { return; @@ -1011,7 +1014,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor removedItems.push(key); } - const cellTop = this._list?.getAbsoluteTopOfElement(cell) || 0; + const cellTop = this._list.getAbsoluteTopOfElement(cell); if (this._webview!.shouldUpdateInset(cell, key, cellTop)) { updateItems.push({ cell: cell, @@ -1030,18 +1033,18 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor }); })); - this._list!.attachViewModel(this.viewModel); - this._localStore.add(this._list!.onDidRemoveOutput(output => { + this._list.attachViewModel(this.viewModel); + this._localStore.add(this._list.onDidRemoveOutput(output => { this.removeInset(output); })); - this._localStore.add(this._list!.onDidHideOutput(output => { + this._localStore.add(this._list.onDidHideOutput(output => { this.hideInset(output); })); if (this._dimension) { - this._list?.layout(this._dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP, this._dimension.width); + this._list.layout(this._dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP, this._dimension.width); } else { - this._list!.layout(); + this._list.layout(); } this._dndController?.clearGlobalDragState(); @@ -1052,19 +1055,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor restoreListViewState(viewState: INotebookEditorViewState | undefined): void { if (viewState?.scrollPosition !== undefined) { - this._list!.scrollTop = viewState!.scrollPosition.top; - this._list!.scrollLeft = viewState!.scrollPosition.left; + this._list.scrollTop = viewState!.scrollPosition.top; + this._list.scrollLeft = viewState!.scrollPosition.left; } else { - this._list!.scrollTop = 0; - this._list!.scrollLeft = 0; + this._list.scrollTop = 0; + this._list.scrollLeft = 0; } const focusIdx = typeof viewState?.focus === 'number' ? viewState.focus : 0; - if (focusIdx < this._list!.length) { - this._list!.setFocus([focusIdx]); - this._list!.setSelection([focusIdx]); - } else if (this._list!.length > 0) { - this._list!.setFocus([0]); + if (focusIdx < this._list.length) { + this._list.setFocus([focusIdx]); + this._list.setSelection([focusIdx]); + } else if (this._list.length > 0) { + this._list.setFocus([0]); } if (viewState?.editorFocused) { @@ -1102,7 +1105,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (typeof focus === 'number' && this.viewModel) { const element = this.viewModel.viewCells[focus]; if (element) { - const itemDOM = this._list?.domElementOfElement(element); + const itemDOM = this._list.domElementOfElement(element); const editorFocused = !!(document.activeElement && itemDOM && itemDOM.contains(document.activeElement)); state.editorFocused = editorFocused; @@ -1154,8 +1157,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._dimension = new DOM.Dimension(dimension.width, dimension.height); DOM.size(this._body, dimension.width, dimension.height); - this._list?.updateOptions({ additionalScrollHeight: this._scrollBeyondLastLine ? dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP : 0 }); - this._list?.layout(dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP, dimension.width); + this._list.updateOptions({ additionalScrollHeight: this._scrollBeyondLastLine ? dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP : 0 }); + this._list.layout(dimension.height - SCROLLABLE_ELEMENT_PADDING_TOP, dimension.width); this._overlayContainer.style.visibility = 'visible'; this._overlayContainer.style.display = 'block'; @@ -1188,52 +1191,52 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor //#region Editor Features selectElement(cell: ICellViewModel) { - this._list?.selectElement(cell); + this._list.selectElement(cell); // this.viewModel!.selectionHandles = [cell.handle]; } revealInView(cell: ICellViewModel) { - this._list?.revealElementInView(cell); + this._list.revealElementInView(cell); } revealInCenterIfOutsideViewport(cell: ICellViewModel) { - this._list?.revealElementInCenterIfOutsideViewport(cell); + this._list.revealElementInCenterIfOutsideViewport(cell); } async revealInCenterIfOutsideViewportAsync(cell: ICellViewModel) { - return this._list?.revealElementInCenterIfOutsideViewportAsync(cell); + return this._list.revealElementInCenterIfOutsideViewportAsync(cell); } revealInCenter(cell: ICellViewModel) { - this._list?.revealElementInCenter(cell); + this._list.revealElementInCenter(cell); } async revealLineInViewAsync(cell: ICellViewModel, line: number): Promise { - return this._list?.revealElementLineInViewAsync(cell, line); + return this._list.revealElementLineInViewAsync(cell, line); } async revealLineInCenterAsync(cell: ICellViewModel, line: number): Promise { - return this._list?.revealElementLineInCenterAsync(cell, line); + return this._list.revealElementLineInCenterAsync(cell, line); } async revealLineInCenterIfOutsideViewportAsync(cell: ICellViewModel, line: number): Promise { - return this._list?.revealElementLineInCenterIfOutsideViewportAsync(cell, line); + return this._list.revealElementLineInCenterIfOutsideViewportAsync(cell, line); } async revealRangeInViewAsync(cell: ICellViewModel, range: Range): Promise { - return this._list?.revealElementRangeInViewAsync(cell, range); + return this._list.revealElementRangeInViewAsync(cell, range); } async revealRangeInCenterAsync(cell: ICellViewModel, range: Range): Promise { - return this._list?.revealElementRangeInCenterAsync(cell, range); + return this._list.revealElementRangeInCenterAsync(cell, range); } async revealRangeInCenterIfOutsideViewportAsync(cell: ICellViewModel, range: Range): Promise { - return this._list?.revealElementRangeInCenterIfOutsideViewportAsync(cell, range); + return this._list.revealElementRangeInCenterIfOutsideViewportAsync(cell, range); } setCellSelection(cell: ICellViewModel, range: Range): void { - this._list?.setCellSelection(cell, range); + this._list.setCellSelection(cell, range); } changeModelDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null { @@ -1241,7 +1244,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } setHiddenAreas(_ranges: ICellRange[]): boolean { - return this._list!.setHiddenAreas(_ranges, true); + return this._list.setHiddenAreas(_ranges, true); } private _editorStyleSheets = new Map(); @@ -1316,7 +1319,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor //#region Cell operations async layoutNotebookCell(cell: ICellViewModel, height: number): Promise { - const viewIndex = this._list!.getViewIndex(cell); + const viewIndex = this._list.getViewIndex(cell); if (viewIndex === undefined) { // the cell is hidden return; @@ -1327,7 +1330,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - this._list?.updateElementHeight2(cell, height); + this._list.updateElementHeight2(cell, height); }; if (this.pendingLayouts.has(cell)) { @@ -1408,7 +1411,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const insertIndex = cell ? (direction === 'above' ? index : nextIndex) : index; - const focused = this._list?.getFocusedElements(); + const focused = this._list.getFocusedElements(); const newCell = this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); return newCell as CellViewModel; } @@ -1574,7 +1577,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } const viewCell = this.viewModel.viewCells[desiredIndex]; - this._list?.revealElementInView(viewCell); + this._list.revealElementInView(viewCell); r(viewCell); }); @@ -1596,7 +1599,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } getActiveCell() { - const elements = this._list?.getFocusedElements(); + const elements = this._list.getFocusedElements(); if (elements && elements.length) { return elements[0]; @@ -1766,14 +1769,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (focusItem === 'editor') { this.selectElement(cell); - this._list?.focusView(); + this._list.focusView(); cell.editState = CellEditState.Editing; cell.focusMode = CellFocusMode.Editor; this.revealInCenterIfOutsideViewport(cell); } else if (focusItem === 'output') { this.selectElement(cell); - this._list?.focusView(); + this._list.focusView(); if (!this._webview) { return; @@ -1784,7 +1787,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cell.focusMode = CellFocusMode.Container; this.revealInCenterIfOutsideViewport(cell); } else { - const itemDOM = this._list?.domElementOfElement(cell); + const itemDOM = this._list.domElementOfElement(cell); if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) { (document.activeElement as HTMLElement).blur(); } @@ -1794,7 +1797,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.selectElement(cell); this.revealInCenterIfOutsideViewport(cell); - this._list?.focusView(); + this._list.focusView(); } } @@ -1823,7 +1826,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } triggerScroll(event: IMouseWheelEvent) { - this._list?.triggerScrollFromMouseWheelEvent(event); + this._list.triggerScrollFromMouseWheelEvent(event); } async createInset(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number): Promise { @@ -1835,11 +1838,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor await this._resolveWebview(); if (!this._webview!.insetMapping.has(output.source)) { - const cellTop = this._list?.getAbsoluteTopOfElement(cell) || 0; + const cellTop = this._list.getAbsoluteTopOfElement(cell); await this._webview!.createInset(cell, output, cellTop, offset); } else { - const cellTop = this._list?.getAbsoluteTopOfElement(cell) || 0; - const scrollTop = this._list?.scrollTop || 0; + const cellTop = this._list.getAbsoluteTopOfElement(cell); + const scrollTop = this._list.scrollTop; this._webview!.updateViewScrollTop(-scrollTop, true, [{ cell, output: output.source, cellTop }]); } @@ -1925,7 +1928,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } this._localStore.clear(); - this._list?.dispose(); + this._list.dispose(); this._listTopCellToolbar?.dispose(); this._overlayContainer.remove(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidgetService.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidgetService.ts index 783b82070c7..f9650ad09a1 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidgetService.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidgetService.ts @@ -127,7 +127,6 @@ class NotebookEditorWidgetService implements INotebookEditorWidgetService { // NEW widget const instantiationService = accessor.get(IInstantiationService); const widget = instantiationService.createInstance(NotebookEditorWidget, { isEmbedded: false }); - widget.createEditor(); const token = this._tokenPool++; value = { widget, token }; From 0921f711c3e6d8eb9def1fb23c307ff8ac09280b Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 25 Nov 2020 14:05:49 -0800 Subject: [PATCH 0306/1837] Add GettingStartedService/Registry and initial getting started UI (#111175) * WIP -Getting Started Registry * Initial idea of how registry/service will work * Getting started with Getting Started * Add telemetry and touch up enablement flag * Add contrib as startup editor * Move to allowing static Getting Start blob * No newline * Remove unused enum --- build/lib/i18n.resources.json | 4 + src/vs/base/browser/dom.ts | 4 +- .../themes/browser/themes.contribution.ts | 3 + .../browser/gettingStarted.contribution.ts | 52 +++ .../gettingStarted/browser/gettingStarted.css | 230 ++++++++++ .../gettingStarted/browser/gettingStarted.ts | 394 ++++++++++++++++++ .../browser/vs_code_editor_getting_started.ts | 39 ++ .../page/browser/welcomePage.contribution.ts | 15 +- .../welcome/page/browser/welcomePage.ts | 20 +- .../welcome/page/browser/welcomePageColors.ts | 12 + .../common/gettingStartedContent.ts | 170 ++++++++ .../common/gettingStartedRegistry.ts | 146 +++++++ .../common/gettingStartedService.ts | 196 +++++++++ .../gettingStarted/common/media/Short.png | Bin 0 -> 177215 bytes .../gettingStarted/common/media/Square.png | Bin 0 -> 182996 bytes .../gettingStarted/common/media/Tall.png | Bin 0 -> 86220 bytes src/vs/workbench/workbench.common.main.ts | 1 + 17 files changed, 1272 insertions(+), 14 deletions(-) create mode 100644 src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts create mode 100644 src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css create mode 100644 src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts create mode 100644 src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts create mode 100644 src/vs/workbench/contrib/welcome/page/browser/welcomePageColors.ts create mode 100644 src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts create mode 100644 src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts create mode 100644 src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts create mode 100644 src/vs/workbench/services/gettingStarted/common/media/Short.png create mode 100644 src/vs/workbench/services/gettingStarted/common/media/Square.png create mode 100644 src/vs/workbench/services/gettingStarted/common/media/Tall.png diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index cbc5c0bb1bb..9ec898986a1 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -373,6 +373,10 @@ { "name": "vs/workbench/services/extensionRecommendations", "project": "vscode-workbench" + }, + { + "name": "vs/workbench/services/gettingStarted", + "project": "vscode-workbench" } ] } diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index cdeb92b8da4..b4740dadea0 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1373,8 +1373,8 @@ export function safeInnerHtml(node: HTMLElement, value: string): void { const options = _extInsaneOptions({ allowedTags: ['a', 'button', 'blockquote', 'code', 'div', 'h1', 'h2', 'h3', 'input', 'label', 'li', 'p', 'pre', 'select', 'small', 'span', 'strong', 'textarea', 'ul', 'ol'], allowedAttributes: { - 'a': ['href'], - 'button': ['data-href'], + 'a': ['href', 'x-dispatch'], + 'button': ['data-href', 'x-dispatch'], 'input': ['type', 'placeholder', 'checked', 'required'], 'label': ['for'], 'select': ['required'], diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 465497930d7..ca1165af6ad 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -22,6 +22,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { DEFAULT_PRODUCT_ICON_THEME_ID } from 'vs/workbench/services/themes/browser/productIconThemeData'; +import { IGettingStartedService } from 'vs/workbench/services/gettingStarted/common/gettingStartedService'; export class SelectColorThemeAction extends Action { @@ -34,6 +35,7 @@ export class SelectColorThemeAction extends Action { @IQuickInputService private readonly quickInputService: IQuickInputService, @IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, + @IGettingStartedService private readonly gettingStartedService: IGettingStartedService, @IViewletService private readonly viewletService: IViewletService ) { super(id, label); @@ -84,6 +86,7 @@ export class SelectColorThemeAction extends Action { openExtensionViewlet(this.viewletService, `category:themes ${quickpick.value}`); } else { selectTheme(theme, true); + this.gettingStartedService.progressByEvent('themeSelected'); } isCompleted = true; quickpick.hide(); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts new file mode 100644 index 00000000000..d3cd0749b27 --- /dev/null +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { GettingStartedInputFactory, GettingStartedPage } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; +import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; +import product from 'vs/platform/product/common/product'; + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.showGettingStarted', + title: localize('Getting Started', "Getting Started"), + category: localize('help', "Help"), + f1: true, + precondition: ContextKeyExpr.has('config.workbench.experimental.gettingStarted'), + menu: { + id: MenuId.MenubarHelpMenu, + when: ContextKeyExpr.has('config.workbench.experimental.gettingStarted'), + group: '1_welcome', + order: 2, + } + }); + } + + public run(accessor: ServicesAccessor) { + return accessor.get(IInstantiationService).createInstance(GettingStartedPage).openEditor(); + } +}); + +Registry.as(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(GettingStartedInputFactory.ID, GettingStartedInputFactory); + +if (product.quality !== 'stable') { + Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ + ...workbenchConfigurationNodeBase, + properties: { + 'workbench.experimental.gettingStarted': { + type: 'boolean', + description: localize('gettingStartedDescription', "Enables an experimental Getting Started page, accesible via the Help menu."), + default: false, + } + } + }); +} diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css new file mode 100644 index 00000000000..7b4b0c101b0 --- /dev/null +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -0,0 +1,230 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.file-icons-enabled .show-file-icons .vs_code_editor_getting_started\.md-name-file-icon.md-ext-file-icon.ext-file-icon.markdown-lang-file-icon.file-icon::before { + content: ' '; + background-image: url('../../../../browser/media/code-icon.svg'); +} + + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide { + width: 100%; + position: absolute; + transition: left 0.25s; + left: 0; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .header { + text-align: center; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .title { + display: inline-block; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-title { + margin-top: 6px; + margin-bottom: 2px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-description-container { + width: 100% +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-description { + font-size: 12pt; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-progress { + margin-top: 6px; + font-size: 8pt; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories progress { + font-size: 12pt; + width: 100%; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories #getting-started-categories-container { + display: flex; + flex-wrap: wrap; + justify-content: center; + width: 70%; + max-width: 900px; + margin: 20px auto; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category { + width: 330px; + height: 100px; + text-align: left; + display: flex; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .getting-started-category { + padding-right: 46px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category .codicon { + margin: 10px 8px 0 0; + font-size: 32px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category { + width: 330px; + height: 100px; + display: flex; + margin-left: 12px; + +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category .codicon { + margin-left:0; + margin-top: 28px; + font-size: 22pt; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-columns { + display: flex; + justify-content: center; + padding: 30px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task { + width: 100%; + height: 26pt; + overflow: hidden; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task.expanded { + width: 100%; + height: unset; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-description-container { + padding-left: 30px; + padding-right: 4px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-title { + margin-bottom: 4px; + font-size: 14pt; +} + + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-description { + font-size: 11pt; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-next { + float: right; + margin-top: 16px; + margin-right: 25px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .codicon.hidden { + display: none; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .codicon { + float: left; + font-size: 20pt; + position: relative; + top: -4px; + left: -1px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task-action { + margin: 10px 0 0; + padding: 4px 8px; + font-size: 11pt; + min-width: 100px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-left { + min-width: 330px; + width: 33%; + max-width: 400px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-right { + width: 66%; + text-align: center; + padding: 35px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button { + border: none; + margin: 10px; + color: inherit; + text-align: left; + padding: 10px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button { + position: absolute; + left: 0; + font-size: 12pt; + margin: 10px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button .codicon { + position: relative; + top: 2px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .product-icon { + background-image: url('../../../../browser/media/code-icon.svg'); + width: 75px; + height: 75px; + display: inline-block; + margin-right: 20px; +} + + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .skip { + display: block; + width: 150px; + margin: 0 auto; + text-align: center; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h1 { + font-size: 32pt; + font-weight: normal; + border-bottom: none; + margin-bottom: 0; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h2 { + font-weight: normal; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h3 { + font-weight: normal; + margin-top: 0; + margin-bottom: 0; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .subtitle { + font-size: 18pt; + margin-top: 0; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .footer { + position: absolute; + text-align: center; + bottom: 0; + width: 100%; + margin-bottom: 20px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.next { + left: 100%; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.prev { + left: -100%; +} diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts new file mode 100644 index 00000000000..8538393dbbb --- /dev/null +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -0,0 +1,394 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./gettingStarted'; +import 'vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started'; +import { localize } from 'vs/nls'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { WalkThroughInput } from 'vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput'; +import { FileAccess, Schemas } from 'vs/base/common/network'; +import { IEditorInputFactory, EditorInput } from 'vs/workbench/common/editor'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; +import { assertIsDefined } from 'vs/base/common/types'; +import { $, addDisposableListener } from 'vs/base/browser/dom'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IProductService } from 'vs/platform/product/common/productService'; +import { IGettingStartedCategoryWithProgress, IGettingStartedService } from 'vs/workbench/services/gettingStarted/common/gettingStartedService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { buttonBackground as welcomeButtonBackground, buttonHoverBackground as welcomeButtonHoverBackground, welcomePageBackground } from 'vs/workbench/contrib/welcome/page/browser/welcomePageColors'; +import { activeContrastBorder, buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, descriptionForeground, focusBorder, foreground, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; +import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; + +export const gettingStartedInputTypeId = 'workbench.editors.gettingStartedInput'; +const telemetryFrom = 'gettingStartedPage'; + +export class GettingStartedPage extends Disposable { + readonly editorInput: WalkThroughInput; + private inProgressScroll = Promise.resolve(); + + private dispatchListeners = new DisposableStore(); + + private gettingStartedCategories: IGettingStartedCategoryWithProgress[]; + private currentCategory: IGettingStartedCategoryWithProgress | undefined; + + + + constructor( + @IEditorService private readonly editorService: IEditorService, + @ICommandService private readonly commandService: ICommandService, + @IProductService private readonly productService: IProductService, + @IKeybindingService private readonly keybindingService: IKeybindingService, + @IGettingStartedService private readonly gettingStartedService: IGettingStartedService, + @ITelemetryService private readonly telemetryService: ITelemetryService, + @IInstantiationService private readonly instantiationService: IInstantiationService) { + super(); + + const resource = FileAccess.asBrowserUri('./vs_code_editor_getting_started.md', require) + .with({ + scheme: Schemas.walkThrough, + query: JSON.stringify({ moduleId: 'vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started' }) + }); + + + this.editorInput = this.instantiationService.createInstance(WalkThroughInput, { + typeId: gettingStartedInputTypeId, + name: localize('editorGettingStarted.title', "Getting Started"), + resource, + telemetryFrom, + onReady: (container: HTMLElement) => this.onReady(container) + }); + + this.gettingStartedCategories = this.gettingStartedService.getCategories(); + this._register(this.dispatchListeners); + this._register(this.gettingStartedService.onDidAddTask(task => console.log('added new task', task, 'that isnt being rendered yet'))); + this._register(this.gettingStartedService.onDidAddCategory(category => console.log('added new category', category, 'that isnt being rendered yet'))); + this._register(this.gettingStartedService.onDidProgressTask(task => { + const category = this.gettingStartedCategories.find(category => category.id === task.category); + if (!category) { throw Error('Could not find category with ID: ' + task.category); } + if (category.content.type !== 'items') { throw Error('internaal error: progressing task in a non-items category'); } + const ourTask = category.content.items.find(_task => _task.id === task.id); + if (!ourTask) { + throw Error('Could not find task with ID: ' + task.id); + } + ourTask.done = task.done; + if (category.id === this.currentCategory?.id) { + const badgeelement = assertIsDefined(document.getElementById('done-task-' + task.id)); + if (task.done) { + badgeelement.classList.remove('codicon-star-empty'); + badgeelement.classList.add('codicon-star-full'); + } + else { + badgeelement.classList.add('codicon-star-empty'); + badgeelement.classList.remove('codicon-star-full'); + } + } + this.updateCategoryProgress(); + })); + } + + public openEditor(options: IEditorOptions = { pinned: true }) { + return this.editorService.openEditor(this.editorInput, options); + } + + private registerDispatchListeners(container: HTMLElement) { + this.dispatchListeners.clear(); + + container.querySelectorAll('[x-dispatch]').forEach(element => { + const [command, argument] = (element.getAttribute('x-dispatch') ?? '').split(':'); + if (command) { + this.dispatchListeners.add(addDisposableListener(element, 'click', (e) => { + + type GettingStartedActionClassification = { + command: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' }; + argument: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' }; + }; + type GettingStartedActionEvent = { + command: string; + argument: string | undefined; + }; + this.telemetryService.publicLog2('gettingStarted.ActionExecuted', { command, argument }); + + switch (command) { + case 'scrollPrev': { + this.scrollPrev(container); + break; + } + case 'skip': { + this.commandService.executeCommand('workbench.action.closeActiveEditor'); + break; + } + case 'selectCategory': { + const selectedCategory = this.gettingStartedCategories.find(category => category.id === argument); + if (!selectedCategory) { throw Error('Could not find category with ID ' + argument); } + if (selectedCategory.content.type === 'command') { + this.commandService.executeCommand(selectedCategory.content.command); + } else { + this.scrollToCategory(container, argument); + } + break; + } + case 'selectTask': { + this.selectTask(argument); + e.stopPropagation(); + break; + } + case 'runTaskAction': { + if (!this.currentCategory || this.currentCategory.content.type !== 'items') { + throw Error('cannot run task action for category of non items type' + this.currentCategory?.id); + } + const taskToRun = assertIsDefined(this.currentCategory?.content.items.find(task => task.id === argument)); + const commandToRun = assertIsDefined(taskToRun.button?.command); + this.commandService.executeCommand(commandToRun); + break; + } + default: { + console.error('Dispatch to', command, argument, 'not defined'); + break; + } + } + })); + } + }); + } + + private selectTask(id: string | undefined) { + const mediaElement = assertIsDefined(document.getElementById('getting-started-media')); + if (id) { + const taskElement = assertIsDefined(document.getElementById('getting-started-task-' + id)); + if (!this.currentCategory || this.currentCategory.content.type !== 'items') { + throw Error('cannot expand task for category of non items type' + this.currentCategory?.id); + } + const taskToExpand = assertIsDefined(this.currentCategory.content.items.find(task => task.id === id)); + mediaElement.setAttribute('src', taskToExpand.media.toString()); + taskElement.parentElement?.querySelectorAll('.expanded').forEach(node => node.classList.remove('expanded')); + taskElement.classList.add('expanded'); + } else { + mediaElement.setAttribute('src', ''); + } + } + + private onReady(container: HTMLElement) { + const categoryElements = this.gettingStartedCategories.map( + category => { + const categoryDescriptionElement = + category.content.type === 'items' ? + $('.category-description-container', {}, + $('h3.category-title', {}, category.title), + $('.category-description.description', {}, category.description), + $('.category-progress', { 'x-data-category-id': category.id, }, $('.message'), $('progress'))) : + $('.category-description-container', {}, + $('h3.category-title', {}, category.title), + $('.category-description.description', {}, category.description)); + + return $('button.getting-started-category', + { 'x-dispatch': 'selectCategory:' + category.id }, + $('.codicon.codicon-' + category.codicon, {}), categoryDescriptionElement); + }); + + const rightColumn = assertIsDefined(container.querySelector('#getting-started-detail-right')); + rightColumn.appendChild($('img#getting-started-media')); + + categoryElements.forEach(element => { + assertIsDefined(document.getElementById('getting-started-categories-container')).appendChild(element); + }); + + this.updateCategoryProgress(); + + assertIsDefined(document.getElementById('product-name')).textContent = this.productService.nameLong; + this.registerDispatchListeners(container); + } + + private updateCategoryProgress() { + document.querySelectorAll('.category-progress').forEach(element => { + const categoryID = element.getAttribute('x-data-category-id'); + const category = this.gettingStartedCategories.find(category => category.id === categoryID); + if (!category) { throw Error('Could not find c=ategory with ID ' + categoryID); } + if (category.content.type !== 'items') { throw Error('Category with ID ' + categoryID + ' is not of items type'); } + const numDone = category.content.items.filter(task => task.done).length; + const numTotal = category.content.items.length; + + const message = assertIsDefined(element.firstChild); + const bar = assertIsDefined(element.lastChild) as HTMLProgressElement; + bar.value = numDone; + bar.max = numTotal; + if (numTotal === numDone) { + message.textContent = `All items complete!`; + } + else { + message.textContent = `${numDone} of ${numTotal} items complete`; + } + }); + } + + private async scrollToCategory(container: HTMLElement, categoryID: string) { + this.inProgressScroll = this.inProgressScroll.then(async () => { + this.clearDetialView(); + this.currentCategory = this.gettingStartedCategories.find(category => category.id === categoryID); + if (!this.currentCategory) { throw Error('could not find category with ID ' + categoryID); } + if (this.currentCategory.content.type !== 'items') { throw Error('category with ID ' + categoryID + ' is not of items type'); } + const slides = [...container.querySelectorAll('.gettingStartedSlide').values()]; + const currentSlide = slides.findIndex(element => + !element.classList.contains('prev') && !element.classList.contains('next')); + if (currentSlide < slides.length - 1) { + slides[currentSlide].classList.add('prev'); + + const detailSlide = assertIsDefined(slides[currentSlide + 1]); + detailSlide.classList.remove('next'); + const detailTitle = assertIsDefined(document.getElementById('getting-started-detail-title')); + detailTitle.appendChild( + $('.getting-started-category', + {}, + $('.codicon.codicon-' + this.currentCategory.codicon, {}), + $('.category-description-container', {}, + $('h2.category-title', {}, this.currentCategory.title), + $('.category-description.description', {}, this.currentCategory.description)))); + + const categoryElements = this.currentCategory.content.items.map( + (task, i, arr) => + $('button.getting-started-task', + { 'x-dispatch': 'selectTask:' + task.id, id: 'getting-started-task-' + task.id }, + $('.codicon' + (task.done ? '.codicon-star-full' : '.codicon-star-empty'), { id: 'done-task-' + task.id },), + $('.task-description-container', {}, + $('h3.task-title', {}, task.title), + $('.task-description.description', {}, task.description), + ...( + task.button + ? [$('button.emphasis.getting-started-task-action', { 'x-dispatch': 'runTaskAction:' + task.id }, + task.button.title + this.getKeybindingLabel(task.button.command) + )] + : []), + ...( + arr[i + 1] + ? [ + $('a.task-next', + { 'x-dispatch': 'selectTask:' + arr[i + 1].id }, localize('next', "Next")), + ] : [] + ) + ))); + + const detailContainer = assertIsDefined(document.getElementById('getting-started-detail-container')); + categoryElements.forEach(element => detailContainer.appendChild(element)); + + const toExpand = this.currentCategory.content.items.find(item => !item.done) ?? this.currentCategory.content.items[0]; + this.selectTask(toExpand.id); + this.registerDispatchListeners(container); + } + }); + } + + private clearDetialView() { + const detailContainer = assertIsDefined(document.getElementById('getting-started-detail-container')); + while (detailContainer.firstChild) { detailContainer.removeChild(detailContainer.firstChild); } + const detailTitle = assertIsDefined(document.getElementById('getting-started-detail-title')); + while (detailTitle.firstChild) { detailTitle.removeChild(detailTitle.firstChild); } + } + + private getKeybindingLabel(command: string) { + const binding = this.keybindingService.lookupKeybinding(command); + if (!binding) { return ''; } + else { return ` (${binding.getLabel()})`; } + } + + private async scrollPrev(container: HTMLElement) { + this.inProgressScroll = this.inProgressScroll.then(async () => { + this.currentCategory = undefined; + this.selectTask(undefined); + const slides = [...container.querySelectorAll('.gettingStartedSlide').values()]; + const currentSlide = slides.findIndex(element => + !element.classList.contains('prev') && !element.classList.contains('next')); + if (currentSlide > 0) { + slides[currentSlide].classList.add('next'); + assertIsDefined(slides[currentSlide - 1]).classList.remove('prev'); + } + }); + } +} + +export class GettingStartedInputFactory implements IEditorInputFactory { + + static readonly ID = gettingStartedInputTypeId; + + public canSerialize(editorInput: EditorInput): boolean { + return true; + } + + public serialize(editorInput: EditorInput): string { + return '{}'; + } + + public deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): WalkThroughInput { + return instantiationService.createInstance(GettingStartedPage).editorInput; + } +} + +registerThemingParticipant((theme, collector) => { + const backgroundColor = theme.getColor(welcomePageBackground); + if (backgroundColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer { background-color: ${backgroundColor}; }`); + } + const foregroundColor = theme.getColor(foreground); + if (foregroundColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer { color: ${foregroundColor}; }`); + } + const descriptionColor = theme.getColor(descriptionForeground); + if (descriptionColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .description { color: ${descriptionColor}; }`); + } + const buttonColor = getExtraColor(theme, welcomeButtonBackground, { dark: 'rgba(0, 0, 0, .2)', extra_dark: 'rgba(200, 235, 255, .042)', light: 'rgba(0,0,0,.04)', hc: 'black' }); + if (buttonColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button { background: ${buttonColor}; }`); + } + + const buttonHoverColor = getExtraColor(theme, welcomeButtonHoverBackground, { dark: 'rgba(200, 235, 255, .072)', extra_dark: 'rgba(200, 235, 255, .072)', light: 'rgba(0,0,0,.10)', hc: null }); + if (buttonHoverColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:hover { background: ${buttonHoverColor}; }`); + } + if (buttonColor && buttonHoverColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button.expanded:hover { background: ${buttonColor}; }`); + } + + const emphasisButtonForeground = theme.getColor(buttonForeground); + if (emphasisButtonForeground) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button.emphasis { color: ${emphasisButtonForeground}; }`); + } + + const emphasisButtonBackground = theme.getColor(buttonBackground); + if (emphasisButtonBackground) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button.emphasis { background: ${emphasisButtonBackground}; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .getting-started-category .codicon { color: ${emphasisButtonBackground} }`); + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .codicon { color: ${emphasisButtonBackground} } `); + } + + const emphasisButtonHoverBackground = theme.getColor(buttonHoverBackground); + if (emphasisButtonHoverBackground) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button.emphasis:hover { background: ${emphasisButtonHoverBackground}; }`); + } + + const link = theme.getColor(textLinkForeground); + if (link) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer a { color: ${link}; }`); + } + const activeLink = theme.getColor(textLinkActiveForeground); + if (activeLink) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer a:hover, + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer a:active { color: ${activeLink}; }`); + } + const focusColor = theme.getColor(focusBorder); + if (focusColor) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer a:focus { outline-color: ${focusColor}; }`); + } + const border = theme.getColor(contrastBorder); + if (border) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button { border-color: ${border}; border: 1px solid; }`); + } + const activeBorder = theme.getColor(activeContrastBorder); + if (activeBorder) { + collector.addRule(`.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:hover { outline-color: ${activeBorder}; }`); + } +}); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts new file mode 100644 index 00000000000..6559c246fc9 --- /dev/null +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { escape } from 'vs/base/common/strings'; +import { localize } from 'vs/nls'; + +export default () => ` +
+
+
+
+
+
+

${escape(localize('gettingStarted.vscode', "Visual Studio Code"))}

+

${escape(localize({ key: 'gettingStarted.editingRedefined', comment: ['Shown as subtitle on the Welcome page.'] }, "Code editing. Redefined"))}

+
+
+
+
+ + +
+
+`.replace(/\|/g, '`'); diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.contribution.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.contribution.ts index 396871dc396..1a59cbb17c4 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.contribution.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.contribution.ts @@ -13,6 +13,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur import { IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; +import product from 'vs/platform/product/common/product'; Registry.as(ConfigurationExtensions.Configuration) .registerConfiguration({ @@ -21,13 +22,21 @@ Registry.as(ConfigurationExtensions.Configuration) 'workbench.startupEditor': { 'scope': ConfigurationScope.APPLICATION, // Make sure repositories cannot trigger opening a README for tracking. 'type': 'string', - 'enum': ['none', 'welcomePage', 'readme', 'newUntitledFile', 'welcomePageInEmptyWorkbench'], - 'enumDescriptions': [ + 'enum': [ + ...['none', 'welcomePage', 'readme', 'newUntitledFile', 'welcomePageInEmptyWorkbench'], + ...(product.quality !== 'stable' + ? ['gettingStarted'] + : []) + ], + 'enumDescriptions': [...[ localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.none' }, "Start without an editor."), localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePage' }, "Open the Welcome page (default)."), localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.readme' }, "Open the README when opening a folder that contains one, fallback to 'welcomePage' otherwise."), localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.newUntitledFile' }, "Open a new untitled file (only applies when opening an empty workspace)."), - localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePageInEmptyWorkbench' }, "Open the Welcome page when opening an empty workbench."), + localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePageInEmptyWorkbench' }, "Open the Welcome page when opening an empty workbench."),], + ...(product.quality !== 'stable' + ? [localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.gettingStarted' }, "Open the Getting Started page (experimental).")] + : []) ], 'default': 'welcomePage', 'description': localize('workbench.startupEditor', "Controls which editor is shown at startup, if none are restored from the previous session.") diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts index c9c0f00f5d7..790fe57fe26 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts @@ -29,7 +29,7 @@ import { ILifecycleService, StartupKind } from 'vs/workbench/services/lifecycle/ import { Disposable } from 'vs/base/common/lifecycle'; import { splitName } from 'vs/base/common/labels'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { registerColor, focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; import { IEditorInputFactory, EditorInput } from 'vs/workbench/common/editor'; @@ -46,6 +46,8 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { gettingStartedInputTypeId, GettingStartedPage } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted'; +import { buttonBackground, buttonHoverBackground, welcomePageBackground } from 'vs/workbench/contrib/welcome/page/browser/welcomePageColors'; const configurationKey = 'workbench.startupEditor'; const oldConfigurationKey = 'workbench.welcome.enabled'; @@ -69,7 +71,8 @@ export class WelcomePageContribution implements IWorkbenchContribution { backupFileService.hasBackups().then(hasBackups => { // Open the welcome even if we opened a set of default editors if ((!editorService.activeEditor || layoutService.openedDefaultEditors) && !hasBackups) { - const openWithReadme = configurationService.getValue(configurationKey) === 'readme'; + const startupEditorSetting = configurationService.getValue(configurationKey) as string; + const openWithReadme = startupEditorSetting === 'readme'; if (openWithReadme) { return Promise.all(contextService.getWorkspace().folders.map(folder => { const folderUri = folder.uri; @@ -101,18 +104,21 @@ export class WelcomePageContribution implements IWorkbenchContribution { return undefined; }); } else { + const startupEditorTypeID = startupEditorSetting === 'gettingStarted' ? gettingStartedInputTypeId : welcomeInputTypeId; + const startupEditorCtor = startupEditorSetting === 'gettingStarted' ? GettingStartedPage : WelcomePage; + let options: IEditorOptions; let editor = editorService.activeEditor; if (editor) { // Ensure that the welcome editor won't get opened more than once - if (editor.getTypeId() === welcomeInputTypeId || editorService.editors.some(e => e.getTypeId() === welcomeInputTypeId)) { + if (editor.getTypeId() === startupEditorTypeID || editorService.editors.some(e => e.getTypeId() === startupEditorTypeID)) { return undefined; } options = { pinned: false, index: 0 }; } else { options = { pinned: false }; } - return instantiationService.createInstance(WelcomePage).openEditor(options); + return instantiationService.createInstance(startupEditorCtor).openEditor(options); } } return undefined; @@ -129,7 +135,7 @@ function isWelcomePageEnabled(configurationService: IConfigurationService, conte return welcomeEnabled.value; } } - return startupEditor.value === 'welcomePage' || startupEditor.value === 'readme' || startupEditor.value === 'welcomePageInEmptyWorkbench' && contextService.getWorkbenchState() === WorkbenchState.EMPTY; + return startupEditor.value === 'welcomePage' || startupEditor.value === 'gettingStarted' || startupEditor.value === 'readme' || startupEditor.value === 'welcomePageInEmptyWorkbench' && contextService.getWorkbenchState() === WorkbenchState.EMPTY; } export class WelcomePageAction extends Action { @@ -639,10 +645,6 @@ export class WelcomeInputFactory implements IEditorInputFactory { // theming -export const buttonBackground = registerColor('welcomePage.buttonBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonBackground', 'Background color for the buttons on the Welcome page.')); -export const buttonHoverBackground = registerColor('welcomePage.buttonHoverBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonHoverBackground', 'Hover background color for the buttons on the Welcome page.')); -export const welcomePageBackground = registerColor('welcomePage.background', { light: null, dark: null, hc: null }, localize('welcomePage.background', 'Background color for the Welcome page.')); - registerThemingParticipant((theme, collector) => { const backgroundColor = theme.getColor(welcomePageBackground); if (backgroundColor) { diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePageColors.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePageColors.ts new file mode 100644 index 00000000000..e87483cf446 --- /dev/null +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePageColors.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerColor } from 'vs/platform/theme/common/colorRegistry'; +import { localize } from 'vs/nls'; + +// Seprate from main module to break dependency cycles between welcomePage and gettingStarted. +export const buttonBackground = registerColor('welcomePage.buttonBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonBackground', 'Background color for the buttons on the Welcome page.')); +export const buttonHoverBackground = registerColor('welcomePage.buttonHoverBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonHoverBackground', 'Hover background color for the buttons on the Welcome page.')); +export const welcomePageBackground = registerColor('welcomePage.background', { light: null, dark: null, hc: null }, localize('welcomePage.background', 'Background color for the Welcome page.')); diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts new file mode 100644 index 00000000000..77257caa287 --- /dev/null +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts @@ -0,0 +1,170 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; + +type GettingStartedItem = { + id: string + title: string, + description: string, + button: { title: string, command: string }, + doneOn: { commandExecuted: string, eventFired?: never } | { eventFired: string, commandExecuted?: never, } + when?: string, + media: string, +}; + +type GettingStartedCategory = { + id: string + title: string, + description: string, + codicon: string, + when?: string, + content: + | { type: 'items', items: GettingStartedItem[] } + | { type: 'command', command: string } +}; + +type GettingStartedContent = GettingStartedCategory[]; + +export const content: GettingStartedContent = [ + { + id: 'Beginner', + title: localize('gettingStarted.beginner.title', "Get Started"), + codicon: 'lightbulb', + description: localize('gettingStarted.beginner.description', "Get to know your new Editor"), + content: { + type: 'items', + items: [ + { + id: 'pickColorTheme', + description: localize('pickColorTask.description', "Modify the colors in the user interface to suit your preferences and work environment."), + title: localize('pickColorTask.title', "Color Theme"), + button: { title: localize('pickColorTask.button', "Find a Theme"), command: 'workbench.action.selectTheme' }, + doneOn: { eventFired: 'themeSelected' }, + media: 'Square.png' + }, + + { + id: 'findKeybindingsExtensions', + description: localize('findKeybindingsTask.description', "Find keyboard shortcuts for Vim, Sublime, Atom and others."), + title: localize('findKeybindingsTask.title', "Configure Keybindings"), + button: { + title: localize('findKeybindingsTask.button', "Search for Keymaps"), + command: 'workbench.extensions.action.showRecommendedKeymapExtensions' + }, + doneOn: { commandExecuted: 'workbench.extensions.action.showRecommendedKeymapExtensions' }, + media: 'Tall.png', + }, + + { + id: 'findLanguageExtensions', + description: localize('findLanguageExtsTask.description', "Get support for your languages like JavaScript, Python, Java, Azure, Docker, and more."), + title: localize('findLanguageExtsTask.title', "Languages & Tools"), + button: { + title: localize('findLanguageExtsTask.button', "Install Language Support"), + command: 'workbench.extensions.action.showLanguageExtensions', + }, + doneOn: { commandExecuted: 'workbench.extensions.action.showLanguageExtensions' }, + media: 'Short.png', + }, + + { + id: 'pickAFolderTask-Mac', + description: localize('gettingStartedOpenFolder.description', "Open a project folder to get started!"), + title: localize('gettingStartedOpenFolder.title', "Open Folder"), + when: 'isMac', + button: { + title: localize('gettingStartedOpenFolder.button', "Pick a Folder"), + command: 'workbench.action.files.openFileFolder' + }, + doneOn: { commandExecuted: 'workbench.action.files.openFileFolder' }, + media: 'Square.png' + }, + + { + id: 'pickAFolderTask-Other', + description: localize('gettingStartedOpenFolder.description', "Open a project folder to get started!"), + title: localize('gettingStartedOpenFolder.title', "Open Folder"), + when: '!isMac', + button: { + title: localize('gettingStartedOpenFolder.button', "Pick a Folder"), + command: 'workbench.action.files.openFolder' + }, + doneOn: { commandExecuted: 'workbench.action.files.openFolder' }, + media: 'Square.png' + } + ] + } + }, + + { + id: 'Intermediate', + title: localize('gettingStarted.intermediate.title', "Essentials"), + codicon: 'heart', + description: localize('gettingStarted.intermediate.description', "Must know features you'll love"), + content: { + type: 'items', + items: [ + { + id: 'commandPaletteTask', + description: localize('commandPaletteTask.description', "The easiest way to find everything VS Code can do. If you\'re ever looking for a feature, check here first!"), + title: localize('commandPaletteTask.title', "Command Palette"), + button: { + title: localize('commandPaletteTask.button', "View All Commands"), + command: 'workbench.action.showCommands' + }, + doneOn: { commandExecuted: 'workbench.action.showCommands' }, + media: 'https://code.visualstudio.com/assets/updates/1_51/custom-tree-hover.gif', + } + ] + } + }, + + { + id: 'Advanced', + title: localize('gettingStarted.advanced.title', "Tips & Tricks"), + codicon: 'tools', + description: localize('gettingStarted.advanced.description', "Favorites from VS Code experts"), + content: { + type: 'items', + items: [] + } + }, + + { + id: 'OpenFolder-Mac', + title: localize('gettingStarted.openFolder.title', "Open Folder"), + codicon: 'folder-opened', + when: 'isMac', + description: localize('gettingStarted.openFolder.description', "Open a project and start working"), + content: { + type: 'command', + command: 'workbench.action.files.openFileFolder' + } + }, + + { + id: 'OpenFolder-Other', + title: localize('gettingStarted.openFolder.title', "Open Folder"), + codicon: 'folder-opened', + description: localize('gettingStarted.openFolder.description', "Open a project and start working"), + when: '!isMac', + content: { + type: 'command', + command: 'workbench.action.files.openFolder' + } + }, + + { + id: 'InteractivePlayground', + title: localize('gettingStarted.playground.title', "Interactive Playground"), + codicon: 'library', + description: localize('gettingStarted.interactivePlayground.description', "Learn essential editor features"), + content: { + type: 'command', + command: 'workbench.action.showInteractivePlayground' + } + } +]; diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts new file mode 100644 index 00000000000..ace92e7ef45 --- /dev/null +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts @@ -0,0 +1,146 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import { FileAccess } from 'vs/base/common/network'; +import { URI } from 'vs/base/common/uri'; +import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { content } from 'vs/workbench/services/gettingStarted/common/gettingStartedContent'; + +export const enum GettingStartedCategory { + Beginner = 'Beginner', + Intermediate = 'Intermediate', + Advanced = 'Advanced' +} + +export interface IGettingStartedTask { + id: string, + title: string, + description: string, + category: GettingStartedCategory | string, + when: ContextKeyExpression, + order: number, + button: { title: string, command: string }, + doneOn: { commandExecuted: string, eventFired?: never } | { eventFired: string, commandExecuted?: never, } + media: URI +} + +export interface IGettingStartedCategoryDescriptor { + id: GettingStartedCategory | string + title: string + description: string + codicon: string + when: ContextKeyExpression + content: + | { type: 'items' } + | { type: 'command', command: string } +} + +export interface IGettingStartedCategory { + id: GettingStartedCategory | string + title: string + description: string + codicon: string + when: ContextKeyExpression + content: + | { type: 'items', items: IGettingStartedTask[] } + | { type: 'command', command: string } +} + +export interface IGettingStartedRegistry { + onDidAddCategory: Event + onDidAddTask: Event + + registerTask(task: IGettingStartedTask): IGettingStartedTask; + getTask(id: string): IGettingStartedTask + + registerCategory(categoryDescriptor: IGettingStartedCategoryDescriptor): void + getCategory(id: GettingStartedCategory | string): Readonly | undefined + + getCategories(): readonly Readonly[] +} + +export class GettingStartedRegistryImpl implements IGettingStartedRegistry { + private readonly _onDidAddTask = new Emitter(); + onDidAddTask: Event = this._onDidAddTask.event; + private readonly _onDidAddCategory = new Emitter(); + onDidAddCategory: Event = this._onDidAddCategory.event; + + private readonly gettingStartedContributions = new Map(); + private readonly tasks = new Map(); + + public registerTask(task: IGettingStartedTask): IGettingStartedTask { + const category = this.gettingStartedContributions.get(task.category); + if (!category) { throw Error('Registering getting started task to category that does not exist (' + task.category + ')'); } + if (category.content.type !== 'items') { throw Error('Registering getting started task to category that is not of `items` type (' + task.category + ')'); } + if (this.tasks.has(task.id)) { throw Error('Attempting to register task with id ' + task.id + ' twice. Second is dropped.'); } + this.tasks.set(task.id, task); + category.content.items.push(task); + this._onDidAddTask.fire(task); + return task; + } + + public registerCategory(categoryDescriptor: IGettingStartedCategoryDescriptor): void { + const oldCategory = this.gettingStartedContributions.get(categoryDescriptor.id); + if (oldCategory) { + console.error(`Skipping attempt to overwrite getting started category. (${categoryDescriptor})`); + return; + } + + const category: IGettingStartedCategory = { + ...categoryDescriptor, + content: categoryDescriptor.content.type === 'items' + ? { type: 'items', items: [] } + : categoryDescriptor.content + }; + + this.gettingStartedContributions.set(categoryDescriptor.id, category); + this._onDidAddCategory.fire(category); + } + + public getCategory(id: GettingStartedCategory | string): Readonly | undefined { + return this.gettingStartedContributions.get(id); + } + + public getTask(id: string): IGettingStartedTask { + const task = this.tasks.get(id); + if (!task) { throw Error('Attempting to access task which does not exist in registry ' + id); } + return task; + } + + public getCategories(): readonly Readonly[] { + return [...this.gettingStartedContributions.values()]; + + } +} + +export const GettingStartedRegistryID = 'GettingStartedRegistry'; +const registryImpl = new GettingStartedRegistryImpl(); + +content.forEach(category => { + + registryImpl.registerCategory({ + ...category, + when: ContextKeyExpr.deserialize(category.when) ?? ContextKeyExpr.true() + }); + + if (category.content.type === 'items') { + category.content.items.forEach((item, index) => { + registryImpl.registerTask({ + ...item, + category: category.id, + order: index, + when: ContextKeyExpr.deserialize(item.when) ?? ContextKeyExpr.true(), + media: item.media.startsWith('https://') + ? URI.parse(item.media, true) + : FileAccess.asFileUri('vs/workbench/services/gettingStarted/common/media/' + item.media, require) + }); + }); + } +}); + +Registry.add(GettingStartedRegistryID, registryImpl); +export const GettingStartedRegistry: IGettingStartedRegistry = Registry.as(GettingStartedRegistryID); diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts new file mode 100644 index 00000000000..6e0476e5ccc --- /dev/null +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts @@ -0,0 +1,196 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { Emitter, Event } from 'vs/base/common/event'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IGettingStartedTask, GettingStartedRegistry, IGettingStartedCategory, } from 'vs/workbench/services/gettingStarted/common/gettingStartedRegistry'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { Memento } from 'vs/workbench/common/memento'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; + +export const IGettingStartedService = createDecorator('gettingStartedService'); + +type TaskProgress = { done: boolean; }; +export interface IGettingStartedTaskWithProgress extends IGettingStartedTask, TaskProgress { } + +export interface IGettingStartedCategoryWithProgress extends Omit { + content: + | { + type: 'items', + items: IGettingStartedTaskWithProgress[], + done: boolean; + stepsComplete: number + stepsTotal: number + } + | { type: 'command', command: string } +} + +export interface IGettingStartedService { + _serviceBrand: undefined, + + readonly onDidAddTask: Event + readonly onDidAddCategory: Event + + readonly onDidProgressTask: Event + + getCategories(): IGettingStartedCategoryWithProgress[] + + progressByEvent(eventName: string): void; +} + +export class GettingStartedService implements IGettingStartedService { + declare readonly _serviceBrand: undefined; + + private readonly _onDidAddTask = new Emitter(); + onDidAddTask: Event = this._onDidAddTask.event; + private readonly _onDidAddCategory = new Emitter(); + onDidAddCategory: Event = this._onDidAddCategory.event; + + private readonly _onDidProgressTask = new Emitter(); + onDidProgressTask: Event = this._onDidProgressTask.event; + + private registry = GettingStartedRegistry; + private memento: Memento; + private taskProgress: Record; + + private commandListeners = new Map(); + private eventListeners = new Map(); + + constructor( + @IStorageService private readonly storageService: IStorageService, + @ICommandService private readonly commandService: ICommandService, + @IContextKeyService private readonly contextService: IContextKeyService, + ) { + this.memento = new Memento('gettingStartedService', this.storageService); + this.taskProgress = this.memento.getMemento(StorageScope.GLOBAL, StorageTarget.USER); + + this.registry.getCategories().forEach(category => { + if (category.content.type === 'items') { + category.content.items.forEach(task => this.registerDoneListeners(task)); + } + }); + + this.registry.onDidAddCategory(category => this._onDidAddCategory.fire(this.getCategoryProgress(category))); + this.registry.onDidAddTask(task => { + this.registerDoneListeners(task); + this._onDidAddTask.fire(this.getTaskProgress(task)); + }); + + this.commandService.onDidExecuteCommand(command => this.progressByCommand(command.commandId)); + } + + private registerDoneListeners(task: IGettingStartedTask) { + if (task.doneOn.commandExecuted) { + const existing = this.commandListeners.get(task.doneOn.commandExecuted); + if (existing) { existing.push(task.id); } + else { + this.commandListeners.set(task.doneOn.commandExecuted, [task.id]); + } + } + if (task.doneOn.eventFired) { + const existing = this.eventListeners.get(task.doneOn.eventFired); + if (existing) { existing.push(task.id); } + else { + this.eventListeners.set(task.doneOn.eventFired, [task.id]); + } + } + } + + getCategories(): IGettingStartedCategoryWithProgress[] { + const registeredCategories = this.registry.getCategories(); + const categoriesWithCompletion = registeredCategories + .filter(category => this.contextService.contextMatchesRules(category.when)) + .map(category => { + if (category.content.type === 'items') { + return { + ...category, + content: { + type: 'items' as const, + items: category.content.items.filter(item => this.contextService.contextMatchesRules(item.when)) + } + }; + } + return category; + }) + .filter(category => category.content.type !== 'items' || category.content.items.length) + .map(category => this.getCategoryProgress(category)); + return categoriesWithCompletion; + } + + private getCategoryProgress(category: IGettingStartedCategory): IGettingStartedCategoryWithProgress { + if (category.content.type === 'command') { + return { ...category, content: category.content }; + } + + const tasksWithProgress = category.content.items.map(task => this.getTaskProgress(task)); + const tasksComplete = tasksWithProgress.filter(task => task.done); + + return { + ...category, + content: { + type: 'items', + items: tasksWithProgress, + stepsComplete: tasksComplete.length, + stepsTotal: tasksWithProgress.length, + done: tasksComplete.length === tasksWithProgress.length, + } + }; + } + + private getTaskProgress(task: IGettingStartedTask): IGettingStartedTaskWithProgress { + return { + ...task, + ...this.taskProgress[task.id] + }; + } + + private progressTask(id: string) { + const oldProgress = this.taskProgress[id]; + if (!oldProgress || oldProgress.done !== true) { + this.taskProgress[id] = { done: true }; + this.memento.saveMemento(); + const task = this.registry.getTask(id); + this._onDidProgressTask.fire(this.getTaskProgress(task)); + } + } + + private progressByCommand(command: string) { + const listening = this.commandListeners.get(command) ?? []; + listening.forEach(id => this.progressTask(id)); + } + + progressByEvent(event: string): void { + const listening = this.eventListeners.get(event) ?? []; + console.log(event, listening, this.eventListeners); + listening.forEach(id => this.progressTask(id)); + } +} + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'resetGettingStartedProgress', + category: 'Getting Started', + title: 'Reset Progress', + f1: true + }); + } + + run(accessor: ServicesAccessor) { + const memento = new Memento('gettingStartedService', accessor.get(IStorageService)); + const record = memento.getMemento(StorageScope.GLOBAL, StorageTarget.USER); + for (const key in record) { + if (Object.prototype.hasOwnProperty.call(record, key)) { + delete record[key]; + } + } + memento.saveMemento(); + } +}); + +registerSingleton(IGettingStartedService, GettingStartedService); diff --git a/src/vs/workbench/services/gettingStarted/common/media/Short.png b/src/vs/workbench/services/gettingStarted/common/media/Short.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a5178984724edb0ca010897ec037046a9f4a65 GIT binary patch literal 177215 zcma%h18`=~wr`S&?PQXPHLd+xcn>eZ`yUA1fP z-QBBuwO0QY!sTQ{5nyp(K|nwd#KnXZKtLd7K|nywpdr681 z0>a?b?Ns@C1z`wvdYb5-+l0Tu+UYQ@O5ORdp*tGxwlZ8zrZ=v#KQ|nw-;cM_96?Wv zqSZ2^%D)|i-I6lqfmRkCpkto80st5watsG{MFyWICt_BRB>UTk``VMZ37Rf}bsx{~ zJrR&G^oL-CbJ!&}g&RL2WAxWXFeGn5>^c}bPS1I62zC3_Bm*$QZuSMHv5&e1WN;05 zd`2ng$dL{4K$xNi;*3CMCmFb@b29vg@*woj3HM-xu?-!scVRhrBI`OC=qOBo6HYKT zOT0>EM)nLzDGndlF(vYJrVtT9!4&OTO>cbOxxU$sjU`7N)b=Kl#|91Qk*Huf@LQ?` z#S5D!6o{ye;@%P%_|wq%1hvigCZZhK2M{M(Hc*I0+qE+URYfL@MC0mrvv9Zsku?}3 zw#}3Ie~?VZMII#?4^dx$@o9eV0U)Pv^gs6pjginyMMPmgz$mSe)ngmKd&!&inr$H; zZaEhEuGYj>X=PA^!6{y5F>CPa9`NHRrWaO5jUd6|KZL8k{JH~6Y#UsilkoL%DV?XA ziczkf8bCZaSu;E2pF9W>jbRW1{;Va$uO~tx?e#}S4uF1gf8z`^MF%qtKb8pk9>9~# z?=ta3(;Q~WAANYRa{$8NW*QnZ=y^1&EtIM%Vm(m~+8INQ9)VWSe2ohdst8*8P{3Ak z3UbB^k|N_^9RH@jzT*rACMST<2*85xL$B;b%_rM7`jJnF7_Sd$Cji2!cG#fL zN8?ZY)4!<}g-Vb6JiyxyIT}Ec8Ps5hQr(Zx`Yi^4xOolxvO@w-2n__DK!2MPjzo4G z#Iy%)pb(H^hYK0R8j)g*0ffTf(_&}@C1Mo{!B)eSNJ8WGN7WCQ=KXm9TyZ)Fc()is zc`QnBtN_~Cn^Nwx7?E826DO8$Q^IhwKqpp>Xq7yuS;%`D4~(wB@i|p9endMe4)SSi z(@@6|h`oF}%2uaL@D^m%Na_LQT?_lER<;e=%pZ?9j}Wqh%-1xXcw2A;Au%J4H*HVB zPs&fQZ+u?gK6pMbyV15oKLv8p?qQn2Wx+CHg+>V{$5scZ3(j2nprN8G|$kCQ< zEpk|pJHs?(YDjhgyrsNr^79Sy_wty8g-h$zinI=6$H|gplIU5a(-CN6*`mk`s){d) znr885w-!#F;MxgzgR@0-rE7|F3iykBRg6p5D(aQp%YP|RE8{BJmUqh+l%`cYS4_!K z%TX(Gm%C_RG;s-U0(s@K3cBUG6y953cprQaLP82e5=EkisiNL-Qdo7&;#p`}0$JVD zgVQ@$X3Sj}?cfzf2m>e7hF7Lqdry87Tc}&qH8C|wG$L9wSw5IsTFB1I%w`v8mw8KQ zP7gBDrdpY>IU?La-_hOu!472nFnlspi7vx)beyEfs^jwE^2##E;>zOY(sfpE?`v0Y z|Ko(~oO81KV0B-7GWC1C*j3=_L9MDz$FR-t*9iXiS2=>EmbsX@oRS{N&vc(2|2%UvJUh1Q^*CC1wLky262lVjTyTUEnl^O?q&MqP_-vrm)G)u+UpKf^6ipSwGIu@|-L zyKx1@hOPSwBPJuRGHfzhB@!j;(@w|8$HLRn)3y{VGCQ&>Y`fiX1IF9O5%DYNc*wE97{VYSZsk1LQ?bRFrN zSeKaHgl}Hpw8U)r#Cz(6(uJh;?x_P1<_wa`_hbHzk(H2pQ$&@I(B;X}zq!THkWHn-) zSk>v(Q#TTU65?X33G@7{ZfC<~n+saS7}6cwn+`9Trzxf-kk@niXNLyqD-~1Et_19xA8&{LG(-x%JlTS+!C3e0|0I1Y^Dep@pQ83fzl*3z>hTWYHk{A%5QRAey(0uEtl7jTWj)}e+faTL>R*5v&w9{aaawizsM-fFv>VMj60Oh zm}0Bhe5(S=*_SZo*4zC0NKVq^vp%%$YMZjvyl@G;AY1RbM80h8VRkYVOcGXJrQ551 z)1GmqIJbEndQUmy_3)JV>$Oe2M!k*IaOKsc>HOgH{%&b8i=!@mD zzM5)i39!-boa**|m_FdfbKSq%>S4dge&f6P_yx6!w8b~+%W-XXW7xmHM{y=Qo_)q& z^)mI+!qrysrerF2++-ch4k6(~|h9yHU^Ec#v%Z>BF_>uai z!hc!V*X*tCFls5o(D&uty^6l9=C$geYHzdrvHj}NC-pk7iNF2xbR;w8TTTT3AD^wq zp?Ask<-r=>Zw)v#k*$F-otw4YS8Wgw z9yhM9Pitc*eL^>DD;q~HH(ug@)!_R2{wJHBnDAd!oGf{X)uiPJ1#KOS30dh_=opCk zUi z-Ns4Zjn>AI5!_@9pclm3fOV>k2v>B+|N z-^2PEApJij^o(>2^#5u5iH1gh*L?B8^3eZh?)hMcB(b@_mg9%HkgU?z z8|eySTWlLMYvD7MxFRbZ;+aU1fX9M5v+f^rP%R z+kta{{Q!*y5%nYK{eS-Y;eb(c_*aKO@&A7kfC&1boxB16KWqDefn@?zL4u*||BIR4 zZGV816AK4tPw+9l4iEq!g#W(yd3Az)1@SL7pCnPBk&r^M=ym%X-zE|nNgB<5AJAV= zUSa-w6mM0~KX`pm`MhC6420nX%5@CIfd*_iP z)(YnSx`q+(do@Y{G!>`ljZ93~Hzv6Bgd^daam6o@QlYkeA+>PuU3VT{2j*XW%tipD zq-en1MS-!hq=n*^;HONfe!?PXVrBcF!tNV7LBM9P)84`RWggik7earO?VHs%UapWs zHa2Mpe*7s7NfI!V`Ni*cH@C`9FAvm`qJhhXpO?$&qMAZ#i!mOGMIdM-AH=gEXh@&j z$UBC4J^MW5p*li4YWTYRR&P@KCr^V@o8LrYGDb)5Qn8mDTU2AJ8SFPwpXzVjzM(ut zKW%xxAWC3OLzt9F!%t2nID*3q5)z+L&#EO3mzzs{t}o;60^DL#v2pzw{FK$D-5r?;8+_&{sb{*E_l&lWXu`WsJP~XJ_@``x{B-mRwwd#BCeo>fGGhxd8P8 zV~K9F_&~yCnSKYJGl(a}$1$!~zY1(4T%rHrVlRVUq_rr+9{I)z_QO9X6ac?9!Lou* zirG`vV~8CdSI3o>21~KNN1_t!u(z&|rNq9J0@m}YsMl9^@0LBNY6IL4XW(yq!{gw8 z1K;i$+7&pA+ERk8C*iD?PQG`C*O}HOl;$Ey?JW6GC~aFwYhI5~(!I_164zw=doIFi z9-wL1)yW6=>>KEPw%)kg*x2~N)ocs5KN3BkEX}wK{JG z5J34bC2UNEJUzSjz=_^Trm=hK(y(_4*^;8eyy%=cy#6*-x7c^}ik6R;uzfr3L$ztfod62<3;9 zQs-q@{_eiU_#l5TvIMGAe)=+2p7S&J-9$mD6*C7eQylv@CH-X_^hF`qIxZB>RjZ)9 z9v;HIJ!}kCr8pw9-t|>8f6VCsB+)slR~*CJe%tqC{jlbJs^R1IHdPL=#gC4ipG0Mv z@kXRvFqW9*41;+HjVW-b?>u7l@K;`5vN+7-^2R)()dKqf1vO|b3WliE>c*y0E&mxp zdC}V1+V4j+(6=`Ym+ciI&a&pTj%h5KiOq-S#jIwgXV(8lzp#caMNlS>VRjm+nxjy=!SYf-s5DNB9 z87f6Q&MYlVLVvV}3x(Lkk9g*inVeapg?uC8enCAE%5JgPh6xA^RG&Fpu0jxmLJIQw z`!^PrLJ|Svi_?ge8Clw)4bJ}JIx12OEs4x5^$ezNKHvY?BBgI zHRDfeV)Uu;Eb_n+V8DD>BjaG!dNI5I23uL4C9CC${6I+D+B{46=C<<$fk(A>g(@RV z8elO6Kq1|sPclLXQ|&Q=fX4%((PDtTPTTz|IE1E%Zco*Okd zM7Vda%2a&`BjPx?m=)gg&utbK;m-rO6{A|eysSUurEoP{zCox}B@yoIQ)e)|8cG;3 z&(W};q7+C^j{z2Mi*@$GKQq}U2tcRmsAG2LB-wxe4)@L=|Ahg`p8=4K_WtcsM@j+q zF6-f9F|aUuZA+jVc-6>cz*d3(r?1n3{bnUL>j~N^kLHE#`SFBNt-*!_j!7a3R;5Y} z*4c6yHQsD99wrsH#b%%}&CyR~IUd>HrW6?a8`cf{ON8nnf608&R&X$04jvpn9|hVn zVsv)hhrpz#If;JO+3)ZgzMTQxz-pp$fg`_{G=1k79*u?DuunQLM=oAJkQ(UG%n^8U zEBXp7a%CkkJG--z*ti*x#wXkmp>1 zd3*VX2cOH9y^`N9sfe@1o@KF2Z)IFLE11H*Fy)G3RNEJx+Ife+N&m2L8gfZ4_f*L4 z=3bDAotgtb%~(!{h*4js@etk4>|35R z@B4674{omybMruR0lPYLXHAWt)ak;1r8*Y~aAn^D%Q1 zy3i{}!E-W8tos(6SdtF^5V*Vc*RcV12Y%w~3voze9yiRumBbL3P-h0aX|J1}Oq9uf z3QQKa*VQp3&4{#!>dZT3i*ce6!ps+jk6WHD&}%Ud4sH{aNipphy=g1);biPuJfnIExzY)#M! z-evc(b99$#kz&2kO5eJMc6jtcj${MAbqBOaVz+XH0L*rfUW3IXkhB$1>yJM<34XfD zx)1mZQz7(~S2Y0EQEvDb4mQd1H%~!*8nGIT-eX5TVMbn%Pd+|CEo!T&gn{nySsXJuRyF3d_xnM*mXwIq}(4Ee|)$~6mcjN5ATj!hvk+72KeEq}m%^)!2fDN!cLTCQ#5#r=SG>L)z2WYOw; zMWsq<424fV>cLGmQs<|bO}K2d1LH-UI1tMHoHjM>P3A?$yN8*S!1(s7oplf71;Vp# zP9FK;mML{bH6ZZ_Mwiw0r@xH0W}^|O)mnSjgTs3|hFpn?baTzjOcO49-jyE_jrq)_ zw*I`^l2Ij}yF1PodLlGOexioCABNNIgBa2KnLYrYO*eZbs0bq?lS`eK|08)eM&xkb z?PNOw0EBkp#Qfr=L&|vF<0bD_kBn&c&>YQ?hHUmYtGZHzN0hj(&i6*s&0{D>Ij*M? z171UghH=S!s)Im!h2xDupZQJ9qh8FWG? zh)nJu_Uc{3Jkp-~Jz9o5Ln40w!Nx42iqk}uO3df6t(->yiQ7Kx82kyxnysOG(^Daj z+XK;$h#2qjhz+J*ohX2;81L7*TYsE_&t&%)tsO7ZWl6`1Y%VH`>h&EhRE8tI76a4z z+fe5>bmJ-7kWYFF8+_f!G6AyfXrnOq95e}N{vX^qS#)?W{i-uadQ0t;E7ADqP_qP$ zDac^&1ERL2+C7XfJmLNdWRksoUEB|sj8*vM%cY#Ho^F2X=`42py^SBo<+tBW}{CKsDj@$1ZJSgGd0y8H%D|* zh2n6t!j16q#1Dw>o1Wj9pWiXZFt~+Ie>$jT0OzbsX4|zyYQ+lL-u~YHLUud<8%!%~ zt4Tz1-g$}?GdpY<8j+UEw&6uf2QAS^NV{N_IU*&LdrUBc0M<%g?Tc}I93UQXb!abNNc6=VVeZaNgJ^bgY zUj|7m9I+{K*524dQ*ktvlXWG}9Mu~}+d<*^QXIN9Kjix=1QOiyu$5Lx|0^-;mZnSF zRIW*fmB#uF3TxgNo6AoFf@t@FIX*hhX(sWgi#o>O_AEz$1@n|;6ztmp)(}g4S>#OW zHY7zx{h=hBaD|al?)f&$Ebmng|NnrVzn(2sad z^P$+Gu}W`yMS{3?&cN=z=7YT)mHN$GM2e-48DC|AJRze8UmYqjv}Q{fDyJXq-RZfV z;SUEuE;W2}^zuy*%1yXf!cv+!!!%~Db-nfP096ZRyceY?V|$X}`}heh!-E(Q;l3c? z=>?^3;U10sl3nn^u6+Z+grb02SEfqCyV1)>-~p5 zkbfHNx-_^yF;TziDhrowv0$6jX-#E-ap}%e+}%eC+yUL1Ah>Q*N7$}#wpSL_`GKbG zhB-OSi;~%8Nkw1A3SNWs6utUt7%3>7@>l)z-6G&BZ&$2aA~+`aBeO1+;YgWy_B2z1 zBFZZcfRznHZMPw8$i`&2h}N{w1f$)stP@;o)_!$os=~&dj0~o|?2SU;e|db2q-^oq z_`*W2hpzHtTftg;_B)^JzIbZg5w_&r{WZ-`gBs5t0x<9V-XV(1cxhE9Cnr~OB?|hb z+Ih%EjZ$!$(HnlUdAoA?0GCqLvM__qoB`t9$tlz8ja9fU_a`7?N2DC7u8Ns*35!~4 z#r~h`bKVV)N)7S9pwg|CTb|-Hjvu2gd)>8$IRlUyzg42@_@2B2yiG4*_naSk+ z4yuIxy3r<1HX5h?`t*Uj=ec)==JwQ&P|B}7aUjaf9ZYEJf?Eu6b#gG)xZ~MWPOg+u zsL3UIeANlE?S~8v{{fc67g`Xwl~_5mYE`A@l{37@$?dcY+Ug5$^l&ANMwggUXf?MH zL9S(yL|@9NzmJOzd&idD@9Ha&dlxrF_w8UhJzP75^M-4VT&Qx(?O-xL<%%cfX&6iz zS{{EH3AFZfmeuX*5XmKtCQqa-;9LW3T%-Bh!ah50_&v_|g#r|#MupGj5*FQV7rc=u;qGyH)7*$BREpIc1CEMLE4DvSn< z9A-rL(O)T;ZK3ZJiwToT6m_nrwNM!mR2!?m!RM;xx|QMG2&aF0k$R-AF97A-ul$rc zE0QaD!4{vEti!smL(}tGaP#p>KkMGa+@MNzW$8kS--0v=#dYNj#Y>%h8-e zE5YE|!JHDiV+3!S(480qj#SPCVH!y~79Q1TnvuTA1$K9>IZD#h56uwP;uqUb9=l`E z>utSM_Ykd&WWlq32>5bQ&Amsne#0d>(Wn#jQTe25%WqL0hXGRRjTxx!k?9knDxHRZ zD_CKlQDPg!xUk!*6Gd1!gGocbv)-(9AC2F|-Hgm?UvO%w;)30G1g zGu{$P^7dEpt^{{N#YWR-ehk}C79R6v{+{6we)k?yH*ya5~Ec1j+a332{GJTb&h2OAvC zS*qfczg|sDlv3hR55eB26 zeERvnp#P+J_6$DU+h3K%cu~DQcWKVb;j@7ht_NS;ONYq$Bi;CQ@Bg4Fyd`^B!hB12@ z(n$9tXeXQ*47^A1OgmVk|kc=!4mWw$uLRx4O>ByYnO_4_W!PEsR#z zqlT%6`9c2NXYZ)ZLy^FWs%hz_Wu68$UTnPNE99a6@J@0>&`AKTsovT6fW>pE7x8I@ zYX%aE{2933=ies1hXXnq@3VRDIT+hW4IOQ$$4A*fh2X`WF3R`m1Xn$d7xX98YWFIo z0n7Ai>mqT#r)kIaxQbQx(UgVcO~dxJVp}bRd-v%OGzP~D`zWe~^tAq2nFl?onvlJN z2p$wp@Jkk(Z(6PIVB4(e`|L#TWlbb`0!jJ(L?>UuJj;_SOQ%=NyUvevgYkYfEl7Fb zOQ7?^H;1hJOi~E%L~3Rx2(bU%f2()%RPm|^t+jyP4OK?I5CmNy)z<6rCVY)w!Svlk zrvOXMS({eq&&K7dD~QRY3hxyn!3NyWFU+|#9h~ROE;tro4-x79NMsOSmq)F)HvgvQ zLm)R|dH4z=NvPmwcb5~{vHh1fzz-2zVKMVT%WDrwC?KhEs*vfb70W{4%jw{AAew)a zPGHdP*4Qm1lc}eYZ5xy09#y;v|ct!nc`1-wI|%GoMToH1D*eYfW>~| zH8g8X0E%h6Kf<}5^5ce;?o%A<2}?MWO$+V;fL8sb*TXNpWR71fYw}dO*WBG)J|XVb z`h9maie+}JFO6^sRvo%yuNl=MZu(W!v6h^iLGRcV?L-ENpRqp1N>Ws`><6dMz^foK z++yL6o-X**{h%k^C$jNlf5;0jU z)_YJqN48X71}JoqI%T|gX-=%byX6I$&Jp%LH?^zw0ZIBhO8y(0EDYSD0wNloHYz8N zv#$H~kmU!11tJ^}=P>|TogT}u)8>^v64z*a|8xZzjF-{v3qvS+9yu#>o=mC`(nhYL zi)PAiV?DTmAAl#4D!Mo+B`m$O2@&cc+`n$048XaTASRpDM4b9IqS6L{Bn79flJ0#!GE0eCaGfz45j>Dl)xXn9iL*eT=Y5yevf0yt58hY%d-jD=+@7D_`RjOk9 z#XiW*ivsvNK=6w#Wb9s*QY-v0n3~FlNS&+OnC*tQ_)8rac5e%hE`1&gipjX80rNrAl6?K57)q#$zmCFbeD&eM17g3YH19w*B}0pTxWENhm8 z;C0j0jlen}ep_(l^~sf{zi&(+;w7Itu(4-Rv4HxeMAUKHsxNZErb;T|$D*h+2c|U<{OO9h8jXLd ze&}spAZEwIR8^VWh4SEw<##<& zD)m??%M`rgrg6G#6Aklu=o}&mdmu5+!0KP$Uh?tr-SX^?1{QG{qN+Ub_WSP9fQ0lV zI1S)WnXRoMm|U*b{sYG9FsDA(Y&Nj>`_(%JgL@8@_hRRYJd-F3pd$QQ^_J^*5xSL$ z+g2SlutMcZ>9CWDWwT5%WD~(D^ZIWxYYpu9Tzv;VQ+kW}-ZUMk{vX3jxDqW{)ANeN z^YFB(BZxem--N9XS>8VaN3H@PvT2ybcLT;y5b@;7Z8EWQV|uH0DZHIG>x}a3NEw z4^d!+LX8SK4J_n#7E{pfadIs)25-@?P!Nd8TZ#aZPY#_UZ!Kr1uFNrnVqqg^{S^_SeN{Yyc1z&6tDM2j#*+t^S92AhB`AnKVn1uFf`w)dO*+|m;OZf>Tl zg4!;E^#r0(CZTj(kJi||)>-_>0fRzdDT^ZzH|Odp3@lw9<_)eIwxQ>ImN1KHKtlk5FOXS37%5<We(;=~8UW7v)}JLPI?hmD)bQg!%n_6-0^oeKG0S8yb^bCM zkrejfEtIHae{R0%a5385-cURp``X&IS<{T-35dhoSC!^%Ri(2=0*O5j(_$*a=RBz! zQtXSnA6G@?C|NY`^kgXkYVYH#OXhP1EEH!B`%k}dIpK*>QaiJ2HW1$a0qjqrqu)+f>f)5r4Q4QfT+7 zzLk*{&Lr}KP326QxgzEFcNavtqG8vUgR7CmNdnQ3MOF82T{~OA<%ws^kGRB$g)(*`GU;ro!P5zDL?nSgw{@8=Nct?5Ux^_?;J9p61za40(8Ju3Lfxl~(1@V?#l-8K;DpVP5hkbC;F)8dJWk=^r(8pD8dU8s(xAR-nN zbDEDV-0hzX0L*%{ii%2wgcR{n%Q)c(7P~3#F!&X#cV27wP@hPH<7z32K=r{gN5?)i zw+EstsDM&so8f(uC#rml8ztfv=?re&wS~x)juRt5-)S{5?7Mjw+OVSxvHtw-K#Fun z;yg<)HAC*yMPSxJ;cLhxr7J%RMpy*WRZ4}dkK$H_OrD(O5!~7kBR~c_W`@(+0NS6f zi@vC(8kHTcU>)w=#}{9z?0Mf8s#AO!1}k+pSFh^n~6? z87G(hu;2+uDNa(;cp*w)_>9z-1cqx=5Kgi=nBeDuszypZYhr z^!_z$QR~bEP$ZD)&Pqjh17XP&7I7RcyaY)pt#doP;r*Ik zt3lFCh)(@D;(m9tp)^*!HdVl=%8`7WjOR@z!WQX<9$RB)^T!wMb6KRGpN5h?v5^jl z?{yHU5x)@`bn7jI??fGmnJJuJ-xA5S*IMuh4f1TV-?8TyjIqyLLTtvZUY-JQ7D+*=0036?d+7|OpL?a4`!R@A;6qA#HzNxN4u2ebl>=$u5916WH*#LbF9un zsTPO@le0SPNMN9*1GpooMfNnGi4S68043t>2DBx$2iEouCfj?UKoyg53dYA^wb>Xv z!R)Nt&X6CX@vF)n`r?CC$8s)-#bN@rc+6_3foM8MCZ!lQC78*HP<>yJBc&okEzU(! zdv?&$WN1$?W+r4d;Z9wvJ%psMzAA#I#LqT+rq9)6~B}DYyYiWWV1^yPPu|3K$8G}G18*yLY@kZ9c^;{Ia#`Zw|0U~z4+rU zW&|bS3(LUy^d1o0q%Kt~(nVl*FC?wPmc&HHT4M~cNx(RzD3=?zCd~er$loVOh4IT+ zP(}l73*|Q;P#TiozhI=3$0~e%X{kL9;a{-x>d0qV$!l&^8a3f*ifa78a+-!POgBO) zI0WZHp;91vZOxkF0UcXxUe))o#1J5rzSD$uGXEAo_Ys{|vpZ(&Tg6tP3hxeEJ)?xf z$UKK0Tr`OuTwR^Hg(~Vmjgs1ayT$$I+v`!qv|&wKaGo3MLpU|cUbwY@xdO3bq~_s)=!!2m#)D>FXWrs;dXktI9JGIHyL;T2$f! zxvqi>rkZo$I9)TR-qH>>3Mi$&5;hMU3uZi)pssf3Ao7Ng_{qZEXXKw1z~1KqQ00h2 zJ$hhcyuqf;ZvCeRQZ6u9r=gN=Dqx)Y-XNB|A*5eoWl_q&cO!^!GdIZNVq8&wrO3&C zIUE0jp*gnat#jJb@-WtDYXT~s%$)PIj&iO8%3hTdwvTTWsl;B1gaseY&?EUu=4P z44q8FyymPjkBKo}Tfqqi7Q0AdZN|Q+LXkkBu=;f6jLqXo0e7}g3|X1+TRPI^<~9^e zn!I+ODC?~M_6Bc=L*MkE-+OYH)0`8EyAmT{=psiZ*Vl1__;0WaVs;Nw)?6gSSR*K{ z-dXRFRgMo=q&igS91q-BQq{hEAUFRymXBF~fAb52%TEdw+`qbzDR@d~DL@Zx&G{D! zMVbI9O=l%iufxIaSn_Ubg)g7Iw$bfAvO)3~6`q^!YYuW{9R{>h#7fwK?@Y4t5KFe1 z$4}Y7y7N@4%o&1JmB@mupxCkXnC*b>h2}a3F++{oK6-R1a*6TgoH46ycAz5fmx#m4 zUz~1;=OkoGQ|ca|N#-k?X_yTQx>p~qXe9FmWyu4mwUnu1{-yt3ntXoSr8--iBf+d? zo-a*XcMibvmw8~rZ~alt?>68tHY03s1*fiNla2+=WQYk%4jr$I{;TGD&mFrk)81m3>*2^DuNl#fds zFjLYW4BLM*0Chhu@mO2!TA&krE%Z;=Beqm78VaD{?TMi2Pv*{3AmFE8dH}tAg*qMB zs^qS;{k5#d(!n`%ApW%I7u@{1o4~iJoP5~MMif+-VD2FKArGdde3wP{)fa(QA!}iz zvT}lz*cK6E!Hu(;wDLvIelF(WjYMB22&0_%#&vM8E?A$+1Uwy7P(@CE9s4zAw=l^u z&D@0f0g@#OW;KyFO72yZ?0m!SZnJVz?HL{*gBZ;H-%{;vtftALy{Pn$Rj4w^-g}~! zZdENEqD|i{K#66-WJw_~ql;Zm@$V>71DT_YQb6OW^08X4#g!LDtMBg=y!h3a@u`bk zJx=OTLPkN-!X(?P0+?T2cbRGo=4UDb`E}51`O^U!6*rVCIa*h+DUTijoH~w+bVc_g zvt!4si@7aR#*k>P$w{g;#r`sJ4gsv-SrqL&aQe>NOO_0JwP%4gt9#G0mE!vZoK3bsxqW`a98Vhmx3-@L zT){Kv$^6-?4q)%_e0Le2Zbvhxv1sJE{77w!8IP#d`3Yw2+k7NMG^zGP^IY0UP$sBV zRMj}`Y|0OjDaXq$ndsmiF&fRa-&G~P6bHD3UjS>T-14u`fl1HkmoMALVL}u7w(o@J zii7%tSK^vY35S3WtG^D8c(17#Gnu|4vn z%eoS>>37e#F{bK@1r4*=v=sswFUEPmIv&7CyAZCw%z^u(c*d@-laZuCgBMY2t9X{0 zv;~;9Dt7|Yr7Y>JAu(`wUoOd{-F=ErZ%Oz;D`gM$)D06%rAc4l>k=X8>dF(z3Zc>6 z-s08YI6;{=*x#&C?qPIu_x9Txis;|{=D8<5gZ7UPO*|CP3C^{uyWuf~^mqFP3Q0@i zjNk@8c1Fx(_Kh_Mlv^- zTHwjSC;>H5 zMk4nLI}?dZRsPfOX23Dq*ze4kjv_Y5Bh#BW_qvqgJod-jW`?#_*o(X7k60Yid3u>Z zCJS=%{()ROI^dY`wb$AY|Z0{HxItY4w${K59 z1*?p!j1-=$!)7k#H$@!QSVVP7-?GA<+9;@D$w;-kt!&m>et zY_rD7dGAB6TzGb{r$yAzi7FgkeQdG<#2G>|xfI1SnsbzN`U2Q=ZI$ku^4^|UJA(_~ zG3v^Na(jIC!KXA^N(w!=mx#C*4jKZCTta^^)VZ@Y)4$t~n40J;5>v$Se-_TXX>;7H z$oF+BUrApH-Qm+GCjxV@&DGRvZt#@hx0Ok|W=DpGx7=5|yZL*50aE_1&OZKlkS3fR zGeY2`NSYvY@@c;by;GcNGGyrtd@+wnpU31MR%loh4n>sZ^dH5Os!FHuW|&V4W(D_sWA;quc7mbB8}YO( zZea}zbXsw$Vg%VRL{6h++=lb9FRc~<}5hj)}PF$wx* z$mJGzi4^&ps)dq@yr@QwD1Jqrf1qP95J}f_+$bnl z7DJMppW^54m}g>QIh0qXENG1gQ_yi^1hxkU9t}8Tb3#g-qtQop2Vd9J7@KcTGwW`jr0RX%&e-{pq6gLS$H%GJfX@4i z7**$i^~>sr?j}zhKTwZsZ_OQqn~7RkY9L5*oW;C%MI|dH)=2uknh)n>yHh9N3Lc}! zc-4fw(2_-^VC%{s-;AV-5RN?vkis>a&E`(*bg>~&V5JQzERh^oquax@erhC`1@{#P zeEkP`Ry?mr6^WSx)~}e)-OpE*&)^ntVtsIzK1I1eJRixEZiY$JHH$_AB5js^f}Ju*rNz zor&yt8t7xa{uQ=uoxb5O2EI;ABo&YRW&Gd<8%%Fr`T)A2!QK z3xA^Lxoa%Yxvn@CB5`e%PZm)j!m-zk7&Ln2V#Lu&^dI2c16GB9nk zcMcYcCV0HD1=6bJwN{Ksbl+)4>~uP>q4?@SjF3RPBBC)9r+YrV1sv8?0^ z%h$OSfb6+9(IP!-SCh@dXRghK25?b!^(!g|+_}3^H(+y)crK9)jS<7vRAj1J6EItL^>R}s#v$= zaJJ4+5ptB&35byk4(U5f5gQ~TJfQlf+jw2SUGTk>J7x==` zPaLZF#z?$=0lM+h*+%|gH=j&KZnL4_laibL46vd*oUWWbH1y;5@frGe7UHT1Sv76n zzy1(#LOC6X2QX>0S*yBl;xAZ>i06bY2+&7sB-Z@Sh&R%qSP0P4$+5GF83z=Rx+?(3 z9V*?&nQ1U9?>wtbV0(ha8#lC5Sz8#446|?=7h5T~HH?^Bj+eND_uYO9F;#VxK+5hl zG)3AbAN1cIJvV0xs6IPRHt00@wAuoiH#K07=`zGOI`}ENywgaie@nROw(p1adCYKU zTKxdBbckwaKt_l%Hq|7=A%p}Gt)%zX2qoFPS%rDDkW?-^K_aAuD`0+EnO^ckf@LRO zbAkOq?IRiv=*>b~VIRyiF^G`g(J@W{ACH7al)-MTJZYJLI?tE4()GMF!X0g}i1P8d?e ztdc^qkLQ3-F3As+lQcsqm)s*cFR=DRJMRD!@#8kRcs1Z5K1`x2 zwtb3?gi%fQ8?`KCWpr}%q;;$RV_tiJq0+sk?jYS>*8y^vF;Ip&frW{r)kEH{-qS&g z$V_Qgieo__&_!qdk-Vfpf#S~J#Dk56_OQ7=GF4|S8knFsz`TsWHoHAxO7~Gfu?BWe zR8A$Vhvp>#ZF~IxX0=pP55CWYU;e5A`SXi~w+*DRD6tr-wZcM07o+09oSj%bn(`9a3kZADROhb zke-GW+z0c(z@hFGtK7~CApisS)gL|fA@sZz>HDgRUx&Uo+iKZnZUYP0${$3lH7nNO zB;_TT@wxhIs=$b01m)N5_@tA{YfCgP&NeZc+}6FjzYiy)*oS< zz0lVdZST0F++d($UhysGC7rt(H6Aq>WfUO9+FJ*MwOTCzx=wZy@hti_M{jlg71}Wy zJTE~8?q@?hhBt{rYqY-@qndk5N3QCmUwJX^-rR#MrOT0{H3;iMl6%naHaW|Dwl;ZQ z1tT4O?j=cj_`YA|fJYc>ac-B%VKlLfL-OgrP_VUCVc3lLH4+H&AqN{NOXCpeq&#|r zdc(th6ep{4EHmCEr9w=;K>e-TtkySpPOGXma1(MVZfYMN%ReK|bFfoiclL8xY{IzP z?u=Qs89qy&?wro)4!?m+=BP+YNaf2}KPFDDxJb`ge~(TT(gHbjl zAtqi}EpbA+dFXhyI%^z~q>?;GZJ{^7e!06!RxDlQ_!(Kv_=X&#mfpB=Rc~lcX6BnU zsQ%y*`oMnOrtLWeo6L@v98nQdI9Tt!^YLrVwcGv)n(G((+PY`Ksk`h;(0z(7Si?Io zjTx>#j1LihKyk<`9z-}gJVsl6@WEqu=2@qM9YQ%8NN^=)!CdX5AQfMzpH$3iXq{g- zwPYq!S;q9e2c%&BYHnbc%t^!yv}^C-f4mH?%LtfNC9Vf;F}uz#`#$TuR7SDUF*)tN z`b*`;a*)a5s%=6(tKEr_hAn%{0x3{SMvp{@EZNpVe8BR7M1b^TBzxt4{c^!J7wLVj z897eZFe?1Xz_%*6MxpWum|kO?{FBB#Kilc`Bp8{|{aUJ#*$uf9Ctp`eJ3eO4Y|zxb zGT@ZdF`@5XRRNFQk5bR)9Jb0fc40hA9Jp9-CLe9iYN9}(A%Qw;MHQ; zw@i&3<>dB!x6Ztbk4F2Bh_&7v>&@6=xNOYR#1aqs?V; zf`z^B+TS&2taU&7`EvZ zls#b%P}Se85y_m}#=da1Or-bvH3IEK%ySE;>itJir*X16j=hWzyQUis)A|JY~&= zN1&B;IQTuaG_E+zmcI_{wVJbL@G%eX>A74nQtl^67R*vm3LOY96Azcmmw{;=J*+36 z5(yGuLhk%rwmb}@T?b`V)nYG4=-;7TuI42I7_olJZm%MD+L{SWye^3n(Cu;w;3(yB zQsZ|hSZ<{_ZxaP;K?&=6DUW%^k3~JsbL&CPlbq&_z;`t~2&9*hP{93|@sy+!S%tl6 ztcl7@Ix5)9#@P&aKQKy91S`0mL2gtNF#u|Sz&$rIP!N%x9>vX6k}F;B_#%9qPjjp@ z6IU=ro_)G2rsl&oCukdzsYlvWkfhNOQrBMOia65bfcmxc-z;>_{>1f~q;KbYhRWerW zh6MrbG)0a^64mu$CWN=;4xJA9>~e=F>Xqt^Ohe8X3>`VqR*SXA_IH9ZX)TiqR{kOc zu^%i;TJP>$;w6sf+o)!fn>S*p8L2~bXj?8)|B(9zxedx%3gERYtH)n}fXy~$d2tek z^kGlcJ^?*&xF!)kq&m!+1sYckxcJ%Xd` z*>@Tc@9{VsgN_F>{j7B_gUPXb!1nScWY09qx- z+!#ynl9fUD{AoH}Dp=RXiak}p)!rVxN4fp!Qf}dxc4lVFuwtQn`Zl5dw_2*t6{0Hp z)AF!fc70Fm?~fO%E}S7$2e40Js6xVv_N&&%Ier%GUo$jPv|8bk#M(Nt((x_%Sq=_v zl8<_}od|w;Yg&2a#YIIY<}*H=D>0K{(jwyppriB0P|?4dC%8^W`y7l|z@?om%))o} z6YqJs#%Disr3KrBkXE zJ9ZP;%tAJXgdCwc9$10>;)!{0F(|_k zG#gA={GeFc_C8K<0!2hB(rojFD1x9df0j^lwXTL7B^9d4I{pZl(!JYjGR*u5?$|4~ zq~zI1^j0$Nf7zP3#hRIxam-kOg!VJXFYWr;=@V{vsr?V_Dy?tmY*B#K z%WOC~7w*(ELr4J@AS|0Rot#MwGGXibJ@DBVoT=a8DUiLxcZBG~zd?CESw8=e!_9Cb zk=@$EP{KMpJPAE|sT`K;tFwIz7U(KzXcxEs3C;;qO25X_vVk{c?QD8eoZ7O;zd~rL z4?B{`$~uq_?af3GAi|wkWeQt%?Jj_VeuL-5t90l$;(k)6Oh?nHglAd$&>t9Kp01=9 z!4|cLdiwSWK1HM64oCjGMcQQ~`f+m<+G0QD3MtYD6DF|-Iho||L(Roq4YP=schKc)lY{Z24JwJ{TcOJ5*OpiSsnO| zO82RQjN~_sRhGHA4GQ+jHpZ`OW7N zSwM|-=&e}E8b=~v$!vRAqSfaal&3wny`&W1np|rH!Q){So{)zaBpi(nOdR2I@Gb!S z6iG`PY-6c(qBd6hGRe%RoP&>D_`1C(cv{f`?gM;Flhgr~4z2lk9x}C2)miR9h?$Cc z%_O9=wd>+OZACoheJ7*u`vqc3(h9+6D8grWF3HTa8YVO^`>2ckj+IF)!nCB?yz6zp zXZ-BwMMF);KB#a@`Q;!kTQQ)enRfoC6}0Serqdy^++k}BdN}`h`;p0&iAM;^FZ9s;mf_61Uhp(GNiOw9+ z&x~tl6_nyf&pqMhS-ENbdLXPZamMh&Yw54RnYSLCbaQis0K(FXOuG!tc ztIhDMnoBz5R^dG5wv4SQv-!CrFISLm3q~Of3zP(k#omGOG?$0*I=7eU#RB%cugD9U zW%2^>$g_nXV`x**Co`NTlw2b3+fUG^N|bO|G?RmsM(yPH5f-=(6}F!9=wMMJ6` zUhq*tUvT8~rpTzOMK5LrOw{WO+M=$WKlAQHrtmHEPf!HGOq0dR6#jOTf#w4J{786s zpfS1~{mVs=xkv`onVw8UO89uP$uy|}O*b>t?48s00)Yx;bGXf9+!sLE-0~wK1eQ__G^;uqCYfE-AAQxTZJ=}NXEFWf&J=1?CliYOP>p}J z^VD=k5;oE|mIR4(zlFIRuNR_ps04Ww9i?S9R;SG-aaxFOKnlRSrFQLrIr2%JB)sy# zS~E0GJ6+b#^G6fzZnP)-;Cc?@Q04_tXb$v=NnPi*?pGHoU#_ zrpv!R?FzfZ%ykL76%Bm1g4#5Vp3M~rOJnYYj~wX%8L;3*$tepeEp$*km(Nm+TPVaj1AZQKDwxO^ig zP9A`PJQ@a=YeZp9uhdRyTGv)z1%I&Xrx?y1N zfFX4~_Y^GymlN@VAEkyz2wW~CySkEv%_;{sQUqg(CY$#3sUI~IUj2WQ*woi3= z>1_Hoyn-?Wj#>%PR{6C^JA>o5rypVhbHnqo%7glI&nc0F=&PFs68NPHd^p^hOWMs0p3*7Kk9{yDP&cJUg@5V_xnQ*-@)Bq_aV1#kG+mSuO;$P}4n;$X~pi{z@2fg3U@#1#Z^t!Df!QWyi zo9Y)WbmG2Q5lw4#UUi8Sy%`3N*@^Pu2=!99CO=uV{Yt7_v4#wg9N)ypMo{43n#aTm31q*DEfF6<%m6F2$hVC8Z23fz> zB0Xpo(7@Cw{_XzC?Dj1CkVhVc`gqW-0R+rsF`(JyTRY(VYq^`_Bt4EE0ix1G(LcU^ zzcS153*L#=EY!OQi$+&{oG|+DQ;qM7lA)9o6*Zy5)2_aQ z*68&7Wt4_VWisb+I$M{wTpbWYqSC0DMyZm;hjcC_S@l;T29$liXv+4VHw|MERaEg> z&TtxUv9Y2R%y@yJ31_tD=_7~V1oj`jondiO%L$;ODYs7rh0tpq$nV~)z!%J9JL=!G zj^-ZN?L5NXaCB!?nALRtT&1Oug!7YqnVE;5SaS+@VJ#F~FxZX^tgJ}!jYq8jHN60v z_gE@b#0NB~8;fP597;L729q@6wkuGD2PxC&BeJ{7qV2I0w0#HKQ;}lA^eA?-r*Kvl zyE~0>bJa020ioPa`0RbOC zuiGtfI$vz}G3!1OOLXa}uDUrisoB5gdUb=92$Rk0@C_C9z?M?m_?qKi^DpQRwqG_l zG<1xzv8a`Vrq`~I>$2Ahrtb0cL$DAG4SKBE7AproEJ+nj85Gzn>O5Z=(?i-ZrBZtE z<6J?q(wbD79)raiy0A5W8x#R5P~&iLQUby@EJ4i|cv5x!&EXX|C0}NKV4#B*xODWf z%`+4rstJ}(?Y2$q{LS1Iid{`+**^yTqO%~1Uu@GNZy7~kzLAS9Bm|Vv5C^Cf49%p& zZf;*<4n_xYnMqfGg0Q8SY7%L^es{Jr`VJ58JUcMWwEbPW`u;mvqOd0MP07dEckxSz zpR$A!Su2uvALeg`$eunK+<|*z@PbU+kOtzUijt^UldTL<4n#mdgPgfNX7{$mH!?}% zOc0oYWQQVh7b|Kx66Zq7n1VemQQBM@uByuQ^=NZ3>Y}{brP3%bmk1oUj=;a{okK-J z*u9`B7$NV*N~;o*lDUe!aXTELn^(~62;P522v%=rU%9sj1Vu*&1Py=!-*yo&u(a4I z6V38$3c(3eY>bM_VxBK8;rRt-QQyIbDBqzI$OG?j7%28!BJ;@tlJyz~;Pc$QbJ!9x zZSMO+t_ihP`7)Vj-m{K`a*h5tYUHnG(>9$6hG!ixvDx6Z^;Bflc@V zyjcU2*UQlw-Fa@_@oIbJh2*8ioyDd$lpL?nj#DN7L{N{*_{FDU>F(BaX=mHH7B`!D z5nTXd$q;kWEzpXbIlTS0i^2tlFp$LMkazT008W8|N z*pdCADa70LLw^JVlhIuP^;oGk?}~FQK?#gYUzU31kg)6``U!zqLrwz=x-)Tlq&OL6>_Zcmhy+EYd z_erX{)3@D^pkpymbl7*%ws=S?<(t8H|6{2OA^I{33_+nedc~XMeGK55P_5k#% z$r(z~_@Og5n!TwxSENXdNr$xA9?o9`^FsJE_z4hak*vep3>I}LZImfXC5HiB{)W<0 z;sbB9)v3VACj16qS-tm9K^A!IWb! zJHB{c7VoGj?iv(1Ta|j7if@ARdJm1Fx)1oMnl>+MLK4Y7ipc|utQnrGy6H| zBt(0QclQb<^Ls6Ocr^LM&AQv;Nsu%#2#ke}yTgZNzWTQW6iQ3`)E!)=MBZ}_kngm5 zG~H?tP(3d5rGrU9SL*u@RF-x3W}p^%{9Em~P$0Kv#TQ(Rc72>&ERf@b4RNyrZ^r&u z&ntT*s})!&6**_aQgKUPKHryd8KfsA<*0^UFDZao3@L+rqUWtqBp*kL0g=F33q=hz z;dB%kLhqx4iJ9Xk0mLdWuBxBzSGzDF2n2prYp!+gB6_x39Vq2W)dSJaAJ5OPeNAWV z`cvF8!PA-0iPiJK0h6-TB|1mln8?pdr#u<0HZ$D7=g(%kgJ)5U{3T1k$H_<^ zhsCccaW@Pe22R|2l4;z`;#X;QD;5zi8qXHOw<|%iftr#uhd%h41uc_&9Ht)6c1VGa z5%BEOCmCM5Z5s>S)Kp|5E(F@cgi0?K+JPLuTUbPg&IEo7e&-z#DR{B}!=!Hj_X^fg zE1f=7HV!C~itm1)MIP#O=eviPk@m=3r{{Z_-%KwHc!d?hJ;wOUxp`ynIQCBTK~=`y zN7TU2K9ZW`{2Bs#5ffzLGb|-InQ4UDiA{`8bR%olp4Vln6N<;q@l%lqhdNY5(R6W` z%!%a_Cknd=;aD+}BiR*3#tRSl^W#tWPYfg$Bx6xl;Z{W&fTAtawK8GBYZ>M2q z0&G%pr-4D5Csn@t`r2-O9~u+~$C7JaGnBGKGA7?_whwCfmr*eV&5B!(f72*Ul;{-4Lcjo@*oj%=XHEG+NoP*l5IX~! z7l?mes5e_DzJid^JbP^^Lu}lv_HR_LwaiUP4R0t5ci-!eKojYFHSIt-u?i;%v-}f* zc{Vns{BE%TifjtvcgcqJvA)bKY9=`nOk!Q$PS7-SLgJ_@n%%^~PDcK&7{v_iJ#Or; z+R7X%5j4+Nusru%2C=^Q69Ojge3>&HGuRD+?9d#F$ADjdV^!GF80AlEVndp5?|$hQ zD$6Xji>|VquPZK3qY1zM(l}xn6~KOeaWuxLfhXSgUTzahNFy)5Bfa3(?zs$=QRC3j z)$OVCG5(cIH0+#?!XWZE zLkiiyneMRPFQOyz(wIyFn<|op%i_rf7>cr7ue5Vrdjzj%)-)rF(VON~s8|d+H z=jHH&u1cGhVY8MZQm4>IQ$WTX0>dv(M6n>c(F11=JO7Q>?bQwVW^Vo~hZk`wt7oK< zuGG*7^JBT^?JJ${HkuR>3}GGq&s0UGx?yoX{QF7Oo=OT?492a>dkPX^)b-}sRy}kU znYQEKP%-t-)JxyzWB5IC+3&=21qI5~?;a1wFsQ>(FUH;iN9naU09KW)gQ~q;k2H{; z%F8beQON17kSQ~!K%><^7!1yOcVF0GojpMBd#`Tfx40v2mn&ml(%X(-CknM@pH?FV zrkJ)h^jhs80U=RFCua53u9sR2j;BVYYI$0n?nTg4yY@*k~aPCx#Ob6St1_TFy##Pn#7GZ)wKs#X2`jUbSgzmM@esn%;v2 zxycUP<8EJxZttHkBcY(c3`U>_`Geo$7YiD#*{j@%aosyw2YNT`lmr9RkhncELn-9QGzggWk*w3#C0)O8Au%8wT6Q z1vMGU<9i0~n%#+R-Gg|hg_snIyjAHk{2PyCY^@M&yJ~nUPTv&CkH|B25!<#VA0ky8JSnHWj4->Zo zi~r^aRO|gx2J|V>(=hSUb%Flm{iV^mJktI*wfpp@iE&Ijr0Omvyj{cfs| z!kMO2{wcP8IF=3#b1(@adTSiCSyk>Q0}-LSS>4mr*Ld*C41b@v&w`4_xSDq-73{oO z3Fy}6q|DBFi+t9c=DouF=VW|C=5XC1=JCCOVKN!{wyzlY&)*o!0S06fa=g3Q{MQ@# zmyY{%0P7aFphT6ZGg!`XM{bF=)f2lIcTcmuCbBLrS=a1$nt!35biEvAuZRqmcW%v*~?(|N5;=u_Rc7wLn$-tL144tiDAUb9M0uL=5y`%X7k?~(*y6V+;X-)&KpAss9CE37Xd6RkB~8fWkoU3^39tFIl0xqNB6q`^|58S?yZL8uaVW zw~-8XL^TbycSw)P4l_y+UuHiW{#(Y@7crqYT$AnA+`>G7Ss^|1C{VlU>z$o|+N7Ze zUp$FqoxT1REntB3{CI)$54qiPY&K$=gL%A{@vq$cWB9)V!Jw}A-@f3v34`j8_c>d^ zBdsfawGTWN(H>aSi%4(RfK;LEHl@){FMh!r6~%2wHBu!JkdMQuFo=V%8nWn5e9$k` ztDn7VV(G_;Y5)1z8Jmb)dK{aWuroFReuB{yW!onCZM`eTn$J0!=L&sYUs>Z*9!RTP zwx*`Mj=qreF6R9EV|NP7R>GCM=NcvVsAMyjHBxnR&eyv_G@4Hc%c0RI zk&MUFMJK>3l*>pP0Uzx?%H2W&M7c=6p(w$uh_)?3c*X8e_g^k6C~IUt%~*OwnKX?n zuKA(-p02vghAKIC!RdBiyts?H*X)yf_%&t zASULWsbBa^SY;<-V?2M&NzKvy&f@u`inxxm&|cY#FGxI*Mq705anzuRp* zO3Lxi)g&rs5U%chTiqu6vHFd9pOGGo?6Zsz#e5F=rY$iFOV^xY#gxnN(rlS=h2vP? zsmqh%kHgu{Cdk32nylsMvHfX1usHP}P)}#lO0TY(95?MMtSP^$&UATR{VX`5yEq1NoZOZ`10LHof7D>c*de_9{01r*XvjA$i%Z zk2qL1kGIqd3_7Mvjb;b=!`WV|3RGyUjyEJATD#*y$0I)w+UzwkEU=)%Xd_r=zQ~ha zetp2cpw#Hb;PR(N(%vxCI|A5ie~K=pentXF7{;LCY#~G#p3q!*B`TY44D><5-{3`Fup*W&=d0P(;1`Yuiul zdcD)9Y2#J7P^h;Bs`XaqxtY$j_-dhrze=r149)!=z$fU@*5IXS+{X0Tpj-^|#0!#r zmoj^Y1xxw+S})OP#R>*{gRk!V4O?sa=6!)XTpLiRo=I(}u*$!6(*|PEb9W40RI!|q zJDANU>c!R6nG+LbvFM9GsqH9G=-Fw@BO3K%ahT_e9(ol)U1TmfP2#$WnM*Maw+yeF z1?j~56+SnqVkw-b$x@}{yYG_=M-MeLwMvy_3Y~6Vt$zRPD9PJkekb)oS?9mE@E=pf z4iluC93X#_Ep1C_lZcc^b67KDW4|<5?(mNA-IU_@R*!EQdo-C}Xtg+~ecK_MxZ(WKLiK_D-Sn*o5)oga>^2D+`#AO&7W41PQ)MdJr!_(KxA*5! zMHcTvE05=q04CEh2}hG(c?|k}trrexewS>N%7PG39B(>5&>o}%(EL87cU;QrTh?6W z5ZPQ0Y+iOA{IX?IslwsWcsML`TAbR$?Oq(@W1)NuxsZ!hiH~e(S5+v*f3ETsMAWQ7 zqkKLGttru{V#7=oTX@9-vx-+-7Fbc5W~;^>t~!Wg2~=rvcItzwW%40Yx~-HG^%om$ zq7#FaC~cg%CL2A+^Ct}kJ0I(#BsO%~=q3MAeg2K}BV;?^?RRq}-F=~dH-)}08dp`= z`UC~1S!pmXf;JRaNE|urz}C}ry{?T@s*#nEieL8L=luDhO)>UWGaYAJEscEKEht^2 z45dc0ZS}QOC+)i0>Rv%v>$9OT-=K*JgFT-);`VsX8I{El_IiJQsB(*&^b=&`Ri_;3 ziD>)WbEg}FLp7clkkx;ode|;s&*km=^r@Nc!N+C(h*c@t7rKYEB-X zJeHEZC}(jc!Im=nJ__cs6;@%sTqy(6Qy~4SkUS6V9aYrLZ?)No?0jV&aG z(}KFb?z7mk-9=OIeF&$YwvGqaYVJ=e*n{9OLi2+W#mMHw3vbmYBo!M#w4T4;5key3 z3e>?v(BIY8F*{`zBKG^JT*d%C%Wa=^hA4Zqx<%qoF%LS4~#071VIM^|F-7$ zr50x(#F4d+%G3GBmCt;+V4e_GkKwJl=$mi|f{fjL0=KGcGcT_0mWVw9lQe>u{YT96 ztDsd9wW0;I#$pqelF}mJGZt?+&+50&Nie~;e+`MM3HZv-X1Zkx@H?? zDNa{|rZcwvPlJeTkf=Y^^ukBU^{{VTNwhlwuQWE?J^kLSoACE7F+BJU%sV3aTT>(6 zt^=XSRi}c!Z;5Xku~v7O?x zTeOecVYwViD*8?38jY387>Am3o_-$DJf7la+FU)p*&;{XZajGOEl?Y6`Yh~|?+ zSS(%}5byWrFv%xE0|Q)o8?71JqHVqj2|HW+m?GeRz^G)$&$K{zf9XD)nwitcdA&s? zzUX#)k#&Fde(NX!Y#mOeX|IC<36>X{L%iSzlL^u$jNAr1{#SzwmP^kWFOkED(BQ#8 zq6gaV^PV@P=);Mf-pi!&9`Pt@yyif`SLe;x96!>;wzKU@$)BV}&cD>q^ z2k!AG&tsP@_|jXGwpAMnKvz$?m)wYD0I0kw z>EFmYG$wZx)$rO3c9CN8_sNH1DbWVN?abpvBftAiForeDqChk*5gcoI;&g2_<6TSG z3oNl`w02(6$!so~Xqb_8Uy)ARIvPoM-QtIL^IG@bwP?HB9&#Qp73yGqWZAA_8weJB zmcx{;Z)kRpmv|b7OuXBS`Al&C{lpz!Q>lEY0!5fi3H??<5H3d2ntX{Boz#ytx6Qk( ztut?m>Y1Ge_K~|L%r3pjH&+5a=&Cm;ePQ|ZLihfT&7nc%mPyk1bYhCeqr6!u61>nzo@|6Qg)bP5fY0Wy)8%2U1_p6aAO@Fb_N!ca#~-^(9F#JPH^&aq(oT3?ceGNL6I_rxSNCOezC8dnqR?Dr zTdG=W4yR{{25`tUlab!fKAOHig2JMJye@8N6YG0_Q+)tnClI=&C=d$Sze$iAHvTt3 z$f(W3>cfMe5cU1Yr?yhHf^)m;SGT$rcJ@5on``%SeVf^hLi`05t5>MnFGlJ2EyURC z4@d;$9=*F(t270%(RB=r-_ZAhmIMl42ZwH}9mlhsNNwHHQVpaYAl?Yv9}_cgo$5S3 zi4#Amxvk53{#p`eq8n;gvw^X2hTel!s?|AGnD1=V z%cvEOXZ1ko+v9t$xcE#L9$(#cYipLdo!s^rB}NV-U(Gd+?hWP#@@Zw)=yd2rTJw25 z69zPr4B7nX*Qdb*91O0L-5V?lHGAV{##idC9i3}&5=sZ+(w_8}&?{9q$!ah(mTeSg zw|k{HEMl86PcAt&!0!o}*o<8T-TWA#?7u1UW!|yoMbz#UarJB_`TPuc!G$y4ACLDx zM6mereXUPoUL$Cu@+A0kh@e zgpj62eA189tJP*nvur_bx0Ub(Vnp&)q}Uz+AD8nfobhP9q}h3%6%={LTI%^wp%6@_ zzQN2lkSHTFNdMnmBi8y2i3#?mF}V16i;X}zTz05w|eS*`Iswk7po>lWdD0)I)u zMk8J|O%;nq;R>JOWOxG#e;NXD8i!vwoZ?`9U;|Tsz$#gznexol>qX@K;8A`6Nq<~U z7#cgF!y?$&mRDV!$5UAyt9_EbAi4R9t@yIt(X_sVuSxR&F-S1r@WY0-0fiOEQ}F=OQpA5bvG8M=Yk(iuNY} zfu4f3zX|lpZqyPEWQgLz7Vlm$aRMmEqkDn*`<=b+r;DCrS;RcN9xrLpI$tZ0F{K%? zT=rk)RH6{N`Eu=|(%wDZKy5_IR@|`@&>P{j9bVQW&<5?M&x&A~83K=`hIC5MwlyT1 zuZ*Yo`!+R?ro!dKHGrI!g&4~lcSJJQIK@qM5^}SSxJW%gY`#g+^Cdxx2!O+4Bdhzu zyV!$ColH|`(R3=mD?$#x11#b*nu`cQiS(MmVt0Mi14(=YFM`L(l$!ELrq5AVN~iNw zCm){l{>dz_tRsc?1!W>P`M?1X2ZrKfsPD9YY;U#uGwwNC!rF5Hy;-f*sp-pdvpq{q zZ_v}{X2SkrEvy|kj@@?i_XdQ_K-13awY3ld37Oq?@BP*LN+PSY3Dy7*g$&>i2r=(@ zcp5969_s6_JXwtBnDQa1gVL>4qq>O_BqKA>BgmUsi{i#%z7X@2O ziOsLWQ%4Q5I#xe{r@0tm+YGhMUmXcsOBnD3J=-lqZ82Bg#njsyaC zC4)90eEB>x&$D=NlaL_@JKne_S7<9Y^ zOX({TjwWd`7p=BF6NA$PrJLQ#_1XW7yXQ2r3+@PqDGY!d3j!PG)Ah}%%dk1US5KtX z#DMAhfOO#*F@=mUe_OU`IEV(1)YiX+05L#S>%W?EzO<}8gZAGbJyW55a3-K&`pW0$ zf7Z0GkOF<38kSHVSB#7&QY$jF4TC zn1S?T#FI}$Ib>j?jfbnQl7OGYZ@~6F4vcH6B4t80O_8inXHV7a0t--#g2(Nf!FI(T zLdsHU=zO}K8^|%7qdiQgn3inV1pWs=6rdPBP)8}W3_y#=8}Qk=8Ov}bpn^m_-t$~s zyv54;rBNTj#e|I5){u4N!dUqRR^XMa{~C0M8uEm73D!8VH)czjsQ(?ye^B8(S^0mJ z+i!jX>naqTc|p-%zou&YLcG;o_S=$uZt{*?P)m-TGz#J0mXNQqFm={s&Zb5}5DDB% zCKD&Q&CBmMPa5{`O=wXYcBiwsud=9p^^vC^Te{p)Y6kCebplD~ZHt!r4xrb(7k1gL zR*3^9qbX#w7H1=W@J?m0`gXa;)68B6E@ZGSH@T5>P2BE^hc~8)@T{sd8mV7tw%Ayj ztKq1Pk8AwV;IJHar;yGP99XE{8p&XFY2?Tr@nE-Elp3gOj%Uvh2khF_n`}T-{nC0W zXFY3l)3Lg)Udj!_m`3%WmG$k@aM!>lw|J0en|}LXRvYgJ>zs7z4tu^oNnp2}_H1B_ zr^Hzr->;h_c0(y`@@u-bDsG6>lM#uFX;KCEd41OIc=9Nb$`KuKJzEhcIEeC$BeJAJ zPNDL&v2}^Iz~}+?o~w9UF@Ke24BjRC&}Kv9*^;9*y3J>h7o4KJI5INPPF8wWYP{PBipRO`4DZAc%zB-ACe@%vgod`>FfGr{} z&#wsaFYQt{bL1ROPkdUfY>u^~0>qRHA@5E?;F0ZvZ_|DN6j3iX1;6WS@fIY-5tGhh z=J>Auh$?qb^O1xpkNHD)v>v^QZPY=Fx7+7#C?iYMvt&9`I8i%S0-BkIW}IHDGg3me zT#Ia+GNVWPMeLTiAlUd#R=dl+Bv1u0Bl>zuv9=Ur>+R~hMkbFru>Xz0Z?kKJbv_A9 z_QR*MEbT6PWnh@P@2=T@r{DGbzqotH;L3t`Uw9^%>^PZdVsm2Kwrv{|dtyy&b7I?e zCbn(t*tmQCI_JFg)~)mTeoWP>UFp@mx}WE#9y<(iC9h6IWF0mov}TnpOV8}o>~Fn~ zcl9Qfs*DA!%zsjr7;C;QUdH{3g z;-cl(UGCcQJ{;hJr(0uV%`e>cW5}g3P}Gnb8ii<#YvEZ-y~4LzwK9SqbBMFvDxlD=$p>RuL{i$)d&Pp((|Ukyw-R@Y&k}_=k*#S3H9r8-S!4EhV>H5UzaLw$U z;6gh#IDM^q0+qDtayD~4jPjNjSP_;@GNr(4WjtEGq9D8XU9GAj$Zsp=d`AaMvzfam zM{TgK1P=48XoxR}zw6|x2WH4=eInF{OL)DHyQP+FkeZ1dl&!WEBrB1_mTA)Q(_EvH z%hyN%Y7zR~EmRuGq^fC!lzAOtT-Fa9E{?tR7opdVue>u#5;_05q1m>|)y~ZO3Ry*^x zoMO;Uds0gm1*$GV(`xN%xW3!xPaE116SZEhuaz22evbg5?{ZZ-7vjr40y&`i3z|vX z;??(YxQ}t=7yl3mKV1s@NV`X*P)z2xrFzRnh3vJnjHZ|fW&+jQJn|_nr{l`#uZIK< z``sgqRnlj0ezXlc3?QV-JMK;s?{43CBvq~+8e_*2S>uHBQXdU05 zLOZ?P4LfqHeZ|mfGxuQw!)<%tW6`*v^0+%mYy^N0e3F{pG|LxJDM*emEf(qu1>Z*r zG#O9aBr9PzeiV=W0*i5hDw5L{bx=hx<@rm4P~4i8&FBX6nDIx6czmItU0p;RgvT`_ z-;1_H&O^GfVtDOL(gxnYvjD_$*v@#Qh^OinzHRXs?du9Or>k5?`0A54d8tLBcCAh0 zwB!VP&?EYTWlZBN<2six{)^|~C)}b2^WzU)%(B->iPu;nX-r0? zNx>4R<6#umFTI0Rx?AqJDT4C%-S6Ia(>oa~&p{~Uuj1LX@D-Y-wJm0e@))1e*X+5W zmq!}sQTn5cBAm}q8wD_^HUHcTM$haH$p!N0EKxyR*mFZts^qcDeB+v_=HDQa-X)ho zcBm#^YZmbCb9(L$`k*!OY!?!dAGkJQNxyt%?zVo3(jfxeCm0;!%(QxwBO`cLCr@Ug zK1c~4yff8)sT01z()RpzVuMZbqodjx|Mua>>R>}cicOGKIMXgz!e>50`yFVn zZGJYdX8SyI-MQTMpztt9ZIsG!9e*H3rxDWTO4WQ9M&ls%Gs76)+p~NH)_i^8Y0YaQ zFzB84#YOw)pcM8|V}|7lHpXy7GLXy%Tc=I>@FJgSm#_Xaukn^Nsu7D6_A7`#B-?Nx zPvi8xcN)$7UZhcX_wckA`=-h|5$o2wSJKb*Cfr$py;u$Z-oK*_6chb83myJ=?~aB@ zk3Rvk`uV6}G0txy9|C-N8bB!n0^fFP&m+ zrh>A$kjf1o>5(PVr~Nx2FKQ0&-gWftK10r)`cjp%}C+l!Go zRaLk)ZhXsbnZbL+HmHm14Z(b!=yvTftwi(@O8EELB}hO(uvG-XNqb4gHHF}5Y zbma;YXq3X~E$$A#U?}K<81Sq`{ znk|xr64W@&nS9>TqRZS9X-~3bys;I;_a^iT?E7f=ko^u=$ecboo;m(*XGFlSYm(sH8uPIXJG^?YOmsUzh_giMM_Yc!=j|B?I(Z~hv;BxNhruTG zqr2FGIH}(0K9j%Mn4J$%R$T7U+`U;jgp(oxc+5!7Wk|`-YFBUm$<%$!kN4~-_vkQpb%2Dn61i5 z@519H?>*Fc!%bs~45n0P*cDoD^_7-%HAp-G#@xdq%%ZZmZ* zGhKZVl}+W1r?31eoy{%4?%Y7FkHkf=uLB_Z7R4<*9Pnx z%UI(Q*U1p1I61TvyU2R;!kpUi%_M124CamvTFLEz17{}I)Hw-mFcvQpjb)_$|Ar=Wcly`k3 zMbgY0!ku&f7-3wxbiLFU7&+Z@qM1+u!-ed)dlpCeSeF=U%E}pQ!m}_Li@&AZnawkh zp;R%nBEM#g4@1RA5Ps3p|nhd7I>t<@?*Bkd5|hKp~qfQGBacf+jnmP;kyoQ52@- z(@JSSIar591Z)55qVPRyMVitJYhhSPCpS;(Oox=1suZ;{co#`0S67kq6!=JPHuk65d8i6-W_)dGzTq}qrbq$wBRdCq=C!QK(tEPx7e!T`ShTn4OgSv^P4imReOALXyq)6s!EX8U= z<-Se^i}y{=lv=Q}WDQq2COoVAOWZ6NaXg zPMNxWTXmgo;SY)@xTE>-H4CaW@l<08IS*ClR% zI>?zfpNlWG^}=b|FJDIO0q-g$@&$yRYGYz-fvpSVJe;g%FY$JEpDy)upmJPS5vtrh z{F%PWZZG*ZiAtjpl|wMqY~Xz|-B9Od>Ui*7cuF*g^<&tea2<{jG3xoH-Stp49EB^1 zS2H8vCpa?HbhON^_qVJ`{v|9cA^HUi`L4=H^$+Oa`=<&j_@j_TsBrE4uOfDfbG}$R zat+T({C5A4ycwl6xu4;RO%tWMY%f{)yyQk$j4H;1&2Ay6JYm*kaRs%ndFXr+ z*^nC5TGO)gEkeha6kar#p{SXO)e$AL^0+Z}oK)+kaIv2oc(hg;*o8G16gHWxHpk63 zL}Ym)Z3Yjkvp2sxb}DvmS*P5;nxjpwTCqq|pSO+nS3|?SRCGf=auHQ+wqH%e5mya^ zb5+=%ofIFPzks;%aVqQ;VxY<@f=>C4$8 z!nbRQ)$`)MnJ=8yOvE^igCJG2BB)k+mVUW+nKc`+NL?S=d^Ypk@E0NCIh)Iq5k!8wO-(gftR8YdN~Tr!B)*0qaRIEOFmyCIrY_aSD8szwXxwcq?L^|Pvkcjw!WsevB+AeOZ-toR{#)NHZaqG}^ z{f{;bHU=~=xkG0jdx(!eVpBAuV2!cf9(&ETNoHGKj{ZE#ZGJgUCKb!_-&x*U=U8d5 zWwK9-YJYx#JBx%cGS?5j`kLiVSuRnQXt&2FSa=h$d&k(&UUfisIO8idlwX--min>F zV#NIhhG;f=TLFKoyQ^x+Ixwl{xh0<%pL{WMea7puoXgD^TLy}V=MWXEiq7t+TYMF> zTD|jJxcQXtRTQOI|;A! z4OMq;Gt_<#!0pj^)T(4*P+u-m1{{ZAEm3BMc{fLr-SD@LeAKZp(ojqd+NegHIu5DA z;Rt8bymrew%?cZP63a2<)N&!;x%kS7uSXPgc0Go9@XI%-mtQz8LjPni$yu=hmay6E zIO4`Vuj?^2dGkkRN9V2T-8>;Uhnd~w1Z260QbKFK6buh(`fZ59(lm}Px7viL;;%l` zOBRw_O;v(0`1Icfj-NDr*jr{`S5#^&WoR}Qa+G9MLAa8FUKk^q2yU~Uec*5*a=%?8 zX_Z}6cJ>DX1ShEHJP0J{GqUGy#V!uSFHFiRqrmo!zaUeV6if?{Bs#60l0uFna*x2WO zf;8Z6ArmvwdjU*SLz5L4B{pb#$q<|;Hf+&!Me;R@5Kv)Dme4~v z_c*e(Uoce4RHCMHy=5?^F-6soY(?lkgs zu6bH-hnqUtY!3%6R(c6Zh^#>JZe<5hhtK3hrhS%*%I|r~Voh~sMeMlN>;PcxFo42C zIN_~vWX&R(^4xeXVcYbtzo6gt|Dg{9xjIissZ@|t82JH`v!f`|Z)`jsjB9y3ouDO} zw%>vkISfdtAx+32BZ!&ZozCUeTbF)Xy>Za#{_+qiol1>bE(ivlfW0#4I0ponhBX@N*D*F@C|+9k_9Mw{ z3CkyrqLt95w})Xe1>37b*1?w3P{qSyKYEboNuwjl)kBlf5!{_FSyqi)&0oqQw~ZX3DcMCF>4Dhcb5g3M^TscXY{Y< zFn7HA($Ks%^}qU3O8~{*ER)aNC84Rql1NeHG&G&1b#>JFLt-D>uN54 zENtUv(NJjZwVx0ATotlkXU&$q4g4Xy)SP8Y?q(k|saz;vUa}FxwI+F|!}GHeC^P}# zxE#%wGJfYhcD!Esjt}kTJB>q5r&r|0`MC`!@{6^6**3_(=oY zz;GG^LxlpfUIh{Xe8nag_zS2wd3DyS&yF(HERjx0F2#3bxcW0Cq79`xnFF4zu`>SL zUVFJJt4(UI1{cs#-r0P<0@2H_sDaQ>(9aw*oOK)A`t()xB*;lG)L<26;Jd zsW82tnSIPAlM+{THEz=th(w6={ebW|7Ci!0y0>I-zcP+E40{Kb-=i^TO1$<@KyHd} z40#bgTpBY42_zCk9#_3ex2uQEn}e=WY5Y@MQMRkCLG%xh*hBVnVehcAFI)PUn+A`F ze$mKlzGFb1Kg!+OkR+A~6um8$DZ4J%A8&&)5b1xA zmL`FHlSrK}RZDP)UYc;&44O9s1{S@L?({C-7(8%fgTl%XY_t?!-L8)2QtNtoIXeSl z=GX8~yA&#;V1;u(-u#YnQl|U@Y}iu<(VxU)iDqKoJeNA_&mR<%dSDIuSMGL-XzH*S zX`(zIa0wPZE%;yB&}ig+Bi&*6{QS9{Pwq(v0gwAzbPbHvvHg#WSI8ZmFGO&gv$E%_ zil&3uQKdsNDFq#qqP%RcHy!pMfCtt&1Uh+@`%6$sp50~_ER)qY{O)B}R8XuR$e*wS z8LjZu++`558{OB-Guy<)Y|xjHj*b@)()eu=l{zN-W&hCW_!{j>TRN3pm5hn&1jvN5 z+j!_o1@(}POe9LMG##S%`B)rpV(#kCsR&RXbr)}Gb%^aVkkk$w8F-)B=DIAbq7m}e ze>B$Q{OYRQX(QateTf_9<7W3#Bt8i$#Tq)=JsFZ)ua;Ic|0BPFiguj zkM8ZbPslm`ssshH^&OaY)=Ja`*5oVh0SqXdhPQ67ZZNLh-qRY-y7=1(2nJOQghB`= zh2r1l0$~rR(MsnE$`&ibo_gNbSDD4;RQcN&awH>HxPfgXC!Ee_IoMLFB9#APGz7a@ zAkMxX^|5j1ZAe{kXbW{&UX|F9#=jZG0IxKk&fLhkQBK>Q3x7*XQ!jt*fLAQQDKaEMz>JMHJp(x{g?r1ps)Gn=a+zj9BaDQy=ibmq=(oMW+e6$d8r=ZmsxTY4@CVqJd*F9;&D$#i zbj>Cp2|C2>Hv5n;(q5BxXm!0`6tg<_(Mo=_{Xy7fl0Rg;dtG5F%>uLeS_T3xhh^&A z*#k%~Nhx+;ZfYRPw{f|nWa~l}4hc_L?TLV$-=*k-0k*z7k0Cj`57+TxE^8@O?lvI? zJUlEw5&$0~_z}cU$Mec)!}p;1eXJ;+=WRx@6SZ*UIqe% zH_l?XTFzbz@(fqWCMEUw7dZT$Oor?&5`ED1ZV+L>tmMPu$X`Ga2NjjY zear8Nvho_R%35%9O=`Xfo2X?;Z{Pj-6VwhM4VPViibERE`t~VM4J#paC{km9Bipu! z)6SkmAA#TOP5eguIvK*WDNfBiXE&FyB|j&=^{C3J&O|hIrQ^Tb8($=gZGvF{iozM> zRl41Ya`2-@oW%5MK7xd8?sMbb4;BBw6_2ok3q{R_i1<>stigVfOjEOuu2*l-Q?x^4txHBHFM#-aovu%@AsV$g}eVZO_fpahvHlBQL=(i^SEuw-6>`i4On7|8Vt zUSG|f4H)Y@#y!9!VBwiNy8VbVJT&62@HLdo=29HWa~rhHmk4zl%Tr6tnrKnuSPF7g zN|JvH=H$zy9MNgE2a?}NX-J*M77|jd!omZUqy={=26P}eN5R8D5)9Op-n2PuY&F$f zTpNx{A^&-+h3W8ltK)_9RY4}Dv3~L?`#>_4p?jOaF9bXMS%^4{zm}q^l2G@&I2N?e zhGeC4N7i3}*?T`p#_RiAQILr9m$y;H3C9jeOn-fI(vPJ5=pWcaq^psxYO}clq%zwb{XA3gPzY2@xKZ1hb0n-9fHwSKyHV? z8y@rWlfS;h(ZBNH)IzUQ^fT=$9V_odAD{O&q@zz@Y3sgK?Q&(&ZZnI(gEyp|s;F^k z38TRN5~L5JDRLWM>CA&ogGjpNuQx_Swni1)3MDpS>Zml@^f%%Wde*AK=CtnI2bsJ< zurnZwEREu~k3iK&d9ukR-yjvfpEyTttmV40VP8r2^!Om}etPjaE!B&ob1G9%bw{N@ zeauF07SZ&x1~&B9(g6SvoLE7fMr(m1(g$Z>g%cL0K4gEP>)k=beTU#IwQv0BV{;j; zPpt<*xPp42I$$0>2*thaD1iRvgn*E!shnJ5VLrOP-XPfT=#v^ z`IC&PQz?p5jBj$2!u&|D)oJTN>8B{bE`7FrRT^}TVOUY8InoD~|GB>QzMh)w|=r$3d!=m_EXwbmV zj+U;U<2h>B%g5P^*PGX!R$bIDRav_B2QB0k__<@3Wn0~TYXtwt#M@>se2B&6Exgmi zG;G4uiqE%k@n+ahs0N9PCXCrgw+Xw486T~tTyJ$j$nPfz#w~e?hmv)e5gMeoMEno zdoO77rJVo8=@NtaxhWb3P+c)pMMHNo!QT9o>2AM&7RB#+*QX)LvJZxrobH9n7njbt zY3@@4yTPIFGnj(?;?du z(1=0oVPCM#81=$2aX0Rrx4G_c3WWRpidmh`{f!U@sns8FbJvF&@vBY+{o=`pbvB@4 zqPYp#9oy2CC2pRz82VC9VCC{mjfW`0cOKZm@kJFukUg zf{H0fd<~N(njf4#JDtxP5tFxB<2K&UCo%%dbJBD6Yj#WqQJ~j1rDsSuIRg=rZ!+xj z=?(gs{uc6R=1ym3XFESQt#vA?9RdHbQTUfly8h)M71y!!%{F$Lr@WF6Dh z=!~?QF6231=}zl?N1ftE%U}vmvHJqF{&J-{AABoho~>qbej|F} zA^qO`W5eA$4@ypVrVK>oa7*4&a8E>|PY*qSO%4YXRUP#h$q5*X8QxGq8;US6ZSK(0 zXScfvP3m=`1oAL%6W6w+QN;Et%!L}f74R-!d=3cyDqSE^X9$=CIZ9xS+{c*zj76tKKH7Gv+*D3tS1Gco@ z9kn1VLO&af3;tPQ$)K4Y1A+)}a8zLP{BuclzK{?0Gk1J-&1953WNcVwCOyzd${P8o zapvPf`NUISS~iHSx%% ztku=xYBz4@{I7$(3RxbaRgbuQR1Lr$`U%I}`D8_?PKDQNn14HCuIH?a1e2^qEIK>q zKC>03LeBj7uLCiTROVXhWKk^-#Drj-XoGO`OGJpR@&=~#dVf|f<{7psJzV{IRZ={9 znHrCCPJb7|`hXfGtFhpD!{kKi{3w{uAA+BZvKe;Czv83_dNDEuF#BTpMOmrlAzfNQ z=-;CrXwDQ#^=&f6_nCE7&gwqV6FOdA8nn6sKlk8yjO+{)g9PvQwZ-iJvao~RA|+Tj z|AUg7$~MerD~P{NQ@Ly&6fKf2uP4bRQ}6im&eQW^p&J-1bzYl>M%wi^LVGW$c*Z3` zM5tnVzE6H(K_w_d3Z3mO>v|>Nq#G1ED6EMThKWB=D>S^@IDD!(vbE4;Eb?Ael-Rdw z(*;ES@&5cikbW-5@>uI(zTF+tWe*_a7RhB#?|)Z2p4tD7CA)MGh0F0-0F;3sO0VVm zbfUsJOlDf(?XiRt(r2DhBo7)aB82`IfDa}2V+W`60X3H~Z~oJ%-^~Na==0p%oDXpN zXm%`>{m&r(QtG~}pn-nW0lQi~eED-kGrNwM<*;ld1YEq9K7bpagSUJSZ1yL9!< z+(rW#63AU?y{kFZ{vjp%a0PTT*nnIK*18xOX?+?7Ag{em;nO@aWO#zH=S1{)X;3x{ zJ3^2zJn27XXhH@Sjm}2JJGK|nqBkX$H|}t_7~u5%QTd<20so~>!za!GIPrZ^N2@}r z7XCDGu;qlXvQO^^HpD&>M}jPi=y*6P0m|5@{@Zd1&7`K+yV&{rE6n}zfc{Bb>I60DRg|D7$hXjo;;CF zhxo7xNnsRx+xY_vD~DE`<>2GXXLi-`tfEgn96uECUiAMc1!h8!NhVBfTj6l|e6?Av zkt)!uF(wRx#aP&Gr^@}0c=TUqUpFQMC|dx|k}6uT8xn%o=UG?)49Z1(Y&6JnE$Qy& za5Asrb5F*vRa!~3f`4oQIKo>XyRLO3af*cU)| z^625D-W*Z;XI3il|4>Z-FjW$45#<1Ge|p*}kNxNH{bzQ`|No!e_IhN&%Yvn7Rh-bek`^8A4~c_{?h+iQ2!Vdpcy~`#PGT{$RNYKCf2}D1=}Z@*ST=617ym@|Q;YbMC(hq5nQ(|7}@4&I8Ip zT2Trt#fY!(R$ZU3@6x*oltZ^r+3j;a`9WRG zf^MF#3$WjCeCi=P1xHN?Y`HK6! z0o-2C;eQb?r;**(DtVQ-zoG|XFuhLq*+t+6kxmNI1?FmI%b^GZF+{#Pa=?pvm*hWZ z9PBIDX4gj!li8$V8VJTz9*&`9Io}XXQ0eHmpdw&aI1F36}JA3>=@lS*Aq)-T`p)s-}au5i(yn^Rk&iQP1 zo0fjld7{60J6e^F;|3b&^W*K-B=YhDAz-mcx{(Y-ZBz{YZl(GI_bAG3r_2g(y$0jO zrX@J<^9i36fT1l~#ShJic{ETM_k}peC@)rR7mNlQrk6x3j%VSbXJcP*b!L)l3uGyL zOY{E@{u7ukKA#fss?5CSS?G4+G+rah0Jlu(@C)gm-Z{iWWc9jJ=J^v&m0trM%#=dl ztEw)Y^odG@`hK6#+d5=k>4N}xb403d*4#H_R#7Ua`D&SWIG^6=}uH2nDUv)h?ZL&+Cw)hHzOcba!rWOQA4bge!-Rbi7L&$EY zcd?=q%S4QO;@N?t=bwj-4DZ%{oxw(GY0c4}O4L?Tcp z=w%@}gS%U-9xV3n@|C4#Wwi`v@L`^1xeSxTrxn6QK^ z8psmJ=Z`6CcJ$r)41k1lwszRZMwCVv)nOR|->y;CZ^D95JM26HK}m;zl@Mi{(Gj#Bt0a zBp!WW`+@uc(@7Pp10qS^wKS17J6m=pv-xHp!<5W7{Q{g`CUn3`V4%N}07#`{eo7`% zi`r;4=!>x9Gb4K|Q5Hc?+F$LE#+I2x6w+FeywpDPu|9!9E6hjhF`YoERIN@=Fx&4^ z64|sg&c}0EKlX=d1J+#H9d6JQX+Ip1eV4XAEB{s$DH?qU<4+C(Ifp}4D>bCzizbi+ z1fEi}*nODMXsn4gO*oyE0k5`yH}Ov!4CTT})M^stg1g|Hd)Yq9EsBtO4fW?SBFr|+ zc(G=uzb2GP#4Ppp)xx|*KWWvWps}USSZL(a%N(f;9ZFM){1oi2g1+56$AqSU;FKOI zC|e4#<)OETo~MnEI7u24k=PNzNIL=*`T1TNaZtr($FA0Yy3(WM19a;yWaGya+lDiPk}f!TMBp;@QHV{%C}I%b`3S<|_NE$RGrtS{)}%XbNGea!!kyprcq&ik-~Sg=_V z)@gnCioxNqMnR>~p3;Zmb-vp zBG+2yW}b@=Mg2T(mob_Rr{Zc)ovU9jc_R+S^U5_CS0#6po41liRZ%0D{|do$wAd7G zkES!I#uUJG&^x{MEuTHR335@xGttr)Dt3I7H8Nu!i+6z`KeLgKuw}dQB=ai)!jh)p z!ijYvH4(CF!#yQ#9`o+tB;_zo2MFjhc^XD1Yq^>1598UD`AO5wL8~H39XB5GS<;e9 zy=;#hardsoVz@1Zd^C|nQ{zB4e!?lUiVZm$s6QByRtot@GG{7_?YSq(T1cSUMoa&d z2ByX1kin#QE!n5qz2mP$F4otx?%Z)v8tWAu<6<(hy|>x3(?iUi2^6&UK#tNou~y25 zS!K=gkz1#B5e8W;C!O;_^>hWItzFFCsZy5K2E~3jj_xt0?k-Thq70=`|K8;oXaiZz2wPTxLa+uP1YKQlNUtHf;C< zX!q8k+x?Db`L_Lz2X>PA9uI9`b}<54*qzTp$44#csAS3j4{xV%rb~{*L+p4Swy|{d zhF!QbiEWre$5Nb4V;BmER=bt*nRiS8yHt+r*-R#@?FJQpsa_NM-PuCWR*VAOWEM|R z4GNh;cGmiuWL7?cNX}{OJImpv&0@Q=XQ^5nS-Ryh0Xm<_IQ@BCl|IAv1A;8aWHzVe z9rtkkySGy?zwh2v3JeC_xFilAAVOpegYFVICV%%GB14oP>4?uwGI$8SYIW|Kn{PS?!{!7s4Vsb2$g3xka0LvsdK z@v8Wq#M@{)w{P*62v1xkC$*p)$r0t;lgH@>&%PkMkNjuX`qR>qsi^Q%Ncsek?`~^Sfd#xF} ze^%;CAv42{U=ng1XcIy^W3qwnaei;K?Zqq>Op-usV|ZWS?s!NiLyjfn-9-8oa$nhO-6)K0bpH$I+r(`a3r zmx*D^T|j}{_m?0DY6;;eLkuhb|np7Xk-PUv~^>*9CG zx9&Mmx(*iXbeRn1AKFd#%(4kz60>eIT3pG}j7&w%*E_n$G5a``sxNh{RvRz>&9DhD zvz-b$MO@nc<0=_Xjj%tN(K~fToG~h^(W;fw)y-qAQdgZjTLRhM@qxK1C!Sf`LZPZW z3&WBzE~8hY7MT1!B{uFx^+PEcI5Uy2Cj3^+MYmb@s-YOloaFm@iWz(U^M3!nFZqbM zi9>ZRRGCE0a(V;)WukRGthg;JmKQ~J7V08BH|#5qq?;rT8y0BAFnn<&Z21Q||m2=s5XUC^D#aW>DA*rVr5)P8#AHRx8H z;rDo5f(pxnPezT-7uX#A!2VdrrpFeq;eJ8;g~muRk!HKkE}~%At(#B8jtMseb`3kr zfgEJkuG;lip-1t&UeCRSw1x`#qfZU4y~WgOy;F#|+}@d$S9KnfeM%_{!&$t@CUVIs zdBWB2syUVJrwB7GWr)I?*bH9glKqo_XI*x+24}r$^T2Duh~+?7dw*k@^x>&MsoXP4 z8&0c^N!A9}%NysbL1K^IN%c|T8VaM*N99U>(YC0vX}yX~$6#6AcB$yBj=Xm3s3P$w z769|qzdE~XwWa}=e6DT zJy2j|_;SITez0nVj#2iKkB^d}$0X0K*J|FBrRhVb?_u%Oxce%r_nQsK7Y-ED@DcU; zp?LO(rOirv3yy%CZaueyyb{xNynE8DM%$u%=kk?q*-IK0$l(&?V#{3E?HTE_nDl6> z{gW38NLb)p(fcZ!nSah*+1p&k`Xc-|$m^ybeDLid63q=qiAYX!J7J^Pw%v&0l=p!q z%dWlu;Q;C(H}^3!9Fr7`r92^dhAhG=VP4Ika))JmGt&?Ul|@mVfwx|zF#GW|Y1A%H##=FjRBqJ3A#>9C2%^EHjh!F#^?1#=!D=yi%$T`z`ZEk}>8o58 zH61$*Q@AmoUX%OUV)@Nc4;hraC&sFOqG^zt1@!q5NJ)Qe z`Qi?3e)BidBrZ`Z`w|3W(uL^xbe-sS zc-0Q(s;zdBu{@A5l7*s>|BSRyD+A>Kbnw~hwoRWz-}#-f&1*5A=A00J-kVILqxhvP zU$9#b842R~u!l)zcv4DwIw4~;ifSzBUERZJt6KIVu75);R-?E=7uPKMl>!aEOmfb zQ=XMf^A>CdJ8Fa)6raMc+#&38ve}wPAWFS^rNt>ws>{gb{9Z<~Uwjv>QXA(!J6q~d zQ2`)4reOIJ-_FL0m`_65HtU$xeFVv>!zO!7F)ZfY%$;3p&E{<6$d=vZ6)&(-BasLu zT|382EFJu3P5h0lVtVG$Nii5VqB3*K6NUSJ^bN%O-{EzI57Mm=e$h*^NLQm1CgxOY z(q#X}>51|-UO-)7^!Ak~k{8IC^{RSKF9DIb3%z^dU{i0-o-L)FSN6!$V&^RoC4qvi zNyKaM*9mr{xNey{(3OQ;4^Ltq@%g6wg5k_EnI@&@9HNyg3pqst5Z};3K!5wV!)+E^ zz+9|jLKQRbRs&{1yLp|1rBgViq6<++ZWk@b;@OEyIJM7(oh&iNg}^>gr`A=$t|9ik z2a<$^zc!5qK*^;G_TtXD7!I%3A&wG=`zl(az*=E(We2B zxm{K+Y)zc2ueVR%{nl{Cy;(y|r2I0w8yg~Ks%7WPhs!{6_L)u;HJUmAW1;KK4}Std zzVhUqanb24BeEOIXM3$fV$Q{__q=8mX7tsSx+-{L@~S5{LYs@NLF4+L&;A%cN?p@> zVNni*iO=k_wRmFQ58lzDFygQMhZ5n1%1 z@W3?Nxl5OWG@4b4u4I6(k3Eq=>~dBAwdeLg1nRnI`Y@^ndDd7b&8SlL!M;h%^7OJ* z(&F)Gb9Xsm=Ocs12I~ofOUpRUks38*gbO4#Tpe8F6ZYi!SYLd_P9`RXz5^gCjZo?3 z?RV;UuidYqOWCNDI!wNxxh*pfWWH4ozx=b6S6+X&p}c&W9(Fj0_Ocx+-I<#2SzXv# zqVitvQJ4}kE}z=MUkGozTpOe3Tm%fbr>h^RWA}Gjdzj5vJTylm;5>RBOg%on7$OVe z(@ruhRE{-X8Jun?@)zU->wo{sk<+WZb6fGaf39 zHOPAKkVUAw^#FUjC@4>;Smf}SfN0c>8-x)_Z!5~{pB{%+ETH7NhOyzfk<8ZSvQuOx zld&>RbG7tCC;wN-pw_s?-AHRfv{0X=CLQ2tmfaCS5frG4e0!4kl%brI$Yq9r#bO8$ zF;dhSUAl@lAH7Z8IXt*4tH?00U8#-abh;qh0l5rqMNL_(R|I3SYpHSM@RsEWs107! z>EvNB8LVRn=#hDC2Ccy`%Q4K24*$ePTF#Zo(R=46udtNO{_OHR4S)!8h-)o76WbFXzXVjovASBG!j#l^HP7KtM6|qQRy}&A-lV_GFR zSrqJkZ{cTd3~SqO-L^w41nk&iBBb>RLE3lh(t}Q)IjavA=h&@3X5>(@V4{!I^C~hN zrf`nz-$msrRi}IR@5^9u#Pu%wcRqy(5rP&iUMj8=5u=6=p$g^7n5C6JK*IMQXc}X} zR(;trrDT-D$2;smws@HeB7O0qg=zAHu@2|8l`un=ob=)2N5g2?A;$ufErEkm5Z;fU zJTXfWH*OqSvT!ctD^y&BgQo&t<%sBUTE!-6(zB@=d-9Rn4yDp}@7{}KE0!#@xfo`z z92KV!a5n;iK=(Rvh8}b_gQv^Wu!$Zi85$BL6dwJYagazEu|-{&4fv~ z6eAKxPLz>mc&F;rYy3)~^?R)$GXMZU07*naRD%!k`D;Hvh_*=V$*hsxVW^21!6Yep z!k82`bV!j`5?OGn2j_ZHFnNNOI|Q0g`Uwz7BTIoMJIGFV%3tjC51ONpu%SaxhLi~? zWbj}@BmDJSFA?6VW)T|Sv$i;we{gRLHy%NUSX&B{M-YM1E-UU?hRT171qhH(AT9Ox zOHYVkV!d?hG1mHwLMa%tn>-1Gh8nchAU&IurGMI*YYzC=GqRnvW6QKO4MH$z$8(l| zcSu}fg8A&#d(^#A85%lkqiDCgNH2FhBQM{0QPCzN{(Gms(JQ{MZ&`Cwisk*2;W$DQ zHgmOp+D-zHASn{Y67Lr@&vBnXdP2+R&_eS`h))DM$j?{>+KcKy5CSv5koZMA(_`)f zGN(>R$CfxYFssf)&>AL$Akfl;Ml!VguHSv4O{gaHu4_f2muNnkCtu&q2;GB>OWt~e zMW2A(G0av$6SrzstyFbeiqvLM%yaqdu%<%|b#eUtjJV zHm}p17h55Cub?>zGdoy(g?2XtiytSJ^|R7M&%?MLKX3X*hYuS{_~(GO`SA<4c_&f= zy7%~nh&Lk8u}G4tTra}z9|(3&q~rU1i#0f*0T03Rev<3eYrA4Wsm*`nw*Hz2wXY%; zMDd(qx6NkOES3G(G$s@qvnDz;rsEgs#JfShP=RbIY3D4{LZYZl_oqVJ37r3&c=kMa z*F*%qHg|}#*KApLJtpiV(Fb!6=nMQx^xun4f0dwrS^NJRFAk+-hou*IcL7LO2%h&N zi~CsZaB$_CT^$#=f(f*>C-c}#3U+hd;oS>Tj0kkRGwp_&#%f5Xe?E=g$I!g1X5-`z zvPkXd%(y^LprfFXyvT@!^n59!ycg5d%Vc0R=9?;QI4Y`g>L@S>mJNj-r+ znw`S-VPyvN3(;7k{mj+-|6}hQ;N-}jI9{=B+ql@d*tTt(7hi1iV%^2o#kOtR$!6pE zSG~#Wyy@xT?oM{@UoW5RboWEQ{${PQ|XJDELHn!gQfI!Mr!=J ziLRUSYasf{Gz5sFyE>Eaor2(`Nn! zW5-X@+9K=ZBuNqrEA(g2pKHrWXeA*`S_}I{Kp!z`ESyCv)#E2l3KtEu5)vVsv}l6^ z(V-w4S{YxubVU;@$+~>U){Vl#maK#SS-wj2OA4!1Dpf#>^=EM6#3{&{HM6j^rnV{3 zePip!wLrqQOccbE1`Q}tpiQy@CIR$3_UX;rA38#vTF~#0p0bMgl>$1=kib4_%y>wa zG>PcfrOQ7D`6-C!j42bfxZO(SYK}j z5A0{bncAknqvZaD5Na=n z)Iqq%A)oUxW5j@6_;rPR{u?r=KUA+;Suo98pa_tA6&lc4IM+OQD%+O7&0Dv_`g_Ix zJhFc`(6+gfNIY-cyp`~GPxZ!+83|=dm2jmA!?Lu$KjA%CCK^nTX~XK}HosP&fsTU3 zN@)Wm^d$xjEIfMjSor2|)uJg(nlfE9<%)n#UmlPsPl-G%kf#NEi3Usx6*Ieip>pmH zPS{%q=P?1d2%yD?>GkFvrb~HBiT@w3-=al+PXC^JZ3BcW#<#7OAkJ1<)>_Wq^)E8=7-vHIZ<@Td6A#C>q%3kv6oC}2`;lt z=kEEKg4Z_pui}_X+H(Bd&J?@FQBf~^gF~i`r(SA#S0DMB61P7t@~H0doA0zdbz&&Z%s@mF5K4g)CuAu8Mhm< zNX-hc=~I{Pn5a**-a?H=n4Y|Nqpb@?R#TbQ<3t|upzYA7+Yg_cqULEM$|Nt<-Gl<8 zC{m^4WU(w{rY5F6$E}Y$e7O_(a(mHLfko51j$SfF$=zC%q4wXr|9PHT6jWwBaf}pb zXg+R3XKrR%yX&N~c9RKx0$Xg;(oKgg^8I7RKaUX<)lJiv?J`Bm*-G@Aj!`;y^@+Aa z?k9Y~Hobo5cwfjiM$Fly)kT*kaz8d$`)8-N+%FS!tWaC(f4L6&RhP?YI*!$Z z;;Ys#I7c&-h(N&g~hXE~3bbiQ0$Fh1& zH@fDJn!8!6PuDtiU#jb^&~Ack*6O!dvr(dr^cDXw(RB}9+Gu4^oYStal{-w*mN)J* zThyUz?~Qv;wdHbxxJS&q! z5Op$E>g!Z_D&+2S0a{pV{iAy&C3M50Eu-^+QpNTYwPo^|ftI7&7Hv75PuG;|F6Db7 zxyp;4E$JRX`z2Y)?&!_nyHz)F5JTH8x+kiM&MUc3=~sV!rE^Q>mlNo(TgzX+akE@(@q6sVNv+JtG2>16MYYMt z$48Vw7Z4`2VAt|dpth(>GpW*N7Wve-q9x0kZru3!OoZ0JT3xi>*6N~=ZAy{$H<4Gn zeq$55)6nuzST;3j-dg0L^|k5N?K@f?P4xVupVlVjpE-A4%SYkWlp}8eEgxNPXnE?y znspnrGU&=i&9XUNvTQ|Br$~viHp{r0@%qgh(~`fJnKEX{DcUYjq=X6GrPyo+2M@G< zqpJ>^<-L>Y7;slx&J#@F zR}vu0Jk#@q%ghf$c}ttV`I-eazjlfQZ7HDJ`<=MOTKHDiEd_LHWA?6}q6n3_`~0J} zj_ymWMNTQ8Q{8$~ud2<8>1011$a41mDW1;S`B-bS{rsOdZdsW`c)2|drW?O-sscKd zRUg`@odx@zYHe&%1bWIFG-Q}|aZw)vD9@EdFRAo$L;sCl5Y)C*5r<#X@?KGfGPoftAFI1?vuI z+luaKjH*}(B1VO%u4FcI#crb_hRXu#7@-$i*&h;;jgri#-@q=Q%l@k(w*KXv%BVsj z?Q2((Jpr9WYbl(PSa|=*Pw~^0b?D2IAgS&LXQoMLP!n3$YHh6EaYD@!(`|<=)bjPB zt}Lty=+p=ObyL0GsKTwR@6IoYPP8r(X3;;tVG|qoo-yIq5{7xU7NVbCZF|uLiLGKL zcLemgYxZev8?h#CXkjVJlxs8IV%_L2LaV#?xb@33`svs5)0FFFQI}@$%LI{6A`@Di zTjgh{*hj06e#@=$X@L~biFnZJ#bFTcjekA z>)ZQvcbjQ&!~+JXJiUNU0}N`SdlwDX(z=aAMt8TF)}fxKu09v2ee{oM zPYLMmJ{PD0Iz0za!mqZp;|8tq#4>sYlE;ZUAiMqW1#P*}K!~Uuz<*p7(5XAa{@SSZ zd&l96Rz2)Jeub8Q<@QgJhYG3!I$bM_k{q}vW@>%)UT5^&No~<`sz(FmjuPz)I+q+7 z$vA4qUjB!(7d5e58d^E}eX(e{y(Znt^Q(Y9WR11()pp)Z?Okm5CF}c%zN5|x=%2rS z*9^2sNcUt?1u|O#6^Y3BwX;>XR1wlY1auP0^n&B+wd=Ka+}(TkS@l5*=u{Uioh|aw z8da-{{=2ojZax1H%hP4bZZZ-DN%*EbYID|{d0IW1P(@o3>hy_(d@1-HIeJW=E#_Sn z(CHaT4sxI?7{fOGvXDe{*=HIAu$9~q&{wQlt+l=N-yK#>)3%kZSWT2^+S1b4q+Q3Z zT3xgRx2lUi`?dUHrOH|5qbm=QpC)5g6Mjiyl`jV+Xxs1IGY|gi3rPW;%HUTE`fO97 z;-$qpDp#+q<)OP6tzY<+hPGTz?A>=j%U}ABYu7&NXYTyw0WA{f(Zz{uHb8#W>x0p` zB3CK}ed?RhAPk*<@)&bPK&Nw2)|C!RRMkT=~q_Uw)M;_QFp`1pF$A2VbLC_4qba| zRfpCYuKpoWCQrY!R{69*FQDrSk)?y|HwGQG$fgU5ytvpJ?Y5}k4>PLpNtVQZO=N{g z){~SbE!nQUh^W@mavf5vpce+CL{?k!#Z6kL%W~?AGFdk2lWK{JpRQYEla;+}*T~YA z#Cj=2lV!Y7`V|5?i8|Eps-3KF;Ln z9gL1)49=-B!T14&-BAT}^b>AXh8WUuME_}k(yxguazkZqD*8oV`1nVXR=(6$jQs6H z+ieEhwq|ihK<_zrxo9`$@9nJy8RRyQ7)$$(20+!6rP=_o+?Mb}W#zut3+Ob6EAvXV z9IG~~O{@Emgg~RD3g}z*pR+1L^=Kc{z=fK~VxHDd!nFQelA;%h!bZZr+KwyJe%a=- zt;buOJCYs!(tgpOSK}5~3o5SkRV}ODFXH1@A4ZAxFZG44D{At~Hd8x(c`i`<;UCkU z642d!E>Hz@x)xAU1$23w+Y->#dpM}DnL?N`9BoL3%wZhGuO&-%`hWj{wE>+fpuc@<`Cd;#o~)}{ij&w$@6BYPYAaQ!QbUv> zL0nC$fKC?D`m}z-CheWvmeswh0y?cjS}dcFcl|2eo|o3S7|>Mfv(Z3_T!A|Rx)e^c z<^J8~^WV@BW*r0ldCOIa-*T1A!a9l6wvyC8^a45t`_#4x{p}l8pE7NRR%YLR^ZiU; zP!-Vk?6dqrlFCv&I>yi)i$ztkn5Vvx)je6-tLe`n!$n@obeRl=eYLE9dh*nteb!s- z>&yDbyfXqiop*9S=+76~2XsHAm2pKt#{jNcJ#`RFw#&avz*`6ep^iT2I}G0K+y`MZ zXMlv0N4Vt*Mqg>yg*Q-ah}o}e->M0qa`tHYB4R#nl#mb&qoLbMq3Rw2)O|$u*Cnp` zW-m7M0_-|(_KSLVN;aT%IZ9Q>Ux778%|2Z3P0a>z&|kVfCGT_+Za?`5F(ZY5htsm_ zvq24h6BW1Z>C7BfWo#{=pdu7pgpxA>7HqZS%5t;-2K;5ktEqq|A0p`xG{u9!m4^%bb%a8C8N`4?O8~AV}zqK0^vn4Y{ZNw+z-Cno7_JUq(uDu`VtLZTrfHoF%aC7RblU^>6+iPgFd(F@ zfLb_M05XVZn_5L+e9zie?S8|cHWZK%U%H`c@$9g4R7lLVozMWEqp$c4`vEZrp6aA^65>%-*Qd zt3J@>c|k#gFRmME)eZIdt%iY(myB#-RYnc|+M#Z77~QRgRT=+Wa0z|kW~^wwW{|IK z^11D5qCkt27jMTn6c_NEe+3i+fqYU%jT}z%fv=C_psoW4LSW$3wPF#)ksyE7j*@!q zY+kLPVe!)#gM$2=)A9Q5sM${<6-3b;UcK>w!nxAIR`d^SlrmK6BZA-R_vMA_55zT# z>QI2^Y5mN>w$(ON|HPB~)PoiV{ZoUex^lmpgq%B%Tq;(l4~R&9+0ktfc?Sy@*8;@2p05{!JN zYnjS~y#BfRT%h_umjQDB#W*yjTaFd2e>(LS`mhZG=)wq4I2OyEADC?6-ya9mV9fk2 zN^bx{g$yoyhnFjm396OIj`32WTIBoZj61w&{S-f9Ek3u>HHv}>%b>ax+a__buA+-Z z@m$nv%(Ag657S z?*m5tQ-i-A*u5QM#*Cq@!`{S#MN8n%p=Nz-_ROj9d%nC{aTNRE_MN-v&pi|Ty=cC+ z+?fd(d^c&5#KNz?Gj;q@rvIQJfL|zxCJye|0Wo4&U-QtF4V0~DK99O|Y!5A)|9mEq z>n30I6mXZ4t^Fa(s=sPL*M5KWf_imos@Xiv1iXfT5YX?m>I%MRFGA#UB_MWBbAUL% zZh>Edh^p(B0y+i$ypMvmD@hg5eHZ425K6F4TkRAdb`f@-do8kGVMKQd9;#27dY*>! zcRxVr5JBPn{9O8M3jw`4K9DWJ2Qz2Wwtsg(n+}~t@oAICL(#&8oUQ71Ike`3?fB9} z>G9qP7QrJOHTvoESD^Z8;452o>J2OlcCqvA_FSt^d{A4-hkdJF&cY z-t@3>YA35Qs(?NX1;3^!`~_q>eD((9uV)tfje`C=LnSD)kN7bQ9-LuYA5U%goku&M3X5>^kMz77Q%3=>5=)+;Uo z9;)?dng(*Kp)f{i2nJm3j)7P8NfppPoR|qAf?MC?^>t{Tj-iA_JBtA>LPE)p* zsN(D(gi-rO%lvDbsqJ4Spxe4%1k`?31$0-R3yk)GUzT}FKzH}Kz&`|Z;)7P_F#Vrh zfM0Z21U{xbx(4)US{nMbtU$B=p4=7CDKK=|)@H*9^*%a#)n33aA4NZpEbWJZtP@%E z*%<+y0-a{YK%tZdwygxco0S#Q!)I@Tz7to9X=nb}8u)jnZa|jtL=aJZ|NSbUKb@5W zqK30H)^bG-@1s%{vm%H*DMtox1fDJsCH81e7gp7SPnLsRDZ0GNnY&KQ-Ucv=q=u*du|@ znIyN_nX>uv=7zbmrfWr20sZ))y$~rk)H*Q!DdUZFyU#j)DZQluP z+MA#4yLIjW&6_q>v&FP3pkF$B0)hv(ye3#x__2V3wB{{PR18j(Dp4FJjvFO%?%cfx z=&xN&J3Dxyu0w7wolA611$1&oK&L>fbsCsO^MU>TfZ8>!-wR&6dBM{{4>o=y`O*_JuhmRpf%Z3oGp7n|1&PMsSfL=0F6xg7P zu8(5SN|`t|Tv$6q%@Wi1pS*%3#mzVImNg2&q~3L{%J}yJvKl9=L`p+DRkhoE z@&vIAt)r+CSv8Y*N1~%l>Pw_tCVy1{y+)~=uxNO5nWg=bP#z&iOYwk2)>ZR{G!=Qj z>KMVGi_m(|0?~(^b9zAjtkwfr)9~wt_V|?prGT(Ncjp*cxBHYhZ>UfCu+Q!56oXWF z42BOE8ouKGTD<;{HZWjspHY2EB>e3?aRqiCy(|O{vXrG1CR9i`wQ?YkMY&9>1v)Jw z%faMm)xGP;C0PXOm(L5c|FnKE)e88-gew9%tu7S`m^V?#j1wa=+{LeG^hve$rY|?9 z_O-SUQU&xw_%%s3{Hi1%6Z)-%xCPD8=xvGmw$@KplIhC-A;hXgaia@?Dm(T!3JxOD z3(8yk!bA@4sba6bJq)A^4SWA37B3y$3aS>%rY~YO-(lDinEJQ*#g;^BvZ}L{LgLFw zhq}eIY;-9E=#~KTW=RRV=l0N+s}mU98J;5>y#=~@F4e?q5S_33gz*6Y-AIVVi$=77 z8YOe+i+~i+-5K;mU(>L7!yzFG-rX@q3^uEl=~p%mhoteHvuLvFn85=7+Gc9nTLg5! zZnL)w=<-@dU+d8`lQYTP=K}u{&}AR#8Gr@`>0YxP4HOQaxh}H;(SRPh zk^*!$1esAJKZ;^GC25&X_r9C>Rh~Yn0{T?^3Z@x;4Wm!A?WNF2gVM}_ji3=e8>w z(={w(>I7oBtv?O$UK67gh)$+(PnJknkb?;(+rqVKX z6NwTggyO}DXiNP=KwrClBcMNR(IyG2B(OS4gN6);g^SH!w2dAy6e^S}+dw*a;uKMaH|cf zB!h^S9cAs~+EJs@2YRGNhaDBw@&~WJr}f(?$~yTh4_^C#C{t?q&*;-y1301jKp(x~ zftuxTngWMP-&5{Hb9T4_g97L#Li4%UXQHuxV1sI6k@RC)xx*yGA|+dl(b_f&cqo0K z;|ri+ee&Nc{Xy!3W~#nUDfpZ|slie8{;h}1TCcUM&!cuIU?K(fqji^VW$bU4{273}puJypjHrSAP)s-Mv+4`p=r}N}is=WY_ zM%|=9EaazFo>O`*wtS$!eB)z^g+8yT9v$=KQ#>G(3|5+><{+n5Lq5x?Z{&j-2YamQ zsD5i{8;z3cKbwwaPo(Ji%znzF=4sN!I90cX;b zzjtVD8^xZm*G8VYgGF5mDlOw==*!D~>wTb;KV}LZO8I)f*|H7wo^a%>aqukZ13hxC zR9N|K88)G2rTR zfni7eu+SYJ=<*z)d%UyB-RA&@@7x%3 ziu{R3Z)WYM+SWQ7&%CC+&l&k2cg3eUt;5yww)%DF`A035R{Yk+fhld(b+o*7yN=pB zu&}cT@T`3Z_UEj-5EEwei>7`BrT>S|EL(H)~}XfYM$) zv}hIU%$h5|>BS4{=RbRORUhaS#8RKghq&Bs@`rAe)F6`c7aHI1^z|qpscg4!@iK;i z8ufMLJo%iax@ZAx=;xk-v&yy?E%{qkv-%x1cDz>Z^5rX5`9=#+^w;Vb`HVNJBbQaJ zSy$Ah0F__9Sijp)IoWT$4|MW7PQgPdAH`kSq{XkgFVTgJMV_3IKF~8}%_SE({i`0^ z=x$fkLyLUTCv!D`>(v!9=LM#J!7J1>S}5?|7XdWM!yK? zw61y$n~DnzMP$Bn_pZA70GTFXTLx4j5%uIn=footYCQC+;s+9i8=JrFNGXif*WnG+&&V7NMsD?qy~tjK%(vh>yiP%NC-vW$)-y; zADSX$Zz;By0_7RCsR|;*#Yot#(_@Cli~@L4`jy8B4YKU-U`tKiZ~%5YTCT zavjbdBT@{e!3_##t53DNPuDoRDxgzaGnVhx>XR6%CR+kJm6^HXXFWPjjQXaw<(Fw! z1@xhRZP2!f0$8evL=g&@D9>kG!m28!cuGK5MNOKvB`T}iL(}R2Ac->iqz19GC!pik z2pShU?wmz9Yzp9~5AJNQjrK!-URVDz7}TPBkK9l6t4}4G{~VB|V0&t!V6^f& zMgdN3iNt;p&}n^A_$9&I$M=&KY)6%w`pwU4g}pYU2$?&7VMF1)W0&q)yY>Y1Wh+)`<)%!ZX>XNU-pyOLH6fdX|EJF! z2j7*I2M!*lt?!@Z*2a40FI?2}iKjj_XwpK<-?4MIMK=0?H>J;8!~ zQ+p-KR21tV!Tf`-uL<1;iFx#aZ?rmx%P5d8y8m&C1ZM+7mCK%9zWdt-={1L#6Cd?Y5gRS|})kfmJ9Szx5tJLpK-C-RG>Bh!HUa ztW#XLWKSC2TtN5t$|GNR>uYvPQEc!9c>mEneQ0n-tz>F+y<+6sTox!Z@)B%4{YuOh z%@`Tl7LNlF!Uhxm?`CX!ES6IM(QD(gLby;t#XPO&(nDV{z3=i{=)UN-n68p5I&>`? zS4`77Y2A*}{sV`A{EShe&!7J2+09WEKj-%ty9~z8-zwT6pRnY&l-x%ojTZwyHT)`E z0^CEFC25n!v2bmWu~J_^0agUATROTWltBN&U%!5blb7y5w=w^q-|4up1l{C4yKc19f`Z2Rg01Y@6}06@7M6B7fm+YZno|(3fvLrn$7C0HRm%v;1&j zLWy$vKMm0Rf!w}~DHA}KMkOI7y1XEU@ig;8uTcJ|aHlr~asJXH-`vt!fm8iM{JsbXj%bLK(Ho zQfXBs@r8{83x&xvPeR@toCMozBrC)iBv_M~`bI_+LB?=zdqe&?smlu!F zjl`;dkHdf|YeXLX2?!T1)UK#bm09llX;ehIP1Xz=;?3CNG~!>6ycKy=jX3Osgebv1vYTOR$`4@Flhblo9;+^aDF z9ex1?r6r-z2VI z6cDgrcFWH!DYgK`7@!mZT?=)rUmS8~NCrt0#1O6#UcPw`D6~TzyiTY-#_`J@^cUV+ z_-&`3?qK_r^v5Rk<=qd)#WBFHdi;wD_$O6jywBsdI7(=F4me07iv7{N9N@r-*s?E?lVJe%a<<<-!FAQ^d27%KgcUw@|U&M6rnCf(-3YMazy5E{t%^ zr7id|F$Z1CwHPo@%+d2l_r|3mE4mn=AeV3Px=rqzisVdd5%a~}=K|HGh&w?p6E^_ zjGYxaRq_Du+U(s=pvBA^VmmgA>+xHnX6oG2B>H!6qq(p8x znxPw&G^tZzz`z)Q;xeEB2M;j_Ao(9wg9u)`enSLmr0Yr8uwkKk)yhz;NFjLl{yof^ zJr^iYB?S+pL~a{Ol`IZfGiSnQg>P{ErumpZe*7d18#!8(Az#-`8aEKr;jz7>Nt1|a z{T~#_0Fj9#U6@9T8WmJ_?u3kkV$TD}XC+nMr} ztBW$!msqi4Lj5|mAVu=zkStjec>eqa5Suf&FKPRwJCp%`4u!=_|Dh_-u1!l3Bs5aQ zh(PW@&;nir@Fd^fv_HuYJ^9y8o-CQwadQ**8M(jtiu;e;lGLwTO9aP^7A=}MPM$q~ z4v7;b!n#Sty5t{n4})JTh}m%A!U6dt&-7bHNSGi2prsPL!ho)~Zr?_?G-WM(j6Znr zQ1}a{^-=%2bZjS%!H^+C!V&bljp8t%P%7F@qI2Ow3(uTA2WZ7E^2tR}=ML>43m$(I zz;pb>$$(VpDsL;&-^(vAy2NHqQ0X)8M5TS%ynmOvlp8-EDoq3a#O3%b0W8rQZJg^rY5gSR;MWx* z$fHqzC^iEH)l~zaqUAdDpS0SjxVDT0l7I?;M=POzx9C65@O;ubffH)5W4c~vt3FT@ zr>GoVuY7R;jS>wAmduwy6MAVG?XOpdrqZNEqF|&_{5F_Y`J@w1%hX>Q z_}x6Mv$z(? zPJMTGn}3ynu8RJ8_D1ssbEJWPXLYs8qGzYP^@eC7tW^PAuz5xoD4Hv+MV33y1%4IK z)d6{n&gf<`q>K*~hlB=It5;qh9_Eq z9}{%H**m|Nh$EuU8#a3*{5f^4MGP8!8C(9<_2vFw=JB+EJpIqY@#~g?kh=Ywd!>b9 zD5A^c7Xf|5`UmjG(mS##hrj)+C4|0}%>Iu_d{5B&xWhUTQCQ!B?}V8X*%t0pf5g<_ zu)zbNYUPS{+a|G%d}O0#wB2$urc8vwg$h`dAz$9)(_5d?r%Nl0xoXw3JTF!+Uy6Yh zKWhOV_4VX@j_lcB@%-6x*5Wq}2A3pJ)n2-G(QMpctIXYd_b`BDXSjUjs;weous|P} z)IS7tTH&tUd!c#jb~e{dLhnC|=Ue5UI(-Jv3Len1+bU08kTFAgSox1xqamTZGR8{7 zuL4Aopg7P+g0!6P(y_e|o5@$YOoa;m4l}1tlC#?Hh*4t!zZB5s^%Jd{H-*k9bgPL3 zU$k-u3fgHekq>hc!qqf>;uJt@cXg3AT_ArxxQW91y?ggXJ=F)gEHr%77??eGft@X0c6hfn>Mdb;Fkn|7W~?xJv+8Q+&FQxd83IYEm{M*7c$B+TtNTLtA5k=0mdvnp(L86WaTz8M-~==QJxs=QkZ78DRLwuu>dgW=ZU0N3uh44t zO<{>Ht=K~Z3j$ft;$cR!WRM;M*{I3C1@wLU4?@ef9kh!ySrAmITmh0MN#bzSQSFzj z(@W7pdDzSiLYPqlOv-kQ0tk{-?BE&e;1voBGLe<q0mtD^^M*R%S_;7-sZq0O^uD4ggCpu4KuKpFk+mEJBO@zb zvc@{KVxVSus|x63-Afize@t8n=zm$Pn?&C9$>WQc&dg~nADCzzzv>vFb&~~e(|&US zeUXa5wzP}_XSS$b2r3oDK*6PY&>{#Z0iD`*^%(j0&;{r`aw%NC`G~5E6ft}l=+~-( z2+D|`tpmE8ky)S$=rz$YnT|zUDd%s=fP%a>$6%Uz3p+;wI<=_^ah1`^`yUKG>EFp6 z0iF6lgAXnLTmUC8+}6%TvWhH~Kcfip8x@0WswprC=+qzjBBDDEU@K!5sLo-F~L3Q&;QKPIdaUpLSLuA1V- ziUPN{jaCIXPZ}kb?AmI8|;@2{-MHUU@ry%Rc*SRxE2v`#1!G*C~2(rxhTKKa$5lI?Gk z?((7zkN}^oRCl=l*!(3DE!#S?tKoHv@>BtR+1NH1y!si;TCrQ)<0+r6!8CyR*PzA_ z9iO9YC3J5CJ;pAFgQu^uEFpf>o>60R>=`_eohVSg>G1^wNv*zG$I7dhB?#a9$=X zqp4i>Y+0aJ_pbOp5eiC_wG{6Ii-1nsMejk2mMq2KoPVP=@&nO-xxMsDqUwpm`z*v& z{}RxteG(hTpoK4q;(Fe(W5t4fyS7m=t3>;1>hxK#cmDyniB{q08pNUuS<=%$2MOac z(UlnuT-^`_!6Z=@uDz!yg5j3h`{o87&&yY?f;saRiu&}m!OW=> zA#a}CV&2i83l}d5MpUj=jcPEce;-FxIG+i4gg_8Hz>V+l9$9_hUkTB<`RpV3eEJS) z(ESRD=$=aSDHDxO(uGr|NEoTPf1jREu1smUC_sKma3yi#>5Df)gbj!81QNxG24O>o zG+ZB*N57{+{7IfL7DS2o^P!N$p-1!I5p=h@ELuU&fXo zLaq?5-FX5j6UP=7uKIfF{I5Pnh!Y9YF``BQve2hQ`-}v35?KR!KgspEa*WWqLofDm zaeu0o-Zbz-R>0z%!t*I~$PgC$n_QRBmlYUHQdnfuwnam?Nim{?7naIm7uOFJE*M;F!mZ-Ja+}@ius>A#f81t??Kuvp-F^51KB3hgUB_uaD_SJm z!mO<4iRS`Z7yA5$J9ysvpaH_i&tJrOOfFF9J{u9;)Ob3%%d1j{Nw8t}Y2ga*#^#Zl z3p#!O^#Zzdl}GpL=P%#6_54VErfa?l{}D5~=F)&CC))&`zr*A1`6u{CWAIkRX0MJT8N}RF4Xi zD1IB=Iehrwi{f!eA;8Ct8wZ6(+wVDKVN0$r$i+jHC}yjE5?i06xJe=ywL`yT`5YJ% zS;mqjGrd2Pa89mjV&S&fdXDnXZ6J1!(A^CQ!Ne$Xq=>>=*cn#zEJXtzs zdUOaM-qP?x?d!8=&xNQ;+eR*6WFkxH&v?(EZ726Jw7(o}JGnM__~ARUN0<#u$gNW1L6v^3+TTLy>lz3(Y@}y`Ut;Z^guv~{Ed+{04FBkDFU_xbWg3H*TV#uz<-~> zvaLs<4!VY+L~e7)eNJFZXRqGFSQMkgS6AiG2mPw?Z3AOBxlc@h2{=K3zKChkca9Kl zMt7?zzVfnF&6a>}t2{4f0!)AjFagH|Hg4W3T*FXFvZN>f?tw9po1nT4n*t3|6fIl` z$d@=LO9CXG&tJ4eETn;ytmuAaY1?;_LQ(RH=FFH5`ch?XIt|7QX(BSSmXduCTfZ*=#1PSi$n&9qkgWKSCCjaN& zy0_|_I-lTq2UX0l_u6ZB_v-!$1XOq&V?Psm3#Iw6vyUQ}po@x$@p8Z@VH?A&sTFz% zDQvzabf+=7<^2fxvn@|ot1r@KS>4svdBvnt+n+}TYG_p?G}4PpdY$TelF&ul9tne9 z>^Y6-x8nUOApm(W3xQEV+(=qo*=zk%5-loty&7DIA-t)LvZ$T z=8b`_2c5A3s59TF(KIRaRN5c-hds8uxk|qcaY!i>2Zo{4vhUGFs#|wQQ?LzkAC}!%#pPjw|^(Hb%Q=zv= zk$Q)57li_k1IwI?6i?o>W(;en0D`}&*2!2|4KM~Hb=X(rvzHir$hhRO)5OS)l=iXg zqjA2>rMpsU_tw|@cPwm8ElvaABJaY-Cxa0of(3NpD|IfKS~5fezgrg_(-E8{nA>Cj z=YCQEC}3;OW!D}t-^t^J3iK@gdVJxQDSEX50l* z0k{`b{!o@CGAbk&Pn#rgV=xSxcsds~(fQA|*iHNrwb@^Iij$}vjRwkAqW$vqh#t}c z@t%{?JpCR8Wm>KDw+Q3*=tD;ox=jOk-?CLq1PEa)ts&aSxX(g~Oo=Ga#<3-rRf+HM zyjkwlI<98uz>eqaz8JR<74-FhKHo*ESXMPx6OXSwjuLr#nD10G1U*!@5PvC@#`ms; zME&kEzwGYm`#I+gb^M^x8b48n%F7QY2oV0n7!%7Ds*$i9%SNr5!dEET;1sQ)2@@dTGFT2^*1I_9Y74*% zdq0y|b$+XvQ5-k@cU{j1$lmuCV)uRj`G619%z9+PZ@s#yIYyz|3A(IzWVVL5xW@kp z9sm9X;Q#Q8J2ni#WQP^-yB74J|6l+1zu)=a_5AN%`tN)6zXyr`#*qKU&;RBQXodHG z%(4H?oBv>9J=C7i9fC=@`5YAC zi1GF%h5-E^hBb?{x5M&Z3WDc^#Vu9{)aEdQ8r~dIS%mLm3A#HLdo_EWdb&gV(esL^ zPyuxRYLh;GgM}4TL|vGdzJqhnG6Fm%A{L{&vctjXi(5kXK^5Ko6*?xof{6rT5S7@f zU1%8x3>_76yT>JQHdNrK=c1K_Ls#Zf1U_5ucKYS`oZ1x6Nylps)^`2wobEpS4o|M< zyIvroi#K%|zYpDLb{k;5)2rBi{?H7GTEE$Gx!s7~yGCj8Q|{T%@70)@It!oePBt6d zVn4~cfA4TE!bmase-i2@qd(M1MIsVBMJ*i(uGHMS`i7J1^;`kW+2nbRA!8-#kH*8< zmc)SRIT4(JPdzdu(O4GUH5yV<1g_Y$e3iPtFDY;Ex-dfC zfqfU3BW@p)IXLak(&i6+L`{#~RM(Rv?+h4vp;I!JO!y%rOfO7IIW<@ML+XKpgal1=6Q?$s+d|w+;>a)FYEnlCs@tQw>A{G7^TyK!-lnRROc59`G6@PfYRfp#N z#6g9t@5VwUw$z1a1;&A#mObc-9v6D$_%*UM4J~al>C8k05#BA7YKM+weoRw(Oqg*Az*k<2xmEo$&tpC5Md| z%DgXCoz))4JQZj{RF;2JVUk(Xi&?H?!gjO1_MXyHQXBMEJ6gKaiF{6LxFhCuT0x=- zLdQrMvIr)^zR#PVP;P-ig%uVSc07GV4<(|8rIkxW4nT0a$Td^R078rRdp0a0epBwz ztS+pm%zz$9DQ=$VtM^;b*t_}_$EOE+E3N~&6aF`n;c6MhkP!2qcDz>Km=KZ=0-V>r z_9P*7#tMEVY8Irct2hhagW}u*FtXbEGMXG3esF8g6uV)5G^lNE9L=Dos1IlSSuuGS zAqI)I?eI`*KIcL9?({&*#$ciP@m_-%9$W5ZxhLnHh7ADSd-{5%D`P=ownW7aviiDB z$Yvy7=^Z4Qmp)h4n*;Z_T-DveihX~31S5EsfuKOSAtr-2X?DAMsOr;DeO{AvVJa|HoXD>smn!T5+aE!w#mf1-R{g!M}vPIkE3Zn$EE9guq{Be zaFr;f8LBKsZJA$!_^g+E+nPPjW>23Ag>j$}ar;{pGxOR~MJPL91 z8nlJ+&6!)ka9{C>j~xYUey`l>ZGnDqK@FED_bYt4oe7sYw@rNHruN)z473m-V2y8v z*@fIwKtI24kmg7W1>i!?yl$31r9wGWb{j47+)8J1T5Nhp%96#scjqD?{IZ4aL~AZ7 z0}|~VZWA;-7CQ=aY}7Y1KW)(=^1ra2n?k>JL^0c+24{pw^`D3YyUtN-5`u%WuWR`l z9=mCCj|Is1EI*bk34JIW-^yJ4U3Gr)yltYjxwucC@7~LeoolrQk0tP(_cCbI3vbXY z|Hf$%xiRS3PueI@;+O*E_*pt|Mttyj{jR044)!rvQ7>0*fg(U-5be<9Hj)90?}vFv z$$8f^TG$E&;hru*40-}7or`wJyZd6$*K|wW`U|Kyk5+SF3nwdTzf_YzW~%6UC!F!a z-#OU+DL60vs~sgHQ^@ICanOg{Y%8p1=VGW2wy1cBUlGlRzouvbUgC?Z_1}{Gc*g8G zV6>r(5$Dq>z1UQ4U+zR^!%?OZ_~7e&r8lu&o2c=ZKe&V9-=9xb4D-dBpMypN?ObdZ ze!lv6E-{UJh#*fc%+LyMc-!%SN|HnnXGcik;)gI;n5S|&Utqh6qpcFOj6GQ$p;WV; zrFba$b}Xam;<(6|-C5bMM87m(>{N}*aLfT+_-Q{(>if_}VD45y>5~7qC4c$hf&T(Fuf0F z;NdYnavb~n{v)@=Q|T=1NsArY!n;EeEX{J=_XKm5I^>AAPZE{_&jyXA_z+TFZ8YC_ zvEIQ3CKZ8u2hZhuXe`kiZx0Ts64pD}O%tH(`wrQXFa0ubAIofM74dBMr&nSS-j}k} z(C-Rgoy6W1SDDiZuOxHrbxgo_HddL;VAio#5rp8pV)wf711crqknI)t+BxRC9J=uO z33F@R;<_PMvfwAyr}+t6v8&NIYTeA7Yu~Lh-CQ6OHm<7iN~f^V))qQtv)3WHVCT)X zTB(geyu|vu?=Q9d87?`iFMz&dN~9m}aoH@~!Gc0ut?}PqEL~4$ZK--hq}$nf7VuNK zGVv!zG=4{SZdQsevYQy6SK5o_xCC5|OYH#&4orsi$c2gtBw&Q2?z}#Bmq+G%$RVz7=t4kehhOp>g`--{pL$^moi&?jHCP_T~&}Xmo`MkRV(Vhy5cf%_1@Tm`OsB&0b zQ}G>z6upq8!aMiAK3oGA{Wh`8$Kp|Fq{4S^vyo+B)(-Bi@2?i^AbYMzaLuNv^`+G6 z(~>Z)$>-+Yb}@XB3zNo%{B zO-bU~lQ%+J-5QKe$p19b4eZo3!b9-Qsv-tnQVu{Lp)@77;}j1KQ3t{PX`2k@ zfJU}X)Qq>*_s?}95qPkVuUSH(t1V=2cMQyr*R_j@o-e8r^Z9Q%tU}NQgI3E(W4ev_ z`>YBp?~I`&%q0np_0N>yFY< z7ChNxVw;WNtY_}t;)exo=Zk#gUqD0!kAI&|vH2g0rUgO5nZh5$%l7*+P9Qvl@skZI zp{Kde*Iq?vKNBKjH|~{CEl0ZL0_)kK8Q?R?o=0tS%6Q+!2;Z=?Jh>lzWfuJT^q`wA z_X)d0Q-}%yg4BW3*CvG2;DRt1mU@~lHk+OVYqn7SxEl?s6eex3nkQ;?Ju;rFtU%b^ zuW`JbE^+V<8BOyIw2&uQWIUQ135?YDque8NVoYR>*Px1j(c0*(?PCMM+6PNfc7_#% z;J`XtI>TTM$fAC}T4~&xWomYOgKKwx!_VHK2U2#WQgI_*Mo@6TCrUD%T1V5@2l~Q`o|kYvgl+Dlp#V&t)}mczu{rtvZpwNwcd+EJjmze-i=n z1wRTb`aM*vowh{x>}yhbQU9e4!zTH?|I7!gkbDQ#g%qv7pw9i?lNxaC3PI@F*(Sv< zNrWAZHChMr1pIAj%h}lK%<6op0pp%Z)SkT^TsSSdT(Y!3T;QvkRuk#6Js>ou+-^3W z_q`FGA?rz03@fH~B>vc`w9i3UdKwj3a%#a{f(jQ%6SI)SsUAF=lf)_+u%k4X=P0RE~yp1y!FDy-GFE7=qPjlG2y+=k(e{) z6&W0=R5-!Acwji~a$cAq9u{(@qMtO!k#gZ&G!3441sUWw_(m;5%^*0Oe} z1i%l{Mz$6t(xMHVx&ac}pPY&~Bh05M{kJ1ujCy^Z1NNuJFtOsDAo->j&%9+&?t z^gasH`R*mKx~a=#j(2J_88xOcpRrMTA>38Ahsd~-6^{}S$6H3iA7HjS5=pB2#(#a; zsJ28XluHYsv!}aBSA>1Ui}a_Ssa_7-ExgST)Fdhs)964=>2OEa4_=sn7XP9FVCqXl zTfd;6d`&wmvF z#zmlb-!+(cH2WLIw;*_wb% z0zdxlSb`qJ3HQ<7_wj_dKa5;Y8wW~#%Yk~3_<987WE+$C6Hs%0vYkfG&v%gU`5n6L z4zUu+VJLaMh%=L{fwD$>DTUe&%NDczUblm)zd|=7y!(+YEW{*(M(Rf>;pb=*gXO0B z7z@>>wSuxGMwR_3wuY5lLvok60muU?;THVaF%)LeyHIs67;rqE&B7FmY3X&iH=o4^#pOLvGn*F?0)>hfDXmd)W?pXIQFz$x%CeeZIoIF{Sm)TF_v z*%)RkS=8uobjiuIYx-)*iE#7bj$AYDTy|Ho^Fs=&9<}~bf4>b=lWU63DvV#Vk!YONdY@0Y=l7UPAH9HtJg*EItE#U2!Qi^8g#NkX) z1F1v+(K*yhZ(?mk`;G?+;+DT)QK#xsWa1;KZ}GfIU!>Py(!%q$+F0%IqNI_I1l_2K zjFH)3@#!v%>19Y8JXd^UpB@qyVXUZrTUuQ>uFkBb0lO zqKga)K^q!miuW8pWfD;Wf*U%uY?xH&6mr%B&(p>(Zni$$pIyUtc6d?4{zOEqX!;JTVk*0bB33TRgb;dYhJux?--(srd2H<*M!5!tl6;b$ zNZkDqg(&xtU~wMZHZpukfBv`qm$8(`JRbp;brw5~{DYvRvIX(VOuk&Z!}!KrYx6^Zxo{V`N4G#%=$`LClUFbiuLk6q8`k<{5t_3R@l|QW& z$}kfdv4vf5l~vBL!SbUJcDab4#~Aqq%a{cArNyOz^xKCa_>^*25D_H$%RE}iYN~3W zDB`exCD7c4^O%2h2q{b3YRuDCl}BdnhIZBGQPwhITeTsz;?h*7__w@^9sb~fGFX*}Qq(c$NG%=>J5Qmm|0C^+ zua%eg6Wr*j8+P_)RR{OchPS9c(;Ng_YWx9?t;YhdyOgp~HDZdGD$3vC+Ygai089EG z!WLnvF!FatkgqI~j-MQ!O!2~jtEz-z1Fo|E`b7#>K{+-)wSq%en&GH({2!2hbaB>< z5l495T8ig23z|9^dPzaG0koJW*Y@@zL9ZxqN*Lv?@WPv$QuiOJjW2ZNIrdpFe#E|A zG4aaeD^Y*%N_I%VgNxHOth(7#r@ZLn+4E=L3OtU`9-BCEpSX{+6^Sr*W)@Yk`fTRaAaQM#ZD~A88&Unyd2@7+_;5*rTC8Cc~rTy zD^72aZH0jVksi|xS0a_=6>0{CoWzf9^w^&Dfh^qY_m8>cfMM^BTZ|o%y z$fyx}X^@<0^`S_IP?$NRxRa`j-?ocVNT{KhN~i#y%w zyf3;RA2LplHwav{)P?^Vi7Qm=c_G|A?SU}f7NNK_#ikJ?od=_;CR@iQP z!Nw=1*I;Ms8LNT6T9vGb?}xLd#{E8v)t4koW9W*J;&M}|K$U~bR&&Jy#fiOn&lW2` z(JB}}D2T$5HXQNP|2DG~Yj)h)gwzCTE>^ zDIkhhN+BK*x8c^youNR#&lQ1!2;rfdVgEsbKmD;gy#v?mOtyHjaZDDlJadTUD8@jW zyW4|dW^tc<_U(wceDeot4cFSXBP3l*REnX{1*-?<;>TZhAw9Q^b}xiT6M?;~t4fcJ z76nj4Yq%?*(!qRZ)(Vv-^UB0%ZFF51tv5QEAl~pxfJ(kuiQmS$a*L@)*-1zYMcDQB zZt0Ashq({G>nuA5IB())uDI)BM)u%-+&&}Mcq)F|LW$)|AbcHAp#e*ql=~Y75@yD^ znvIU$Og$yZ=W<}u>G*@f(Cm4Td}!k<*(9N`_eGG&`!9O+icfLdDE0Ph;(BLB2SM|> zq_|_c4S{Q3wGB{S3h_kp$D5J&_E_2QW!qwM8shWoB3vHk}CKh;=27|Ddk252BMIIqV$g!)J2h{!iRs7wC8h#gXY2CBF?*u5|SqZu%|u( zO)?Ud5!VurW}L{ptAcyJ-Whn>#^IwG!A?Z~g-;qX3}&)oP9Q@sV>Nqvl!TSLS-u%C zGFW@PGRs-<2f+96+)&~A<~*zxslj9UG6!e;UK3~cSklVN0b1Q+q> zo7JNE8`0bAX}oGo6pSb9&-|m$(&g;l85s0hlamw0ijc#qC-NCFA{mP&`83G;l3$69 z0r9ZyT+f}a4#r!s3mw5}Wg!4ez90^UhG`rLJLEaY6_{;4bK zBCV1KhsTWtIiaS01d5lZ&LKX0I2{e^v#G-uiY|Tx`kd2?_g3LosB$c2GMPK;&)t}h0U}cJ zS~x-$jKT9e85amE!(X03Nq5HVuPF>9x*}?uxHubu1<23XLD5=Z!e-p?+Z#u9Jw<44 zbG>#zG08sC|EHN`+}0Rh2K%^cACtS&u9wfZT#5I+PZa*-dTB*iwBR_Au|Q+97NfMk z{(0vgQh6~rZhj=P`D5jn6sKe`i;&+B^5!Fo=a$~lA6BQ5rkmoGDgTIFGiFEh{#zf< zcI9!g!99CazET%h1H5wmult4Nny=s2)+T;~)=Ta5wQJ9bW5vvEAW7c0(U|QLalts> z1-W?(<_Ix5UR&S_=7q5=Xf{O^V4mO6aO(!xn@>ICR18xZ-eI4{8NUt1pJ4Gxf8n+%c3`*jjf9#$|h8kXaJErdr z0=A#aQ{AVgW9%X#nICX;t}JLUHdZRW9K@Fe%WDyX&$8LL0Q|0wOZTYt4pFY(q#c;0 zn=#lkcd*ehrvo!caLMXmr>lcKX#I@D`wRm56+<}sstRx18o^XYW<74e!;AekQ~S|< zQ$Yc-W21@!r7Dx6wj*6~3b1!^RHZ?YM^6k^kttXBT8}FM^#V8-R zAKP-7CPZaM_}6|9?51+ynt9$OAsXn{;7ck4ZStuyIBt>*!;~&W&DCT$>3==N#v?s$@2sA@WPNXtOyEu3IuOCd6YHN4Y+#(=tzV1~us@>h`C*4!j;a2kj^u4eMtjdjL^FBN+8g zV=moDHxuD7%^Icgg~gIv4v~2=Qje#+A+44b1_C>p3C~1HrOJ~{4x@~+S->qcxlnD5 z+7mC?;yH?ZlE7QTat{+LYw_WLMO&SHKY{=w*Q3raF@vL{-#3~_=&RMYPVWafP=;fs zOkly$XJ3CcAW5cxpMNk$3}Vgf3(pT$fZ$UY+{+QVKXnglu!oly>TOd>3SpKh0Z-~w zHT2{>)$Q9MrR)1MNGM-*kBO_gw4+=mxU1cPzusQ4PdbudE(+kRKf-o2i?61of&$aJ zN!wkHTpeQqb{Yvb3TiAI-i$F?s5k&cG7bC|+~+6b#jHcapcIySeSH8wT+49i!6jXc z+Ua&l>$7D71(mA1F;2@tT5*3UjaLX5byZhaJltJ}*yIWR<`c1f7iQ9^kWKv#2<&5m zdXsP8k5_YTe{#?xsl+Gho8Bb)XwS8ei#0;J>oB4s}nLsg?$m(PcVYk1F}q-zZi9S zuq>`LyJfSZk_R8RnI29M?6(zXqfWJCP!DENF)k%Ms`@YJd>a5;k z1!F`ZM)iZdGPY%_B1Sr0w&MHPT;H92&AZV1EV;OV_8qTlhh4p`MOacHt1I}j^RF$K z+1f?+exbm^j>2cb8UCLed84UqJFxhoL#c4)CC-9fakP?)V zvTc$-_&C@}sh(FY{^3+E?=MC9O3(=tbPXQ~DLf_6TQjl*Km-EcO_ya9r+vx{SB+{j zUn-)(N7)bMdYEd=oe$9@@c#h=?p5?QPM zbmpRs+wnGR0G)K;$TuHU5T%hgn0#hx*uUG&=$aQLTc|FR9neGdP6k#c5Y)U}?vzUH zSoJ1Hid58t-vh|+efTNVK^0k}wmXsp$1u`ptf3PJqA=?-GQsYlQuqlOEK4M=6@I;(<5gvY``{24+Vl`~{qS3RAIu5W5#Qc4F zk2HSbq6y=CA}_zbAv-#bq=!?7f%y6(i>`box|o>j&d)r#wf+n9Wqe+rNkG36BSo$~ zW$ef{vVTGTbpR8$nNtbWh!tSqjQn#LzYoDL1W}p%2cc~MD_81saQ8k%b#rX2yUJ%T z^A&@1k=^p)ziRx%bH{08^{zaN9dNefSoUg`7e&eMom4pq1H{LV{L;UkS@O}lI(pAA zG2xeBy^Q9p-+?SKc_kdQ(@T{t5Oto20?Q5LIj*xQH%&jOO?f2WT5-@6OW{Z&G}$6p zHpZDfw0)X1`_VZH3tl1E$ZeRZ47HuM&F+%o0WO4R)Z4`K#4=va4M8ojYyoI}o5S}t z3k)!oePL5TLl}8ufsAeqjtM2940_S8V|@@ z<_bjf0<@ajB${~yT8k*ml4LwbmLl@=sQK%xj|ljgdN8aFvE_fb55h}M`;a{zHNiF= zEj&6H**w;jWxYa3K^7oo434JY7*!4a2|pPZoNYY0dyY^?0T?H+d~U=%38%px z#ssv-wfy#vwr+zNkPoY*0>ZsGDJ?>WxmG>-1L8&SFB(9Gp!1=~`jrL&5^$`0$-~}f z*iBfO&mO(ns9qG~ag~Co#tY|O@RMyOr;KHQP~2kpur%z&ynhbaIxx+a)fX3zTk!sw zh@;4&U(gWxRYCq@XriQuu8IN}ks+G~>>YIy=F&dHX>i6jXTTzEqLx%~R5cx;mnR5b z9k(OpCWZg3e0q!;Di04pdyXnWy~;!_4j}~Z%u8u0H?PlnD&8W$Z6bmY|E?o3*GoT_a-jky=!PL-P|p%UAr%6rn8l%{J{Pz-tPbN0x|P=fs?}z) z8n!Ax#iQS^4pnyuG`#}`YpV#WXH7uqa4Nsv?Io!`$-3nL@kPI!HxJ%N2jXF8q9okE zK3R_o)|eDL$)CjuOa$2-m;QPb`nGRD_!UP1B}B~ER{2f1$Q1zxej|$P{SnW%3zi!b zDzYwgc3#f(CTq4cpXX#d{ieU1X0iyAsP_l->~u}1i?a61Na2m~K1)RsRPr4scpgKT zr-T@v%e%$Gmgv}rXGT-`)254^p4Vv^hc@BrdJDNrPl|RY$ zcfLn^fXhegV}#q*E1Awmuc)-f-|Bg-FfPnLi3No4QG|HC%C32J(u-jrTFhQZVYzop zru0gW<7W;Yt9fu&Gq#BHTNl@)6sOh6dp|rJ6g)h?`$FYshXp2KCJQMq9{^+`@ov*fS?Els@z<_sDD7GoLwsodw6I(HcH zLi8v;;Dz22uW>7vg}tCNg$vohVVX~69n@fQa8>VRJ(+dPV+7Y{o;~$Ld?#|Y#+0#u zM!X&({-QK#jrgaXxO+q3gzM3gbAd6JmGk=7+vUM?}UYPL^D*=-L{QSQc1V|CoFYD|y5sXKCGm?Kd z)%aGveFF&59gHx8Dg)YB7V}_E9f=AJdbM+2cginIpOjvEO@MqVnY@=zKIv=ck;6wk zT}p z6ISXH=xD)erH8R(KN6BH4shC7tf85IQ`?{BgCw~IMbGrGY%eZ=zeoWHBxtqCx#5=v z^0LBP+6krUX*19L@L4{Is69HF6X3b=@$~FaZP0Z-yt3%2)o<{wNwN!t^7IY5P{UBb zzGeH?0CFEFLrvi%Vm12RXcjMy9SlUd5*Doed4^zA7Ldsf5XC7cBvzr^;3y-0?3QMh z!51|eiKJ%tS5M%gH@%KHE;U19*^Jj6f@Zb!RU_XSQRk@-)o=~AYpSQLgVw_|AbaG} z%uOMI)7t|K<;8?w6q*$}Ohl6c+RGAe0mv=bnQGNr)Gq+KYHnV1KvUjsaxcKT!H@9}p!m4EqO z1Rav8+g8b;dtsu^^QAhcI67E+OcG!f;S{i`H)&|Zdq?lVt10i6jar5wSbgON1BPBQ z4wpTa)8;~wd_`y3ccNHyn~8A-BFkvm4o`g15J3W1sy=^&Ql7=7gmT;wPS%b`jNGI$ zKYWib0e9g*N~Wh<%G|**y$J6w<7g^95|kdl-el~-zaHFklOFxZ+!zyhp($2AUrn7#DGEOvJG^ilf&ckfW=O9I@JKx zit_Q}2(FdG^}A&UuV@B2B+NhpmkuD(C<(HAaL??Fk#2=K3Z{o&w{nuoYkj|E7|K za$tpy)BqoN3R(2#dCG}PTQ#=r`;9Ln9wn^A8sJ06f$cquEP8M)r>1TA>$sgMUrDAn z^CdeFoBt3Rg~`)TH>x@q9yhqSn-nkP$+{fsjHyL%W9LF{G5)X|ZTCT6*hjuUAXyW{ zDUBBwtZ-k87~j2*Jc381MX=xyZTbnBgZ4`ZD&+diD_`e6vzNdXv>c<5(J{^l`i7aB z!i7y0bUoAzev-6U*~rvX1~-kIj#&JiXEy6OL0Ej_1YyWxu(vtX?LUDBLk2E+D6Sax zn6mT>_r44d3e;Qm^VOsyiy`W;k@*w%(9Xw=o8yk)zzBr+RQPWKc;J3NsI060`REh< zQ&Y6~mw){I`+Mp!aE~1VPZC3gI(79V@OGZ)W8XX;9c8vg?q_^a%7(lWd@qVCt|30q z2WAGOT!rF<`};N+NNOfq9e_VT?{)Tz0C1Z6Dt>8MXvB7OVL7W#Ic&M~rdVYd0{Puf z0pz(6eyF))h-k?ag@BAE6$!s^X5sHX(cy@D; zNaG`T)Rvq3OOS5J`^N-a`kasoF*ijo*egq$#j|}+x8{Fkx zOmHLoZm$4p27lw|i2VsyYqe~|$q0M~1t;KG^)k}1h<@h}ja`#&WNUnD=)-AbSsZ84 zZ6Y*SME#0N;0d)0lqC1*CWpS&mTl_*Fl_G6LzfK;11%V5u)sp8o)I^aI|i0e5u!5I zn=$Idn+FGaM7+&+_{3&7Jkze4H{^O^?nAG>HAD$=PKw{IT=j(4NLJBC@Cfkk6`ya~ z!A2xKf=F=W^BwY34d0d&HZluec?_|>);b~9a{f!G_>&SsGBtMQ_CO+7dbz<*pc9{l^o^;w5#hoF+c5 zVm$X`zH1ckP1{o%%J-B)txKH&Eo>>{j&dGS;$c)YQ5rJRxV}J@=+P)zI$N{%VH4S&Odj6D7%9HGJ%B>$B=5x$l1`Rj5_kiV8DyFeL7=@4?Xz#K?}vdK6*55I9CXD*&vE)4T&ES z$*yIP3%IG3xsppI`!W~KJJG*Tf-18wxLqXkPW z|NL%;K}M3%s}lg19O-XY0NyO)!?|l3%|?vSArb8)v+gLB>+FYUh;shTq3&d^)s+K~ zr%lcak2Cj4q)@2AbCv#5bVy6nP5jEBb;@c0Jx}feK9)&Pgm#|5G^#f7AaM0KaFkHn zBPp3MQGNFe_{3AnoH8Ik?=|jx0J(~%QCihTn-CX)ENZQjXZ$I40l})L6@f8`wUzQQRRn`5m1X%0~Pag z=h3bf0028sR#Hselc>Qd9Z9a82{9%P3B8AxTIc)DiCGU3A_!UeDJdWLY_Y)1BSw>l zOFsJmZy=2Qt>N>fw<)T@#e}eubj!nA!ABPRGP(AvW5`Io&s2`)65wp+0FtNA>;=

{NPS%j00Siyi7ZU#Uq@C@^IXgLpbGM#+whZvtzecj7#m#=1 zR~u?z&(x-6VT#DYCK;ABtl8}KuM=_PfsXc99+{?$U&UKzh!g|o{Yn>)y4AXtS&=WF z6y9zTIp?+7;DpYRNIe9)T9U^(Lf_F$HYDDz1Mx0=_-f=}x5jp+0$!#OZ z&U9$TaqQ9@KG$pmkZrOV3X0?^egiSjxC%q~_Q0O%vv)wCCi?^#r`c5#E$+|-??jCt z#PW7PtI_FK=Mi)A>7{`_yF9FA{f900kFpH*s(K)$c^4qcJ|7X7-Hi+%8Z!+{q>Xbl zL?`T45JcEa49?@MzQ%szFa^_0zwEQDK%?XZ8A`51zA@AbJwN)3`} zEz^wA@JBvE&#QGqkwwN^0a2*R6w!DxSUpsHaGG4BYU5Z_#D1c!2zQidstR*uHlTuG z$E)wJy;8p)rN~v}{a7v3tgP<9Yf9x9-H6U^rF$9JDW?zxy z&)F&K-0{iLHFSU87RK$Ok&ohZ+rhkdI%r`(qNnq)9Isjy$%J*p=oTKyO8B%+SUM1F zeM2F30`N*-9P!g($o%qqhp`Ac#<3c0MxmK(Xmv`}jOK;47)iugzF(|zvp%!RJ-!<{ zX%6^=_vERLe9)syMhWvGxMDM`b zabz02QlsLp;h7b%;$jY3st8UkA?2WwxS!Zv_Lx->%oX;>+si=|8Qqh>MMJcF!orv< z%@60WF4}JVQNI-E)B#y8ylHFe0ftwfd|h@5Cs)4+K@vz9?80wN8J zmGfoJ)m_PYZ%7$L$j1fi_*y(>9`D|CdL{(L4t-jW?}iJ}7XfR#3hM zh8}qt7(Ge>ism8Yt6qjj4Ai=wWi9Z9;)3ikj?1ZKiftG{mHQ+0@7bEl-=|ap!1&VH zd8hOb@<}XquAnhrY7vKXGw1LRn%%R3=3(`zh}cOl#$lWG3?8C1_6M8#>Vg?8R170y z0I(X*S`n+tiBCgUsy?)TGzWEQ?l# z>qDEsd0&c8RWF!(=ghfBem?1}p$mxr>sRe2#8k!ZK z;J`NqcG26fgh$`*M2Q#vB!0B0^cJAC*rn+kvj%dxD+BdXa^*JPG-hhMlXFpv{6 zUOY6{jx-NyRhZ8mc)^__E!oAQ*f7rT-4C~eoGcnkKfpeHvR|5K1mtuCL*t^;K8qC! zvz0>zXP0{o4ZI~68q5c5ZY&;iW08Qwgmp3)@Z@pux6f#;dy}X08HqLY-uB`}pLh= z4-~$aakBYqUjk?yRZFQ+vjEPwNslUD3nksUV@>4;eUu8>Kc@{X@fcv{pZDF8$ZjZ7XZF9cy40L)^&lSYg0<1NURRtzeozwgnr{J3+^2Ghk((e+KoTI z(=JUFhQ!a!hu$b%ZG!zNYFy!mZ0^5iW+e(r&|yp@PLW#j2^!N=Li=MrA181Oy6dD& zzDV4Dk99Nat%J&eDf{^uB>7Fb+^kpf!%yxdGQ-dGM>s#MhJ8dhb{sP0IpebYyMI>c zQzHO7xfcfq5%|8tuodJZ04J%Z^iwDG&{K(Lxdgxut3YQGTv6p_x9r6u?i`ll1unO^ zj<8f2u|ND5Bv`cHyjhQP`(BNujWsP1k67@%HhcOP z1b(9hRsK~pAI}Jt5lEBW7|&0w(U93^S(2)e)D1e zfLU|a%7?SEZq-$HovU`$-ZkrtDl1$qcBmAcQ$mMKkJVMqL6FUJL=CFD8AfwF0T&Q= z&ew2DW(&x_(>`aRNqXMs}|BV){ zPwaF!-a@!eBUGN0&iK}Z;NWMjE8FXLI%7Zq(=M5&zOLm`ZA~>h;zF`9Sj|>AMc%os8bzOA9;unJow0ul9F_F9r(1jtiMh>-2l12NGEZi_LK?-QLmp@9Ng*HyG9}q z1O|^HXW%8wChM)XqPaXRt(JvnIp><{6}S<6BQgdnc@OKuvcL4}22JZ^T}6-u-CfDy zFuzSToIoZS0}g;D43jeRxK*kDHrxJgFUKt9u=y*K+x~#~c>-)_o?9tI7HeWYt7qDF zZmPixxak!*U^yD~svVow>LMW>-#k9>0zkIM$;XI6li{dPrdzRsGmXdTnS*7PWFQ6& zhy5;#z3jePs-_G~{tE_;hs6A}P2Fi{g!cL-U&h=!CO| z^%7o@a-@?Qkfz$6r!U+nd}<`!^GiGZO?FTOohg?S9GHe!w#jE||6=j&d{52}zHXps9O*i@Q zLZ->nQFvsK3aH2NrP))zF$y6QEfIr&IFSVaw1aU`g}_X46s6CY zPvJger(dIY%wgC{+2oJEZ0e5>0} zh=Bq8-gQehu`2%SZVy<~1XSS+_(3C5`F=8j^}^-PXdp8|l-umgh-;b?bK3NlP(NHi zOHWV3^z!JG`UwJBZumzP`=KGndxT6R{*;3>}JZgye39VNV>wg21 zwULpd;v53+^GbzBNB`L{5<`$OzwrQ9TzDCbg>zgKpstyDYgV@@+4}sa95koiP^mnS z+3gVV*@XlW_Tv%7F!g1bgH)p2-_#}JX|X+m?-`$$12X%4Jzxs7ZeZmlR) z6zVeV65bl~AZo4VYSc`8-$F z=jSz$!spQ9ksmr%*xT266Q6H`6d0Rt@*Oo28M1c0OFDKwU3ot8{!_~eEar17TaD<0 z1i`1U83$H+#i~+dgs#3o{=C3cX*KC$0BSc4|AjmOzhVB`d~Z~3cWd(C%wsH;*`1sD z2ofq#dJ_SKRAsw9{Ky^%j`ukCPj?U$Sn#dG4SpYx$~ho;Y>_>u)YZ~{>VygE7$0>l zr3=^t@a&>Dn;<7EMhfJ;K?K!34lI}r$3Vta#|uPoI*1S6^hG3{x{Zn6`2+{?F?JpK5`uEWN3$G0L+uA3{L+#pdIel zOudRC@WW5nFlLYKO(i#bUPzX2<8Tdm4QoWQs=pITPc_JA-qYQ>7lZP7lV-|i8lzk8 zI7Z-0Wz|#jEZEnpE@#5SQ@|vrV|KPaC&GppFCZSL>qP-Q7~B z-(q*)KtMp>->wI_(f?DL@j@3|15Fl#U&^>3U^O;!^LB0X-@i@32QPmUF9N!(pdcV5 zKmz71pJhe&X{!S;#fOXE$-VS>Gt2jQl4q>DFfeBGCMJMdIj=6GSl3zTTMH{isS7S5 z5M%(qfpJ6y9kH&ZNvX32uYzqo;C+Vx8xlU_J6P%~<$EhEgF(MgEs@p1OGc=k6UG_q z6>1A&xUMc2^jYb~(L=ePXWIV^tz-uw5AKKeR{X3ZiY z*9pQnr$u;+#a1Fj!?TSNt}B!hm|~0DzA5agu%Ezqufv6{Af+>$3TR2wb+lc0*Gswr z!jFSj3!8C|;J#U>OlA$Yc&`xNk9t_C{R`|_C(j(>59zd~klN*BJFk)VdipN>uSFP3 zm{{Z?K-17eb3&DI7TKkEtIpV7qA&`jMIleP)`to{c+A=dK3SryeQw5$#FqR&BM5Lc z9-@|bJpHjGvi0s81=aVPb{_%1q_kK2<54HDK9a<&fos-K0Ej{bNEDl!l0{- z8Gh8vCy?i+Y8=+A;X6D(K(=hR>C=~Ou}5Q?j}AX!UESBI*glv?z>U;u*C2k z0SG9J%}aO%)~w!rDvTzsjuL4vqh_`l^LOwe;KL2JvLg=PeIgbsKJ{gsMY4u9bX?KS_-}|?J`up_HZ42sr5Rdpe%W0Hn}2}NYi90e zW*@B3{19$#;vv#^qt073H6d38IP*)2XgA)cwA%oJ*o)<=pcfYxO(l5jR?IaF7UihMwy5+HlR*YUb+?$4k}>Wh-TwZT|OX;1b6f9^24J zmCIGZLlbHZn*;CeB1Gwf$2kdN3$;w1`}_Na07B!<@<=$|aU2~^p$YV(b9MRjnJacc z?KRJ6ItM}yr;{Mv+JPmDA%NIP`*DQEd*pI9()qn(h{@pyBhBJ+19Y;|QL4pN0j#K~ zsPJ1(1PUHH@L()?U?=diz&-xTz${INt$d!}l?oP}4*a6+d@<-S8iR63TwGk_@=ca- zCwTAG?d`?TVLDfuDz=Wr=z){d>w|QCv(dOxuMLme2URRSfADT`_}p=>bIrgs^~DBl zJnh|fwg}v#+b49y0-`h?FDQr0nUV}gz>@lc#~~uLSS}R?f8!7Ru(+6*aB9{gAulhk zjjhejhd)Ki^bmlaSpc|yTHiw{G{gPBsz!RJVqg7aghWKZ6{^*6=W2B6Vy7GMaBxB6 zY-e>J-)=StY}P8_a=PAiJ}#T7bjniZSSdSKUGIpfxcyfQu&}VPo`9y@pyLLnPVeiH zd6`U3c z)T}3k-w3gw<|WMpn{w_fZwK;ZJ)_{r(=GjQMpNu*G`mA+zV{3@Tz z8y^A=YkCiTG8bGHn=Jr98WsY$f=0%Ovig%wa@zOJ^bd(t>S7zuiomTc`vSLMa@w|< zNoP5_F5qhk%dM(UwCyo6r{a(fmMDqe4_nKv`gNaPh%UOtFMg{WtOTqKmjx=~JEaT> z_8Pv!`Nab46+nv&X=+sV7ACw!=bq`I<$kbIC~jAOQS3JV zMEkaxyuk4RX2(+dPe?6P*oo_{!xU=2H|#7Pp?)7w8NMxP_TaE_Di#iS|v|bG_Q>nDsAWAq{yIxl4ghu#Bu#N_+Ob++9z{tfN&hUHAHgK!lw4a>*aHYGW*l-GxjVpgT4{&% z3Z~2t=skWC6uR(Q)9*b`ySK&0daa=-(EAB5AX2%cu>hcZCcLc||NzsNvDqgBM{EkHx|GUb-^r~CDT4j8(+K>pSsbWnp0V`#))VGv_< zRr~f=QTk>H|Fpt17uqcB!&$TgX4@K0h0)*O)?gyCB<6{Z!=Q^eH3f2ask#;k_@BtK zJQoxF4O|+5xz$)2h8{msT0Lot~{1WSc+CcS~p@k1N#tce2!3f#mbLNB+&N7|pNf+igr8Uxa$rG#Nf zd%$?!c1W5u$}H3$`z>9NPeP=F_bfv%5OKcI#^pTVW7Ri`TG1Bla$0E^% zJPvS)EIMV_4!iok0-Oxg^@jou4Umc)X*!!0K;$AW8= zG8zvWqHd+@$qV!q^Ia3NGY1yqwRCfuOr%TwBwl5Jz}JNb36EJe2nXv%(_0ure94%( zz4>w_)!}==5Ayk?>BTkwRBVk|h5L~)L@_YYE%OPtqqK!TZ(0w~#De=(pJRYaIi^O4 z#%b^lcK;Xw#Je#3|wa(M*%BqY7foEV-{NF zsT?Fr?aUhn1_c`z>Qg))M0W)%W(z;~E?IXj{?SJepIRmMUS*I!ClwLYnZdE?oyRcQ*b^<9?y z8Zu^OXcy%;&ubs~Hdmcn8+ttwyv2)vWAxfSd4m0$EQGKHoUJ;jT4K>?sW9bn5 z2`nxq(*fuM%?Z7NCe2$k$W`k1+xgTcqD|+4h_OzBdERbHg4Pv!*v~e$xN?~~EueyI zvJhhT-*PAX4e8={*nRhY+`0KkfZmP|LK_WPnSOpgu*MD8^5+5DW>8Cjz9#eXCm%5v z@=)Pz>xvCId?EVyD-dRyyUEWJW0RptDR!C8E$xcUKIHzzF`7d~qQmPgWjzuu!7ud< zkik(?`|^1$Fn(v3_;nPPLS;h)1HGIOPY^iYY+t!CNAfF!A853}WE#v?t2xBUR5}== z#SowqMVu&pi!u@$MjQ$YQ0fyUq@=|B=s{_rQLhEiKI@Vr*7>3|gBJ%uvbtd(Jg8RAGScU8tg?Tc}bcZQlPA@>m8v#WNblW>(1so07Bl2bfmN8F@P zHM@(?92Ky3rsvS6&n7y&(HuTw>L!~l6}HGW244u6K=Ya0@aA)ldVsj(`EoVg&%hFM zz~;X6*l*_QTNu7mj@AK)jrRiuaqE%nP$96e&@iTqd@rI(=2Yor!+!dXt4MZYi^S#2 zVn>ae(ULk)E|{kDn`b0%gmpB5SQO?%P7(s?Wy@>#3VPk`!eoW2SrVh({)8uK9CcCw zWHZGtkP7S#=Yr!%JUrkf#Qvqr9-gM-*l4@pfKkLZ>NI@2Z!;a~qOJ+)WL_waK9{He zg^2{5(&cOT-CM9XWgbR&egj!)`2=>EzM0VT?BRxv9tOEzfDkKHn^d7k3@mtC0UTPA zG}U*d*&wq6j?@Pxh;!x~vE3O;1FZ~Z?ipT~xiTf8WgnT*d2~3U!UX*#HuySAp293R z(^rjg!_9k4DAxDDT~CC)@gO+>LwL~mL!jv-};DnpSc32 zMV+`2R^#8X(ctyB1OjJ{)q#JsB&;=OL6@JwnXW&G;{?jx8hVS>eKgtXHsN!^^Gakl zh+S9yGZ?c=+#=v~<8(iPPg`xR2~{GF?x8d3?=P~6A))gnnlyv_70DR4VZY4kYP$9G zr_fPP2#M+(jULz*(yAD>`Xd)F zo%bW>PmDg?zXFe_w9AZnmQd}$pTv@ zKJYOA3OFgICv9hGgi4vrME)4qBed>$7p@!LUX<9=&Cq~~BH1Nmvjyx#D*4|3Nc199 z9Pyhgmxr{^G#V za10Q`brtu_#c`p`9Od3#Q_;W(Usayg1<0@Um$byE3depwYg_;&(4^L2prUYv%dMh$ zEvYiKS+tS!qOw1!yGHP!iTu2yjFDt6^kws&cXt{Zyq-G5@=cXYO}0;3s=&G;9s)QE zVfx1qSx6J><^4KAU}u9sIJJa}Wlo)JFl{cy5r*56-w(1`hKncDyjv@9OQ^CH63C?Q zHI1rrFm5!X3nu@;z7SK;jh_t8OGoT@8L)A*&qjT@F; zLsB~>iY--JKONXpC!o|LBGky6LtR#n181}+b_LnC9=4}YLAt&+jvba|g{YwpE#JFX z{~)T2m)^Xr`?6qiS1Z7YSxzWJ@$ECnQ-fLFXjY9C<-w#J^=G1RcMZ$sb4BCNDT^ZO zDzC*~ZJOY566JNGjEW?W{!slLZ+n+S^h=5H4b!2+A6Bhew-%LtP}(2z=^8ZnjfS_X zXt(4bHLcNW6GEfKi0ytdElj#~EIOQDtSAi?j60RX{fl_D&a<+~qS*G1kw_jzmB-@+ zYBGm~fS5Q%U{Gb@@nQ>2?1%aWj}mg){9FL4=ate(PG^U^%_dY=f=g-|m3WfUo7yEe zQ<7dYzhQo-_UMGDm5c8K0V|vU5Uc+FLAgBsyV7rj#pz8iW&|6{wz|!75uV!t!K>ei zoyB7Vsb-B9%)~h2g%s6`Fa;}r1Sh2jiq{$PJ0#uN?DV^%LfrCy3TGp?2s*jICl$S| z&L$e~42~_(QvKkZ9Z9DDEfgH2uSd%k zT}TP>L}jFSLcLI3;PG6qEFbE#i)ZN?$N1{Fh?wYMw@~__xRT{@i>wwjgz;9Qa90@eNy!7O4AE?P7s~T{uMO$=VNADs&yG6~*Yu$n z1%7-ejFS?*Eg;nFyu!MRA zKIuWQiQ+(Qp!q~5l4I!xTVT6c>v9(W=wyc_=p0{PU1k@mNDldyS2D0Vts1Z=C%?G@ z_KN{n$`q%x`4qD;0XMX>Il{=ngNkX7k)O9OJFSSUttBU>^pa!j3r(4@hTh_hw(oh_ zbD&+ZR>+R|-Swl9A>DJM?e3Rw#$xao`>wV&TkUvezkfq>HOyYAds5X49nkT+&1kPW?1JK`mO$O1(ntS%fBN#&#Ej*X zmL;6kbsWq*klAz4>dGk=nmI|M>=K@53~i(q>nu8TK{_FIRWgdfu@1&!Kij(arSP)^ zmwG_~B=^o|@YKwg!;4A&VI~3;%M*E?wY{0oS)`Em%$7Y=kb?Nn*at>c9`;F>pP7wN z3*9HnX+XRLdAwB;mRa){y_hugL#qU<^55iV5hBbk{4tAyU*3-oj5zlak?v6}fEX;OoNuGSHk*q-0B}xCBGP-lyc+tU~T^TSb7U^9A2#_1WkC zMd3N7by}d*I62v&o1|)a59;MYAo7ZIO|gp@%A&4PEw^%^fbb2QrUD2l;(03=&oBK; zpVveH)^wKw!e)ckf? zga>Ey?GN}eFcA-j9M&k?WOMGZQw!$P=A!tJiCXg6Q%(T#I%BABu%d%-(}n{Bt&e(* zCqDR=UxJkxGTpT7jwJ(dcCS;EKr#FHr|4$c6d!9Pq)W0*%PZ`S*QUAz>8B(o-6Q*@WCh|kf8r9btuK?{MUrj z@r+d_i(7>D%$<0)T=4*!-@K35P|oqdvfFS0eYM><{UTtZ>Qq@{Q<$rt0q;6a zw!fRI#awJQM|{+m#@uNHa3IoHRTU1`fuJ*!^9m5dxs>9)0hUz*sNxwAw(gG zpM@2QT@&inVSL^Qb(yHB@`Hq)zZQUk0o14=3bH`C11r^(B%%g2Mv=|{3I0F`BulgY zh{E89v`LQ`y@!LsZ@ALkd0J%E-Ht@KVs%sGGfedo2=Ji-kwkC z&bjgdzO*Eo#0ERZ5^qKT{iw{T2@u}j{Yy49QbbI8TU+?-tb}y32x5E%-`g2 zGf*Z~KyveNSj=XYI4OTVJO2)QOxUokWp@^{2)?nt;7PjsmIUK&PB%-B7vBmv&>XW! zbMwS)(+}UCN``;wkE03XhJLVKu@}w<4kn_PQ-t`z-D0r?=5#nYmRDS5AnV^vE_g7N zi|A++M;S;gYo*C-~jjq%w zSm1x_Xncpey|?s!ltS+r#cH5j0WLN0031zAk6L5`Vp&4HOH7(17Jgw$Ng~f=NXHq$^0rq=gM|=6Cb7gv@8}xEmeHZf5k-H=hWPnR@%JQ(wX11`BDIv?)1e z%hg&XM;pXb6q|leAKy7y4uV)%|v5<7`S5h~Z(7EGs( z-jG9#%)A70k`xFw%y(h%f|0;Uene~NNfwDmr5^e@!USO^F05V~NzPHA%gOZ3;0xiZ zyU!tKewF%X6W+V^;=k0GWCPRjx33o!r~>iZy5W-T3ZD|w=#Y;7D8PjA5;kYnA8Tr7 zh7BSmUPoRQTgxP17qI)r$r>Poy2O6U4j(WpR1DMSk|m&q8T=$n5^o3JGC%T|JbIzw zb7%4p2n8P!!reoTUnwS&+A0#%L`ZrfMX0>6d(M1-wBA(Qr$4CVuu>SN>r5Qmu- zCEQ3(a`%kaupx)$OIkr_Y-VN{E8a=)rFrpD3=<$6Wddi?ikgasCsJDGxL}1Na~S4a zI>$22xO1O-)?&EK=7mdz@Y_q2f2Rvz@r{t&1W#kvI_h%YEG7~ntIe(ye~@-4jur#C zk-N>+$PK6yB#5_Pk7yK(*jaV*H}YuFNcx@99zaqQJpSC;YqG{BjOzo2^pfZN^?`(R zw5TT%BOyXebr^x*J5Cf7NGcQYL1L6V%5sNDzNeU+_{^NhRFp64IVz!_9YK~9T{p;> zq(57{R$cx{&bIEK-wMK%r=mHVBNG!*A&TL z;d7(o8x>*jii?N$^COhCpP~410D(41a4gO%cRrpETTn8tv9^l#mUr&8AHJ2IWOD2M zmB}cyZaiTtQZn^qTs%bJbTpY2QJ2QWws@p`;%{8~bTq@(j*;vHt>9RDFwBht* zxy+S__9kg83gQiLWInDG3suvhWCbU20liM=q=_|szQ9zT;ai%la^op~QZnnjD#WhX z+tY)g>^$yrgnJm=X{w1EYpT#nar!e3d7)8+Pg=onP{Zf*afP!e)*L zSl~gG&8zq{c9VRJ%*#*I$hW@U(E~4|-s@uF?>Somef7$sdr?!BfZ;pn(~KoKH&-^a zoVFn)lDO~hMM^A+5KHc~a7ynb`yB;G#H9H|nVAD<;{wItx2y)LP!_7x_!l^FEHGly zDJ32zX!y>Zl=(S$&s>(N+ZP6dJR*d91+&P6GP2Wj6Lhr;0m9R)NtyZU;TMmpeH<@j z|M#G6VTlHEdBgahR@`C*zvW7_ba@Fakr)qnlSkZr5;(@|ih%B2{?s|wo}4G8zp3NO z5Gm#6T7RJJl{FVh=OgZc>NDZ(uv=9#>v|JUCa+VPxshKgTGGe9jguCNZ<7fO9J~pu zFr3R9e#hqZ2~^Sv?0bA4a7)1ElE$698k?o-Ia0pJ5NlQ(EK?~)No^w8oW-n3_z|F! zK~SMsCL|BWZ*VIq`NZM!0JE4)sX9UZ>Rzunj4t$Gnws{VXSR3;sL)+_%CCpj6pMKJ zg^~^6fa;rXe7S(JBAxiZIo>`wgK>i32I>a_#TF$W(_C-M#p=Gsven$w%_|G1!|tNS68l(hk&zK9S&73aRdG z|0dp-D0DcWocN)SCm^5!xFXOFs+1fY0b3dp*FmD+*(y;NZ?ZqRTT!3i$*3Y>Jn`KP zS!U$I2*T;%<~Pgw*!dom1Hc4t#DXj$dTriyewb6N78*S@-I|`<|K5Ku(rge=^|5ec zTNJ8W-&z_MT$ZfE#{pFfkVj&FXuvY)oH=>9j&hMT>!!G+=&6nBpNAe1Op00m@Wuo% z+Z`}3iFOH7R1sD8{u6QJtkbe&Ah`Y_&Xi=b_C8+1&e;cahhNMt4Hc2>$;JV!;s3r2z$82FKMP#nr)`j)rM^`HWY5*U<78E=Q7C4Y z2wz!1$uFJ*2i!#fshS)eh?^KK)T=o@mp$8moMZvfMCa zljk@HfG`)jP8{tR*xPH7N#=9_M1yRER;x4{1OXN6La}CQg(?fA;F4W($7B!3|9GB% zY>*38wcUo*-!EXe-ORXHp{Q&AwoL^5?^5)x|Hm@~klailN=Up!HPF?U?OTAGnT`2t z^1zjIa+5>YR8{{N>tAsC*R22T0{>-YF~VMG7ZSmJ&3_&LALsr*PWm5Tcdo?)P)_{6 zxsJp~|JO48$NBz`2l)S||G${@|1IMHd}C+5)qZFH9X^lO6NZ78w@`e=pUCzvtN(Z4 zJ;}kpFSS1<$nEXz&h9I69#T*S~>xJGgiE_XrUyD;x|4H533T z3aGBG-hzCdeMH)5^TfGt7bKdzKG`X7*UL-z*HcN!KzdRHP+a}QpIh} zH`359>4`Nv|GNiGEB<+Ngp-oBA1&f1LpleVPQH?cwU;qT`2haCs8EQu<_WpxOWK2q<7_0|~-=)jwWJ;L8lQZDpgOF2 z#MQj|4!f=ix!^&ba`r*M$NyFqzixu+Fo5?hk1=Sl@W@XikXdnB+Bmt$z{TM6AOWCR zni3`sj&LJUn17I^K}KH=IM10=ZF2b$q?b9Uo9@|oG0xL*ilkSXZkO)84hSx2v$0## zCl*`|qn@7Qkl%&pVO#!-4D1{z!effVH%|}i7vSg9;B~@2>Zw67maNGV*IQlTTc41D z#}n#C#jLAqHLlW_d`=mdGRN=D-lZ6z6Yd4 zCIxsvLc2a}C7Z937{<>dpTqm3@rXX4V8@^y+O1r9pke5~Q25o!C}SfGP=9^EV#EX# z2GM>;h7fT1KxN}mL)`uNH+bI!BfS_yJ*2Ki;>YA#_UX~n0dp;A!gfeLozL#mhlmfI z>uyy&tr@BeOy&r#;4r<0M9aMjjUIbQ*qZ|fpP8h{4~l%(BDHmX(HJuf$IvZz*^?&CDL4S5kg$N8)b#fTDgFU_VFVUge0l-3i+@XJz zvIy!?&{1J0ApZ!BzGJTKb;!^F4ONsR$NuiUjkOmtS;autZ`boWVPwxAZtAfP>HfE- zX|dT&!s~YzgC|v^!)5rl2wDMk%-PzS<~Mvi%86Lt(*QGG_cPL!x4+q8ynR-vXUkXJ zxLOOh&iD=bxF~D(wud;7jE!5jP6!GG*2uaMkJ1xDEnTQyiq|PVhbj z>WOch<7MbY3;^`RvvK*7h*l<0=rU``(BQi}VPp+!a?)kSZqsoO-36~FP*tGG883sQ zv)M}7ukv$feY$_-W@g7E9~;80%u-=JPR9odA+O8ObNI;y>R`$`#W-cz4 zy7vfcGnVS8cKV)*8T-hddn&HpCUIl7PHIkI&tok5wRi2ks`~OQJvitO%jcb&Gl(uv zV7Jw^C?>CUsYf2K{8VU8Cf?8|L9^jSV{+aaBs@VNKybajWKMA7t{Aq^?9qxlTMC&` zy>>f5QrR46ikq0kQ&bm_$-o{#|GN(e$bPPbse?aBu$u*{pod8$wtd=2QiP zQX8U;P6zUQ5tHnF4$6t7FS{&F?a13o-C@$6AC!hRHmfD}%9^FC`gXw|~g zA}*4_UYCjZsQq4W;<;%mZ?OmecqI)w0qm>#D(CGe8hHHJ#jAFu^$#FrNqRTPRBR z`L-@_x5F7&lPmb_M*tU^9T&dZ=0TanfWy1W@hYANUvHzFpZgAvYxL7YSQrG}<0vdy z9N~;^<{opU?PRWlU_qs|t}YhU~m_seM|NXxIMg+X?E+B-Id$1dxuUJ+Xk^?S7 z{$P}s>K^^w*-_=9&fEt;-gx-Gik(YC`k4txXST$J<`UyIP`CnX-es`v=gK-%^7ib7 zdoe*a&m}p}d@0~{kFR7ari4A$ln zZ+D)#k$v=j3I??HTL+z4ux(&bv%fOo^Aq^|GLSod7i4D6ye|ncw2u0n5@Tmcy=3fv ziVgAerF6pPH}<3W#kq6=ht)Fn1|M(l@-Re=9ycs&^P@LDb7V4=`mKvj8(jc)mt|^LIQbm;U2BKKIcae!7FPVM&@l=bmck~99g=!8U3EM(}*p6u_P*k1y@v1 zDQ4M-NC@mE#ee%q@;=y$0@h3y4VHKofmX?9M}8~*xiv&kUDkTMJ4NuCU3twq`@wML z`XLa|^Th1?gi5K+>L`CoKz!`^@V85J-O+(fVId zUjk|P5cC6SAk!EOQ<#ig!??eq&@e8`HSA|rvZ;)|1mP^~uFWrT=M?jsIb^~g3VVke z`;2aaHJk(T)2AfmaqJ@YIaFcO^tlzBeMei7fJT(VbCCk+vGgI>BjJHJ*B>=!AD71p zwa>z7_S3V=jGfYW!4of;Sbi8FpXT`Y`5G7$v&mOgjv%@mfq5<#=lV)Yygb|QuOa}A z^IPu|8dL@~)Thh8CGMczyO65YUa`B?@$vn)hkICcjr-Bq=RXML|4D2xLj@a1o<+Lx zykC&U59PqCC%8a7BS$k4tnl)N;9pQu$f0{JzhCE2>OG!NXWNSS=;2AzMUcei$;Gez zL%j9!clqeSw5a^8$~0Huoqp5*W;Y@N;xlW}hfSf&aKYng*B}Y^(r&YgpC(k;#K4hV z;32^sx%WJh#8jC~#^(OmhiYkw^3t7ub|51T;xF2dl=}^w*5_P_TOpq@UE<7!IpErA^**0XpwWVyo?U{qz!d z{5VkgcYV=9pQTZ)Mi;Cu)0W3FTOFq0*Lt-EK5+qCZTVWrff0myTKj`i51p5D91RU} z@mNP`$`wLTlgUis7OHwh=$nft@tXl}?iXFSq9Jb@5-Tr^@(W6Bg2b^}g7C%$`b*D| zGpz0!PLf&?5ThOP@nEohqkcDdwH=+wxKxqIfnej^zE{HfA0ujHHG#7LZUK|dD&v5t zP-W97?Zx;PwsZkbR609|uEpxBZnuL`EXR8FqdmLDEMGVx+1Gqy@8^}c$MYG>i??W? zEDTE+8{I*9eCtQ1?a##?!^7A$Js9SKuXcKGA2!UO&x6N#UFua4FH*~cn3`xD5Bf0} zRTrQUnPnO7!@~i_Bj4)~7FV6|brE=sOTEn!To%ubj%`?Q{rDM!@D;}`rI$%sBS?As zkQ1GsF8v3Vb?)Cn%U>ws@Pgf)o~teV{xQBY(555%-ghqp3LXc+&#YUpns{`D7A>f= z1s+AMC32fAc2(K(;)4Z!rY=}YpzJYsON#{!Fm+tod187o-% zw|Y@@Dw($$tSw5G7UfOlN@p^P7X0ugIOW!6T@sh8jhhYY^L5Oq^zxC(cj2%{Pk&Q= z2|z#6%4OWS(5&f_v>Ws_UXuI+n1BZdSmzDCR2Zz!)5!aZ*kLzPjpv;~>3dGh)q7Sb zD+=l`;)(i(Kp)%3H{5%N=xs+(HSnh zv~4-3heHE9x?=#ToBatIdS_zDw&C}Y)tv0M^*dxDO80mu>u@^NnVmxOH5+;YUPwiT zR=a2kdPcN{_B5l^f44KrYfzXBXK`AW!oD%#)BGwh-XDq(>J(+Q{$edGmr=@$;9|v3bT*2?Lt<3^4=;m|$L0zRvrk>6FLR}1btaqHF=LCB)6 z)aW3vr{kkZ!|z}|AWM1-8Ucl)0TRf6mmAuH^@>6Xk|of$RN@ABJq?;rU| zo`n$n;wSubEfJJULT~#{X7=eI?QE5#7-V6#TwZt^H(HD%Y{c_LEulFczKMWRjj~AR zO01__RBVFH10EyTw0`HHu$^uPR2=-f$thBq`FK@gp#2vkDNOuv^x z61F!et6Z?SYH#-kHF$9sIfMta&|A#Kj<@O+w3+x2-4Gi`et{J5tlc}4|A|^H< zF@JBxD3d;wwhe_Rsu;^P)tGXiaw?SbqTbutEv%eYOB&jfPSFTH55PMwS#)Zf0KG4M zo4ws4(uONV`ozLv>OBzpiLA=a0G^pha2{8JgxqgzvMb2W$e^j@yaC9MCA0gP&jIwB zl#)oHBc`!ay=8l>mBO#3yK)KT!a)jQsvU!Y7qwk zqp1Su@h@B8>ad!#*-kO;_J0Ds$b3iMQ*0NsA}!ok>Jy>}+-f!_X!F}gFOoin;;7Y0 zKreJ%PkF{glL=0{O!w};ybft;YLJ0XtNZP*R~7?0lNB>szq`II2-R(WScRRWyIvmy z$GIR>2mS7AFl{&l*?`j>9r==mJ;v)%^mf3bc`R^OyY@EAm|l=fWJ^A z)R1?Y36UNxHT;kmU;lH!9`0=8wymEdB_YvHIic~Eb4u;|n|j@&5+O;eJ{=wO9|%4J z6aFD+vCl~5->{TF*tK0d!J!YLDoZzq*wmzUxPc{2+iMb`-+gv&auG*kk(KaarOQ;U z;q*%I0h>as<>Sv(Um{&Fuk9(ly04u6IU%o}+QGU$O!1atef*P`_z$D`O2*BC>(dtF z?RvZ?BDPE-Fz(Idfx4cyI|2XZz2&Fz*kH%Rx-0Jv-+y5k+SK{E0{_B2(+nT!0foW#pD>7dg?IiVOQ#$&cp+_QWy*#8-MQNbWWyd3CLd)0#m}63h z3Z4~i*X0~8xQ%hA8I{9GiQS%N?qxd6`IxQ)k7O#BzrO2>r3`-%*w>)mYp0(;Hwm_M zySdMhQpSN*0+2lon9{_X^u|28%HE2|+{0hJ7);};=A_Zuk(R`Xqj=2@wMtsVm=sTz za423JYA~g_U=LDwO#ZdVNOYuHJjJksgT6=@@;=^vL?%+Df39f{7M|15fo%n>=n%`L zR>a8eA)T#WI-%uDmhYV#Um-;Plc1Ih8q;~ahyCoDWI7l2)i5*IH6wNc3%D7ah zQaya3EF(H=7bVw}Gi$)NVWSI7DyghM34i|5U*}FkI&1c(3y^l#gAzUc$mQt#0e7jR zO_y7^(xMPhbN_Mkx=uYNPn=9_Yhou8+s?$c zC&rF#-95i^&aMCXa_fG+b-(PYRPB1R-?div>ZkkZr{B1Fw^k}JW1_EH2wPxlc6SmM zt#(aYMHdPVXEAmz50Si_5+ZZyRD7=A5mIb9^>K@vK8Eaz=6g;RrU>tLVP%-harpy= zpB%vTGvA9+pRsOnUeD2Q%RetSyRk~;H1YTQ{W|ldNU)a3ai0vkAA`JOGwYw{$ihV8 z9rW2sF-Sizmf;+>G<<7guz9e(pUx@8ZVdmE^~y&JG?P_$^V9Vp`H8ZY^7=SQIw`9= z+J18j1?W}~9-W73fb&MN5SbCUjd>Iw2&rQBj^XP=Qh3!$(+M3@+_{{9#uO71I(+|e z4I^EoE0w!UoefDyDt#H6Yw8023U~kWto|{ziEB|%GetbG1N#0b`fp$tz@*nVSgI;n zz^H_yTAl-YMa+-)_!%>=R?Ugx-)j44+`bHi^|UmV%(>qxnMPBQXD8ox^X_sQ084uQ2wW5cRy$pfV+YO5upON9WjLgU0RzIcH->; zjGW&GNo5qw+Mr>@Q)*?iy;YWw`}K(Q=pr+-Joxi@K*O- z2j5TdE`>4tIn!LeOu;?=^C#M*Q0<*&c7IK4sbDbmAbu_)=+-zofrQYGiABX3zT@sq z0pXg$auUSuo9<2Yi$YuT&FOjgykJ?>JP;8B+LiXU4ybGh#D@D^U8&z1k1N2g0j;ik zAg43%4YMaCOA=#s@}rh?){B@d#?rk5isTAo1~d~R0fK$fR7o<2Z4)A??d(2CsVU0h zyXhOeho_UqE<4ASop^RmK6RdY;qHv`{r!`FCKupEqCx(+`UCp`iIY}FCSTJr9pcio z8^)8rbi{TLi63A}ik1gt3_*%4`%3nNLwg8Z82!Q1r004bX*%8h~alVlqmY&nUqzv3RJLk2YQ zV@(i*yV$;5>x=p&k2s>w5Jy$U8{CaZ9F)mhu;nWhgJ<09i$-hkj>FSdd(Ewu{ErsE zMF!rjg_8eg{iMWaq5)a?4Pk8p6Z;)UZ}byH_r9M~3&KO{0koUx&G(02UWU-C?j??S zPnwURz#2YVV<=x|)?@&P@^e)|e-o>z{@}3?*CR&5W9P_Tg%Q!sfT!1d;am{bxqr*x z1MB-r${d$!ssoZJ^nJb0cGNV%{dp0GmM(et8&_xSx&h8x&|(>RGTCgfs7StV$tisg zuqNG?VY~?syzrk$V+Lt^ zKMsp)z&?^cU{@Yak8#aEEj4iw-21`dE@f06mw42j^~3S9h76ap#eRg&n4}MVAC1 zw*=>#nfR?msE-d-CCWSo?^H-W zDP~weWuyuEF$k6-n4ETxa5MbO*9Y{n$vbEVBdI1{-_J?wTFb zpx1_Ww^?~7EPA6N-D6Fmu5`*hT`VAw!xfaUEX8%l4T`U2l9hy0R0Ou@S`y~|S3w;b zni=7KsO-b&;E|L5d^7@d7MX%`^!J|}M}X+H#X*wxkg^PG%Edp-d^k@mNUHj1Jlp)3YBEdER2VN6pxjOQ4`N-ehOY|5Ya zy0;>TBzhHNOb8hZ<`yr=k2?O_SG`sD8Y4InfL)(Yv*eP-t83T zcxN$mFWH_HDuoOk%|B-(6zm1yj$N>K-EDfY1T0aF)=9zKM*+$`%~eRa9(TytBxA;a zNN$+iD0Ami8lH;G(c$)#5=eBG6~ryC$^{VgHmNF5CW{^*>yt$*J}aZURVETH7o>M& z;}pHoXvS?B>vTz*O%Q85LE$Ez7BBd^m0%@}!3b?_qIsknqcY9g5E(#+*sEe3H(Rkw zT5;0WZmq8!{N*iQv)9mj#c!E)ZGq#$t)o5|hMCzJTS8_YLE3C7x)Um2k0jEXaR}=x zjhrC?fvOr`6isrkdX*$l=c}Ui-rE0DWU>&m6FE=FZ_yr+M6BY{xwf-u<3cZ}3-%Yi z3s^`1c9?|jS7JQ91F9*+*RtuLw*TywL?JDXSAQ2(O{pR=`4t2CeL2=2DAR*Gh~3$o z(#A~fWt?o;Y4nCg>3_{39Pgg=l&C|Q@-nI|<<}>ZDM9q%B*R28Yn?akd?!3zWzROT zb6?8o+YOiO1q{uXw?M_k6G5_Mp)ic_islW-UI zKD)&7rJ<%hpH-$5`p5BurB&dJFX>*%jCoXg8pDGW#_j2Tpn^47ONwa&62(Y+ARg+f zn7`kaPTW|0D&g616kZTmCEWV4(Z>DA>J$DU&?DV{cJeecr$~V2opUp8>iey;I@fIi zdyGayR5&UuVhG!8aKg@IYZHT{R`YQ6ksEe?V&f!+baQrF7(6sFN#d;*UDOiKAC4l#nrW$DzM*n((zQ-Nsfu0?s?KP7O=Sn z->Ph{l^^RbD^|tc2Dp9Lu=>H=*ZuY!W!V97JspjBIvI)#B}RI*ACtPY8vWs@<-;LV zB@-tU@P3ceWc3&59|SGP-A*=@(s~ zABeaB@|QXP1Kj1V3qa}yX1D919MGHj)@rC5vy4Y2$bqBGhEPdQCY0}CV4@6ltweUo z<;+7OGU5F`$WZ)_&QC>=6rlpjf4xujjGPUC?xUT(8R70k8*iY_o%*CsOhm9mO_=*O zVtkKEwYP;VD}&&c1WtOAHOG~JfAwCZH$WVVvouiAr3ph%a{bK$HrNengpUbGzBkY&iv8IQD^*1~}(S*U5Sq3SH#FtvVd4yzH(< z2^YR2kBPDqb%8nr5Y;7-&4#)Z_pXy07M~onn40wVh4Rig{}>gx7Skrjt@5r5fJN^M zWVE*!ZB*6ep10&?0GELa!Zi{3>Xvw@sIwSS$HC?(q16ZtjXrNy9WOc zu|Y`aCkmk0dfhZO$cmebPmoQR!S?$+%GJwXINz_?_t~l@QoT_*d^4DLC;y<_;e$h8 zP-&Nb9j1q$qFfXia>P!dT(5o+L>uPJOlvd5v)ba%;Sm54DV_wB-F({cJz$}H;nD)8 z>3yylIhh6A8!VvlXM64%P!M$Pn{;?ZAaubg)zdOybz;nAovZ8r;#x?3#052fh}xonoCE_+6yT8 z5g*Lnt~j}W`5eIrUdfqAD(ln;<*RCSvUnBPeZZSErTna(6QE-|E!r%2Sp)B&@jQ_Q z)?WS+a^(xJ@0yWcphmskXWSM4M8T7(;D;kLgbS13$9Q_Weu&)KRAn~AK3Z6*Xqg%q z^|C*SrIXgTA&L6H^_c{5EHY9kd#i%SRXgQT z&)LCId8yD!#}6bVBt$G3*R-%+Z?#8IrHaK`u-#yO;7`ZMi)9m%&&}DIkS#xPz`}ii z-rN?ir|iguBpi^3b3k&+@Ti}qZ(bq-uxm526Cc=_js2Ee)TILI_uryT^0eyCAW%t_qf*=0 zqLi{{%x=2gv3i3X<>NQLgW42gN=ai6p>qAQR+TLONBUYOAMRN1xg@atQ7U(VUQ8VZ zUB(s8GFmOO7=RTs^ya~{)vLlA>^BCv{gzazL|Ui$Fc|1+&10-<2&zvD*H|p8(BdDj z1o<)FXH>x$1ro5HPBt3}ej=zP?82zeMs&JTEiaA0krWU8j@^H|R;ECLy5|C6Ud0pQ zWs6$yc61I(90^}u&Fcj5s<=HIvp}zwC0~#kep@D_j?Gr=cZDQJL)UX~YUFo+z;I{}y?>^inpUGGU6N zLE#h+o}R~28Ka&?;F)lGDEyrN{UR@6X7bknZmos3eg^d6IXMNqLy6#I4Cz;W&V_&g zpFUYX4Kg654h(VLE@MrUI_TqQ=xi3RR&t)JH*|!79axT5t+7AxO4AMg38|x!enQ8= zQa;@X1ik&VxJ^7BXE=*jjS)*2`yGV6Imx1}FnGqi<4p+=+gcz$Jg<_ap`5HRMN}81 z({T}$Qf&A!2z_2by&8#hS+rstcum;x`N{yTuwvcVk$B{2>ZKQKnD?yEZUqjvGEAFl z&iwRv+bFLsHI!mwpSZW@DGWP4Mn*=+YE?SP7bso|L}C}(UXI_!E8 zWrlZ;QCLZvl0|Geb@owEJo3SmNkR1bwVlXONjTlJy51N`0F^g&qSyn7+}F2}fxQ6N zfj%Cbk|~poCMorG2anZ9g~by4JNTJ`Xf~OI&aLK!!bbclBMY=zLS@ln!RAY!Cpk$fjS^P9nCm`|ZUz8CmyYGVDV7l}T zX(r2S&@V4*LRRcO2<`EYF zCl8DS(tE&p7#!M-t3X+eg~$=RnSZXA0sEPjfz}M{XaFEy|4m2}=#P0w8G)X%ewo!jYaL1jr?TXLHIE}o3Fj62 zf>D!*AF)z-lYDh1{aSgW(vqZN% zLs>tec>*XSQzC__B;)D?dD!i4VWDC?buOG6JVm6|(>2JFQxuvUHvTIPIM0+f3MP_! z1s}ACGl#q*`HUuUZ4-T zSU!`XmVC8^4pe|^WDuoEy94mwA@URbnVpC}P?AcbV19?AYw-e#%5iFG+lXKz=Yt>g zTjUMst%Eyfm1fHDR}V#8;e~nU3yL#|>iEXS2$-A}N%m&j_dEy6zva$x@WxnYXHc-D z3ISCEfIzLY&~o1UUP*=BZ#qkeSjj;D^|9g*m<7~F(!A=LXOih=wN{Xdc1|)2t@Q!F z!=?mHl)7Mg?x)k5FrK!F7E4mNA18_LKXYzNi1}DA{%+Z^BTmaLV*Kv-p)adTgK~+l zyAOfo(X9$gxhK#mOG_QnfF-sn`!Eq2vV!=wdq1dY*Q)mS-l&8WLIefH*l_2@973Ag z%$;R)H%Vud@lyuoof0eo7Hh2E1}&^SnytR ziyr?q2h+(4Tciqi__YQXe0+zU=o+)6Cn zqiEXx4|!?ON4_u7pZ&jz;y~sMiPxu<0*kfl+9UrWx?|{vSLUvi?PNCIG3hv%3g{^v zlIV*_0~+<53RZ~@co93U!9IM`EmyuD!iw^&`70`b0n?{%&WA+KfD+Y`aXf>VN!0mY zCd32DYO{-dqT*`L+2sL%M@hj{hG+-5@6Dz*A(MofQHfx_TLJz$&W~k0Y6sCSYS4dR zUSpH;H5wXD|NQ!Rqtp`7kc=b_J&0?6HqTSarb0JwN7{9*0+1Ddt6Z zsP304ZLrk&yi_4)g$lgR5)FgwDI5-;vr-=f6x66p$3e)(@0*(1Iibl0g5#f<(Z2CI zSL9eG_U0hu%_P4#kc?>p8B<$OZf)Lj>L0P?^xab^GI*=l6Ml3vvL3EuPO}=ny=>{M zRdgtBf^WppWJ@HS{_ECmm1r;d(}qlgBaJq;Mn*m+eVjc_Fx7)BM_g{3<`KAH8wS%a z(>whj@kbXpT~%Bx71e)x&W&iSDW>5PpH2r2|Sdl)Stfs@~}5O1rHEX z1IL!X&d4~e{u;38TFyV$&z6ho23NS#Xk;=_%CDak7fi?ght&Qq^)IS$cV4GNnSI6f z>J_)An@K|Dv|hTQ)HN%CP$1ammCBJS2+0({WnU_Dd_`;X)Rs-*A@NhT2cp%liqOX5 z1*_&}?TD-`4!juqs%w09pxHn2sp=LJ#eOKY`T=!DMbL%}{iZi&$Y%o{NDHZ!eg3>$ z^pFZl(O2Zz(!@QCgY;v4?rSHSXCx{Z+pYe*m{1+pHDM~O_f2mqc&P-t$Uv_7_IV%R)k55#C^i|U1idNz)Cak z2EIlBDcr4`!O3`juwTvkMJ0ol8;AkA#b1w$gFneGXc_yo!LZWEb>ng~{LBsznot0) z9JxV}6NsmO2W>Y-gt_(DRF{B?6(wH$|46@WK=D=!_`t1ReFUxVrQJI2nGwCXe~UPrs3pU)d5Nqc_O^DmN^l zw>a9`!|Zx!L_4o@6vNrr$d)k$53oB ztcaGU-vP#IA-kH}Wuz8q9^_w&=B zCCXbtd}E0oX0JySBW?9ZQiA9qj~@~7!*lYDeUr;;A+%-zqDm^1{4x^>b3rm-XXYvL zRN(WA4=USOZvU+4kdJCfvWR$B1kQ+mNL(?X_(KM`Wt@qfzX;TX3+G^91nKUvsbG?Q z+MtVtAZ>u$;?>!`qT0U$IAgNk>4d4{g)IW%9^;0GCh;ot+kUVg@;_ag;xiTk`}Vhwh$L6n6#eqO9$vm-w~a-YD5sL6bVb=a z9gS0^IL$r!Yw$w@tNfzm>z|?nv2yCRn?N}{AfKU`f(9CxjM2&Si)TOO_9>t=tx2N!nw<0qPVy#W7yHwEz4A7|_Sj>S^)S z804(i+1>cYK2V5K~vuhn` z#$_fuspjI6+%XYfm5-#5@r#k#-CKQ+`*lA?#%rlVTOBcV+THmwd3G&*=hskoZiH6(ebc1 zF1Xy@KES^6IukRAkz^Mj+z!apNt6h1XcQ8$j~sxp+yd^%dk?Z~xGYb%oT62_krtBF9*wMRmys{5+X z88pbz`65<5R-JBCbc)eB>Z>*|$(Tm~hQLnU zT#sF3Q?H^e`+o*{L-V@LX1}nnTBYaHy5abG5o+8HH$o^|dq_wsHID8!Na%Ct^?2V6 z7z}j3{k43<>P5fX=DRFoXxG{N6CG%>WxrrZJybLphV5aK+^UjI!Yf*-XMUKk(MqzW zwLavhuf0`|;DDX2IV$uEwdMZHRHzBrZn2i5%gIQjYUIKu!S01K?j_P%?S^m#KpCye zah)hU1G*ITTW{CXvv1H_B=N&3mS`^H5umh1XHQ;FK)GfXwV{NxahZ|T@ zK*W!Hu<1A|;j-ch19o}%x-u$-d;}akYE}EWfDE`!{CdLYPq*j!Yc@0U{^xKz@b5B( zK%--Cl#-1|qd3!`<<;6qfsAvd3L>XTu__a%h(jo*?AVE|!N-|>d&FiXq@Ja9i;=pb)mvgUv;sNF0_7^Ip z9vPR=Cj+CwM~0#~oae-Y{l6Sq>;I8M`@NNId5%lVv#!o{Xww^CFG#Ov8Ep1yv%)tp z^h{BP;TPV~=$>AwgQ9<|rigX!Xv2EKesaR}#fUjxc>6A5Y93v=kWb@dkxu_M(+U7! zudzvEU=yG{O?63eKK8Ed95xIIcs@$VEm)pvl(5YhbYtyP)^b&$TaGG(#<6N~pU@(( zk>knoI*ftTBgFIjB1|)x0U4MzTGN+6^tSU=?}6c@Y-jlFGt=i#2LXrC+1Yu<5Bz}Z z?0j3(pSire9Ox4hgFrzUe9m)C*S7GmOgHbR`s^Obo1Cm}zneNA^qBdG8@nwZ(e-P; z+}FrDa209M2^PG#mrj)SpJ(Ki~rbZ9AXa?qG>@m!e{vsYfv zXM)!+rfYwWS+QEjJLr9i18}z84|AjmD9cjQy{h9Sl3`Pf5Kwr%&shCBIrFkm0kZL7 z@R;vXpdWDjo<*F?iDVGr28~hRs%XF(BHv1o5Gz9$xVPuDtC$}fM~07Kz*ZA9!4%jR z1lsX^7vpG8LG!flSA}pXJ(07nB4k*qkR{h*v7OeLkHEvqmCs3?E+pXlnqbA8SK@Z% z{moTzze9rKg@h-tN3KY8)JXS z_!GCLaaCOYp5^YNY}m}$@fB$Ah_%1OCf0?u(HzrGrLZ6-p?68IWs=;o2b1Ah-poXN z@A3*e^JkScS@SfCs-uW0~xnNQyPu_@>Vfii4>p!e6N0UoV0xM=n6d{ zGN^9VXGDBSO;grqom>jmWHpV+R&$`w^Rj{Je{8LL#CA%nzGtg#hfksa8jl%gw_7`TR;DMRMc^No}*j3igFveBxJK0wEQ&$ZgqH)UW3o zHB!=Up0nE_{SX*fA5LNzd2k=0UoWs>x2v=PeUU@~*aS76{0yZeP(!j}K9O9%q%`+e z1I_aZwIXM*YwR=*N||5*dB5yF;VgF+pJ&86R82d1;g4{Wimg`eeR=)(qz3)yS5^EF zXcJu4@~p9c@VXQ<4<5VxWu#GeWNt<>d)40iN=WC(JI87Hs_zqG{H<(bb?Mb~-ES{* zjODJm5Z_e{74V*=xqc{&Wcp^g0ps@>Af7MieXkXOzV7j?u`b4$OWY|vo+55!qPFmllnn8n-0R8?5{oW5v&-;mMe^`O>ayDeZSmNp{M-KHBO)x!@Q~^X z26uAo@mAq(j8CD+gKs2rZfQ9WRW!`9%cclObXavjRD~Cs$y=z$=m|RB2Mw|%4-aOE zzaOknO9p6SeJt@B1|pBm7_4~=aQghZ3uZf%!5;)3jh3Sl0wpR#lY%GDXwWd1ggI%1 z9Qab-?iXb6^exTnxVXgFVE*QUzU=8S(*C&3u5W@^ON7`fjSzuHPE4VZ~oFE(7kAmi7}gfJ3?NPcr&_LbVE= zBnmkjrM@Y?*v)DwmZwM(ZGZ}2pl1AgVp$j1ZA!i5_cAT1r0=D_UB8kzQy(NrVNE7b zX;@4oL7*@nsMg{oIsKeN?wh~_{V~ja7{+7SXszQpnZTSLeq*6h#Ron|7QwCk611u? z`=;;6MCd>03~N&%)wc*pK{UrLM!ld8(1P<-cset=L&}ua&6oL(vNJEBE|(M&8Kk&4 zorRT`Kq;$7UiwM%c)kTik~g@ax?zAaR<*F@U=k4$-H|85zkj&)x3A zT{?Dg+PM!z4eY&VApDX$kQ0pp31;t5&ix|T z`RE;J&1p_!+B`7XcjSFkJWRQY@8UbFnr?^~m7BvT7+E+9WnWT(aU&e<&;||WqXa~u zl~mz=r@taZd*i=-)n5B!2#w&%gA=N+e>VtI9~eppV?>Ly>GXe(HE8UWD^eR3546CD zRs@NE(J{Fz@L9O-I3D!YqR?wo@r?8OD1O_?udr*MScjAM{EU50k{eftwd=I3?;PD1 zJR;ZQiVwziW-bEE745GUbW0_1u~20-Uke;h^WTfk6?AN)%htzK(jXS$1-row~bs@7zNiJI>Y0kaI390=WLeBh>f zZ2*9z5qV8j)~SPiFm~4-oCc_OW!1&8k6ivvAtOnezZ%aA;%dCdhl25t#*sajJezrq z&0-mJFCMK>FT$maB`Q*vD=x1^@t53l)eGLLKZl+$Ee7e101eKg;P>UI_9(dCp};K> zY{75z#e&`7y_)gGQX$uSe&Q}KPj*=kP1!BL6X5b6(HxZBf%gyS5uizz{$?;uHsgA) zeKK8%twx10?BE4N5wSCo+17H~u93f>pm;R0NV$is8+A$+EN?pX{*aP*Z}@)gJ##tS z`GZ1&#t70vzhwLX zyr|Qu?42`(FMZ;Lsm0QJraE6?)Jb$;Td&W%fKVS|P^DT1JNn&$R4vs`-z@1u0at-+5#C zM!%rck`ITPNFQ8}audDjt}jlcou1)7Mu#~OR!olZCy>^#+mGpW;FdYcD`9aEZpLH0 zRLgwL)7d+g^OGa_6?l$3I~EtPP4vN3#k&4=cZI-<)x?da&4>2 zg2l~736dr`X>vUl*f#qFx|}!|ZGu9xdz(<~$wAOYJqdyHuHLE0_x7R-tZ(yI41a?Cm zarzW&D_%ZUBe)`#g2r8|JKtJZX#o4&Nr{mXF2t=wJwkp-AQgt?-x`V)1L4aFghChv zd>6;KG^}_tmchgtE!FyES-B~&MhedrZC@TXIJq=&zGdO%eJCy9*B-8;Nn-A`!8CC*C&kUaO7==f~1&BA*gqa)mwQmQGF>C)G< z2RL!c=%cB@@eS6}ZF)T)A>;mNFXMT%1ZDkiACiF^TM*qTW_viF`ES9=t4FpS#zZ-o z0kQM#ENR7-&)#My<<;n2o~u<1za>CizW9A{fYa!Ozn0a30KXeJJ8BME4~N@=Pou_w zPDiiDjU)=4*2?|N=Hh;uU>!K7WLjg%9;lNTm&Zjh?lMUh=SMD2N({UzwW5W7gTGpm z9^+1SP(fSD#%|?i>LM?lei!8w7~&!wZ>}<_34tzzx-s@{S5yqy>Zb96j~XiYW(`t2 zXBT@j@pQZ-E~dOJFvALAo?hvjryn{a2+{yukNmH<-DJSZH9> zb%(D^6gzB|uv~wI0|>emEBqQC7JEtI(CqVGx04f-B+-{N&jJ$>D2V@yH{#Azqep2w zH)zGnNLOp}2c0v!^jm&`cHp@5oRbh`Fi7S^xPj?VL}!6I#_N&3Edqg$`wwsDCD(Dt=f62ke<$l>gFa&YU*Ua1zrP?*mu0`;U_KzE4p`6Q;L|t*I%84z3H$>avzrlGP2|Q~?IZ)b}2<-0>%2?2J zK>g~=RhFyz4w&e()D13_mpq9S7^cAK*j4YzD=TJWi*(y-l0ESW8+Z9|`$odZs?tB- z$sD<%s!h0n%EZ8_b0oLftQLI@LvTipL?W+N>aa7eaT{li!vqT+r;tlc>r4`0r`+R$I@0x#WdE0wG>mPrW5jD>8g<-bo_gz!prR}+zIJ> z4k776#}f8l)6U%yvqHx|M)xrm=#2<9qLJDwY4LJReKQgXFU;`aCCHL(KnP1CHB^H^g{1i=d z+z=^c8kO$Vb4L3Q`q}v0QD9%&)UduYc5&^W29GbK!kv+kjWF#6Z zBc+Mqn7j~kI*rIG8+AI<`L?+T8S?#jW=gDy){GdS7qjNrE*IABW^BL=oK78PSPNBl z{etkqwr%N;bPZ=01rB&&zsqoeu@3^;|9(|7pHWzUya zk2%$mG&J86^kMdVrTq9|MOTF|gL`AQOETO3d5N~7T)To_2iacFa--EOrob;upgc%> z6&~qz>&>}UGWO%gu^LxbQ!jQG^H?$XZJNYmrl^(CezHajF{fa59uu@RW1pB;fke^$ z$V7-s({JVbjiQdFp%=XPy8Vc0oX|5h68O)YB?OEO#eU;?%T_a}^m{b1>XPr-BY~8* z?m5;iS_RoSP9{S_$-cU^7qio@ShxV3MyK%A?c`w9doVUi0%%bYAWAv#ikJAngdSL% zuW_^|qKmL`$4PP?SQY18l74-N8fu7s1IwF%XKVXmIilr9SUbot3jz{&)Qhkf`hpAF z)u2W0OuXs)AR&bFzB~Bq$J`Cgb>k?LCKny;T+f@F4pqyGVz$7!Ea*lWVWXo<;qYFNQCoG9_V_# zZW>%uTB?d^iT?#$fzGG{bYaU@Am2K>?PJnVQG(7(&gcr~7lwIb2Bf2|FcBblg+CAq z;>j#pzW)~1GAcaOejz#hFKZRgBaaA-+g3PUBFx`(!2$o%Mw9c4p~1WCv=gEA-+(%) z(s|(u@8L9xj=q0bMdz3#!n_o%kT|rqqdHf6U z@CY|sKp&)UEm(D|{Q)wR>&u!|qMkX=v^D`C^rE!&6FPyLgZ0U5eA>6W<$D!68*a(h z_ikcLUF3R6-{|q_$J4ds4=L;H?YWZEXq4oE!cb4n)f1A>XTtM`(nQKiGLR8fSlc5p zgn&XXPuwI&o{6kxsy817!{%n7R!w(@4?BT(HZIxeq6Fl+~dA8X2(LFB>g%yaxJ+ z&b%DhHJYqUyjaMtg6%m$=cmEMEp>iLamki{3wgB-xGXsJeU!WUPFBVPp3>KAM=7v*EW z*~bB;LWK0pgq@#=z-)VU1o>=xcb&j-n}Qe+XLtEdODuf*N?s`qMnZ_*Fr`3=JvyIk zzcb0FASV9i=lw%8OM_t&W2sEHLjo459Z@mU-h^iMH-qPihXS23{}J$Mhn)$Ra__%A zNPzFv>sm&E%EyV|k5J$v{i*~S$dT(qbf$P}VeC>1rIMq3Ku}|T`XpHG>z>*E)EmvV z(KHnV)h51;>6>%?K?^m7NFd9~ZZPW+{GE3hHSqG}1=k&q4U%b129qg_F=rhv{@!Y? zu)Gt6R`-#gfUQmb+Mbnh|>owAu!XvwQ@G54z4}#5zX14(yUiWV%_U z4aIAMk!V9=Z4g+gY)4CX=q#!}6BJ|YMHa*3%{drN!8Pstq5v&)SoJaBDr82PGIJGM z&2|r;vmLQx!sb*hv zyq^IqK)JD?k_nBdkL#+LP*=-BtHgoVk4#;!!;{FO5e1|Bwn%7rc=RD}w~Lr*f{lzy zlcZd_0F;DHxcL&0NAaTbN|G&V_0&lnaq!nSU!-O_dnn~a#nwyB?6Dii<@wGg?=%9q=%_*6 zi++NBD5}4`#w!WD4ynCbE+0`}VkGtBDZfLEO;p&s6(ML$JIw}sNLQ=O~ z=H2VY$g41mAcoaU)!|M!c=E6K2@OXOV8A4=_s6~78Dd|(5fDsZ@lXyEgY07S8Vr7N zkmA-}?+hGIMne_`3EbR#N{`r5P5XGR$DF&{b6eyR^au0#%8wMiQQ&RQ2q5F21=rln zLZSo(1qp$O*IUbu%CgIXnoVRv0Ox|&Lu-5Hxe@{VXSPPm(biz3QKESlM$J^RL2qGB z!m#H)g+yNEOQr2BZ(eYp5AiNoztKQ59j*yh;H1&wbvUU zoZ$UMb(z{S5S?B+41O%Uyu56`pRmH<&&w2}M=^xK69>V4 zLK@*g@gPXV)RR<`tRBM-3<(ANPaQWj?Z0seO3#`g+W=Xwku@u5dW2ey@uZ53VY-+Yr49JtpCPqX^8^k!Ksp8!~3*n#7OU9ojx@R)T z#@^Gr<6Zy`>Go1MrVJGYEhg8-ACe-%JAc9d!K z{*2pfQ8$ogt9!=R7~Vvb6W&&D60xsQ7hxycL&bM@Kg`FYwpZm(v%+bDTstMob397h<2~7UY!AgA zaCAu<^oDmvI`mt7C+6wpD&Cy?qSpCe4u??G_rbIO0W#0qy)dK&n>T&2Ov2 z*?E8JL{3#M-IS#%lIxUF^Yl}&&@Smn-wbCfX+u|W^A4aBLWV&$y7hgb%^`zL-uAjX z7#?&kN+9*RRq|;C4)k=pTvkol2kB|D&S5qI7@^bt5?t&!1%0~gEYM*f*xl-urDD;Q z&S6@i`1hVdR?t$Q{A?j+J-`S5!;9}N(ARFtk2YPdPmGzI)*;|9K!J3vQLuO|@EVnb zn|0NzsGrs6y8)&y4ravd2-c{9U$`K-C9WYs>m1o$M2^;w#1n+ML|I_k4B!hNwQp7z zpFN3UW2PP+&fESU>u?tvEe$O;ZR7Tv0m9(e=Ju|L?;iFO)RkRsf0`Gzo4!Le*oojC zMjbsR%~j7;c_(h8BY3R>cL*$yp!3K6hmYaGXf8qqD|fiG&-?lV9+$@_XoLBL46BGf zGLwT|7Gmb1;rfqr($nb-ZUl_+)cSG)ZE4_(J^P^~fWKb(TplL=-#aWsdJTrMV{{T7 z?->OYP%oaEN#eeG@7bZW7Rc*4qYEm(yX@4E4zw;7WRfSnHY9P{%VnDG@Iyvb@L^0A z0~_P0uh$zt+R9L73CE{r6TqTB=?B3C1M4LQ$|ndcBt2x*Zu&)4dgKD49dqX(*kulv z9Vak0kavXQnWRufjpS8GiQYk-!teK&)^FMyxc1)H3k21M2V1r#bpGv(nW)iJ2Z9p; zw}jhSUoL@@%VOLO%GxW#8yRq$#0bI30|~vRL(e1sd*lAqg}x-AnF9$MPjDI~2X8ca zRKH!$Jl#|4~>+5A;* z(y$Gj#bkANeW-B09 z2tAH%x*LsBO9EU)Y7@REvzh4um_hwP3`0xV&a!2bp~W!4L4$hw8Bg=X6eQ9J#XtRhDf}LO_7M-( zMTb$(yWWK7F@OD>0kx!@DUtpk*Ya;Ap4Whe_hFd_(jM@i$l~AH{M*9+_@4h-s{i$8 zM9M!yRmsI%qxpaJ{r~^@|Ih3B|E2ZmbBycDYIStpA7a>pBr#t^Q_=Jt0LJJ|g{ zoShLI=;!C>p5Gp1w<@`GHa2^uCcD+qMW=^WhaClQsAb6cS_7&4soL{?ydeCz*7`4Q zOTr``u859l99CkR#ouXB6MX;s=mmbE0lm;?fD7rN@w+d0Ztq)+2T?Dv8A zr|%o$yY#j#OVO8g{rQ*c(VQvO4v!1Gfww0B$+bT_gIcwt*k88>XlZPq!iK&3cUZ5& zNjF!C0qOJpg5W*#^4!Ey9t49Ck5Gm0kXQpNwcFP(uK8SRb442@GAXlplE4v~p?*o^ zb*+lGZ~ElDb0~rVJK>%%MPvqhfZj>vPC>7ztq(}p+jpS8a^ZHh4%<+lzaMmPVTI~nt@e`WT@@FYX-y9S9ZPCnBXryd&-n}J%MF6;DwzBJpg;({6AU%_e~0Mm`ES4 zvsk`JJ%i_kUxc~9RbtWYf+l5l9f-ri?s|;0x;YpQYOT;cm&BG`%$%cdZuv$RX&P-2vR@{ z=3XjM7At|`y-qLRg#GT4YE!KHY`*MQRmhEzB&j44pI6!v!Y9g-?FQ0=qdJ2FmFYyb z03@wy(T}(TmH+qt_`gYU=M(9xOinsau6nlTz>tHjgiU^)Obo~2XSb=0IDtbrG-}P+ zilso=IIpodcU(mkNv%`A;4gx97fZ&Q_G^0I^ow7aRz9>JGCaH`1OS$uzt z@L0j~>@1KqgndkP<9Hnl6-pQWTy>31=hl?ZHeoOvj*3+756*F&C6kUJ`AQvVF{K8( zbK}6QJoP%EGZ1S0Y{azyJ;(a${enPMxSA4Cl|}u#Kyu|5#QVZKDhjtthyobLs% zQtR7!+irLSyFUF}Li2LPGZRe4-$x>PIi_~O=JOVtZvkwhV^u(G`@^Dz10Fd3QDa% z-rd`w!P98ab3t!ch$p88g#z?4KBto~lYprAFn2+ds_l6Ny7#{d_{Pw%)C-wR{b^Gpw zGb*b`&7m320S%FxsgY+f&a~{J<^F8`Fog&vw2@R>p5kTN@4nMbKHG-VneSXSTi@<#+FiypEq`;O!)@1F<0q(f0RyDtrQ>p%E&bkgK|Ig#6X6g7-muf=p^w%{y zwX+8ixr-^PR^qh4e?bwGnvVbI7*$Q_K^;6h$pLn}{o^9`|G}@yAAbDoLNy~5o#}g6 zz69s_p~+4>7>3;xlK9Ky1BTrGehMRZ8DAJ&VjF-1|C0%-jT#yAs%_8u?{lN}lW=xZ zjV{bPZ}qi?(%m-{81p6@aZ67v;I2gnaV2N@u>#y{HcLy%V)94|)qeutQP9?OT35L4 zkIe3YnO+eCTgG;_NDechv$kv2-Hj=8EG{%1r5N2Y_qFR2dh=9Q|EZ7u9$%@TF?|v) zqf{G7SP)3%56MjHr;WO2OiwS$1MQ^8xI=5U^@Z0~tG3c?B+8{$zDu+Xr_<>0Fzn#? z&o3T@rcR^&*6B-urI~H_`1`yveKk}svjHCB*K;f!B#8g*9{o>5i@Sp_KAR)Vz+`#O zd8-0N6d-H##tRZTm!KE|0&k;_!LL8(4iW@FaKWxjk#DTK`w0uNxfcK0{_TYSzWdK= z*b^q2ujA>QAuy`)U>Dn2;AC%dX!oKKHiU22i$V@9lL!Oa@s!ic!K10k6%?kT<}gVGLoAn`Qez=8c&Ewfy^8y$VQ`QIZC#`0(! zmD*vDwbRVZ?n;YWc}augEIxjm}O;d--mprAmzwyruhxGMecMe7p> zT1}d;&kHBoYxV2S5Wt5F);}h-L**~ukYr>>s5ly6zhBq+jiZCcRmG;5dnASd=2wO* zV}Sr~k`fhYfH}7LHVi{g)Fz)69a*seztWfivFFYN z*a$8{!;K}AqMTu~B-+ttatPiQM!G6!qKLbJnwS+^pZ6|?g6F~Qinvh9!tGWR;VNVf{F6Jb=x!5%!MekNu-;~pDa@49a>F*s*Z$W8 zKlrdDKdnzHANpPaOBr*g8h|axnhp$iY=d7)> zytu$}jJ@Vh{T_;_zOH!!$MW}MfDN(T%N6XK8h33>+76ZaT&s}xGR}veer#X^a6Q3U z_!eq5vCPnIHu<{P9VgYyGgo79)y;Uc&>V+#Fu~7H=C-Xol`qVV z$}X(N$%@*%s<$b7&Bas4_k~jW@kyR&D|g*ar7@_Z*L#IqN*X|D*-dc2ov*&_XXvo9 z<7c+k;unWiWc=I|Zx4DSq>x2}%^Eh*(0v?wKVETpq2k}}7}h2ha`m~Uj@}W1M$e`* z7X{g>Lf;q$yRIu}*JfA6+KMj;4V2Q`Jhh8@PY^7mba;0gElvTr?N0^YAO*?g+78Ur zilO4DLv5Rwi>n2DjBnGrA6Fo^x;{qY2hpJ&3dD$Tqy`!Q9Zd~*wf8BFYcJ^LrbM1S zGB1-gtbT%~)xq9eTHVJ;GDdmM-t#?<0ZT$(VTTVah0Ht5_K31$tL_OLQR|ng=7HwK z?^$}W!Q8`Y*F~Qf&xGkC6+c7sj0_@whTs7Ht<*{O1@8ZD@qi9ta;#41GbH(;4d;jg z)3#p+77Tq4X=fHBb&5OL<5A;q5v9m8%}QF8&AEHl^w4qvDo8#y7U8kd3C{AQcf4$`4+VvUH0g|tX5%|hh4EM}f`Z}HU zn%^vdbIi?~dAz{BleQ!n=M&cQR2Y= zMi{oSrkh6F5WQvm#54MM|95pSpId;qS>OFp%s<3t^@VxM&7+@E&V;*2CZO{3s%PD$ zfjQ27B!yJKW~(jIIw6VWwoXR^YZZQCU(n?G>fafe)@^IzFef5q!-F13colW9j0z|c!h%j zl<vmhOuaC~wj|JzNRhpD7az(0?;PgiI zXTREGSZw=rN=qJoP}+95UZZD2c9B63qDsr*9hui#PP5$QKkkth5KblK|NPcKhUx(J z0nle6L~_GXd2E-YR`tvme}$wxFIwPw|F|^O;mrx>b2tpa={OZ=c3uXJXit6h!;Ide zaO>>mBdbxGjG|D4mk|;48Kz2c-%bxF=<2##FwY>pN!9Jm3pE?W$116Jpo38Y( zhvaUzqOq9i5Y%K$<_6A}^=P!pGNh|DatTb7vJF+J7~tR5%QTz2O6F=lwsB8+2hPq! zMA%?Mw?eZz256VY)IA>`=*>JD2M|FgiD00j)0;rpv9#mUC{*VMx1;LHV!7}A`H z{<}}IetH7FW`tmiz({!YUWB;&gv;P~>_6mIFN&nW07PGtWp_CqCAE-B?Lt09l zDgN1FT)1H3>O&Jr`svol_Vl%s$Asq5;CFfLR64U-bogCZG{ye{X)x4 zr?~S{abf1lN2(zIKfGv06F*m*IqehVn_UTyicMos~>u+2Fx$1 z0qHrKPIt?Q$;jud^p~INa#Z5MwyqZUS7iq>|1Q1Q@Dq+bU_Y6jdAXWIr|enV^zah? zvIX~%cPKGH!5wk-gHxFAPx3ZkMqy6D z&``bGFDGYg$eba!CNOB%YNri0MBHS335+lK4()zfd&_D9oPF1$;&5WatvUQUl+=48 zVxusMoaNT=QLrlzA5h3-mP`~Go(2&Z32x|@Qn0&0fkus5CM)rBH7L$_7MF{7<#I^_H7gXn$`@19cT@cDWZaA4;*`StUiX+TBVVtJnYsR}kcsEM$B@1%Ag<~|{E z25txuhdEcd{+F!%dt7v_MWXDL*Ox$k!mii|0O8>_Ei`CPSsHoURi}n7c6xWuK$+6|o zs7do`yH{UU-izm>c2~;QO__JPIwtB97$&ek3Fv?QT_$foQ(eY%Dy$UKW87y+5svN))lriOpFqiQ_um>?9t& zaxkCbZD1gO9rafYM%!PG;I9;ihW3`<(yzW8f=y0-R4W5&1uUL^fR|Irg40Wh{)4i9 z9J6wXG*J?FropADHUh7P(_QZ&SOBUjU0!^P&G6*voZs=-c{&{}_V!?Jy@8P5I2Hn$ z|7&)+b4-Fp=ht;mLcPZ9N#j0z;PUGhN?t_I^8)!JLN9BzE}m44k$Czb8{P32#~=DGpChAv5i%KiZ`r5)7XohESR-gS^=ZW%tJd>w zHX3qz?^g2M#}pkcTa>p+52UsvO;K3!_zRIGMtTZc2b0Gwp{PSRcenk19a76#-T_6J z8u4npSyQ8?JA;#Y%bQ7oo@S*tOMSdax|kPd$r1#RpR{~ONgraGy2$}CRHQ&lBkdVZ zfsFV-SMguCF6kY2-6Fb=|C#V`UIdY3ulC0tqT|{&!H7duo)O%lkBW#LUm%kH5is|a zZ2i^R!2#6<(2eI0-{W`d#UYy>{b!%IlaWqL5w=A*mJ-_89&?8)xOUx3WOeJ_q$OD? zkAUIts(&e{fKF7^-Jb6VLZ8BI%wGMai2=xKWh>qY{{CHY#m@p>FEVth6{on|e3W8U z6XrF*1%(c3CFiCfHH6=TEln?V7v@=&O9t;<`4W--^5*g6LAva7c0P0um6%(s#jtc( z<5gB^4E=v6s1iQ|ps1*lVPJ2KQB6_cDpHn!tt{w!M(6n7=zu3gY9v~NHTFOdKI>_+c;gbg&E7RK47ojMOA%=vn=1*$l7AixC?+MaAcmxRbZgmrVW zCU*(R3h2>6xub^xVna;u2#Z8~D-H z&Rn{+N?E+m9b!Mp;T&yR@X&`fY0Yj6Xy;F#?-ee}O`E4$+}~lM2o}*7<%62dS9K0< zh##yfH7c>Q1m^D_?G=gwhhFw$2e)r?#3e0?V5)sFm{7+M~!q;a@uroTj$6 z!4R*#rAxk(nI?`SCJl<)Vgw%*SCug7r-|PX#E-rn|ByB$R{mt&)Y$-&Vu0mM7@m_15mcH_9xpIk=(V5v%>Wsl2EgELe z23=(8Ku{aofOz{Rdx@d7MC~cE1#EjL(Ji)SM-}sXX6u3-<((m zzCM{9pLHky>SL1oK`RBn6!2a4Spn#XHP&S~_fBm+&O_X@?(8N|weAMz-S~UE(>N?M`ia7&;F#wF&kc8VxD+)nS#3Cn6R{2fACA z8|%9ooId4xNvAE4GPEcB&z+hy)Q1=p19-HMD5yF;&Mxo*Sh=&2o0d0p=X{I~4f&m( zbtc4(<1*rlUAALp0ik>IG|qQ|SB363Sx~ioD=L~q`6;{!tBHC`mA)||<8uO#hRAsg z8#ZhQ$hgRpl4S_Fueu^QFNV5Y|0~d(i{+nSe0hq-&KQ2SfXJNJ4B!(&f3o6#@0b|T zc1N|Pa#l5y-$kw_YFW|5{cO;`MUz8u3)3>f=gGqvZJ-$@&{AcvSM|L%o(q64zdy*F zpy0$;aSoqNPP_-$b+2mK=~OV@2kKkd!yaS zQO%d6wg}BYX#A*<%Ug-M-=`(Nq_G+9_Fiu=BqyG60P4iTvT@OxT&?5?hb%sm{|-~` z37=%>(M$cV6bfG4<4#VL{?Sis$SV9RUSHs+dXzA(i9&6~9wlZZg)e=o&C>`JHiLS3 z6RVyv4z;PV{Z;OGqQUgfb#6^W0}dp^r+-3OLibIxGZyAw;&)Lo&LDpMNLUZI?l5ue zYGQmFZkir*tG72A={XForprCPH;((NkuouW7Uv8g0Jg+oP8bR`ikhw zba%}BkAGq-QyZPb;-}YUkb?H!Ug5aogfffe5M~0ss#bQh*D(|5ic7k?QX=OZ5TFkB zGqasF+HC2#c?id0uKhcy#qewzI8vrpiBP22zz=7!5!ATeWR_F^bA06GcvmV;_~Q50 z-vmS*gwrYv=CoC|=3}QgX?RRX*-q?35eo#gvZiD4x@i&>ZW>o-N)LaW%2)!*^FmQi zvf9epYqOl`OE1Dl<|mR;RR$5mV_M5-okGWY;gpi>mA$y9N;}{ArTocHCe0w@)^ozy zO_QqB*y0M#(sHVqR=ZiPQRQN7m|Wl#?uF)ARKKMYq);Gy@Qasd2AXS*A1uL2Tyb>d z14cdR*UjzKloNfSLF8lSu5at$v@|G}{2T0`lQ;3eh#x~)&pFGCpz$o_rW7jnO-6kx z_)n)owzF#<8MsFd#iE}29h-XCnTw-SIu%a&nUX_cC4T9 zaTio2lc8N@X*H#OocE6r#=`BfIq-7l_MZ;b%apt!k5ea2hwUQN0vLMP@4))^ z^F}+6>Ht3Fq;_%Z)$7~Z{>5x282!t*TBE7WYICEg{AcjV*-WD~r*JRL4V+gIJ-gac zs$ygCRkW9VYOK~}lpo()-9oU)dG%ta+KisJ43otFzCyLs8&zDpa&7hYDGdJz4tbx6 zB4-%3>WKby=Ocr6ECgD7TTiJuWV5K#jEzw_3ucE4n zI`jG$D6F*koM*=8z94k%`b#i?8+pToGmf|Ybwi(h`q60#L7l-Oe}1fN)mZfQ45Ve| zy;Dtyyhaz`6tUi$E-308&I}a5giE{cjZ{#`;iHW7gZ&p;OZx}Bm!TTvyuTpcuRFVh zp)jrwrD)LL42OM;0RNdjUbgDVK>0Y$w_oycue0xI$yWS!S^3q9NB*!HoalZwRu=p| zP<~lqpzi34ZARzuI*g0S%~CII(8U(CJVP>_zUD!r*%DL$ENIcC`p>GY>*=oFL@L|w z*Q9%xMLIhi8ovZ9HBl5llQ1f}hXKaE`{N7aS8?{h{9| z2U_E$!1C(4Yoa;XoA(IkR2w+&G&e4?3#5$pjk*G7fyVug1AqO-4pIeXK)mjr{pure zPcYMTyDt?yQwM(sv7-)t6SDQ>+GuM=!$D-OkEzqrrXjIiY?lNb-#kcsA<*5+JAT_3 zV^T;0ch>PJ*npUz-$**=Sy*kL@3$1f$)`M^S1ryrlq#Z!Z|l0IhnQ=}FY;P9#ZN*3 zWoK9RC=|PF(qeta3oADowHB2n&JPFZ6yQPm#gAr;rF+sU@>=iwsk^ta=lKu}>ZV17 zlKqZ}YyhOOTyk9*(=gYMZdDC68SJ?Kbx^0#Yov1?sZZl+`Se13|79T};G%`gDtS~p z4f=Pi#k9Ip8cF9BLMG4xc*}G-ADii$xE=bR?YcOU~#HttjIYUz!-SXAB0xGL;5K z$QRDW@u3C@M-UZdkIEqsu6hNu^&EH9LndjoImXX0`u%FRq84&rmymf*EnKv$8aG%0(83(JPA z{3y7g`s=bHN9F3`r$j0kXs&tG9|Zwdf1qj;R^HoGlwKd|hz(n51JLJMNzZ`0dT@*` zmkeklh~a9Ow*o&`%@h?1+I{S|SC>NJ5i!eRgnI%_xtw|_ueYSOV;wgH-j3j_%%P$z zQX@}WHH@yI`-DqyGjk=DC8B;aLoQrOmc);5>Io?oz-}xCPLHpA96^hm1UW~4&%QSM zm>XmUivLW*VfhE*GpcEp5#L@Nf34AnT8N3pIn6~zFJ5?V|DBD7vvkt9qXif|Kx<@h zqID_KMMN1D{s3m{GoXW}Zxiz-O7mfNcXIBUxK71!zri5c4<0eDi$|U(Px~1mX;>1F zv=9%{8EAJHM8REKTI*^m{!bVK$t}4-tngKM>3x^}YP%s_FB}-DCt0HcHT{`)6K!K1gLqE<8fz zP=(@{TuEG660;dCA}>;4|KZe_^t0%Rv6BYN#^3KG^^{qmhv+ z#!2DmewvY|PJ#CZ^c{FI+YJ#EpU4Ml4P!bvxZeYVb(T$Uc=%-ESS&Qzy{IZnUK{*iEYH!JhMYkU9trqf zauoRETP(l3?)$VE@{S(`!XB@~*zW>DQVv=O&x8-P0LWmOr;X0~d72(WY_X|JgYCL3 zL0VeDR*ebt-(!RuPW33S@utfYA+wT|2s4Px(OXDZRHMxy1=qI~!mR4f>%(!JfiNsY zFh)!kr^a;n*B|L@#co1n`u%kMf%4(D_lOmh7zmHGz%`IiRkOs5EED%%OVV6I8y%UO zy(qcIP~~;UX_I}nF=vuNJMPYT$YIVdU({2#dWp~n*tUt0&<61y%T!T3hb_=PWkXns zf+~ehOAp*xcVivv5Hk3}#i`0ds-U&C+E3H{M}69WAHNe&mKoFy#Nj@c3sF?9$5+Q# zKRTle)U?e23(j-SUxX9%)-xw~Y9}$SJNJyLn*Q_VIZp{5T=1LI6x!r53aa^;{J;BT zG9C!zMOrOqG%n&N!jn>{<&ZQ!VB`IZSYxpz z>c*Mp)_J3R_tNZ~wS3eTMW?Ju36tPT&^);Ao{A9&k4(6@`r_n-|C@4V(J9gx1;ocv z503WZMw#d)YBwqnHG&GU_$fb%`<9-|>6$ zM|}gQo&|(gmZd{ODF$yTtM{l4Qf8~>h2eXGqG*xC>h|aB?b>|w2;WW`w|tVo?^AM1 ztDP6>6c8}{N4N$0iB4#!CY6Y~3W@Pjn@P1v=V)CM( zX#_qq#aBMUqq}XXe4FOJN&B9-=~`v-gs6Vwfz%--H{J`6Q2WC3L&lZh9{>QuZSaJK zFf$6~@zBlsmhpmd$FE~el>a#i^8|i^hU0*UwE}#!ZjocQ@S)a*qfX&dZH*)~%Oz-x z-6q$Z`Uymja&5~_4@a?J=SqniO@||+qYO90Ov?JXVgO}nf0?eIe1<*Vh~`U(4c8!U9^PX>Od7wt5|v;_XL zRaai`<*}k~Ok>`zqu&^x=YnGF(M58~59OCs>>9giN7j6-E4n@Y@jpL(W{q!&8fCop z{N>@IKH`j_`f+{ai6U$<$`(@*m9(70IQ$mYaj2@C^TTq2(urYruvG0=terB(kk(Zi1tO))akq}a* zWN`o{H_AJw>4Hj8-!$@>MeD!UvqmnSgPjgQ4%<#~csUk(g9#93x)`ewM5gJRUCbdl z*EYSxOhWZT2;g{@#6}%&!WfW*A5H_|MJ2HB0X<%H?d{6)hB=8h zqHrVCAg_=!UHCQB880B}EL94THpjADrEObnTJ0*OQCo_PlljtDGVn4st$=u?KHC)i zdIH~ghnox@6nJpCWqu=O&mByAB?BMXLhUf>(24I>Q!jyy>PSpXe88-t0t!8()%uYm zBKNDr;APML>A^}5! zz{%x_Aij9LKbTmK(hS>ncaxt54Sr&?>xkrv5Sba#Ckd%SXS@N+bL~)_mfzQ7(oDe@ zijmB>{l8l42+vc%IgAG!F-L@-7FO=?$qltE2Ca%+lPwXg)`O6l>zS@Synpq}D~T0y z?gWDuc@Vd`vSXP{JsruB9U141tR*4eUnaFnw5wxFcs)-@*ljfQ%Trkj59xmr0KL4F zo8)Q108esxCm!st!xS}?U(8dSDgHOu>J9Th!%c^ifI5$B*utcwmO>)>e^rclCmS|% z4>;EkVrVJyJZuzTt--ApVsMlL$){h-4*aG$6CGFD%};9Zfsax)^$8-Sv0V14MeFsO zq^GD~waz_;OXw1F?zS(FYy`*r|FjKU^*nUamE$)OnA^LAp2*H^ba55o5n{9qU$6%}iGk z2Jtf`!Iret;y-4SPj6S{ZT7XY?L6K38NRzb-Gv%y#58evd|x72EoH>?*1jDGB@ zA&}1P-6%bV4yjs8?%^E=7G%i266$wIl8L(H)7IiJS%l`SqB`Y{+-ay65Y zpT(MAv^`SwaL!Vh&}DMUv#p1Y^-mr5TOVsb4)ANgYl6ELdA~f$-Ae^=Ui6*vWaeDU z+3V(9(6+1F-hp|8#j-L*G!ZM({b!Y>4piq0@<3E(yM#NK{E1bz&;!%{Br05$S)EN|f2{w+ z`2ikSWtgJ6YhQMg%p~qd#IxW@S}_%zGFH3p!x zu@EL7DI^!=p7$=A$+Zp_hloqSfRm%VKtWrFe$uS}ln-7ExQZ1JPItA)__^(u7sVDA zTi(L!rV~Wm)1JQa#V`aKTG*;N{3A$igs#2@11mo4YufjW=|WH^e$uM`5bo5)9GPE$ zRHFUVXTY)H4VudT6{0(dyMUW{mdv_Z$q2=3S>3*X8$r$N)V=&4n1qqQW^mUiinpEr zYkaYI&*>ldx%ef!j+Uj*CaX)Wv??5#{x?9}jMwhe!iKaN7@)af108qIEr0VZ?wjAo zA7{aMgZ?uQeGRbOz_Pzs)=7uBOLU3|-dUy^s{pw3(^0x?odB3IVU$`ip|K^K)+Y%c z*I}Kupw8OYTVKXQFWymLp1&OjKAQfya{JCt5*q>|Nj%>pYLz%_;R^3)lME@hO&-eF z<)cqM?MaoUJ=>X53C7=QY;bmJsDFY_YK9H}k6|{(is=uKQ%=ZkPe74p_MTsa#^e-S zr^EdOUZFLLSsK`p%6`*M3w#iW1P@Nv?&DTmx{&PcOvF**McfY44!yuvZg#gFx}NP; zo@gsu2sYz^;Kco6k+kRv*>2xujU^H+jdD}o4B>RF06u4> zwy|gz4zuppYJMlk4Rnc|yPg8MDNn=hM7pHm3iEj6wlQ&|Kst{5*Tx`WQ>8aAisk

_?TjrrOERk)p}kX1&>xb0e3PC6sL+b$D6nvt~y$p zP_H&g3*wOQ5c(yjyC7>EmWh;&-p>w4;&a=Bw2ylGm};Ve#W5oH z)6gHElEktM&3~i)D>-OQY|$JUI>2>N2vfoFThy8Oy9P72X=m9a^p)}11_rsXC!~wj=IepuWd{K=j#Ci$ibnWXcU+q-y)h)EgjKj_Ysswsn@ENC}7LG3mG;+%Tuzf~mt!pSW?h@ zi*6Sr>EBrDrMX4|9ga zKcT{=%r|f1Yz{S6P4JOos5FGw5bp%g^o+beaeCqpjU|_q0>};yuOxdpg2Cc)(q;~? zYU3O?o%HPG+9b8TzUh1S)AtK(#$!1p_HA=rtbS9+;l>LZT8GSVw%CX)JowG&jSTLSVcue=?oUqx3@Pi#yJ=_XF7d2<{F>h3X0QejqFUV zQYRK7qDfK~uLE>@+qdNf%j&g65IgJ>0q;n)Bj7*kR5DfM@`PA4Z3zo&SBf-*}09O&C%n94;cbBo(K%8*i;sQZQa4KPYK&nmhqGZrA_ zTyx}@Cr%0}O&0%QHxV{>NZ-G|NG}pcv{DZlWiA?GS(tG%7r$jr&E5?~RmEdx8rnt+ z=2D5;T~AMEcl9Q3eZ5c}7H1nqlY+7_68TJTagcNYPRk#LFU!F5xd-VBoE0v!9CHR$ zjYpq2W-DJ1pg-UjwU9daiH~Se#K!o@;PT5|Pu?kUOAfqd*0(v=V<|;&8r9LMAtzbv zWk0G`$ygLPM+KzV=acmS={=>_m@%NYA|%$Wsv&+!RsM6mD$1z28!mU?J6og*sk-^5+aVi4gc`i!nHX@m|2zvrtv}Ci3Tvwq zq30wB$MHD$>QZgJP@*X>6g_cjF~AaNZ_*CyDjYDG0n2-A-=mZ@+q0CXiGf5kqh1kw zkE#!(99JU?%_TV)kH@!EXRL37M@iAHw}IT~bV02(8Xmgof33hP>2iLD`LLJ~zbMv8 zo!iSCIm`V2l~tcS5I*AOu3i*u?Vrt{ltUw&K2BR+L>gx$E*ADOmi`rF zE$BwqL>evOu;klu%oY2{AOBg6gUu3aW{_7Fa_%H>leajP<;MgjY^T>;v=8aV{L#AS zt^_L)N0R~_n^@Pg`kln!G|9e2ez4H8XM9+urh(?hxD@Fn4(57$Nr}fT_QqQnZ0osB zR)WlD+7f89EN<6ZuE6Yd)?jJrhXb_=Hsp{?lIdSYh=_W!y5P(x>!sJ__KICNrUv7o zXOA`;cxMtGt>%;(q66gq3yp0nh;0$CP>$0Zr(6jlN;AR%{yVRz#6Cy9)PU^gU1-oS z*=bNnX)|Qzjw$6CPaH(YSwaRR6JCMnIL_cYcWJ~;bh{m~XY(ylkpexW%3xe)nCaa} z>j^@V-fv)cnmf>tML%fkQfZhm87TYU`Qs_^4r?3W@L|IQr3x;l!bzt|?;9(r0wkaT zK4~>cJm!DzKCtS+%gxky@t$P7s`lxd_j7ESKQ~{}c@Po7P%V(=e$=V>bvhu4bw6jC zf2XKv=8F8RuERTx!TU{(h}J*ud}1P$U*ItP&AF>94hj77#_u9 ze?VPWDJ)~3SWY{JjE3O=a%XV+TvuJj!UDXPdRzD;7D#b6WQ%bkbxk#~u``tgU<%G$ zt(*D7N^nXb7oa0Rrr|-Y(!yB8zx+98W*VJ1V)xVa5q z@6Opa34pO`_kpG-1AP8U%Pjf7sfz zkzC{1k=oqRn28b1x$Bpe&IQ8PWKHktork^nBcE(aH?-vmfq#T3MJ^rw)XhR>mwE+G z8ELvPCmp#co)%T2$*DXsq{$EM^SO=FHAY)T4q#&&dJH`*c&;Y!I8A5!n~5d@b)O|K zj;%fv7(LLMndWqksAQAGg~wJRl*VB*GWsjM_}H?+Y+euP#jX%6=9BAK`t8@EXCYlo$z9^f|H8x0SRfA=ddFLOeZ5;$|aP|`u+LMZ<-i1G?aBJ6=VXC zjshnUd;v*{n;j>m5y;zs>yKYR8fZ6Xp+fWfqX>ba75c-%;9#|{p>eTSd>&ht-#vb* zPbB_`Sx|FGcQ>bXS_${$j4g3^@Q7KE%DJXfzjYm@m`ERlmLI`&`feHR_GOpN?G;h^ zes`k7j-qcMqf}txF^_j|0;=QZ!2@VHz1(jp!p{WG~_)Z{N!haeEZ{{uch%Qymov};mr>D_`1bf+3D4TZb zlyk$Dd51%0h@@#5DZT7hXB$Kpk0s6?NcRhg&cg}qU1S>_;8g>^JL=!5b){QU0d>Kp z>Aal=R|+SV2yaw^oVHN{t_r@wc(*-%a58vEJK{H@Phn-kn`bC}V3(c{uUr!)pJ}bo zBG#7k7T?qZw{unFL^A;+4zH}{3;@5OA%Oi_qFhjJqiQPHp3|Cg#_a)ldgUh9lwR&g zhdQ-nKoSf%nALaNV4O`ROMUvDuC@)!;n$UGO2wadJkcjseI3FtyPAT@EC-n>w_c3% zO^{6a-V|nYTgujr%7lz&)La_T-F_XZFJ8duI2>mB1-yWC(@nvS;*O3CCzyB87Wm(_5nZgPH-t;kESKw&>~A)lqj-g@%0 zrP5GG^Z7H_!Pbo0TD|8&dUY0mh*QDhUaBUtKm^0pIB4v1`&O{y0O7S7rh;cl?&Fq- zJ5Ztko(_&o;b+2@M`9GFxe7F`e@F=&*)J%G0%`P^Ef3q=U?@0vs4cEfuhsFc@y_IB z=@{E!;#LnZAmp$1C2Ts#{+n8xzOIH2!eCGG2P9xHS42zg;}Cj zrAAi_HJc-t`5!M=XC5@$8Wz=5h zGNj%wt+N-|Iy#3X``ngrkxXOyKPn*e{P?HFy2gR<}cjsX;vr+Gy z@woZK3cQswwd_2mNmSR{8(=J*D|$^K8yEl-FmPZH!NkK>{Jk4Z6`wA?c^ts>=c{m#ZG;cv!A;>Z52%EUUU#_}1+`a)G4 z?8fNSk9KGf4{4+>e87EVD`;TDKUUOjkgogU)awy;gL&kW(V1?+Cn_ek>N)1s+{?yM zUHw>s--S%X510REbOi|>(#3pU%My3IE$6Fu+GJUQ-1LzI+e%|`E;@>@0Cak$bQ=2^ zRPMz7`8{hiP<^FC9*rL3z-0Z9?ixA%`;BH0k~BdN-dU(2|96LvK8dkZ@^(3ZYtX|xJY%b zrj*3AX;wEepyibTW2*~W5uE`8LPs&4m6h`N@xd*>onNXa1BsJ*@6LS>{n2HIUV9)d zU$k=qw1u`@H2iR}DYfbTfCa2SKz>7sBoJKL{Sz2rxo|weL~jYZnOWwDkr6hWW} zkFhqnKVo<1#6He6?(?RZQ4nv>A_i6Oc)K3ATU7;?oA`#WAiW>O{6*dPlzZ~)|9JTo zPk&8T6wmg)Z-W89;rIFfaQBu$adqFGaO1(xlg?{Rr7gjS9SINa?Yu>*8c6~OA|#j+;J}1K9J%CkR*0%HkF@bJ^$om z8oK%F_0}(E1uRaXZ35SM&*kZucP-{1zJ2WYasWUd;fSqGsZgm<%5hL0JZsri(kr0R zIoqtXlg3G66Xz=!)?dTFAd{nzDOB3HnJkAz+fuN!07{PWRk~l^^CR#%REi#K{~$Y4 z00$-rBR7pb4rwG2mIQq=ydWZogaaWVA$9k{Naj0SMYQ`S?Y9G;wlaPGxaA#{IE5Ve z{%dvD^+F(Li!dmQH%T~deZ)fn!L?{dti*y&fu-L{B&ou2Uq$uwNCYMz_HHJTw`NvRaD^4i^QetXg9%H85H zJ`xr7{y~_r6Jc?+$a~M>%l_B8If7IQr(cb$fx}gBz{~Bku5%S9 z_|yJxmggS$jb1;pCoBJdFZ{Q3{P*t4)8QW}Idq)w_&4|deJ}pc-Bm1@#*eXn{B8d_ zC;vV*|8v)U`wxdjvZmA@<^M&Xf0OHf?z&}AECA~=uqS8#V8H*)nxcW@^nLdf)?8=! zmq`2@p8mBXEHj;4B7e!g38IsaXPv}=O6yy$X8aj>s0;t zD7Gj zX^yvY`kZbLm`}^rHIkYB^xXeeZgx1%bh1r zJIQ0hf3A)1TipS{%13f@G$W4>cI;xFxs;(#(S_#zP@NGOZ?bgpS#^|zaQ)##u9!3t zGNBm1d9E@AeEeQeiO9QeX_U|Qo2+O51|boVmCY<3MnIvGN&)jihH^DW{!(&pT8 z(psnX$Mb9XH(QMQbSgO`_5TjGpVD+E85CLVgOlVYY1%~dMBwESpN#I<30+@GC(nObUO-By<2QWzPs9%n4UJ43J0=?cs{}@0QEdZ#$m(BEVX}T`QjxU+?wLa`FJ{QGE=~gGJMMa6%O>O65Lo3S-sQ@0Ti$U zsS~{JQnk7db#BGqFEGU=YIv(izDLxZu2&BQx)_)DN|!N&$-G09>CJB|tqtgG$2T4R zjIGyMFXyaN*LSVu`?5RsbXX7M4Qb}jWt4&@$qP(DR7tdd-OYw+9bMY`Uko)4SX3^H z8bY#=lC)}rri?J!a?V2+Id7M`oa7awbydkD;;d{rbjT*0Kcf67B5HOzW_P~W2v(%kM;bK!Rb^V z+Eghc#JwYNzCxPXre?mviG6w@T3&4cSIq*T$KD@)+IjnE`P|hcIfp$G=l0UqH`e=QV~^Z z?ktBNpR(NxW@iGMz_A9z>n@b+V8P#tq#rI?)twIS@psb8_3yutYSe=8mnPHr;4{+o z7ixbR;6xs{&mpu!0CQ?q%Ps-1J?E*zLT#=&)OOtYM0~YnQUV>9yf+HkcVjr{A7e!w z#oqU7O0y>+=HcKOX8_R7{A&DV11j|HDAvRmfkf{k9Lxa!3t%DB2QWBq2!pdo6aX~Q zK5J2LCJgnBY=6H-*Y?(DU`lZ6eF7cx%H(uHqA;L_}y@p$WA@5MLsxoEn>C@=~&mB z_so(L^aZY|3tIgH;Yr1Wr0OCrZ-I4`f-O|p1K~I-&khTsnX?i6z2+!yoh%^)O8h6a z>E)J~v*j+&M-vXmx`mEBH+%D}?pP(r5rWu3B-vLo%12$feo+*~ZtiCo>*u|I*>ZD$ zp+nN6<9n-oN2lO!%-e81`!`mFySzIvQb#}414qg{zlr=s(L*Z0;W#((EduZ>mCbqO zv58sZnhZR#QIyE-@|aHl)bofkP|RXlC7Y?t+|07lq(9LR&Y->EyD|U(?V#5SY`9)O znW@udWN~|O^-~NI8wz9)^Se?2PQWE0x%bu@s)^$%LiBxU{q(Hyq1Xh2)zXGA8iKMT zMbZ9ld93O)(0Ag6lp9#*i-MWMK2wCg7tz;KRj7SKy_vX%_iR38=uJPrioQ2*8s1#T z3MQOQjXAZQ$qwdVXFxp+~I4-d>V>C1rnE*E|RANe5Fdi+D zS%;bb4#he>nt*MbX-n5(E4a&Lx((_eEK7o)Gn-9_aE#U~5(cc*2;n53l_LnL@b8Y- z;a(v7W*&7^?0jNz=ji(Sjwf(0-BKSvZH#Hk4JF$_0YQnJ-DZ|o1#tiVowq~n61mlV zqO(T57CLRb1jMdhs*?HhrgwJ{y9=GOO!Qab!|bDiE|2WcO9B+@er)ta$<~rE=cLEt zlyu}+5iX5{OAYsnrp^0NmFz^n{pCTSm|b(x`KcuZhwFx1(}nO1ptUICmfR~~M8@)d zgRFEa?enVg8n$QF3_I$5NfOiGj3>STssT!Y8tECP^KXRgvWMI@Co5&p>s?q)#Q`*_ zqLy@)XPq?kM~4NgI@8zgbjc5I>Hp&3HO!Go{*t z->uW?!rlt}{^6n);V$``8-zyRRC-ZeMcdaC_XawXB8_;~fI|do`<{=b(pxvTNsYG~ zDV$pROD*JE9^WW$5>rw_9<7Zk4chsymyLseGWo-^LJ@whHOp}sl+f5@CNX_YP4s$A z7&_N(u@~XG;QG2pxSq#`e7@AZ%kBhw`H$*&>2~O-B&6~(-us=Qn-D-e6tQ^LB{ASg zmFI=IKC9hy0{jTyGMRT(?(>8Js*;|$xLjInrY@i`;6xGw@!X9RZ_$bXHZ43sL3;=h9c1_vfByz;_+pfj;?F6%n z5M`g-P(%&*AR7aI|50qPrB4JpP1*1Efe;NoAOEq>4^OgCrtw!}{N$WXB**d%+~dRP zy%$D4k(16=`-7%H33PYXQAT6AGC!$!yV|v7pJu`!5w@@jzpLrmNG04Sqq9>pZ{`DW z^p5voTsCzvciRpqgA}z}R(Im_o}rAdl=}L<8L>m-#?6zn=EnW5c-t;$&XD;;j;NLJ zSRN#V3=raeEw#^C+H+Z(=dv7idhy&QpY}ceDqIL#wRqpmX5B=Z8LmISLy;kOT%wAsP$d$iEZw4^9>p~ ztgKO15rNM1lytt2=5D2^h3cSVG1!^P4L8X@bu`#+KvD)$>jU9ki%WKICBmpc71lI) zx?$U3A;Vh%mz33Z%GwEw=9hBn`eEWoq0nVN2|In-k~>DgQD*1rDGJPNrsHEE-{)kJ zXZKs=m5Iw?fj3aQHaoHrM4QE|b1TVB$VOGF>XMD-YxxGnX5y~vareOM*-A6kkK_keOYh%0p?n>lsHkwWo%Vjfi6GycviD*`2F(~<#dz+f!qtjFn%m%m@2fl zJR~2YcE2`y<@M3=o`+^#_cmuAEoP?;V?Fo>>u4lDq8Q{_mW9dAWT$k7rXnVYdm`i~ z$V>Wp=}*&Y_+v<<1<`G#(lVx%7N|d7Lpo3*E@yP%&Q`m|xZ%ZS-H?ut3q>Fug)$$O z(>HMe>$8{Q6@+HeR~bY`=N5tnyqkk>8YQCgjgMLJ8N=1u-juci&Pk0|?a;lh0%>k6 zBUVUbS$uR{m4>$9p)lKa9{v`j(X&I$B5008okK5Y)hro*BISG{pO37eHbS5?%vR&@ zviK)Nq#y(}b+Zg&v)7NqJheF85wi`tyaT{3c_>ovSIV3%7HC``7S#nRb_ORtBBdwZ zr6kW^?UAs@KAe=k7CTEYJU>pr9c_gwIGyxzjV5pjVKc;J5G*n)l>C*66k?xxfGV;a zBWW8cM;N$Oi@f>sBi>%f`I;Y8`!o6}gU18b>P6m-;$q4NWx6LWiPkF>Yp!ux!HMCC zq+(a9=jB{xnNb#!UXu}(t5`La{Z~6SsP2)H>BEsmz)DdRY@8LYEzf@KB*HIo+Fpz2 zPH_CdJvwaP_X#K8EY?cZA5IDF{BVQ=b?oB7Y9S&dmr2CE}XSO07Ntf+hvl8Enw-pZq&JbSX(dhu^&z&E!7jY$V#oir7O(CnE zf`L|%!jvbe%iN^S9#jeu=W*~#)o#=gq_0}S&7|+&hs#-N)Abt+@9tr43@iDDZt;Kg zTsE%dpB-b)UR=9~KwtG-??&ku=W+WaQi@Nqj$w5|90A4E|Zfk#&Vm1FZ?HVlQbRA9aOJIq(@yoxfS%)=y2VK}{QC42Z z734_rDX83(GSTT9A8vB3pxK{O{vigXk?0AEHU{U!)5_Q*{LW#gnlzB&p1!g2cnj%$ zsLT&Obe-MJX24R(riZ~Qk%H&gr)ct3*Ix`3)?FI{@rqynEzFf%4p;rVQ>E4$;l^}& zCu7)OK}Jr9X!H|&J#RbNop#+_tw|whb){s2a{|K~fE+GArAkh3(hG)Be_|b~V}Q~- zjMIkqjvvbx_97Xbn4ZuhLHmF40x)iQq_Ah|owp-5El! zw?Bql1PP;?d_UQPhhCUj9IzCpop@^z38{3@*$QS1`REgLa^PN0pwKfWm|+cuQrczk zt*jIp2L+6WJO5JLv&`DXz`b$KjB5v!H>76G>Sxv&zO!;wA^PUcGbBiFNwR0O8w(T=5Y^Z2n?*%%~Tj3E^_+(osg!au!V z%Qa{MzMJ4mc@iX^-quD$H$caSVbFv{rHw|B3OWAKu;nN7b}`uy^u!V~cxz5Uscr`a z`i18*+I4AmA?%MDcU(wG)25a$RVTR+^UEYv!A&ddBh>OukQ+~Iq4=UuVU{~SkaUR# zE9)1|(ftkMQeQ8n>erTPoIi0tvmvWkc29mF;*-(h$VYd0SMbDmZi;+eb0kmQTKBQZ z_%55->z{t|<14SzS-r#@JgeajOA-uOn6HBks{Oc5OYytpYcHV@A3l}{TZK(M>Myte zvCA4ShNUKM%p1lN?QRT}$tmudDf`T((jVCn$hE2kMi0UHiKZc>VRs(t9S10 z39T=OC*E*~XQsE5t_l6;yz0D}6R83*39Zb$#7sU@i*?gj2PFuDWav>-)Yc7OkZ2DS z6Wq|*6Kz!&7zy-VKZzpfMzQb{poTpOA#U zXM7NC!@_UfMUmC4_9Zj65Oi2{#L)PNB2!Uh7LQrT|C3dvO3i!Y>d8w5JsAEu;X2q7 ziX~#bK<@G|$NMeHL&AJ2Gf(rhi>|hJd+01>wu5f)^Ar!#i>r~(r|Oc5nKsXSk6(Rf zLHMCn9#~juO6(I?`?wb5BB;Rkk%Bxv#etw5kE~3z>u?X8eAnOQ>~TDo!-3dI7X7ZO z;Nj=c$~A1NUVCD_2Zi##HyrWK0CK^CPX|hDWG81&UXHLMKE?njGwsOfDR6@?S|Wen$yq{lNXrS{t2%Kp(mFp@3djqBj?{iPi6ZZMo07^Tdl zV4={N*(Rkff=Y{#$MMY$C$g4w1Mp4}lM>W@F@?{SDOELga79dE#DPK+BZi5V@U)Mzf!u z&eCVi66Pw>@hJJKy082;OOH=GV7(Zih^X}*s1`zL0CBgni!wXdH@#0#t`NjC*^_pV zqPLTgIf-l0M9<=C^2~x7@Z(~5tahr|UEm#t>15RRSu>u@*=&@3`x6Wbv!b&2&tj>s zz2h*n5?Kc6kTZ|m<9S=A0V6o*7ct=K;6)1=%Z53L6+P5dOA@oJf7_p}|}lO#1`vS$;IHa`vs?S6cwh3ynPh|!K{4t{&r zm`CC))M8G0r|#V4k|ouz>w633DD4hYS{;m!z(Ia4d!`vW=4G&HCg(NK82SmO2wgcA z=hLdAQdz|Jo7`Dm$=|bw&HaBoGY)}=qTD6RW*2nYLxAQK-_ z*rT$IRYBi#u)w#R0Sn;(pU$Nlf0M-8=&T2io>@U#eR(qOFfSIk)IIR>d;r}=_tHz_ zL3@s`O9I30g%QzrT(ezK%BZtI4CKz~bt8$tKkdA@UH7eE;Ct+0U2H{(SKJBPK{O&? zmm#Rf>0t)hO1~*LrbK}Uq(bXa99f~?$?7Fi!BC(~tfy6|6g*OIf5^tw(md4qpyNuXW>7Vg=wxAs<+;b790$t#n5n7 zuRbp!srMODLzB>I5E{*VwZ`qKl521`t;OfnEZ^ydqqK_Q$ySwr6jkYIEi{qWcZ?lL zVZF2Ver|<+JR{(Lsz;zza zx2Y~Mzmy6Rxs%-n1<=--?O86T#;e2L`io;6XgtvE8Sm$M=2S`vafiE1t--%QWH7ao zH?Z_ghRj;ZAZ#v3%AMmoTn-+ANcMz`L_fCARysSB&$wCY;x&xK>kQH1v7I{aAmDy| zfe^BremJ!RcmqoEQ?(%QFSqI3ILK&A65*HJMv4il!#O72fJcG%vf+ffylh1cm#M=H z3auUzfAyC*zg=>5n3aXK7&}l<()xb-fGP|_cKQ+Vx}Kwf#rit1xmbMrHk-?g6!_SaeHnT^}G{{lL!|ICm*~?r5-a^u3p0e$6ST#oO0a{<3zK4t!tPn&fSuS~Ndu zV>QUCts+-%D2_m40O?_q)x#73>#MFhkVi*w8|O`KV!WXpsV21$Mm6xZ#U(_rrDFue z3?jeIT*q2yEa`6X10(;awL=8X!nA3XJ)v|-klj8;u)=5WzMEwJ3a+KO7k?w(btC0< zCGGJa7c~&k$GbG0u#I_1zgj)fayAvkrBM^4@;wC487)vqstPH82Q~&Qw6spcIf@i$ z^_{^+o2KD0z8{_Ia&DzL<_d$oX&apsykBa`9MTisevUv6sxQo~juQC)wiCyf{Gd^L z#ot`mE^#S}_NnnzkH#I!M%{E+tHul26-J!BQUiGq-Y>qm{Ql3nzY;rV!!vbhYuFw>e3O9q0cDDksECSeO3#VMCThZg53dpitJ6Ld{; ze=MScb^E-g^{q~tODkVyQA=S_bu&~!GPBOQkQXpZg1skgY{4II%dKXiL&nEhi+DID zj|*uBZ|f8Y4*w|1coULV5c}8)DBiaz;fnq`A00S~o_e|Q93`chm2uPrCQo@|KkmMA z=b^65VLskOLj$ipPP$$HjHFuaBismJXEk03$R$<5gyz%5(d2yfQOpJRjZA>2_N)m@ ztX!MywtyBgBzt-}M}zBmOTZ1EE#>oyco=q92Xq*mE*`C_ul}KS-S%8Q+Ol7mY_~J0 z&m&z;M2a>OhTD3~|I-z|lbvFaXKW<@mlxeg3@Y;Kq&)P439&mH9M=KIsI2T+KI%zY zeG|)ThoH__1_*A4yIzO+7UpWEoYyx>zHkK9$7uCqLwfnSLmiVqy=P;*i7P1hB1E3D%tmzE9*X6zzKlnPVAKB_}nOi-Kx+?<0M)@IvOW0c^wPwKkdeueXCZ1jdLqzoL0+Pa*ajmLID z>Ps=;)3p2t6W%6tnu_Hck_M(wY;|U{QOOUPQo1KjKMQwg1?{^4bFYa5xf{yL?WqnG z03fM_%*ozb))i!_R2|m~L_U!~WiS79zB;=FSMHqiZB$bDG{N6iy;UBl;jNTfNasg zhMonlqVI8?$tp|reElyO?hqUJ#t9T5OdUjg< zXQ^#l)cc#>&+;XRyxW21O{y2+q$JhXKjUTlwwlj}hF$QzEAMZRo~R zEW4S52|Tb7FWnrDS&O8tCJO5=ZL)EVAeWx0wyj-8 zXaBWj|98m5$;ZQ2RWExDJY@`NK1Lv~!U5XFdE2_lG=3iQ!V|9P1Bg0I=2N#oW+kYL zT<_WFmH5Q;mSvEmobMp}T>ICY2eH#f?8Ne8g!syYh~-@5rPt6g?FLb&(`I7JEDFW@ z&H1lj_x)(QCxJvkgUWUt_Knrk(6}NS?6QUGeQIm$@7Wz#5^pw9=) znZr`Z{c8{DZl?t7@CR~1H!XyINAPqE4`V=5l`=c@PYY{MY)-K`vS|I&$eX} z(_NsBslmotDbH0SM53L&Xm3&$t`&asWq0)P11TH1Q75eJD(BSEO@5y@>XWN&aS8*! zMY!dka59l5NFl4Kk69-D(J8lObgp+j+RB^J>FwvEUu|R%Qmlh9c&Ae zYRLmRGHF+XUK_T}p3HLXx!jnG6D?t=^yJGjtp{-KGSaho+2_q4J=nc1;(he<#tGa? zbiL3JQ)8HmKsmVE-A=~kT1V2V+nQW+l&M<8ufAI5(9HmdFUDpCqh1fn18)?;es~F|lO0DI-bGy^Ji;-@P}I^RAzx zKJIg;HO+5on|3$PS=yGE8@?D#tKL+{4iBZhzM`yLT&^6> zew2MRUyV}t>2tXoaNqf;u|l@_6yA)<#r?dbNYUm!3Cpn7dcE(V!Ehyoqc7!v`Y z+S)R3wrf>yzZtqX>wxr@yf3TS>Y#-E z9OcU4B;hd!6GGg-_wE8yMz%E1v!`VoC{y^iX}Xu#M{TQv2Lh(fjim39y(85qu%On{ zL{*$CGL=3$mvj{8VK?0E&hhh;6#{Eb25}En^M^_Sn92OY>&B_t2oM}9zBRN#HS}<1 z%;wccFqeSowNe%MW|3%2IuF!E;M1FNOB_((B>35Hw}yS23U3{dK=`;E#!Wtj zu!1fk_WXTp*xepv^@o^2nkXx^p~kEYy=(9B{1dkYs7ofIIcfDv?K&bd$If@vp$E0G zYiZ9|o*+E?n;_*Rf@?2o=Iu-J(kUD5!Njf&QFMdicSFJjWcqmv4%L1m(A_DljN3j~ zp^I>sE-EN=DceWu_T5AJwJVj`&K@R4@4MlWNxTKiN-y#Qo)c0f!KmwMi0=5Vp?H8# z*quR~_Xd)PI}RN96|Ym&41_S=LpJ=pxZIDv3RR%Rn`ok6b{W=qHj>y1R`i=b&KO8Ng z68g_7hLrz9gD`)-G~b#BRJMY5bF10WQ9$!IshbS*X$eQ>8d2CgUuL^ zsLb873;bcDo744V)}zD0_nH~21OpU#+xF)xL&nV5+uxL_fO#!~$Tn#IJu=ufVBE`~ zQXhZ5S}>N|Fp&oEq^T8QiEi+Iba<$?Bl=7nD4*~RF#8p-p5!WN8vqTQ?quQS-E1cq z&aR?#M(_Zq|=4JQq8!!A+@INWb1a|=OERQ_n+acaNU%u?+t0<^Mh4%FJJ zhQoh~(||UbQQz!<0qze{amQ)x3Tn>}2!}vEOzB3iY-wP+a~x1~VX0k5l_1iN@7|>7 zbUa$EXGUdM>DxivvF%dh^|D!~7E8H1p_1WlF}&;eO_5+9kh58<;6dU;3xW9(2tFo8 z*tUo!_ng9sbTj#-O9O-49kv66$e3Mq3uh*XoPNW#XxO5fe{}GD4u2LyXdM1-sX~gn zMqo|ZK`$yVVpg{PFO`s8t*fFuO7BWE~r$-|}+@P!CYDcnG|gbX#3jk*2hn zwt>DVLlvV4G>&|J-xy?xj z`+DyO_>;e%6o!#4fAsG7Iu3Ay4;ps+6-B7vHRY|*>zq%!k!$S z;VXDOXU?aBGeqVb_CTw#guyXw6`xL}_>{EhoWJkK8l9{Rmh)21^0p09`Ccewnfe(2 zFT4@+gP+33i}({2h@2ehiRwZ>8cpxZoN&Li&=H$B@ex{Rq@Vaa@9bOU=uskDkYBFn zA_+CTOp~Q*-ZfxO6&_L6SVGk6fS3w@BV6ep@ zXms&dWb&;X+X1H4781h*tc*E)D+jl|mrr~m-^^f$%L#uhm$TVTTA8%%{X+ugMN-e& zMF-HsZR@(UH!VoESK7DyvBJB~w7O4yaQ6g5REGJ}z?1J>206CqkS`S2A!AYLn+|b= z=Cm&px=zdBkJGAX0*gus4FAob=1N}R(#of2gBoA@>kO$H>J#}Z()n4ktd)4FfP3;) zMl3?%TMY}XHak)_FkP>OM*i!kEy9)f*dDVo2!cO`F%kqey2beq_yVCC--@%m>Y!4E zCXc$HvtMt1mI3%hd19b}`^;>;;MXrbbvyoQV6A`2R4qiv9=pWd{`;*0njz9E--7@E z?)Z8eF>*1KuDnfUeYa@kVjw*>O{cztN2C?5BOu;t}s7N zl|oP$vx!MTLW$^;n9*rD~A!IT|(OV zerD~IHq^2krQ7Tznil)RoM2npO5fnZx>HTL{q{?0(^WyTg&W($c6{0!%MgWI!uCzr zvnW;iLab#|29hfH_#e==pj(re|1jpLChObB-ik>-TskgB;yy{Z*U{4(k&_mS1!sy; zdW&B}?mIUCGjB~hRrXD7GPP9||4}xw5X!|F))XI`SU7x-UO)IVJDck~i_vktSH$W5 zH1x7K%Q4L85*p0r9F^rUgkE)T7ZCT(ld5rSAZ3fdciGK(xa!?S^2hfS8b)wFe&|)= zyeh7Xc%zxM)m-VU)}-1E68KhTIgVHPvTW9Ax3bj6Fv5K;Tl>~mqRdxVLKA7Kjs4W0 zii+SCv%LNpyQzm4n$M9X>t|H@iXIMn5?Bf}|n;_Ta|HooTd)9K}!Qd|jYL*F2jzI)z(COIbw9-t<8$ki0$q+rZw^moTw_=L|KR1Rd$9RY}0S zYpz+L2-B#BF1Juj<9-Hac<-KU9RjS?RFBBS`5HI5Qi zSdi2w2e1BFuPwBpao4KyN3q=cZZw#sY4LdcYJvASlx=t?BV`o@xT){&NlR(>BdWL#(s2{%(4JitJ zbWMdBgZz?l8T#2MY-((XT^Q1m0?qQIu*Kz2!NB|*ToiklS#&M2P1KN`vhCtC7(KXw z+wJI$AHlT}K)JJVC~gs++DH!-eV1N{)my6Ng=LaP0hUldsn&_cYa@y}3F1?8(|aL` zE-R?@6A$0pN*oU5kkU@0!`RDOFBgu;=V$UrEpJumz9{#Pm*sIe!T0q>6Wo=XDeloE z9#l}v=+CLeU2#Ts&rz3$m)cnkptMV>PJ*pU+K76Vmp%E(m_Tl$s$_KOi3dZEan+fU!7JE=3@L@@(&#KT0mr?h|$Z@Kpq zj?vpW*nd=w)wjuy;Y;D+b+)gR8t>f-Uen$lQlHXoK3-Lwg6ZTP>^(vb3ugpn{I*^V zNdz*v<4)%6G+sUD{(z#AN7C3nyq_>3r|>v)jlMX}SiD!wDCD6a6cx@dTi(BH56sa9 zdngYnan&_(1981NlJO)lq(Dy~40^3Kx7WFsofGc|*VB@zKs%}XORi#!2^2DNL!GxI zXAj9#rcI}pclTjF{T<7&?gs=N$K0#z!Cv=K z6IS034hNzvC~TTPgqx~l^H$p4iZ#Cyti9h`xIObS?pIkibzMdw-&w%?##bqKg4sqp zZO}XgmMa&!Ysrr<3pV&wjz&%H{h}M|b2-I!p*5pkB27fupRGaOIK5>^jr;zd$WAd> zj34$v&1FyD2xsHs$+El6>P9{G>DLeU;{}Or5!i=$DME5vD4pe>kEWeh!R=?~Pem(( zll;$ERI;bEZ9+@W6zi#rYSlD)LsIeOYK|lH{!l=;HXrn^IwhgLDA~Lz3C&`&az{*HQ7Bwnau!Awa z+B1^i z`kq$e^)V%B+DjN8zN2}1YMG<(`Q|^4!=6Fjv?+>+wxQ+AarK7+s4ny?TPjoAIeSBg zV~f-8uwx}B!End|2enLmOKkQT7?#DBf1K{Wy^XRsp5qE7~Q4l=5@`P-ME?2cfbfj?W2%RpEt(686*o@VCNmbg&MF&VBI z5ST@_1go4x&8OF8N=lL1sg~K9HZ%V@%L)oq22WfvaH_gQhGDE1*O92#$vrkUBchT) ze|0)Hm81Ji;nN}J^gcRa!43Q;&FNP>!e}g2MnQmDKhv9KU3H&uqwCj3>z_%7>YJKr zUHI||3epCyKA=?%E0H%utj|Q*{B?dLr~*Rd*dHZ*0q0gC5J#9Ay1D3^dNEQ%zt_hB z?%0R`;wXtnaD!p1MB&qyVtBNuzNZXVBs=-?Ru8yqb^t?O z+c|@8W;+*As}x@f8%f|mnCg=`Yj)oJota>wadB9!!S~f)s{Kp);6es?uWczKhUp;b^A4e$sS9Txv z61V2p0aop>YE1R$1FAq|S&t}JF^`?(mwjY94$ycSnccP7CkvumceL9zMS9GsuaE1J4tD4#MM<3AJhkx6l;mkAK5rn1 z$`J7WO$R4>R!2dQSyIy)GF|AC5j;gX0WO#8;k@degMRHH?F%Qc7s^XIYJIL$#Tw}I z`tM!<&rVjX1600IL13WTi?-GMC`<4leUj1gjMJ`fb{4GU;GW|@8>^F`eQQN+6?V=Wr zDvT+j$A=ynY=Xo7^?h8f82(bw-*aA6Q)HvbU{tigfsYwznsKvI=uSP_57kIn(y)W* zyW!`TD}{vT2YINT9YL2jnsonkTM7md9LQwO&ri1=62S3~)-tc_*VBvDIj2%$TDKBe z`jY{Ivp;xO3L^s3Xg4{bv^}EOXdF!j{&W}qyu(%gtpLmH^|J^J4zkT6eQpZv^EwuQ zyI-fr5u?Wr^SFLLYR#g(>yahk$Onl|zUu0tgW+a>UBm4>64qUAqeTdVjyBRRc2%82 z4wM-SBn7+}d!w$7^UZdTn-7sURo2Ar&MiL@w5L19V&7Y?;B_R;_S;sI}q9&aG*gRmkzsLwp} z0)`p|$fJbkxo#X`AvDbA8$Bljr=Ww18ao6~U+Qkc_kgvp{*6+ZBrX&0|EXyz=L(s3 zm={c@=sL$C=1m<-Qy0Qr*;Kxzj$|B5W9wq*y3LZw-1@uE+s1tQH6&G|{(W*@Do?IawnPt(FlbF}r?=LK6p%}4#5jaVgtvKT^##K!vusZl#?ewqM$xXn^Yrx?w`@-+w zY#*OR!7#fVvByc@mb+bphsz11YzYn+0{ZN0ue8vzI+15bGw#55%)=_xnji_Onb`G> z{Ot@v=`oj+9cTI(!;nur)^m~yXGOldL&_=vgLa`afJ`V!AMHIl-^$S?ndf{92w^s> z!t!#x-vJFsh}D7~@jSI)n;H@Gd*O4o*xeU#N0PS(98qwK_FT{dn$q^(C{{Ot2VXH{ z^s@@>mSyBpU_uSP6-@RkyTOx${)5ZgEsQAYODQ2dlih)GqCFhm(PXsDmZ;{-ej&|g z9$KSB|9I0gVG8DIA7OVQ&jd(>#q0kII#d;xw*BQH!Kc^O* zRK|r>qs1e{A8WN8!Km;ji%>zND_ma^5js0YMLe+)2FVXtL7Ts0doO%#Ka}fb4LZ#m zSd~q4I>V=?i@FTZrRpmaLbbn*$ntSe;t)mx(d-1zlOe(cpn&r)_G(U00SQkZaCT@r z`Rv7H*3TrV-=r-F%Z}$?vtQBcWBok$^g2XBl;DCwkMhfrYNHo-S$>2OEbbDBYObDt z$(rY5;QsY_`5*NQJ9un#0ouKmx{1NP<+~Lq6CMRV}}W9)_>F2~$$%N-!T zzd=AXdQ0OQ1?jkOA!CypYxRv*(Hi%=-LGmNnpS)#o>bV@QrUPe6M~axZ{lfbb07W6 z?}6ZI7>Znx4|@t{!rO*sgRWm_>I~*J7iRnE`sMjh4lvmPa*2Co$WHT}bT$!g@-tvm zagj8Xs{TTIPN~KBRgz?0izFRK&{pl7(Cpae{K*7Yz%AyS=%wB;n+ z=&pE;aa8RwUD*A{8C3?y4j7-pa8H-ItoZR_QVq4ycA?g+_b(@_ggE1Fvr#TCXr90t zO8HrYYGt|(rHStje0@S))cGXa$Vt*IoxLbDtEMu}X*%s%F2zVp2LJg)oEe&LXZ}vS zVDI)))^R{GU~fOi+nu()dxXD{=%qSndRNE}K4oO8DIEu4C}fkUzxT5xP6` zDk>H6amJ;|z2TC~PTz+!!D@3Joq5-=ESuW$YF~hVBud!)s)hXY*D|df*`={R0{1?Z zcq~|1{-{c?Nf+M!L5=JTzVE6yO$86sMd@Q5gVj@nq0#{8&&zo=xV;(hv=%>^Tcunx zXbzx1!|rnL##G}Ysq%A9 z9phI#S};!Mj6i4XJLv>v|8zMEL?8)cg$qX3cZ^I#oXW2_u}+LH(MQK zG+$EzUunu*iPH&i#S{I*6!A`t-)qGDtHeViXtwJ6dO=3Z-{+6ZIn4DlBEJURw>{?d zEAG5`Tfx)mLR6cOvUNEH3+&prNUr--NP zLNUgaPy__b6=!U~epIaohJs7X2?UzKB4n2)f&*{&7yR|s-!>&JH<`C^s>Tz7C49#w z1jmc&c%b*x^}uuf`npx~E5g2ILWyUKKw%B@Juqm|wO$2KVnlYIrpv^;_nk7E4IHCp zu+0@_Ya&@;F;Acta;w_(`V|Lr-&Mrpz2)KZA(LmQ*gUj-J1+y?(M%k4!>R&!EMO*5|v!*R6)X3S4VO~~yF zU$4KZ3tM{%=+*2DHp6d6qMhE5bBRztv-;yhs840qr>_SAt#Sa6Gr%0@ zzOBfPi-;bGTjbD-Z?650VlsRG;pbFy`2_@4!l4okFX)i!!R~_V!Q^!#oqk2SFA=#M zU1P3;L6>Zo?L{~R9M#T`=FM%!lRqpvFit^<12nvBON{qh8Gk&C?s%mjG1QqMAg1@3 zHo+s^HJMP<8|GEPwnh^}Hw4I`o8qS6&EYrodX)QS#8iW`LgNNbp3IR!{X3bs0uUUu z29Md)5YdK=H(+L`xZdyR-4VG*xJ%1g8&GM9nqD<7v2Z?+&rGDIqd*}sEze;1SVCu)is#Ry z{Cc6c_teIqotL?~)vbEK^-)?w;55nS!N7ffubS5U|L6upfo5E~l6$p}J&WiTf z;0Ru?H>0pp;3B{Tm-{=ggz>)5l~ow3#K}UYo+Z5W2aW%9W7JHS)$4^pv~lkrkl2W~ zq-N%3Mg%+tRoBbv<8!+1o5cU&!sT;{0tpv{AX{7yIPPp7$9nN#TwTUHjUiY{$=PK+X*EJi^eAXt9f{tLB;!|MR2P+aDn)@7o*;ZVJ{He=8UM& z-s7TepHq+gWvN$Sp}YFnN(yh{Y~#%EzUXnx;eS4_vRH`4wxs=l`x78Z)I5q*QqAD- z#Iqdvu+4FU5ksZYaSYZLKezJP}E# z7=#G0Vvs#SP*O1V_!~Prv_f_0Bt2yf%w9p;tbaS8@#;G8a2Z>7UsuPVXM9u6=%HT0 zgx)_WaCO+zX4yuw+CjJ!Q=0?_2_2ke(lT z#Y4Ngqn?!2bo2fIvoZF$Zjk*Y77;G05sFG#9!6z0qq3}UOhZmf0uL`DzvCO*De-lA zETc9As`~gP04I$tl|IXbZu@-us?CNXY8vN<1#TH@k9n7R{bf8Oy318MJA3}I=^3SW zWWdiB?pcJHVOgeM@D+0;DJ>p`%qTPy6|^vDt&-=#HD2&D7QnUJrip%>bgmJt6Pk`};BVSdWbB$^5jq2Wi9p6fW^T4mXB`$%opi4w{3lxDCA7^}qCuM1Z%%EP^_PA8R4}W*GFe zg34Ja%0UFK1BZsb_twfO5k0?k@%53B{3HU{e^IB#mZaOV(Qi9xqdwuU!lR^_eYO-N zN8HyMtP|lW<7DK9-2x1?0@}bC9(=>& z$&vSAXUCj~Pn4@e_>;4eM--E?%#fnSu^nO`CP*7;MEF~LH*R+QsZam9o_#lmp_q5( zFoPLadF2nk;}85_#U5=x)`jE+QQh7oz@0MK+YaB;UHc3pu)naX_i}<34Q)cAvwVi+ zlhfxq`4gZJ>i}BKvG1TALBuCp9$uaX;XV1(Hi(R{RfhBZoPYXh7PpJw4|D_|gUc1K zt!#taQXZ+9f76}P^LD!i7|ioJzSA&iXX^Y9V1;(Ya&>FPVtQLDLyF-#9yZ*f9Ok%^ z-JBL+!!r+WQg9)&bdX~!q2M-@k`QX*th(t>9?j-3{EZPM2Hp2)k zYcme~$pqr?-xmp2D-m}+0P80x3ok3%5eHRVMp`#V(?{IiJ`tCSo3~u-4`WYmoEw`xk#zy zu}tA#aCz^H{lTf9?jWeIXObg9kgis8ypN=)@kpw5^`M9QbToZSweyo)F7bCvRi*&v z>JM^f=xF)QyHsUcho$uG#3-70 zGOtulgtsmr=6TDwOd>F^@1Dy9Ts5w(glxxrDYgld8+%ZdO8|FzAYJzf+-}2DkK=MP z#Y=O4z}P;iuF&KZTq@jfod3r7!}CG!TNY}k=#fX&jnUDo7~fx)gQj&Mz5amBouDjMj3a&=MW4fQ#}^EgRXx(As`sJsCV$Gp3m zKrhM)%N4~6ipTeGe%EN$V5;JskEtq3!)AoBX&P({)3VP*lA_MgpBFGQt*;~@QJEi2 zZqI#6;l%Gz_0~UleC1Ij$iUsO%VWQ2u7TiMb9?ss#%gNtHKr{y?#Ww>%MSuX1&7jF z*c%8mb6U1zy?$%5<8?h*U8dT3A=g(6w=kDiEUj@MxRfaTF5x{r@bst>lktQ*sc)=Yjw~3=k?)buewz{K3 zh1w(Wfp~0L;w64!33d~I;UcxpxVGAa-5`?P3TMA&Lex0^EIsRn9Dn|m?M9l!@qx`- z&4VO$o|e8&#odX~jKzlQ`woGuFQw;oG&6=v^o*UE7qI`q=en%=K$3- z_Eh}fR!HfoS<1LA-nldczMorv@oqxM^oM+GdTsY63v4>K-L~hi>qjiqX;~ti{RANH zL%S_oM6KmOlPlEY3ILiB#yhV#fq_iwxx#fVpaYjhf zny(Ca@KGKj`SomZO-Sw8W$A+m?95A(Z*(!hl&)vNgzwd!HRhARME(X+V^?0G?8uW+lSpDwr0>e(NIk3;wF%Lc03qRnv`6^QFK=K9DB0w-& z_p%=j*uVby^qdu(6b0Oz`p2=D{USfiuOF}|e!6#a(8vyQ{JqiR|0ilB1B^1K)PAq8 zFy}POZY|`CBTW2*GQA-TC@Iw`);t^=l%TYt78>o!98B<-VCT20xFX3uJPI78VJ&eX zz#h$Ubc${TgpyPPbIF3wx~q2b(VjVPwC4J+rq?f4UwwGNMQwFh`!KaW!zI(feOQUw zO8^a-k#mL3--R?vU(FQmzW&e}5V_G@vL9yZk;>}fkkzkj_<>cneem*NZIaKx*>j9d z2M8tTlMmvoY5-m?vNF!q1eY`J(01YKC1BQpA#KcHp61L8zI2Dv>5LHF;IBoy>U6Y~ z!1vZOGreqp)y(#9Q7U@uIDB{!>9S{W7(WZ*ys$7G%P@u1`KyC+y^AOwg;az!Hu2YcSOIZJo4NQQzwS9I?Jm#g6If7>?+e=4bcC3= zXTgSypADzLSqQ^dx4B8j>xcDIcdM%bx$BZvsLq;IGZNiyti3PvelmoYYyd{nw8tmb zLqN)SEeW*1@XqVOuZSU%4SfhMnn59a=%waecLF|=)$a|^d_gZr0-2zjV&RZyVrjz5lDFqaRDwU%*#MXuVj)yM|@^kJVe;MnaFa%P9 zt2g~Z#p(}8@m0rQgQJ9BKE5eMS>4drkvZp>H;?@&h_bFjy^rAIgw8h=IxQ4xaL4k- zY+3V2T|R=f(r0dvIp309hj($@MHC2yShT;=%&Yp$sE-bVYcQ;LM5;bKyp(G8F!x3Ch^; z+Jx@0NgjTs?uO9;0-71@*iPY?!8s+%QLl3+Dg;YOXHIDRbt*Nam?Ff-PiPSQ!!5xT zI6~~sX@9Zdk_Krh>4)O_8e+;(Ju?+}u%*v~B7yvsl`v+@tAP}c1E2<}%Zhx?d)C0o z?<<@^a8bF?mu#792^ro0P;QneIJB5?(Kj-|F6}Yz{K}B>O~=!q?Pwhx36ZcT3r)bs zBIcvH&?!6j7147I6m}qs6HHLwmJ3r z7u()(n>2*6>Z8fvLEO@mP8R{UBHuIDON{{T`$n+Eg|-~u+vRX>zFd<6yZx$^uGcLE zUv+eTDe3g2Y(}T#)AfNXS4dcp?_-1Eu%gwPd9p(>XEV6Ir56_*xv6UiV6j+pT6*Ub zbr(8Kf3WJ_K5a!up(Tfu@NF3WeANK{DjnXMoG7O1ndILF*I=W-(x!$&EE6#|=fyf= zrc$HLv4_~9SSn7%q9W>KV*=7c9CF5ih;3K=`870JNE*g)Cc8%E8ur;sNF2r6h+{zn ze*}E`$JPLQ_<3)ka(V|3LBo2R->5XHD5DRX`<@g-(U9UMz;&h^y_c)f%k!BP0+{NRmp}O!ZO!LhC@Z?LjInJVSwe!;Yjg{G z*zJnzFeuOt#1(R~H_E)#heiFv9InmZe+9GH4$(@bvrq%rtUsxigM12P=!9Thecy87 z7a4X54g50XO#Pj>Z+C#cD?vmyBoV_jLX!YM@ zl0j%d5Sz73irY*@xBJ++`-XTh`_tceaOpoP>)pG&-e78o=H&cE&Cea|g7NXhYn_7} zIK@;@OPS|RwU;t`YcP#i@VN=yqS*Yk*DFv#_MsDaawxNR_IP;oVB?#@lN4-rspWnu zk3EPWs)>b<#{f#r+4{m{{-EoVzd{fEt_M5Q;Ieu2RbepvW%-*QNa07r{Jo@P)!QFNOsv5>Vo26_*ny^>k znw33NLWEz38Qi{om5u?b!ef32=?t9pF4w9HilgoRa~eur%7pOgi{YAhG%<8Q zhpAlw7ln@t@W(coKigQMD}G`Nfco{tjr9@jfjb)_p$;Op4Cr_l)5&@Ft!fRBQGdhk zlgyiA%shb!>0!>jxs%o2kIRVDHoaog`?62{v}S&pYI_)tjC4r|?vwL*qR)Nu4LRu? zay8BzY>mERNXvMG`^b%p`T4aH%b9?vDcX|uj}GJwEvIK^U|HP<`V*7eFa1-8-%w8+ z_EwuLAxmuyyIC~yU{rfbxmp8fS*7EJGRwWoKeu9U%ce8RZGDO2BX4lCjX4`tpT)n( z>$gtT|BhB7mzQd*FUCGl_&a$a$Au}-(`;GHF%{-Byvl>fvUsyU@@>})x^Ze+x0^a> z;+JRr7Zw!(h|-$txMBZ+a4Lk4(3vbM!-?zYk<&j!5KolT`lJiU+u-iefDh^f^6*do z+L*|)$;>wI`=7v*8xqKhCytbr?`14??g?(@ET^Com^hYb5Pq@uK75r-;IKFy_pq;7 z5wQc7;prkYLPt@-ttpX)qUO1$v){C8(BdkCvCT%~Ie#q^V($rl8j1eK4oQZ&J-L*6 zAdDK}OCxy^BvyO+b!yk!$17kGN1_(~4Arn9Id%T$yKzj4qZ;y+Yj-Wpd{!+7-p8Y$ z_+Jj`f54v@t%;$+&gpqk+T`TVb&5ndzuCmvgEc8SF0D-afczK*JW0P!65J)<&YGp7 zU+2ImwP5?{SAJ11bxoH{cKkmNvS za81wHlIcG%;*UAd;L^DF8qRyEpkmRNX*on&AhnI#rxHyTOB5ak{8k_G-=9!$vB zC8vAomjmtf`f|Z9yaD|`kd88R;U-j zf%vTSj~?q;h<2i!o=-DxBQm;)2LiMXTb`e0@{;PouztsH`#6T`KN+}%xLMj7IjFxN zRW7PppbXH!8I0|NKGwKVOG{%IqVxxUQRR~uV8ce~8b{O3KDI22829TLU*sDx)M03o zq^BBPkT0#|hm-%TGa3w8@fH@TeZ9ysU2Z{E(^T2ZaQ+M6w%_bb1D-m?0RKL0D3_=f zN3 zul_P_{|*5KUThd1f8=HL;1Lu*#9K$(Xt-Q0tZ$kwoQ2^*7iO;CbJydzVO+TTMAW}u zV!``ZKt0a^TBuX$!cd$ygKfnx%EXUgjpclK0C1G(Sa|4Pzd!^G2tq)4?P!=!pu-42 z{O9`ai01GAZU;sMX(wnC7HA=rae;-h59kf0$o0PG5J+J~5QfcDHxpkQ3l|>DAcTbx z_;bZ&7m7W>#O3SZlRR{0l`RjvyA3@;zM)5RRV8F@bc+#%1?_{(GnAWCbri_a(?9d< z!QbsJY_Jlw*yuG3>3Xwq^EMisaFy#10sr3@nGMt;H|$JOhWjXYC|p(c60e~=1!OcK zc;J>6?Ptt?h&3YlGSz)3NA0rOU~CoY{6CodfBtO-v%?OLvJw2f|3%yX`5<8erk1iE zcGyMmzc~4C4>qI_kQ;1r7O?;9=>K*79)TASkT*e!Ir{a#lJ(z71V68cK|r8!tyU~`fu!%i28?lL#o4>|8M3QkwZZ8s)<%x0)uo;dn8Vqmi%&nZHAnn)$=UKd7RUXJ?&VL6fkxA!sV!Y(Nb7v;jmDF!@E>JBwWjl+L+dM}gTh_&9e_`Psbc4{lB} zf|8FH1zl48VzSha6F7^yV~NzD8>u9VM+HA8C#U*lx*62}MOywRF#=Fv2EXxYwsyY7 z%p`HgnH5lTI-G^R-VEHRc1q*dO(r-|7_NTs+kZQOoBqFGR-|>|um_ zJ{A@!KMQ_5-Cc+;maF|-(B$&Ce}(0Z#rm7T&7q*g?PE{70q1%EW4GZgqPO^5fl+m$ zo_iDsn8X`Ymc2lTv^*cvEq~aG#-LIb!>(}m+PD}gq=syCTEvYnA-*M#jYXBs;R>!d z8O^WhSPDd}`xdxo*i1TqK-zh#)%xR0SAupnLg_U_!=z*u4BD zS!7F*#=v6A#oB&;@;>u1|JvKzcEaJ;+N1R27L{`rl?Ds04&bh>+ha4#?HTubt}pZ} zh!bgBiOc<1!u4dKxKh&=gQg=YTOMiYOmUeW2_&^RK1{n*5#mvY6c9v`+cWAelKl&w z&pFu)cB+`)?KtS!b5M51x-Ar z>dbfc%#N7bizqBOhYv0#A@;}4E5}T|&ydcXQRg z)6H_iBaenLxdNQeCbCt^7D8WwhO7fTk)kmo{0UPo!r+fc#bb*Wt(R!>qkF6*-UH#f zVcT0_|7|CFUnC%)o?lvNc#1POP-i!4&A-g(I|EGS4PWZuR6?rk=SpIL$QbaTp-AJ% z;7F02hx3XC2uoly@*QY%u@wW44>`O2ml^$9vDW*$Fh7m*zQ?e5W4$5)|;0#};Fzg$Ln&^RbBZ->meM z<^luFNAO`Q&h__i{PWJ}S6@2WC({J0wwq-^6w=a3)Pw*1Q1T2*~Q{4*q_#-^zGGcjhjZ^xM{zjK1Zm`1cPp3y5 zW6Im#rRS`A?fX7D(`5FC(_l+TcgXYSCw*)bojl}I;pyuSaU%mX=XgjQ)-IN*xq7}M zYrBmyW@oc9Yd1Pv(H%;iTkZ}Y7z5K7xh4otOKQYt05KFF9O_myX+MyAxE0IyGFh2J zt|_3NJ2zU6EG#(4oh5|mGewxyhZ6UWvg0H6Wn`)2SCeyZ*50V}mc74@A;^+Ly`y}1 zU+omti(DCSC#qroErqDbDnh@%g|+4K$r*^$sqVM|rCqbT@3pl%F-@1l>Xt4I5Akg~ zHaR@mogl}H6eddzPj67Wj-_&ryVfut`b`DTZf-HUa-+?d-@M(KsuY|)3-@{)f4`oi>UhYgd%o{qb10L) z0}kAzaVq?MPnPJ)b(%tiu6o9DlzaEW?SoAF{zkL7-P<3p^eH}cDr;wE*=qZ<=PRQV&t+nXqLs!(4 z+C45p4yWtyBegg$=T`+xB8rZ1hjJ6}c*eQCdq>2;>L2_xFJcnyD)p)3DUU8nK?7Fh zQOc7(J)8=hS5NJwEk<|NcPI-Iy33fJbnm+C{KXvGiVx9Rpq9p_2j=T9ohx3@PnDJa zmS?k?x|55cu5@#L(fek*21o=a$t9+<`PJDtF{KYwN40GwNoa0>orkIEC!XDY_cAyO zT#Hq=KRHX>8ol&6>s|~P&v;#u<+6LEg0D>qB5Y=F95?Y7%y-Z;62iKV+(o!+OG~NB zmAbGty1Y}I_OA<@D%33GwRtyNEt%ikx4tjdsD~nA|KjgaRp5a97uyFRNB}*w*jumJ zG|y3I_f$-hO_T={O+5lWFkxB0D3sPh8jaXvB}MZnlKRhaL#N4j>aUm>2ANUK&c);p z4GU`wj~F34zD2bP<2Ez7m%l38q~;CIux~MQqTL7Mb2z2y(K5G3VHjq%!~OM~ zcPyVz_JkX>5zTwJG)u`Nfs)ZF!!v5=M$HGVYgo7b1JZxBG#4pRRjK!k+}8Y_$e#n) zb+Sc{(S_4lw<7eKnC3wtt5I@;sshuucaUBaeO*P@)2Y9#3Wnx5%e)gfWA)vWhN|0* zs-zp9tui%SMCFMZo?BH0OtVn+KbH(KPtB-qexFUor}ekTNnGAK+KgZy1z)lYY>F8q z-N39O-V&Ezb?=4Her5NubP}@WnMDShJXd3T5~0IsNTK2}ghg0YYvto1$T%{{cs^wp zJ58GywM^r2arP`ID*q&L?1Qe~ECJWsjyy@L?_;XM;)Mr1P^<_gcGWQ?-6TG3xyyo8mBB zOsGOeo-=h&u=6~L(DNx;6`dVE&tcZIAh0^Ow}@MYp&(6IYbGxtj|~Y_^Fr{m!_Y;v z2NK$He91PEMwRB-{6c>z9p@O8fJ>%otyw)MD=W)#cxloGGGWev5bj@%U4&SF^cm9? zg7-r~$ZpQh%rl4}rPWy2l?>DZ3q2Plxg6S>g}hpRC6m%6;YC! z@z0!Q5;1Axq~!afnGy7L9_~9ztyZL?gs9OBBAWAf;=;$UxANDZ&PsOzKZ&RMlKc}| zIsMr%KjRFO62e6$QDB_Jz##T4NtzmHd|YuJ9oAOMtnr?VC^nUpM7AdU=;rOxT*YSQ zXZv7f;Yi3Y_J;Vdn*v%rzIif4-BoT>)qPnA>3vz4TMA~)-p>1=Y_YDwVf;G=w5>I! zMnN`Q1@4CCF$Wz$A2q3=3d|zyQG#-MA_`f20sQWDmd3)yderhtle)!gdPPY09yKhQ z;{2spfJndirN=q1uh@oXR(g^vYhyxSDI=OLP20JcFBi0_%e z$*|@fdhk|+@u>!^SJ%GLq%8Z8ma_0u|BP>2Z|FSY8drvdeIX$BR1%PSKb2Eim)umalpASA!lya~gkBxp=PaK=B(I$qE2pU$Af) z9ctTs4{pnDErYL*A6@mKQr-oji)mF;vUK=k>f49$w}FO_(~U0k{N(`Ll0^K)%q)Cm zGIg|VRKlZo6v?2cy?5ED5E2r%=$ew!(!0V=$=aW_3`umyRcjJKZs2mvB*v`Ziyrsw zFENk4cP;WiavyB;l9KJ8QtInGGAT>ovcO=x@5o&CUxr_r$^`qlmYLfhx9?$= z|H$A53_NtZoS_i#SFC$TCB?7S;F~tv^?N4luIsZ`bdyVU30=jGD6VD0D^`x(%tJ}% zFaPw|g%NJ-nT5&c?>u)OP$E)dcXWcF(`c2*dUrl_lR7kdx@da$syd70X{$Az_i}Rg z17wf@{5;_Pn~(Qj9-zkqOuPz_`|18t0czsR55>aGS)=+g|99}*C@I?Uwf$UN*M#fp zTj7qsEXL!=xSbp-i*zUZ!mJUU^&pE0v@$%@&4NT5BBm}`deSQwQf-OG$Med1poJD6 z>7=E(O+ha9Own#Utq}eBfh-~YsH)4Y{a7jznmU5M|%iu-iX)8nwpC$Z0gD^ z+$Mx}-+B;bU)pH@wwY)>LmlVsL_l7!2@Joo6#S7AKp=i9Bi0XZl<^nuQj_7+!DmNv47t1J>ca@7`AmQdu>;-(NP(&=$2Ib)PeM>ycTj6xU|%a^U2Y6S^BTN@H>xEtO_RU3ZO|*wD}b`%51d zBaKP7j|kd^b>IC=?!I9SMHehLLA6giNV+{BxET z2jlY;y`F^Ujju`GVnumLT-@GphKSMj&Uz(+>-oafq9lI6zl9UXB%maxbp2lIFZ~N> zBHUTlTW`y&BM+7kLEV^4N(SpXQm1ZbmpSR6HD99HLwr}R96(FQL|5)H*287q+AQHR zwjD3|k-Ag~4IxY0Y6Zwmb(G-^E0_k=vW}&VP(w$*YO@LISq}?<B7xX7!lve57{z-rOpSUj`)w?ZM+3d-#m|-*;`qb_frL=)*`YiL z3cp0{sFhc^#5(^pnZk)bEN4_=h|2~m+j2_}?}XC<5fGkRC^EI$<@6t_VQyO|H2Loz zL(DVtsIPaP$AleVTZ5KEvVQs2x%XnSPl+4Ph*(tJ_V{rqB<-o4ec8cd=|ml!d{ zKrkNGz(DYr#M%78_K~Zs^%jMY&p5ZjepL^Y@&yt^oacYo$R$?@2epn^cCfWNuk0}$ zeO)HMHI(jyC*UZ=JquHjFhz(tH@e9;Tm7UP_XWzIXi zXC0RspGAT-hl5}4eIwUW#Nzx4ViB@-{)*B77-q^tSEVuR-P0L|Uo{_d=FP+BonrT7 zaQXe~*>v~M+Ss_qoC+;J^6JR9@v^(!$$_UlX0_SIC+!7BS=ig(KU&Hzv4t1fYViEz zz|(k`GN$~g#}h>(ZG?2zStlLdL-#vMFA4{bZwh^7OO*>ELY$qxTc0cDb>z{rLB6?m zlZMFA;fLis_5Nw+l+D2vz~p~f5c+XLQ->IFw=cYQ8WFIMselnhCW=u$s zG9H#%NkcD<=#Si%$BF1}`!h?j+#0+~G}XPmK(M^i;V*7(X=jN)15ZV5sjmt}^4PQ8 z#5OMeHs*_s@_+?Pq$eZUt|w%shE_zHb3AV7nabX_qlGTly1?b_*ffv$&RFiggrMT6 zju*y7vbs#3FuiM?xP6+9X2+eM&MW%v;d9$tBI4b$t(!#O^g)hkAwz_Du99AvB;T;w z^&P)Ziv0;sllA4N2nO#CzcIzJBjpV3gVg)Ge~!k?R+}IlG863Z1@e7c9+~_vNXlrZ3 zsgAA*jIbS=|FcW15}Ke+pE)zSV@uQc7(%)zTy~a{Gq(^hN!x5W4E5}UHP=++g2u2m z5jR)-zCS1SBR3LrG(@wjDW!ZjQr*5mH$pD+>`!0UO4WeMz?3L@8sQ;Ko@siFnylYb zF*M+be|J*6%D+3NV3+@gAwDae8`D|HgzEAKOEWKPrIHYVbRwX6+I6>a$mr($yVb%W z_u?j4EBB2`!4*@r8auC8%zH^gVE)(XY1AY430PcRTa9K>R&_re|AlF!L2A z_IMm?CYh3y4(x638GG5sugLP6p;Pa(Jy32;6GID!kvG64fAUQDMzQQ~P35;+sP@NV zX(y$5qexY8gnNB{faoEf&+|G-BDpT&yxr;ZQz*ZkQjTXk=f?^)JL~(vUG$3|2IL#M zx07Gb-6u(xrpiO;dt+==C$##z?9)3bvs_r+&WRy%Nr4jkPCFHbCGNqlIR#m)LA*=X zRVIytmKZu$t!b_jHjP^X2?d8uo3c``ZI@eeeQP?!lMb-Koava>pyPKS27`(BjVzR= z?mVaex?=ay*E7MDZ>lFy{_)|v={HKJvuOlfS!pUibHrNl_OHs2x;>CLo`Tp~>*^2e zeYelAuLGmxzSjfk{`7itJJfWhv%fsSIh5C%G0h@|4ev`0QRtSZKBu4utY(L{2{pPT z{!#ggk_X1Dhp7ehUtnsS$Y?2#Yq zU^G`a?oc_;J4IF*FTFWRsM>#w#!6vL6vY7E%qqO}7yG=TpWA2t@%xT66+Hj;SNv!$3Rwx618 zCHP4B9lHGK!-XGWX)Kmv>7d&ANYv<2(p6G7j7`k|R3S9)ESk|@pw%7)u3hftg{ec^#P?i65UPVwP& zpjb3_@OQH0G}JF^=?y#^{dy?OvaCOubqDUkratbP9@YiNSm&Vf4%yx4;{mTBnlwNb zXJz*$qxwcaldSRJQP~O}lFnHvRBDKg&uM3=fNE?*_%OHzb7nA}O1Hx=Nml+%3CF_M ze4NC{@xz!Vua*@OuzpXlPy&Qt4Y35ui2kX1`O)=Q*cg!lw^;t?kb-MU!G56Pl z4LiTVxaA&anC5PcdehmQ22p{OX3qEJlym34nQ5tmB3IzuoW9&zPeHBS-|jlVm6cp82#BfGzJN0t5$w!jfK_JD+1FG6uX<DXYSZN$CemA9E3*r<#`MF zIns4=@Rg>f-_{~=lbX+U>GVLu^r1ftwP%Xdtho$HGLo4p*Hg+m0ReH2Zfs_nN zNp2XD=vv2-#P0{1;@^mhnMtxtW$oHx!8^;GyPc65<}15+`P$> znzHiJ9T()ENk4;AxdV$fc=U_>y8CNhkTcqh;=fu9=tPkF0d|&aj$qZJ2M{XaAW z*2;!U>?Nhjs_j|nZ56xJ^A~HHTyv9$S;+u$;J#vny1tRz@ouk&PKOkL8)QI6}XhxJ@`X)HpS-6m#c&lmFg!AF25rRNvFw$ zGW?^y{fsd=)5DrTs-Bc5vmiBr7A#c&NQDZpbdARv^=@lDH&b&`zDo$CE!1Cn6}3A> z^>x}{Py7X#ZW29VwUdX`tuz#wNg;uH{5xyg)S@~p9>}2RX+}J#BEawYPLpKEB$d^W ztfQLMc$pvF%HQbp)zg&SPe>?dONHJK59&FAQoaEcp)4a(zD<+C z^x8u=z<@xPmwVgtS5I=O>{r#q&ZDOIi8|2M_kC!(!(xZ}shG^h8(FD4gc6JCGI5&l z!y|u^MB?bWu;Mf4zUK-Svwcj}CO;d&v6MlMHNQ_Ikg%XtK{6u(a+KM0KlBF&2rA>69=tzNjUA7;Gx7ah#X~B)+Df+ zJrMEap4r$d)r&Ze#gT?KnSEV$rDwhUmeu(hq*S*tA&K=zSGHSu4G1>iH_Z*H-fGW6 zaMvR?JxjF=u?rkG&3oQXbzL`?mS9}kasee%jeZ|JV+lTQ_7&9L&8Y>6(RSCLhz6Lo zI~$55NEFe636wQHkhR+fmr4DKMDgy+ent*Tt3BMRmQ&nvO*FL;xGieV#m`cJqrO zfrVb<>Cu#1kD= zs9fTrCMhQ;x3_Ei0+gEXzQp;r-2T?v_uqTHPjC#Pf4^p+b^#(k(^aE^=0YE(m$OST zFyfsCtQrt;%05vh-5!)$iDO-njqY<|tw`_5*&fK-flm_)QcpaGqR*ef{*K)bo>D|g z!P_kfkV7*!nlvJVoRSp{$N0*f>3;bli&G>0PQBb&I*VH)eV>xw<}HBPJI;^wE-Fup zB%#M(mQ&tLTx!g)!w_xy2=^u#Cd)PA=+xPqKCVRqmS4 zfmy4LjpUwp1s&;A8FXD%TzzXOs<=!Kx-|b-X2e{fO!?HH=~Q_jD8h%+;i1@T2b1ll*2SPVE*+@YRJ-M47+u72A5pWdh8#w$!*aPg4;kAbmM) zfQXlhMF#*!CZsDR1NFQK@S9)OZ7*}11Z2$m`vMjmeY(OfwJOG2#`Lw%ag zuf5IlYzU8%;C%F@o3Z0avbT1S>G%KBk!=<3k6gctG#-^*!Jbsg7(Z%e@mf}o>S4n5MU!S#y-I-)F{UDY{wv^Ioa8Auurj#2 zbBjSKe25fuI*1n$=r`QX(}JGJCQF0Z=9FPZw;?$0Ve^a*gld1K$78pZD+vswcD15h ztG9&a;Cn5&b{Y(pXZ$C-h0mb^Loyy8qOkF zN<LS#o%s-l+wWhs~hhmVuf_>yGfX~Bfx$RMUpSe%sRsk zV5KV*z>;={Nsva8&9j9*+n~Pe%&`2Yfd)F>kL!9fxHXsKL~ISZb9Z#{I8fB*(Odyy zwcl{8v#~NXLbVA5D)6|>RSH!unN*inNb1hx`#7!W;?eQ$l-cWS)c_~(?9$ipp{_C& z2yo<>}&aTSPLf~o#2^w*1Q=jCV2&TVGPQ~<0Rwgf?iMhMH~q;PLZ$l^ncI( z)OV+pdgdrx1m)zLb3sVzWM+K;T`7q!ay3p=FJ3BYkja0{o|$|jB3$Tax`FLaiu>DS zqs1#w+2cw#fvLXjkOHFQlEcmI^K!g(c&~vk7MRZ^P5Z%#H{7AU@jDjJU3os!yG&mC zmmzi!+OB;5q6#ddCiF-V|y|Uqyu$si2CM=8H8JTZBNFg4c5+e3XkQgC8u@ z0(++ObYQT4@!gy%=Ov|~$0htd#h%%>mBx`vxD`@OQ#SG|_Np3Xc$NJ9 z-rQm*t!I;wtSj85QR8@j5ZUU2%~%*IRDkK|nDkM{i~LHGU-+CC5e5YsJxjTnE3qTr zQs~z8u}d=!@d#3zmX*@S`*Ct>{_p|#$;TNq_r~*B>tiRv$}7~m`^mpX?p~FZh9{!- zWlh$+9`hcV^gr@Y$vehUn`y~BUIN``^*t_qU)sk!=@XQv>-D$a|xKA(p;$s0!L z$P4kehocn?3kxe$Lh;(e7Td^HCb0CMQFLjY%Hxtue|+(9-#wMc$pPK|Z=7LWQKxKV z$Af6VMn$97tlv51I7bPXj8?goK{3Fj(RVvKgzI;={NO)0o0v=bNIP2heKS6FCDehBxJez?(+Jwc=;IpV z!A-^6bc%^Q0s(njVyM;>eoh@VVoX;^412IuDhGCYNd=v=!m7_WWe%wt-_6m@9~Zk0WeZ}IetZ4uoX7d&(bUrLqB4G69% zrTwZ*wxHz+kLDE3tn9uPZ#vU`=8{fI>tz{;Aj;(BD5=`b8QEt#JsR$g;#}|+OJfoj zW!-+)H_9m5QQA5h4|sBOFrXNRqc8d~ORvw3L_U#U0dhKMtI9PyKEX_v-G4ct(T~4OvPU;Hq=!O4P)LDuB)h-iQr z{q;4kLfA$KM7ib$0$;>udHZ{hoj!V>FAsySBjoB($@S_1-XYd*RG9Xw@j_~2;=;z+ zMYGC)6T7W=zIL3PyBv5}j5q1^I27~IQUbp!j{~Qu6l1LJUBa%-Q(r|ZHneH3uB~|m z?J%%C;K+xfihZ)n2_l4CCvW~LbBz8KYZV^HZ4wUU95rMFvUSzxz%eYl>BEua2RH9r zR<3q5BlLh9_Z{{#(`ifDiYfvQbKQu@NnL#pu=tv=87yVc0Jmz|BWkoSm(iU0%>uVKC*u zKJF0O0ECbXm5r*#)+FI4d^71Y@v9int^z}QIhZ!bZ`&KbA0a4;GFp1LVSl`9@ZeUU zxlXBHerIaF7M5+`%OVr{SnJWOG@UXSCy6b>*Vg7^E(h-`x*J2;ej5-dP;no-zwT2@ zjl|c;051pP+53yjG7}kx7SQBFFhi>Vj!e!*gFx?~ld$);8Aason{^N36dMZ79Z59} zn``G`x*9GYwN7E~tlLeX$y;2tAhJLznw%Cezeb$2>4;f9)6aOv!);sVqZQq|Va_&? z?Ss@KB#c0Z>ujebvo_*JG*4fnB)*7=B~v|?wmjPr`2eIv94xHACQ?^!k`qb@h2)i# zl#LUg8<@L(17}wEQIfhlWozg?)){KBt1RsZf5T=ZZ@<5)%$P8T_S7>eFZw7{P|^2N zMC$M5kqgktWVuJhcG(l0!BoJ#=Fq}&`TlcM2#T4yP(OBJI`DRx;R(TuopELbm3V76 zPFQyEK35?rj%24n=H|-jgD+E+#pLKuRaq);MzL|wHt%Vi6Xe$S^S}H*uuY2>ODkn%7YJJ zs&NrB!N9vDrVh|$VmrJU*G#hVrMC=J=I9ge^^}oc3abAvSE~L;ZzA2k4XD4W!fx=} zx}nPW0bgECpldioj-KDg zYLxdZ&8Gq400=DlCKvwq$DSj^yWsMiA%dywtp2(GO6QSN*f@NdKXg1|ssYZC|v$%y1sSjEI;Z2zhElCWUxaQ~#~3{tVSTYMp5o+UUb(!7Cq zG}Y6{mOv|EvCnjEwE5o(!jWsg>0o(nl17EMF<@JldI(;^wb$QlWVo45u3comuQ^S= z9&V&LK^_^$YG%fiL+yoMQ!wX2Ru=AIVIR8*34MW3WZJVY`u=`&BxwypzPq`I}#?2asLzP3~tF);TmCdoZ-sQ7ny4a`*!B`<5RvXQiDECnZPgMSG&TK zxCdRr@&w=ce21wSsL+gvAXsAh!Nw5N<4nACIT-xC)eI@++OTPMp9z-e)c3$#Rm_5 zBUi_96tq$gP7t$5ED+ZmCb%Z~9zaj;8{9hElZ1ZY5C}-Js;8ESwQpkzu8K|^iX|}Y zV&ifRrmX*-)H+KU@J2okjy^~>8KgV=B%p)WErgcJ)%UkAc!ZpOA~FW|4qkPIvJThe z)mzED$9w~Af5WNJZ@DJEN;iW#98u*wi&b0DU{4TVCB3jRW(XC5_%1@@DeC4^QtQC- zjI^JxYw0Y*M4VdnL_f;j(Te%L;P_s!L>v=Hcy(;LCNg-($Rw&NJf}XijrUm zV=oNBt+`)sC_o$B;+0M}!vvZ>TrEH|#FV&9HajT+Cberq2qWGU7qQq~lar=%a96aCgCo z!Mwq?eG&lhFoib8dbr_$@pmc*VuvpdbhWWdBB!LT=+9CV2@E4CdvcKg2T6}Yz^v&k z**cq{ngg+!(!a%O3IHy3c$WPs*bfuzB&7(X@l}?R7)vmlt zsh~8i;%~)-BAp_g3U9fq-dQ7$*t!V6Vpc(yVyE(J%M<^dFLG#Tfq0U5>@V7wSNv3V zee(o1AX^Z-M|wzlJKL0nE3-Y4ia2S|nC7pgiI$$D1%RcNWo;u%qjUp`Wuw)dg_Whk zwET2-fnJ%9w9e!JGw_GCDTfpC4craG%?WN0^PAD5k$P+yk(1Lnbyh8pFOPTD_bi?) zULFG%t+w7at+o?q0+*bl?K|t+;-iU$)nYf{i#yG#T79Edqo^Tbyk|v{-_0{|GdU&Q zGVkfW-2r*Rr2$Ld>U+6^7DHu41^Z?DkwZ(6y<%|11;j-Pkj2fS_3Ik6-YTutxli~i zrZhLX#x+el=33U>dj@7HHjK-pvPLjf%FEg<+Kyr7)aL|P$?K&|Zze3qiPKfa*C(J4 zGR9ZO1+_G_DYPqpnm4!`mKlvS(f_Qh^|lskzHS_CEU#;`k!x^mo~+xj^y!Cbbf`sN zQeDw)7PHZ_32D-?;r)gF%Oe^yrUKt>D%SMSF4a!MXwhP-A+Eu|a?||Xv}5@(>FVTH zbIkkp)=vD{&(&>kL9tQGuJVxSkefV*yl#nf$?Bx@A=;tXq}-$(^^*LS!V<@J7h=Cj z!WcrTdg?{BZ8gTC_M$!~YqM%I(Dq@iajjroqt)P=)cvzN{WaI|)!^K3)~TED!yJ8A zeJ%axPJP*i%;B6CukWeN5u8I_CCzJL`-y+*`z6k;PRFjQu6+*7{tVr$?k?`yo#h<+ z^}NgZi~3XK3T&z5nr#L4q>$<=nkzaedi^xD_qG?ioI^{DkB(1|?@~;i_Q(So2LBBI z>01Y^z6p1zKAj@?E2;{6#2;K&E;Xcfv8Qq*~1@X&bAK1szzAd|n$FZ4%D-_K4@m!=crllYOrnnZNwU8^=Y*j4U0j z3ud|&s`o^e~Lz0$+Z^x$)fVyZFluS;3~>}(N9 z3MGRT1KU?!-K9o8XAe2BCAjct1EJ>2s$btb#Y>q_(aq=togdasWK9xRQc|+F&Y+&l zzS&UDn4fy3yuo_cFPDj?#(~ECMz_Vk)vFriO4^DmjlQ!_p~#iUg9HNBnXOlj%fWSL z8KoJ<8GHNSeYuPYj+*tCDiKA85|-RL+o-pcWE}yUeVfkK2|JxL*Pt`X)$Vh&^OkN_ zXEV`cF|}oeo$438DL3j<+vma8)Ia>5Uefp8n{+F5n>h6s-i4$t4X6Rors?dhXf|#aps|Q7!v-%hC0ERjfKBSu#9s z&o4;{Piz-6 zY~9z)&wngAJQZI|)Hes(>UB(X`P@zJ@e;Z1UTk!8o@KuXT)aiWE~9P;jQeq2nqL|9 z?e0+jQ5ensBUtq`@zl)ITJfT4rg+$BRy#%P;?S=D%JBNCBfj z^mfCY`_ANn?y4eSQOwW$rFK8&cZQMQ)2l}nV_D5})n3)kdig`!#e?sU%e+Rxw)f+q z%s8l=NWl}|jfcTknbpOC8h)tyZg5w!U-R3>3;E8Fkyxw<*?}aNXcYvC3L8Js*1A4~ zCkq7B30bL1nAaaN;m}P;(a-M@VbAAe4$!58p}h-Ve?o7e6=O$1&c8swtmbnG3T0&_ zKiPqcd3lkC@(tH1x9df&HX!`xkuLS}6_KpfzIGYe!K^{~r>t%3`zj*Ux(%u#`}5qb z^1l5A{l#HF`x0cng**DOu7$Uk)N+D=z^44?gp^XIxP*X!%(76`bk>xUy8|b+@s$b>ea72mFhJ=cE2lGb4cXUo6g6`~XckMN&~a zM-x(Z1~vvJfB*t1DJh?$u_=!-Nc=y=KkoPe=FZOcJdBKPZf*>2tPFOJW{k|-+}w;z zEQ~BHzz+_flZUOdp*zsliTpp5{Qr7DCQe3<7WU2-cDAJd=r#Oq=iwSCdU8L{UOTtPb-h2g}aHhCdk6Z#MbG9>ynPNARvSwq(H)|?vST?(7IT9Xe8}o*7TL(so{#)TC3 z|KAEYYBMkoUkbefnPu zS>wNW|7V*Ta7?C1uhX76UwpucCNwVE-{W(a_cOfUl~TT0Xm-}t-k^-e5%0I3q_u*6 zf4bXkwAsUYp`M^qlXt5?Td+G`R|}ZKiR|nH(Zs(;*D^EFf1(61LT+wR`yv5$hDgO5 z-XCtnxzLCylnOwhU%}*Buv8@|{GSBLE)C%t@GuYIG0)^gfs}CaO+3w zxC|yd^_o@E9dhw#xaE425Ihy?0Hg9GZ85xHB5v1DZTCmOFiIzT{~7Wykur?IeI^0s zxE=#BLdznbEn6yw{yv zH;HAisA!#V>#6G~sX#O2r%n4E|2K5E{!Jb-@YOG|{0y8>5sI5UymygBCdcXCw#`0|Rco{9t&)rT75F zB4uc9*%J!1=gVCUL32gPAQS8xxIHT_{7jOzK)uW#m)|ZvOB$05dBen-d=?21ie2g7 z+OBVo?`4Kx+hirfq6~Sj)Hvr0%AfcZ6&rn`g#*)6c0I&%=lAN`7Dt1$sh36eU6xmp z=M4oEoyY`w*ea=k?Ks~3di{%b8Rj%&iuJ46=35Yx;WgXk&fP5%{QG5a|pGIT*2k{LLC8|+ij*A$8eyWyW|KuS>?^@*RB zM^ja6j|zugnwqkWiGvzT5{KZ&uynYl-|g!)6xD?fkOft>GR-t%8XSv?0uRXrv%o>KMM zwx&s4r_Tb9kHR~T4tZX4j%0uOUQ6sqHL|uHH;Rn3MJv(=_pAhF$hS^+5LRP#F>zul zumUTO6G9NpU9(ys7cV-|Y>3vnRt)kSP^|#ZocGJ~{nwo6%a^xjY#}9$+nbww5D(}c z`_}hW*us_HfqPa~@`2=a%31?*O=oM+H#iLF!eDZ-z}ET_(N>nCA_}TF<8<$XH4j{7 zPr~>{8hCUqt1nJebdO==eU#uLf=-7Ubq5{%JQ&yc%RDl`&siT603F%Y1K}#r2cbf~ zEefVnCzAx@SH$%L8$+~qLf!+i`}y0Ky25C9H>$&?(v)}%ExUIi_ZuauMv1BnxT>)SQL4vMFTj zQVLV8+Q~6}>O}G4ki%q3F<+*qvhGvAxK3ReB$lBN$rhG!8&U^dpDy=KO}@S+D3Xrg zsd7AtJl2y*CRb%CUu+q)ypKdkiPm=DZeLz{F%%mfkJu4dtQii4P6TrRpF~zSDhwi#t;ps zwSKpDfzARnGq@3@W)qwqQE39=ke);AQ%yP_NkBOc>SX_Yvmy$JkqY=Lu_-*2JO%Ql zsyi@50)i(JIXIkYQ&m;3x1C5c+YX@)iJt;DH9Cvy@GMOa>?lTZA4T+9)Dyzb&p8g2{U8zz{n z&d|Xx^X0;d^E5$4T7F(_-2ubOB~V?^eKS!HxsvC%XqyZRc0*)*s>7fKSGR}=YqS(U zOz>;sru@|Y3E5@8MEG$M)J_T=-sfpMt~qEJp`OlNG=m~^R0&PC%Y>mw^9qsL2@mf-s6M>6-_Pu{VqB_T zq+EJIfVr$FYJT(S$FR1zafNIbszhcdnOFG_d#eN!j|N+8Of8^lL%)cOal5*s|1xkE z7wi1$n0F6v56MnRhFH+m*uA^ZU$_Ivc;0;j-7t*#?e)d_39$${<_ ze0g)&Em1f1J7J!Aev?XVG6+M26x7F~Eic+_h@>H?O;i6;upiArY_irga)=vAFZSNY zznuO3<@>L2NHcjt7+&6co$m-eaBn$XCk$tPur)c4@DuX0Y|LZ^e<{A@aHW^=0r+~} zVb|JkAvgGLpcI;G0G*;Mn(_4@k#OR<4z0CB9f8Z!Skw-$H@t+RIOMeJUqM)<&`TV2 z?q&-6bQ-YNo>C|xM+f4ugv-{v$zV3kHLuqKO)tD~V#QID`k=by-Ck6_=7D9*DuXq@ z8*;98Ul`6ByLfI7Bzwnb=--*AK*#v&qjemvsPxn@yRIIYIEdi{02S82T_m(amfk1A zj&hTJXa)CIGKlZ_u!q(Acld-R=>={b+Y2(C)Qt@LM5O9$uTS5u0X!GOI^YJ=uE+1| z`v+0kni5z?;ggjZLouJ)YyABAIR%9BoE>t7^Mb#b?PU9i0MYOMa@_wNX|IW=Rbm^C zJ*!R>gdB*;^T|ogwufcWn}}ITnnFjN{Fc+Kdp#ihrPTASe z#ZylVj&GlC2eAOG)ud;Si!SOqTuwg%_bw#*pqkkRlpGT~UAkoDvD&?shy35kR`0;o z8i9T{=Wj_wa!xW^`~{5_+9DLO*=7mVUkIm=)cm2p0NvA8DWH7b##sSsunI%+yI14{C!_Fleal*1*Hko59PPIE{(pCpra9 z3rW+gUVpmc!iygSjAn7ur9?%HCpvL@(U%`C_;bz69P@!+=#qjw>Wi(K=vsQNWbXS) z|F(nbbXJFinr?e*s_q^i;qS9tv8~{tp!|fE`?T_8d+FnQ7&z!R9bg2Wo^Kcoq#h>jBjOjSSbjz*#$f5kxZRM zkP@oNjFe+V^VVC>`SX3;#$mZg2~X+Q^_kiBeSyYz(v&aHYYmo$lF9RzX(`upSG+sz zhkJ4@t`E>1zuvIMGSDZw>xJ5qB0|)cmiLpV5t_@0I5xPBiHW-Gan|^Kdd5~!1$?h1 zBrMUza#Sd4!vfCAhaap@z!jI*F{$QnFl@l$4vN2ZB{OV520haHnSqG*R7P3NI#j=B za)g=&8p0jX^gZ}Nr{nOc2pY0Lr-LVQbbhA^!|nZ4D$}o1H;dUnolj`o{~SP~z@OzB zzm4x`C61=o;?K!+gCorf4Jt3;h~b`eGPX5k!g9{tYx3!sp|$-$)i&?3(QO zItFjfBBx?fr_8RRXF9{tfd~|G-(ah(aDqA@qyk2KGzpFL)Q z7A_vWr=ekhY0CFxu4O1_WZLv5@iTv?6tXV|Jp{e|JfNJ-u?hKQEW$(IAv;MjobHWP zr)&Ht*FAe{F`xFCaHg_hV~l5Jm7^v(9VxwuUo3mz#y8*K@7{=FQJZ~S>5mvR!M@YD2El;WpBA^r7?fCZa5 z4+U%ClntMk(D|_2#8BL$dS?L^H)b{)eiFKV>touTHvPg2*B3O?!QbWTp=n1OE6S}` zJFN5BS7`cPFu2AJpg>1YkgLZ;28|hY2{@WP<5|*N773vzsxNJ)=gAf?2Buq?$MKTI zwS-_?2$q?RR24C8(ybyBshG``&Hh%|`Hs?p#iiq&&&Qu#qBXh=Io+Sh+)f zj1!JyZJH!AwL>ID45=XP*%dZhMg<4ImyCVL1sY&79h(4Jz-GF~`!MuiEud z-<5^aCfEKZ!?%(uSl*COIsN_Zkj*utT4rv7@frhXkgN1|aje?)Kp6ik3jrvDyly`16zX=v z@Ark*>ql<5m3&B1;b4#bZdHXX7s=AU=|P4)m6nPz4&o~>reBpn z5?@`Qfs7JwQl&ya)VL4`GYv`!Z!G^K322}jY7W8hU>#AyOgRq%-?)x0_GYPy!78>N z+@g(`=jxRw?{}Lyd>0Et#W^5QL$6W9d3+hX*Dp??~u5^8&jy5(;8kNkaFtRNlB6wj9Wob5!Wd|<-k~E>Hdzqi2;*azB7}lb>)uM z-DElP9-62Er37{_Mj-`Vr}IO*mrAT5v-E5mAPe!DPxYc#_CzQ4YW~zN_C>%9qAS5R z8m}qa(MBQPt(A&Y_MRd&V8})ehCY=1@FKr%$o++?XtOz&QP$eVk@U1f)4k7t9x&>vA>svfk@oo$XsOP&-R~zjJ zCnrDcreg>khGS~b^W8Z-(P}eu>Pt>U)O7u$g`PLzk5$S@1jY-Wz6jXYD101tvwn`f zuu|F*^7HC9rlQ|2YZq!c42IIWpfg-df!wC^iNvW-KfadY5k`9Kk}WHZb`?!+FRf?* zzIs+l#zV5#f(t;O7sE6eQ&J~sh;@1Q7);9Uinkcu7QX{Ht$T;vG*TORUUVAGJ& zQd){7pQ_bpx$x)SBQG;V(NCFOClP@G5XLM%FLDPZ=0$^4f#`uTbMNmPy0t+w|KR&* zZ~xCfp7OCGhOtMmaCQo)?mk<*dfpL{mK(I$6DQH)vBa!(#0=#< z6e8zm9!eBLS}e=LBe$@s5|g6NtK?FF7a|fkj>p+?a98qpZqw?Nj28iQs5#vse0SoJ zw@Kk_lxcH3{wF$&T3!;*#v4OGn?hGKJl)#e%CCuR344`N7ywwyy!+@AC5g|QKBqAJ zRDYhuA*Dr1lQ~VJOMlw=GP-~jtJhT@pU&C|eV6~1dHWijm=A-QL%gf_lrXdaYEZ>? zFhj=hWLi7!_IHy`-d(=ods0d=k7(5B^XcpP6GQ#Ut50@#==$2-vQ~~3ObXgHsdoHg z9aRzZ7GgK^B=8qkk|G1#DweR4{;_eTG4r+nD?t~*?U$820P^cGrwi*^PXr1E<$`ln zh})rfQJyb!|Hz(E>bVhj#sJSA#6V`ly8%?-PwGnByaI;VH#(F40GXfGt9a-Xzt{7{ zmE5DWXArsals?zqygwmNZcba-j7TBLF&Ga3ZI0d&MEpUcGKYIu(NC4w>A88{(pmv1 z`8=`Ol!20>QrIvfn5zY*3vzs$SYTEo>6SK+La?d2M^57IvjiqL=$2tie{dhcB#7X_ zphv~~+@|$47Wl;H@Yi>#mYx7riR2;GU z9t3LfKFX>V5_=6h$4uv`#=AiyHdsuoJ|LgYEY|%FMVNxx4(m4Q4*zMz{2R=$2H6q0 z$3-AcC9W@tulJ&Gz^GL2$W|`N1*3TiZ~2=E+~W(>X*`8nMg}4VSss8)xx)j zeDNdJM=~_@)?CAkk8_9GiumP?fr&fd|ibv~b8_00BBS zqflJVGIp_C4Yty_G4E30!3$Y`(PGJz$dxcz5y%r)sGM#EB|$KYdBtH(f@EZ8r&Mfz z&-|Y~5*F;JP})}M*c6%obpZsC;Q?kZO;4$977?JIZ7MK7JT8%M4W30BOfKP-{+eL#?zhb=y z4_MV2#htJ~^6}G#sV4P;@1ZF%U7auz*z3s7>Jx^mg{piJ*IbKHF{DSVSomvhD=Dn~ z#L!r&onxI{bkUgGBMxq%L%E{ZKmg8%af%+@v~#p?OF29`!y`EUeot4ve_IeY-Urjz<5fh>5ITJ4$BZmQI)O90*$EBt&WBS zc$Ty|@Vvy?(x`(CnfCnf&J$ERG!L1SPmpmUC~9~?OpYOKL^)fGTt~RxGDJ-KNwjzr z`I!OjpxL;s_0yR8*k+x0)9RzkPxmpY8NS6`*5KCiwkqc;iaO^`!sq!<&*CD+V79rE z>Ld0aR*H11EsnzI5`OaE-9zr@2H4ZQ5>2H64-I}Mhs+iGHi`3~6j_VcY425KGMkdw zLhrfWv1!6papiVheNCP=_9ZfKlel%O`28S(g67Yw&+#KnQse^>4NJwKSq|4y0|fcp zQ1`>k^S*)9S;m3q1*i*>kz2@^7}*igo!(S9N7LKzSL_L63rDl(aoc$6ih|N0IF?RM z%+xc?#j#&a0V$F{DU~)3G5)gjXM6DP!6O5%Ts$X(WF{3rj_hFMGoO?dv;+YekK`ee z7TYWA^BO*kXRpUKBJ@TyDL>wZNks%XhC-1sWQ_FTl?ZICUadgMzd_`6Y+5N$oso(2 z{Za`rD!fu!ArT(t8;GsB2Gk#)nBN{%t#41b)b&TOGGvU}Za5mubta({uWhv7?RRL@ zW#{3SY*tzW5i_Y!i(BfDm%grEd-?)f~R>?|OSv`+M(Y0B(S z4I6p(iFtNFpSZ>bLB{Gnp+G%xA&GVn8`LCLHt_RP=W+s#={Poy*j0jtwszQ(E%+_l z`XU3*@*swBCuiHA+lbL8N3QDdr1hXxlUg!JJ103LX#zXQmIX-FDnNs?CvCD+Q~7Gw zSFmU>;B%>?Hhko(*tIEVOj$2m{`@&TeU3+_DBf*(K(bPD9_oI2hw?Wj2Ec0Mp7*{~ z?H=xzM|>lQgUv@BW7*8IVwlpR^@zDr zaF>kjXPns~Bd9Yqqe-tK-+ zfCTD67r%ohR{O8N5&0bKFb}$0t1NV*Gsp~egQpbGq5`kegLMm)E6nHabR7e-P zqM36!;;-0!u51KU+_m3HE!kKjosLoE2q|c0M0LyI<%?ojw;m~9Kj$ZHtbrT0i~;l` z;jO$TJ4IAW%IRCNO%!#?dd87$UzlagNnkg!(zdt5y5@MSuU&x8#mwaQ7N_#lgzCRL`i$pb4U?aG+yXsSK0gS(`Br1Sce zG@i6;9CJ4D!sa`l6nyl5BEB)UAv-gi-%xIqVdh>&n%noUfa;&z#Ux8Pcbd8KsR?wg z@@DD7H2bGNqF^~6Mv-Uz($()1%_>=o=~k%;?DjF1xr18Yzl_4tl$_+?MX_purd%aP0vX%M_=BhRuC?!enLHoF2l_8 z{7nm}Y84bXN}?6!?WC&Xug=g};;B-)_9->2WS3Le_zk*;uynP|6;CnNC6~YrKIpcj z5!@!u1i^BE)CI|y6UU<>_(^w(F^r*}3%gKgA!;ORwU$`gi(@zRk; za|`HHK=-8gtxq)qn**=1PPw7Vz{2FJSH$|o7J*bMcnT#;C>df=2?78CqR z?buoxbM?@N{V^|{QIZ{68`uLBt~J*%C(d9C)UlHl>N-Sin9uZNFinx8D1-0xkXEz2 zrh$gn3h5i|l3WuJ>>zbdMsw~ypLtuWh_VL}Y2J_jw3@A+RV{pee{gy7B`L&0MrMXC z5Gm+a@-lc8j&WB z;?ln+c4Su77mXy9lnVFW`*otRHe<5cT>{d zetQ9@_I2INrKL{E&?TpcM`YHFrsi65Nqhj3z~b@bAq}-Xb`uSMk(W2q>R5)8_>mNQ01K<$sZ zlr;A9y$a!6Pef4to@@zwKXJS1LMdyIg&KIc*7n3kx$5t8<1uQUcxboL6_Q{=7x8#+ zqtox-)hS#2JMwFce%$(+zUU<3vf=Z=owgJg5;_y0&R3Emj4Y2r33IugcQcnJQa>oQ zMj0aa9FCeRZ&j$BrMEVxA{zJ{~iK;^n}m8&ITvVokayEO{Q-#hcM zAtY`Sis3;9VawnM&hdb>Po!9ylxT5v$wRm_-aI0#Napg?lR+Qz-m_he+LYLuHsLMD z0u#G+`)!1^tEXE!W;JCD*{ooXOELG;I@Y0${rYA?(=U8$bc>y-96;Tu0H<*MlqNoY z{)2mto539hP>_=eCir32JgHo+jvwW@-Lpvk)a0i9Db^q2{r zE(}W9s$(9G+;E?WXvANhzU6KJaWHRGpt{$X?}QH*rx1eZV724)h&xG12(g?6lR>U7 zi%8R0odCMQgsPU|XZHnxr-$^+5s+apXF z(r9_m81B99D=F3J8ukI^NjMFpN4M)~ImzX$=cB{X_(Z0rsBzIlKH-kLWI#dPOG9UM z(8)7IBEDA9gP0YO{@0V*+suV0@G;ZK(RrhxWV@xfmPL&2^=zkDOZxESrt>FHxp`Fl z^n9sWPyVka`7dmbl-yxfjEDzpnV0UjvqW{jaRECw0Laz`!yjDDw{al2ubtYwmKJzP z3>3wK71T{(RB8x#szxX^1En^v;o6HVA$5J*gFeXDQaHsO%NRh4)(zQ{Tn9>JhpBtw!ttVLIsfhk6W;-BA2qiwV`3nH)Xrov>7&0}oTOehW z+TV``c@3*&tbSUY70yP?o@E)4$*ho8pqT_n1FX(`Cbhh{;+riJa3o41T&hRw8Yc;I zrCuhDo@!CjSgl5YnMt{Klc0G4JuM1q@VOKB?WK>s5(&4iM?%-N&@IfFMT0m;!-G~i zIfYMg$DWV(ezlWO@lnI%I@G4Y(?P;uD5_^O6>||k37Zj}tbvbYA^2@NA?QWYbfn+u zHS#YRWx7R$n3S=_nQNG5(bk{N!h5K$SPP4r`W>H$ z-c&|!in9hN&&Vq{fU)5^V<4&Tj|7$D1S?K5Y;~LK=K;^9FZs0XZ3SfV`)}gE-!2^o z*&EWtTG&4ZwV)qe6jt#ujXDxsV3% z)-2k%JN6TNUzG@OXh*b4sr@2#?Ljd{p$%FX8iKw4!a%lT;X_}Qh%7(6YQN0v3B1;w zuXbL*eM~3lh?TG_BKPx9TaP%Ate{%}OS{OJHaYtc!#2)(f>!DZ9^qb}5P?Ii%DyT? zTj7;76UDPu4w7tj(yZbtHY%YxVgMb@+Vu#KvDC?4Wo>gAB}iTB&#*U}T>jB0t&L|a z<}q5;GW1oyI!?3y@>;**Dy5ofdd}$9fEI#zzA>x{Tj}c>zq_rmQn$!r%@Fi&WEylP4%zv<7~f7NWjQ@ zmyUx(?Y`)?@)HOTo z8OXIVjT$&mWXlpM2;AO#xXvdejG_az0p!@703^;RD8Fj6gm+`y|K#vThz8X zy4K-b_D_r~Ztz}JJnn-(I|oobQ1z#>ayXHKov-lf-5S>uF<|Fu{+K#4Dj=N&m{o&+ z2Vt9aiPrm(R0b3dP9@W+`+tD8A{!3gzBW=9^ZC*)_Lj5PolNUkR6sv1Z-lfUhtJ|A zs@jPq=Hsj6|t+SU;srAgHE;itm$l5=m}2NY~RC?C+42yEF3_v?n6(NP0xz~)Si^*ECGzK8$Sn*kEGA{|`Cxx61!foc; zr{+U=`46CuYV56k(m)a1kb_iU$`4P*!UpLuoPto)fZ`YeX(dBPRZGzkUS^x1{1oaV zEq27}7;+^mW4GL2k(u1!`15_Ob$>+%LuEgS91G%l=w21X`1o%x`n3L-`BD)sHnuj4F=0Z)uiI6H8o!!y+ zXt}b(nP$^$W%YiE#fDNubMr9%R*NN~*vub}+CxJgOEC7*UT(6+@y)TtICfZ?bow*Q z2g+p%$D=AGQ%8x9`!4??gu)UalO3x<(Kz&4x>=BFBnXb)fYr8>HGVWm?#>#9X%h@} z6Lo@r++84qai}-}S|mM?U%slib5exC)rph0o36v)@*36+OIYbzR8|Dc@|E^|C z2pdpJD!O~YJhrF$Ei~;^8{4#(_nuM0&l2wS{8CTo_HEE9sAY@cp236a(C6ZyCe7PC z2GJ3pWC~(}?MubNY|&JLN^0{r=JixY1NOPEP~G0oc~SF^9gmyFT~RF30^NW66y)a& zmod3B+QUx4!57>5SorOP1p3moG2+# z_+Jb7l)H}}2VSEH<6^7!IGXkHFHrYWXGywGfV0(nXAEIyZ3mQx-6!{2C?s8XMTEA; z@F-1UZ<$bbmZrxYJ7v0W8F4EQ9@E7*j`;Kb7AZz!J$>Z1QBMiZE&0#b=F#lGDYsM0 zrjUcm|A~el^P$0Kj55N##B>U6)GNtjpBH+uFX?($>M!=+ssu04t(&HATUX1?9QA5C zZXf(EYo7JK-x9T+&+}JDILimwjTkyB+bxKq%X4)$UuS6-939@%Wy9>xhO|#{w%Yu$ z3rJcL+zMlG#C+u}x{rocw*NV#31o<@^Q!bUWjV_fwcC4g(}nk>Eq^+Q>%7IB zD%U%a=}n>AFWKcEeC|Z(hCBdyQmMGMTi)6vUZ;HolKUEmoOk_k`+Bjc84cHXY)fY- zgX1K}j^A0f6Z=W4??p&v@!ZjG7z=w|ByN<45ccr;+rD=zf0Rave8O9QYYPr;J+SF6 zXah9ZK4wV9eavH9wU)|B{B+T!&TaLeA3sM1=9Jz!-zOicxJp<_Z!lIMO5iH!z#?6b zqyG(S^(#zlOX0=gT);O=_hI&|guQ~>`zG=um`@PT0qY_=j$j`q~DZ?I0^;RrI61m**_@A9X9B3ocOH>-4mrqrmqR*FYNL*YK z7n|ihhACVg`bxx)kJ`VYoAaat>Ta;A2W?!GN~rYNa8qC$LA3KCds>ktPAU{qS#i}mjK1`TYN(dUK}xhFS@XkU z!70Pa1gy6Ui8DtN3~(%rIJUhJAK&=v?CAbpFUkGuV-=XW1+~ zR2Mcald`42VP!qg=@EBsL>#K`Ca_$93lQbSc0$;GGQyjDcD>-UeW5yR z{ey%9B?drfnFvuLDqRM{CcsC!vW8Q$gz86$c}Me|xg6RFaD+GC2Ex3sNftx0c%C=1 zWk@c5zf^AZA*;$kcp?Hd4F%sh>ZDr4i>>LX#!~b7me6l_N>^t{W~SsWsLQM5^|Mt` zz!-vdj#_iOw$fFCxY{mnh8`XlJ4@IM#f(!gxX7DVm09+#cd{5vH&6fu;@-a;2#5>r zGY}Lv4x!AlViIOp?p&oLJUM&!}wSP~iW2>Z5J1|aMci*c~ zUX)EZ5ad|4?ux>M9ic%jLVNDIvMFr%gnT+SBB(NG46(QpJvFjrBco)jQX-e|XGkW@ zRhIYKCR!%x>`1_4IzzRbjF>s7S~Xl6X8x3~&0gL+FSR?^x{!l&gd5(ZmH%Y^KEsTx zB8?6$ZZ}e~YqMsRHm>cZ z>KvaCWhD7bs6F@nDJ5yp>;`EA2V-bpCXdm!Hj!xaI0-)glLw^l^A&H`W`MZWHycB3 zSr-n85?O+&KdHjgyz4dEEW=0sn?l~M!xp$eI&=S%s$@VK_8ezv;`b^64+^S7RnDB} z?SXs&3EzRYm!nLW?5LtT%WdMRXZyIr$CfH(A7_E)$6;Pc|KbO`X-KSf-p1+c$lW6~ zy@cmSAAR@7s+RGvyM}=x$b@OPvcm5tH2YqLVN=^LO%{1rzCrf%sFN)@7fV^T_WM`V zU_Bd0#$>4>r$a`Ollv@Ce9;?n(%&lnP5Uj32Eq?Awfv2EM7Z9CbqwPV|Ma_WAb^L}~T`3dK1wQ6mxs#-P29KH8(&GVoQAbyV{gtw+L z_708&zNA0@>fEx^0sisnMkk7?n5xLVl`KVl^NYF9rl5+f#w8ytzGMxGa)d)w0kCbQ zkiq5+D*+Glz4$15ode<~AlNSA-KFK|%2M(Cw3xLi8!&WyncUX4CeVdTCOX@jXsVDT z$3;6J2|3dRs5 zp~5V#b1@fza_hbCeqb|fx`VK;5@5vomd9bv@1?FkFoqo>^}5IOB7 zTR^;n`XQbQB&g=9Sg6oO96D1u7E9GT=unnxvGIaIdh}vK1Q@=z_Thq0O`@_3v4)Li^>*D`1dX#Yg^ws>wJ^Ar=h2km3pwK zR49f&S)y*>P&hr?c^ZEm4-X$@*DFV&`$TcR+Yk2-eF}w#$lW!P0kQ+oMbJ&g11V>E z+c#Dw%*FI7<#R3KmyUX3CXCGDz61ZoppbW13W@EWxUss-Vc?ci&~+b+zPsRyUN3>K z_hTqlN0aELBl%D@uPMpr;?8Qm_l|zi?nTc537zmNJrcFS92SL4qZ|@(=5}82Pl^1k zu{Lf3gG{6iQr#U~cp?jA>Io-~K~S^`g2y?f&JRq%{z&5&VD>JFHIv~8IP!Dypdng)@y*kmkbVTn5*-%b1vMhY zbh7`Fkrk+;!lrt&#xlOU`Biub-m?Ns-eVLuho8vaNtTA%bk~n5hOWe29;pGSWU39~f!{5v1s>-_>~K)GB`4sZ=-aT{***0ap6$f`~w&?>x}P+$$3E|NA4B6|>%Q{MJlTBG-w-egl1 zn&jyA7vwQ+=t8mm@vyO3^ZeUwO)V2LJg@CtQ z!I;$73X4kmd$~bhC0XNnv(75!95%MRyG4Yfek0Fz>VNHKNh`n45BfPtLDz*9m%U~y zFZDI!MW{hTiU}=ARc^k@itx!{^|+l2aX1EdAs#uhHh2H9v0F zmVFjyIv#4z+Ss)&wd@I)n_j{@)2MFU#P|x19dffp>eWzH+HJ&}ez!;s5kNzsaKRYz zxLIrf<=M;r32XVGP{MUD45!t^AvPl|fIgnt?S(T68gJktqLid;Dm>d*@}NsI+p z*Ln;3%|~Kz#cOJjNLv*|1pb%AVc(<}OU4sJ95|X&ttV6OnhFNw?_|;j2o(1{S4`S# zQ^?rFQtykPIpnlD;}l|wO&ah9t8Sb&^Hx{D${y0${dJ6rc$R^ut1y8{m~}R$mDaz0 zXBTL^aG%@UyAK=)+CXa5%?yqdm4#>atw+6EAWPNsOwE7ZHba*)3(-uBtycdQ**om8W{|@IIRBU7oegVt3<|OTs$)D^`sBM8S zx@JVSjU2vTbmc3=@UQN^LGY-0Vi--VS!!iDC{#Lh4JM({?!!EH6FO+2t0<+A^}H>CO4FaUDUBR&`Pq^_dXt zO-VSsIF`O*AR~n9d5t@vnD$d^kljkUMHuT|&+o;0@z5zo*Zo zs;9LefR9Gtio2=oWj;f!CUvXQI)cgmqB;*^v|Z4aiAos7TO8C{5=enyBW)^pU{LC_ z!XK7W?jvz(Moe!wv(&JA-k$B4em}e}umNZwz8<}&L~RefH%TtY|NMxo$`rUwIB5fW z82*k_P3(;Kq)$C3V&ON*qP=WCE#Y1(a_*P#m_pWGCmW-xx=V3TWo;>RvT@OT*dP@+6o{KrXLP)nfGN1v@O}wsk$63Cf}bwcl>Jli zpRkF$`L)HvPHdaWMga{`0$VX>kkIV%cS8TSnTT*^omIK^)k<;orTV{QQL4%`HX+c4 zXxO$~e@?5nC6?-6@K|djbGj8Q@RrUJ(>vfB%2lF4-YtCpIFT31;1HTy%;%nVa8H+c($(JC`a_%%Tx^O!Ae@NE{m^UGq?I{U5nfV$nPr8F= zO&&kv)*1h#p)K`X?UfCwRGFgC$OxymPL#O{gzt={O>3@LZF@v#$vGm>hyM=?z@s#^ znyK6me17p2XVWUO7d7#Kvmyy4p`@n$U2dC*f~uJ7h?%~(D`tK`Rr52qJjWJX(zF8a zC|HVS32bM;$7_6&JL(B4IC4zIMG$nrYeVT)unWT1cV3rCJUR=?}L8^7o~8sH3sa9A`F4W>Njy`1gt?!KR24!POuq^N*Fuft}slurPM%O`}O zninsQ2ro2_NAYWcXhEtph3%G{C47ggNu<>OkHxWcv1)}ddzLh^G>+Aa~`iCW<&>#Hk4PT^s}BZyCPwbrNOWku>6S4Uu?LPPF^h5 z3K1_E=WSvl8^2}G=VU~627bT#&Uwj|-bh~+ia2^b+$3vo6GM}lNaL()zRKroYIWm6 z7wJZ8OPv?Y^F$t*?};)Crca-v7e3 z<%q-pp@@-aKwmb~(>CA#%rLnz8a|p_#(eaY_MZ@wc*DOUIKaAM9M)r7NodAeTQ45J z=C3@od`PmD!6UgK3qa2W*^zww8`N!RNlEyE7Zhh8ku!cc`p zoATbAkW-5E1><4yhS`H9HWc+zC)3Tvqo9Lg@cDcTl1=xAZVV}-IElK0n!Z^Lvxl$_ zsZaACB8xHwJ$c5e)syCgsN|DRDboVWLX*Nr(?SoTbwlZFaR_;%BFFJMmN|SL?{Mp`ryu~2 zJf&!S(D|@_AaHgpU?BU|_Z_S~SEIPmSu@Qj5{`48gSgSJvW?A}+3^yL%lWlDJtW^X zUc+^@Ro<^sTJJ_MvL7%cIOlv#I^VU|F5zj4FG~L?xNdvBVi*ZzDYe1iNk^ek%B~3C zLqqu?t82Ac4H&r`^dA`Vm$Eg=-<~LvuR3OO7ZN-eHbx6nh&LKvQ7wEtpoI{M=*}1{ zr(nR~?-EgEGb1nP;Rti99mxM5;>YbQkr0_H`=1t35i&MA0?Kq22Rbq*d#Khp$=DqK zT7J(cXSTCs3VACmes3x?nsmW`-4kF8aRj0*I!|Isvw!r1Qz}`$4FwQa#WXsZPsNdP z``n3}n{IZzghroji>U-yKnf&wF?d=kVgTEh9|gx_r{9@L-M{V1VNXD?fN7EPpWdrx zy2Em5^PuUe=xy71(eW>+R`zw2HwonTi@ZiGfy-3W4aF!#%uk^@=@Aw$V93_j=QKxNZ~gRZm*$| z_m5r=1+<$YvyF-MLFmvC@r0HlKyBi{EaT*hvV)o35IY{15SV`iQdc2fEOZD;5iQW} zBe^L57v17d0fNh68<6npZ&Z5`4duK=lrXHk2e22(b{6OWeh7sr{vxczoDy(djNVdaa>3v&1fzr$Wu9L#M-V zUA%kywS!1qCj~!3*3=lX1Qb%jNRM>PUrdk+!2SE(R(#_ zy~ViW-r2vm^%A2t@)qM|ziujuM!!!Cd(dwTFq4*UGQg0+WmNWW@)$z&MzT2QHT$^3 z&=6FSS~X!Wj&FL~W7p3QsKfrRamFcLe1|VUE@Jwp|Z>-P%aCiDs0i2x{@=QI9{|`D(v`{*Lw8Jq)d<^sdfdw)G z`~NTezpGms3DfUy5vfEj=EJdEcouUh!~{~w?;?5tCIUmR(;M8NqbKxqzDV>;g*;!Z zq0p~cUXL5_bq5oIrH_T?d5zGU{qIltnn!y3aG`nI=c}8KM6YiZp2&757#5!A2gKFY zF0!Y0Mr<++^`rOmZ5md&T8oINPjHr(XEC4e-NC}-`v?_|&3bHSw{q%$YP=OH5Ao!B z_K(2x<bpO}}UNyo`uUrScF8_u`0P|MvmtzY*=X zo;JVL>c$}vi-5CiqYI;oK>g~Sps%Lh)yN8nxU4h6nj>mszcD^E^ufLp$`1CXVjciQ79yzX`jVDb2z#fCNO zG{ljVk|NkiKtMo@0L_B^`z5#g^CvhMNd$QW8Z}C>t8?%~%7o|(L(c6eYoWw-JY_f%c{w7>maX>~^z_>f&;}L|~Fny?uiu*f(2m zx(1`Heyzt{Aa|D7SEN%b8q%-$!+6{LhxT>v1N!npEr`sgt6b&tZ4xl;D6}5=B`%uX z$TOG{Lt1UM6gW+pe*$nfasjD`{|1+jtZS0=DgX38c`=GD?LIFPnLn26jDL^UKa*+> zR_dRK?YRCgAO)s1Pt2Q;-xtp5m>!HIne6%b&gdjHrY~md`J5N%nUIg}+d0=#?`ACT^+s=1 zv;Vg7`z5sDr{?lF17pV3R*BVy`xY`nHYzX5SI8K)jyMHhk_bBX&e`=|O@}0X0deU4&>b zu*lAZksq{wk`bv}z$Yw^#~(|XL`3DIe6EzN(?SuOBli-pse@jv-9efOGU)SwJzFRV z(BpOz`twQ1XuwB`^a9vhU0>gXc)7CJs!qPaVg{`AB(T|TBAE<_6H^vEr3(6e`)9Rf z@2$sV0fQHFDkJ&wFW^$l5qoGh>G@dDJV3ljFfuoljyVx<+ZFQGecjHhz_+HZFeJs z&m$%u7BKyey;SNbY_N0~0C|I7_kmp9orj}u;kHhls<+;tAo>lrGWMwLv^$wrC*?~T zL0Fzlt+JcBt`-lyQBCe_2W==#p_oOTGuZFjbL4bJ22iu+8a-6c7Eaw?wtcd%dZ^zO zE|;0dy7bAKyU)owDR9;7xnpz!=@uh>u*X zyz#)d2hoswvm;NpANv3!AV`DtmdIj20@}}M*DpXIdo6u7 zPcZ7^^8OUL+xrbBkz5uAd$DZvLlr^(sF@yhY+#~HF^@?0SWc-~%GhD&OyB2b4;Vo@ zNo1R^xSk+r`HPp)b~86gK8%V5H1$=?tZbVP;cs#hX{G>DRv7#+~Rf9>iH9- zm$Jf}L8DGn?oXg3&Bw=Y%;~Eu-Do}?c%vljQ2TT;Hh-{>UDgg*1}A5u-USxBT)y|s z+TG6@)72&u_-T`=)oHXI&N=ON1_A2ENZZoTqO33FWGaK%L(A7v80B)-zwEK|-U}a8 zr8ly}Q);&Tc2f$m*>nar@$_lj=?eVsVyBqmM+7H zo|_8)g6Sx5zX#p9Sk%wCJ!3+ayHpSW+$~cmCcWcLARodWuw!kf*_Ny3)KCP&-EMa^j9lUr`-ujlU9rfn^yAp?V)IOnxtHENo8a}p(3N< zP*J~dCQT_>%qdt8EwPw9a{X)9{`uv)H{~Fe%yb$?3Xu0r`s=11UVB-oT4Gi7K3|{f z|13MMQL6xa%wZy_$THHJlYC&R@ESj~l3DLLEhrZNgbhCY8~^NGMeIzo~fp`rj4ttu26t*zx`@sdTWC z{bKlOLHr?K4f-k|I9u4|9@Q@!F!miFrLrVqKIY@;8WsqCk1aM2CVF6A12;IOACLV| zQ-v9wIEQ%OoY7=_bnX%uUWGb`lP?VVj+5XgBYEL67PY_Ob_3T~B9(v_OYjd=TqZRn zj8$s+nMdYPOY2b6N-V*lp zom~hUe1ctW%j+dbG%PN1;B~wRGI}DF<@t1r&_X11yQYaURw$9Ib)z<@`MzjW9>`Io zn4H-`#PaZ#SgA|{zQ}?E3s7l5)+Lqb*^JqKor^KQ<;Q-g-h?b6unZKrF5>)YnFAY6 zjyT8{@*O(KT1ctTLLW2j(@Bw;Yju$=*Y9iK>2hDin96}>Qzn%@#`731j&#P~OrXeZ zB=&%-q0?#xqh~nQ)q|@^p)8{(V-pqz{YBCoD`g*tzh0${AfJj(t&G9f(>)9}iR?W~ z2ABd|97Plkp}_6vrBP#?enOv-%HYuJeUWj9Bc#@1rcv|T*Uf&DH@3Oz`PAi zjv^`;_!2cPVC{ZyL+=LP<@KFTk}?jqxkiW3NyVl#zRjVZvReib)lJwRd3@tp?hSSp zOb``4SXLp7i+vCDM#K|DxJZe;=j7Y9K0L`1Qx8`1u{Cho9AYJeZ4a$;0gn#;M@98- zfr28rNax}qlZ3aqJVkc6MZ7)wP%J3e+U7+ymBT4sYi_l#d8}D?Nrc9SuZ|#_%YP!U zn)~eYPH1wrScQ0hfo8FThEK3vZY}!95*i*#rps9y@*a~Vy3XbqvzF0xGJx4aPR3rT z9&)Bi5&kf)`WwiyS;|WeEXMTVeR;0+mu7hE#_Zu_8YBUqeLz}mElDhd_$cB{T8o`n zHH}6UIYfQ3|4OdubSCx~ER`jEpU(%y{d5*PK8*$y3O2gtvT-0PMn^4Ydbc zYV#~w8J^Grd&erJibUZhtG+dSy>yU%iOO8H-DoZUE|}H01(VOqF}iRvRb9#c!2#&B zP7A6}(RV`V^&+JpH?IemL7yl0;bfL1f|JK1*5BwnGDF&pnq~7$Ag$Ja?(y=mHBzwh zA|Lw+5*e+~B#L!Q2#Lq?xI^IuLBk!7VNg~T_bErfb;ZO*HKFD7TRd*T4X6}RhyRf! zw%IQ@lJgRVBT$7alc`61NUrdqQ#>Ab34&~+#+t1jR`5v-&YiZ_*+WvV-=DJLIqQ<< zY!)9RMQ*0{zPd*8^C%=veMrvMYG9o&7L>DTe~=2Ol!}YpTct%iZIgThMg9w72mdaq zYypEVV6oVb$WFglBdLS%GAuZ73(%C15b(5?AHFqwze`=&;n@;U5l-89dSoGaU5-OhgDC?2d<;Q z-X6~}+YDxF20Fb)IXyeACJ`rv*a60Bf$`F*}YJ9us2gm{+`z`m>c`)|Zl-`T9JxD#g+m0v?feOAvxMz=qH@ht>fP>}F41h4OvmM?S}&Wp>10b5O>=MZEr9*P z?X%)MP8<;0R0f!Z7LgbwbL8RqKhT1~Q|$3nVs0`;o48DEPJ5pV@9M6W+2x3626*=Rrffwe0xXHAD_ zKMwH42-7r2kqNhFuGiaDqE|r-y4Rnb^17|#4$gt=)Cr7!2`CVI3nRD6zm6K`)f8bk zxB!S-Ed^Gyce<^AcS(otWVoFR=#}BGeBhB2dkf>s7o2eS92N^Ak{(j=bfOt>bSW#Z7I#H!_xBSX&AEVwN$?$1yueP^}@Ok|^MYK?_|NM}0>dS#?@O4X`{ zWJb5deeGmCd)nA)u{bWimB(STRHw5ouQRekFnMO{B;Z3?`-tQ5=kb3$t`;2muXEc&1LOSC$r? zh@xz=888IpQln&RCFBtrQlFH31SV-Y@}UrM*NUcHJGMLDmur;_Cnq)P&_6agy-2 zLXqaAgQ^CB(BvH<#NCP>-IlKo!{kD*bxPeQ#iE_17L<;~sgh;>#iC#R=kUBKhzOux6^% z56tV3$fldRO)#zpQ%pdZt?dVnRR^OcIH;nakZkzPDJgTv2j`DhDbI^NQ^%f5F1iM} zTdMR|2qEX><>d+E>F2L?ZvJ5lV+r@WTTqV$Trd~#qEb(WUxM2EJO?>o^>{Ae7$?HE zx;*5u&ndmX|#sM34QhvED(1a zu9s+g&WxwHRTz~~z2j&*wW^#h&gHd)>eY;>iV^?hjdR4 z%D(iW7=CVu8fo2fQlNKd4pw6_#b%{)JxRqg&-H&}56g;i_#6Q{y3ZdUi0hE_lg%1> zjUByYbSo=JQjX}##UB{-A#MeuAzKb+epl@f2gw9=2wf1p|M;M30git9suyR9@k;ymPLFg`ZsWogi-ztg(9i6cZYH4)Vq z(xf0Uxt=3_&T6JgeVJo8V*B6;=+umVq)7|UKA&cth41bjIkWQ*1m$`^&I$^*f zdjphkc_rzq(i1IN3nPjWWmISKgyjj@*_33>iY<*&csqdIE>tW~QDYgeq&x_UgJ!wQ8O=nK(4zo^q>6zK&k?-t*Np-s$~oM*u2K| zRQWd*z7Im4T_++4tKg6ockzme@sNot2?0x=DI`DuQ(G2yB_NcP6nCxtyj_3n7;krb zd~9F$>T7X@5%RLO9nWyyU3Z*h-)KxBhgls($&T+!JXZ8Qow5EdmkX(^l<&e4RiuQK ziLU;$A!l&EoMx!B%8=unI$Dzv4OKl6PJBmZM9E;-(Mc2fIz}=zY(@Ey0grhXoZk)k z)Pvy^{ci={uQUG9-#&87Nd3-Oj!dnLozKIu%W!w`f-ZWq4mNr|6A zp7P0%2Pi4gaK=P+XSlq$H@;Q@GH(R{)sw}a0S0x~;W`MDmjGwNU`NI|8W^~S=1{El zu%f_WyIr}D42wQBYrPYzDvp#l36r;eGk0xmwY-^<4Q3Pj27{q)Hs^YiD~L5coBo75 z`tqzfdVL-AW)O&sG8M1Eob>MQHEmJkvVjn31N|C!N+1b4z` z_Q;(9{%apE5HK~4Qv{#t=*p}nFPFt9%p9Dx!MgJs=~DZbk+SPyx&xcll)Jj^a-%q2 zQI5`4(*|=xSL-^bATQ0{k6%A)KLDeN<#`Npo5IIG>J80^?+qhti7NZ5XR)Qtj!b?+ znOv{`kk1APK8q|MQp*iPDOlPq3a3_XoegKuJ|d4c6MPiqjnJ@{D{{iHlOH$Xs_bDa$S5t!(`R72cUgj~b{o|@<$Sqos}%C8*eK>u4px_= z8?%-xdpujbKj30uZ--o083CEbsGXnw9dwYrTcp)s#ZDYb&`suEr+NF^+@3K|&}-O`plm5$TCD=20}3xt5*9q)LO8 z$S=K^YHM*&IvoiFZmMVwp|0qXfVi>?o#gwZwX_;Z*9DJzsGX}2d*oCq=Ljb!lt09v zSSeFS*hOt_WbN~VrcFoeUjjyCWDEY5s{YQToNUkw7A%Xkq$^I_sAQBs=1!|s8hjw9 z?!a2A#Snhrq5fX@=CqW^wcQGsEcTfDC8>67=!5jM>l5lvk9#Pg0SwE6<_smZBLr4_ zB;SL1Y`x-hXUA*z>^zZs^%NYfVJd9UV$*P-YgT&`Lt>q~yVfsvES*Hb%!zFCLDX2O zwalCWRM;Z=;pX8}D=aEGH*AQv6O<}y_!*MrL$zA&xB8@ebR z0CApvTDK)EHmBFLxyG%rR8fHylC1=;LU2iXpc8y;AI>+A2-4Ngtt&dcjt7{8i>fI; z@8er+IsH&c3<(JgEWn=x>3IAh&6ihUs|_QwNu(6y9I#jqa@vyJ6EC4M>ljqC%WSER%u(X z?fxkQJWg8IP?H26w0M}}BQhzfa@AUW=rXiox>gNh(5Z}fCH0e3#vKsh>hq7z1ohK{ zGLRKo1$glIr}Y-;7a8=uLl8gJsnzpucIQ3*A&990Q13Yd)0tzPd06QqF{qM+IFmPE z;tAleb>=ABEiRaCN9Mnu&a39GES-3Cb;pYTHu(2VeIAmXjYLGRa%J5oH=4MsG+ zPq)Y;75XVC&9?6n?{}pNI7;HJ+OrjGA=u%>X`BdUuMPMH)Zb5i`af%I&zz&d#yijK zuhQ~RJ*X^D;CjiGpwTbfB7jb4z5v~O(uyuT}}cf6lP_g@%Br+rlQA> zJ$pA-`!J2-1?#=C7_(Y!tyi);hKC(!W^*W$Y{jL~z`%fo`-6qB+?BIpEw^U?rxG4g zr>J!q@ntU4WokaDA1Levx#k z5`i0po3Zv++u;V9=q@X_DD2w^_j}iXU_OCMB+5wSLi_xXzQS(Zvx5tHHAxIp$Ch5brI~VPQvn)Nz{{DldY4310Np-OGUs!w5<=OhqjiaNuXM4hfq#io5{&AZI`ya zQx(P@mG+vyKpwU6mnnnR?edeKSvWx^Q2dus-}c}BA-$PDKV8@S;c3!J+A9Hw``pO9 zr6V~blYIXWsl{7mR|&(V(bQJETMo}Jm=F&^c#XpD!7eC@`^(-eXhsV?NY{I?%m5CF zc#qeYkUj7tnO0NUniI8ew|leM5Dq4IyJ#81aIttLHlQp$c-AW==F@p3hC~65=KCX9 zX;R-hxDeK^Y$vAc)Zlt1L%>!hld@2OqvyO=2`daoL!sI%q)n$+NN4<|M@NAe2jt{U zYC@sg=G5-|aT0@sCZ4LDdDgUF;-Np7CgVV_+>K>?56R+mZaR@gnRZ>Zo*XN*0 zjq%-)ED9|?MTY89{`}dM=1R#{M``OaDq&+6(TEN;fx17>*~HGxa!~nSeG7jP%NAVe z9LenHU(PyFdD*~>toE=~bGzGo_x`r+>6ty|FcJ?l!$1|Y*7)38ei2&bRP5aQ@cA5u z7Wov|Om<`50czD?-uYdf5Z#hE4YD2Lm{Li5@h3EHagh)f|89gTXotLe(OrQV`(>lL z;ylZ=mQe4*FRennzPxuj@qRS{joN3utu+c*-E{h5;MqzwrIW+q^Z3mzplrsl=yKVw z`1hNYt4jIw>O;x_0*A0|V;6qkqV4KJoO8*o$CwUd)4yOwjOW|9atD zY>r>Al%NM5M=wjzP%c&=7R{uZ0{w|@Ly@7Jb~ix<+iNy`9s?0_{iKRC3=0-DbIboc z)ujdY*6a#ETwJa>sdb8=v&-fk4h=Ww{%RH29Xa2EhS;E*mFua5!YHaUtmDv)TTo(i z>hiA*`M=t@;5lHmyW_Ff^)C(CkH{IvIV5 zbW-G>`oL$525Mu4850=-Kj~I;r1bsF|)6W zn!y@tC~Z8s%J-K5s^%uiIfJ72c|OkaktE0?3+1_c9F!#LcDpaXw6fZ zhu{LdetmG%ECG4$1oWwWR#SB7j4@nkfB$S2&@nABATL{US0B~u$g_1|cwKn<|z6ItZ&w5@j@fx~fswtR#rXZ1^FC;ephhC}lx$MIL+vyCR9dQNBnQZ;cslMc8H8pLI$J>;9R z)&O6-8)Qa=d-c;JGg@tHjqbVVFKbt9b`*MECAmG8%RHtO{sERK;cVUp(s&j?g{d0b z_qOi|g3aX(0AY4pVN0`#SHDBSvTE!nUrhFw4gz$r3_40$9@uz6&d@7WPNcYr~8LT`5)luoc1Y{mzqPP5^y(>}Qep1of7;kz^@YNS|;~=|s)C zp2kg3z8tFYKkCMMfTjCsXUx-jqJ~aIU5EyA^X;K%dLFvE0IMXhHgF@}M z&KS;kfUjRwDPo)&D*Mh}K$tTCfKXB`i!Eran!D`u5zI)s^$(9ZrS}kKH_H0b{>ps? z5U0HPR2Pzkb%A8K_#yFdq=C$mSV#l{iEiH})$RUopK`0CNCnIHe(yYH;-l-#Jq|cU z)C)4esgUb_i`vYd7aUiu^$cY)8G{V8!;1#@V&Rc7K9A}9OH~TcI-Cf10>O{aMJJX6 zNzvQX-|5bNp1YVE46fKbaiI!MKhy8E(jMnqrJ1VwTE8w_a)o49x_+6O7+|F9Ua&Pp9iI4l<`*_Hd1) zyEpRq3W4l3`dHTR)`#5i?eS8XKCjcCa3M%u064Gp`)|0q&kWcaW;t;u);lxw3@|9w zv)$ihU%mDTk?0~GT9OVv;q)ujHP`#34%^DVM(6FE{4{gH%i{+4>4b>#8g&8^Ze+zV zCj5|H9eN#~Xficeu2v(G1q}^+PH$XCYquiHVN-h)@Yg-XEkYp>8`QBeE{Y`MI`|03 z6f@bN1B_P{G-}?GAQ15@D9Rt5pkciMvse`_QOB*Rhi!X3{as8(w@T}?slweG8Vyb% zPbnl(CpLG4esh2T>e-GTqqbtr*qYG7u>y!!-aG+CWM~|YEUm{GBd_>2{yf2Xru4Es zoZCLW?h3EG7Kwh;o4~IMVuQN$6}wGSIjH?Cl`aXF^I=m3C}?}iSJ#-`&Rdp&;3Vz* zPlY{bW0dipMWvWR<=Nz!0v!g=1!T?Kco7;5R!dC3#D~vYiXZfSq;v-PdW9; zGk5nK8Wp1&%a&i4`sSK;ydwO6=}Le7=&7VCJLyx+(vJFxj@+9wB?eWFQ7|mz{@L`E zueM~H;;pAjqfQUO(fo;?K%cOhxnC1N)4CPtw+8N8MT!PxBF0yl+)W<^PWl_;+QnBe z%buYzhQ4QIT3=!eM zKtMFqr@u)?I{ygN)s2GEFs+|sNyVcJ-38$O0{a7b-MHPZy8cAnzPRfMjX5zImsfwp z)%Xq^AkIw&mO4+{T}!KnWXv5ga&2bR60*FMBs4D+jkgjK@(j<`txh+h<9R;qH(cn{)I+cqs zm;Q0I?_rOJ(H@^KXICRd39_+RrEthZGOqX!-Dt=N^Co$}2J z&RYF5lZyK~eZDOBI1twK`B_N4qrE>k5qAp7R0T;NZCy^JGp}%A(EUgFJO1&h`Q4cA z9LSte7mx>(gLJpip}|0HlbW?OW;l_=^+P=mH*XSsfsT2~gf|eIk9D^l4h%k9$6Dse zO)&NhYSqaq613`6ilPvmn(fnoZ8ixaF}?9nNQtR*l4rNV!<&O2(>Q21Nxd$I)Si7^ z_uF&E26XLL+GVa!=U>f78SP)z_3W+6_BrP{b}!#Ul+JhO^qoF81&$l?NNIj2`=j@- z-MiQw?pGZ8rWnRl$qj2)oZ|cK3V%j=L2k}tx}3jOd`h^6Sn#5@$`4pJ9J{sV1CP8r zcY59*HK$H^Ho?!d5D>`1UgZ&~nHh1zBFath3XzjWNp}@JbSY9rU|_l9h=`!T2!Jsg z%lbLV*}((cFo7RDyY0!tz`tyh#br}zI9=h!I(=TQbla-OHo`L=sZEjkStGD);!B0! z!1o9?XSO1E#aHy-=5oLHSMWVO->W;L$FLXXA;0BNLZ7WuzWcbrcD0K|?U=?R+n))x z`Z%LOh}T$I%R&X}c;hH@7|Bq9Y?SgmUh-Uy-ub5ST>1hW z&~0%0Z)D+Jd14@xN`N8Vk=^UwK*HvDN)#tUM-xeM0rLN__f}DDb>ZJ&3k3=k_o9X3 zR;)M_C{SF3ySuwfkz$47?(V_e-8Fb{3+@nP@_zIGW@fFqoZGp|MNZB-XP@Wn?EU;K z`|E!v{Gan8zgIGmGZ;RDM!s8Y8gLShb&wUn`a@J3Pa`F2Iaj0xnO-bYl4B$6lKYrg zt}2HG3b@&?6GbTDsbe(Gl!dT=wO7e5WIacMqv#%0$*Ix8M}zzher)53Zz+K7a;@Lh zWUL$ugG#Ti55_mS3i3U5)lvTMyXtQH8$bshvc zrvEj9|Ie>r$N&F7{(p_i|Azr2 z!XOHl*DJILJV6xdDB^hRp}$gw!VjC#fmF2kA4K`#lB>bFT~qq`AGi9-+>iSnYUz~w zFLGai8)dI=-lyN!JE5_#rqYwztqdR4$9Bj^0q-rzDgCF?v8c~8+{PjB2jt3mDO>c8 z6(7&}e4Kn?5BMVH%f;0mBi{u`AGTeVh#;X?j;%Vo+!-qKYj)V8^YJ)vG|u)Do`Z23 z0k23E#isk$Xr!D0%3l@m3!D*)u87r5rfRpJT*0aJh9F0;yXTNOu9J*w_`UIzS$aA2 z|2mldAIOCKq}L^wa*q6M@}U^nJa}Z&x%j?wHT5cKBp=8E#UXbp>-Ixfegd7=%2{4b zrT7nn1w|AFBJaBX_@N6%Q%Za^A4%*RjDO9wBz{%-@ytz+G4SUzXB6M0fFzZ=PLYFQ z-*le6P!Vw12z59pKmp6+^_e%5*EtDBLl+@0loP|ElDM&i&MvKnbfb1o(JH)5fE|UU z({{xo@EFx<+-jU|S6pDTQUsPD-%E=V{lFibX8WZH?It??p1iVZSF44b4MBg0<9py9 zV<~tl_~OC7o%!2Z+%7}a{760`h9k}v;V86Puk)(RrS-C zkPX`pG1)v)jOvw21e&#?yoCXXyAjz!zS2|@(Sr5ABMv~B$FE2- znoyKFf;YiHmxZUvUN+A6b(`9>bT(67-(|dLk@1awq56ToP%7z%rdc((RUyQw2zAoh zpLHdx!3T-!~*Z7NEKxm7_fZ;lv!6wDvmlG)_2`I;|i|L%eB;m$eq zG|OLq3{B~%{q5d)iCCeYgr@-m(RCEdcZ6MRmk%S*Y)9!Kj`09Hg2DX zyv+ah0$|ii39Yp*Vl_rZ}VQIi6G_os0@771w;S2Uv78Jm)Rom_1v## z8o(Lv&+F5vPm-KPd|)6|1H))rB_scS#Zk_-0> zl;v)i^nn3g`Oja_-g_EHoUo#DtBmQ*%~Lm)=q5PLSLFKDYGz>%3(CI%)^oRVpX7xc&pcG8sC3wm_$0gsH^=+ac;YfJZgU?YK@UEu<1AtX3ksgtN-eG zcS2;l-Wcq(KPyQE_03{=Lm`*V9vV>hE5Tyn55rkNUPx6 zDuLY3rg{>-ifleN2NUN^Z*M>lPUv~LsyXKp*?fB^gFD3*n+=l;x`;^Bc4L$oQ z*?*I&=9ZoaZz?%XNIGk}k*HrI5YLkqB(k1X=rlK6m0i9GNgZ>WPVy~2oQXF-2}(`* z41h*q51~FYh1w#$W_v^|8#kQ^i_-~`j6FE9VZ)=VT z=vnP0Iy%IF26BoHgR2bF^jBpNx(wAehGX^^Y!3{RJ&~0{#4|OXo zPvGr0_?zC8h0YdZa59nf1%Yb|S}~%6U$ri2&V$bU>CGC@L?<3YDAHj3;(WR5IPW}el;~rjWPj_UIreZ&_*EHa-(GbB!1PaU9pqW= ze$DS2bSC5>d$bhN0w+ubOQ*fNPY7(;Us#Qq-s*ZQY_83lQ3s%uUHsN3uv60hmSz6J zL&Q~~6Px!F*!B0-ZCGr7Bj4O|Co8_OP-yF*Znrp9=j!5lO0#zC*PGvxk8ziOSlVFc zMvr&&c@_V%|A~O@-ucp&3PI|(U24-OI%MA@st)GGhy6{#-}P16QQ*?x`q0a<>=&xC zA+~GQCA5!cGi?v68Z8>=47wB?As7UUck>=Y(~AhNZtEsV`|0jv(~NGW5##5olxC@K zWmY1i&q~Uxt?#8iG3Zg5R|2-^FO4KsrUKiX)6Y!{^OhGlB7qKjx}A@)Ws7C^OE~krvqdnli{~kF??Q`22<6_)R29m^%q0p%i>jVKu9oOnI{3#K(Jc+yN zvbbV@+MSC!Kij#FRD#X!qM~uI)Lo*94Y&2?gmd$3?mH+*#_$A^`Eg4q$ITQQBG%B* ziVyaC2=ZHYh?dv)6@}@n@)iC`7FMIs=FnlC=mH7OTBM4XGneHVcEiPpgl>GY$pk#5 z#?aS_^52A%**dw;1dC~>Ug(q`zTvV;cre6s;R8mA1XxDh&(@R{ljqE*W?P&O==It? zZlo5O5?3mC}-TvG08Zn4-sM_pd+ z+KsH|Nu;j~jYOl?Gd#QILLv$1MV>uuI!5IRrSU-k-A2h6vV313Qit`Q6_%}kXO&^% zS$bmqx=fpm)@XUQW%OTeR;uNBlknWbs06Qtglu_pLq~H;uJTRn?Nys8OJm8b?UMEPvmJ7GUfdQHbR~SJW`Y@EO)BuVxp}b6G!m?s}dq}ld$aW`D=vdDsc12 zl$dmHL-*{yz5wgl*vc*O;q+F%OLTVfT8q=S_lkPbSxl)`=df1ysFp^Z7hrB#@4Q#g z6{f6qfgyD?gM5;IaANEGE{b{U+VyV@c(R4q%o`-@g7I16O-6$+sk@^`s8p z7&>5T|DOGjr(M=a`iZK=o)3s zQ5PnoR^p5IH&Jjq5Yrl~UM=_j`vU8*wfQ#2R`0#@kH=@y5`E;cYZh%`=UawUR#KKD z)BFQoIV_@HVOLL?F_cWj!Q@~o++D@=Loa7AAfTi#fR{6M{a+;+!K??Qxf7NM14_FFAXf7Lw$Wj_Sm=J_yuGZ26zotbxboC+dI)L0U4T<2ch+L9Y`2(+|=l0gatl#4ChrP$^ zNt^`g-n7)OhBj$4U8yq9Hjmgcp-<20&u^;R@%l7;HgH~xpE zLoy11MR(Ss+0N~anNjIYfh+8N-%Sv;1t1U8+e9hWjd!({f9W}0FVzx#d?9oVQHc#v z)iELriLEzHWi4#NoH=0vn$w=)#)|n}o*L_1^%$Uj zKgQyCQ;m06gqwI=<-SPQl1CAsvHVejLs*sNO z82_0`rSq^?9{vkdrgd<|tNM1xQ_1JBs*G>ZH9{UsAJf=vi%#7?x^_aIqa#J1eDBF_puGbq zVYk+5igDPc9~Wur3ZzqmXcP!xGg3!ZI25SFvC=vB*uf2|J=^j6%=O&+>x|z3Q!ew2 zkX81xa9V_qnXsk3YRyS^S>jQ=jumj`U*TFTf1|aS=XEnSw_gTznDVa**ELeHo!r%so2<$A0P;j;gEe{hw5r z&Mb?IRxFtw1*d%&j6gcJs{#DzSeA0=NK26ywC%Zf3@E0A(fV?EIf@i>^9og4Nv&&D z5at4jiV;ruG81)6UT~N$RdRkIxB9;YGJN-+{L~b$e754KWRm;)E6bXE;?NIL_`A*6 zUFyzUMuEO;Dr4!Dfw2=0ss@iAjp0aUm>SFmxqTJ)rOxWn7^}l}x4H?-vlC$#k{5;X zMh&hK+zb!m`qIhlSf)@O-kwqC`&X)k?@PYL_x5FXzL&+a*SYm}2TBXLh;sDHc_<+# z@3hrwR3nn?yBK6%RzTBXR@(V}ghAq0M|B6%x$Ql*9%hfFwp>r0wbzj#%W0jJDMtWi zIXg1KJOeWX7ocY4{8W8%x1O=y_2oe+XaVUAEV+b@XifVe9@BgO&Y^Z3-$2KmoG*X0 zKO8?5rREmtgIF6zwqb?J^dlp;YG)>8uM7F>(CPsp93l_mST|pj_$+ zRWCm|pWK)>MB!XbfYyq2U5|SrII=i2R@7?>5!C30J;;{0&BmCR!bc+ARn;DQTZD@m zx_EFo0mC=NPU&$vZ#iCf-6f>))e{8ROR%*g6qSqz@}7GQb1Q~W$4JeD-%m5mtd{E; zK^sZf%&4@_#y0E|bdC2KHID0$FO{@SqufJaFGoQiwszwP8zEwbv?$C zRWhu~7j)xLV7*OlrDvxL8Z}P&2wHq+1d64!m-8!-ZMI=%Gq)qj>nMVM_*yd3`iN04 z5f3vx=pB^I^rh5)2;3SvISoE9x{C<}4Y6hQ%Zzrxze-KS7+bKhUM8fi^0ZWR`HTCe z5nxB0Y(@SpIaM7x|G?L^_W&6w5hXHe)=@|ZH?;JGB?~rb#=TToDSz&`Lc!Z@)eti0 zVl07)E}d+2U-IXMSZv+Wd}G`)d|uL9A?F~dehsy|wDWy%cNQv(GWlyYwcX7{Leh>^ zuEWl=LRJ^0MmT>0G`5qDP@mv>#BHr#-vS25OK8_D7D^{7Yno1s8B&~K!zjV}~Gg8-joKmmyaRcW!TLe(OxMBO2t&?KpxU9+G^5c&jJF}oe|uC zdc?{;RmAW*@8)Q*8DmylHJg|G_0dSGjHuumSZ3KCHs2J_UHfPA+*Z)|g!Aeyn1)okQWAiTZPa=^DNqkDHZHMh* z85#&&aduEuNsJ7_#|*??h4CcuFrvNs!afyTnaUs)Ag=RXmnM02Y4^tdJ$%AevcBU^(5oRbf-`OUd(oCl{ zyA>0~9+>uZlgN#hNZ3ADzqulM{>{-D#J`7dw|N#U>1Q$ate*|9?cBO?aBG?=KO`MH zQ(bS$53MavitBRO(f6Bi;#Pl@ig3L!-kTogIIjWBTLiB|pI0zaY)$G!PwtgkSQv!u z0;{8Ma?Wbn3LPhJ_PVb7TrCVyBgxy!p2R0-RB!!fgXH+ePVX+`&HYZCAj!4L>I*E# zWc6Uz7u3kd*ejiteTfGWqPB^na_8mg61aIUa5Y{MqVMg6Jr^RYA>i*qFwaO85NTJ)x&o3HzQF`of6N zGU8p@<;meag7!5(m&YhWvB0kV8^k{Qh9LSPXYI(R(o5lfX9R!YH6PXjUgERfz5X3O z<_Ql|V+=ok+Ij>#@80rNzDpw%LGtJ zdHgm!>|or?I`YZ#y}OPuKM!?>x4@y&YjxKoa&406S3EnOABA<^HF2T$@0ANre^H@< zMVU|JZ3=dLpH^?y7fge^i51(I{%wVUKW@eq$(r8*jgc%OFHC|Qb%ozrd+7IW7ednZ8zZVu9)#U&I#zwTq_=l@Y z%+9+dx(jfJxu2BwDccq6I*^=z5YNN>ECwRs>E`|2yyc|$yjedn`fd-st0C;X zc^63?u5J6tbTVs|)i$)kPt$q-+ITE=u2e(n0(w(t#PAlD)$yW%%zmZ$2skS7K0f!4 za_Q*1%#e7U-D7kG&bdu>zDT47iiJXJsmIT^`ohXSwb4A)ii3vD#b-)c&}YpjtFC66 zuuT~rGKF5Apc9L1`7GKT(XADVPreD4IEm`jB2>a|*PK@xJ=fN26^Wz9)&*b~X)9Xb z#0PXLnJ>3XF5uHYY>qI@su0)y3% z&o*w;UseUWDtNET8c_*YPlxQFh4OgzuWljdE!BdP??-}7hbsDaIH*;^z4($rE2DnYbM$MxKNb_eLLUSp)K}#L%;Al^6HY$ zJkwXAvVSOH^W(k7zcFq!7p9TmnC(~(q@Kg1`>Pe$lk)<$u1>_vSEO*uAv`4avu}Fn z;YQU?kNS>ZxoSSC4AsBSG~CrrWYk@%7|tVKd>`W(a3W8%XzSTFu!(UH6jcAVWF0cC z>cS9R9pcA!MHZYSDHM;OHqYYxxAka;HV zrw+RVw&V?0($}^)|Eo1f4?ap7o~94u$%lBj&#cbA*Y=s7dGl+Cvr61%dQo6DvZ(oI9*%azQ< z2$Whz?Ui@%pCRy3AIDCxmf(lUg~;BirPdi0Uy{_8H*l>M4}B>dHkw7ySUlW(qAF*l zQ$N)!`-JPs3_B7G7p@t%FxA2@jvp`n)Do1pR&*}g740qmph?Se^B81IOemhzr}j)~ zYG3w*US0$Mf*zFi42{Ma%*2y)t16d|mjss0Ut=oPoQAt2N1AOQM*q}|kH_r)oQ|~r z@=?cKc9qnj^)LX0G~mA-*mRv?q1nTZOyAE6 zVAw6}hE(cO@H90(RRUd>QH(cFCs9aY)q60FFA(#-F^heAXhmzFUqvGOl!oaB88$0f zA<%$|vs*~tZlRvBe8NNC$10_^17+w41fzNUGtx1DI8$YsoirY@)y5|n92v!~-N@%R zRe>-OaZE$uFB)3$`z%+bFTrpiEkY4Bxe$T+FTV&IS(%4er>VLBY@@>?r zsWkOC+haj#L0z%W1G8|D=oupnP#xbvIUK`7Q)5)`0@K*(-sj|xM__?5ONQUzI*}B}bmbA#djhm<+fY5U> zc7}kEP?;6F!IqtFUWRpPo#1BOZ-4#Ln3-+O{?Y0Gsjeb=@l;_08a!ngT-zXle7_G3 zuQ0D8ES`CR`Ld++{N4U2~7pQuJyiWY}CPY=(@jfT<|>1;+l zJI17O{i*EO^6kvD*d}Laouevf*x{``TJXgH1I0*wTZF~m`m1gcsqUj~^E0=*JdGkl zWwmdgezqeG+V>{~b+nrutwjLVN&_%3;DQO{G5i9lA@}9>xWB;N7HIDookss<&cEKv zF-$AimX-Ow3_VAua@TVO!eFxWyQ~82Xr!`TrSY-p?YFPN#(vrgr%?Xz9ii%rQrir^ zETaAn(e8!KKg-&9p9Y0VaDGhju#7UXR)Gs5Pe~p7ElanE952<<>zRJr{HihUp=KSo(MydzhI zq^9&7avt77^c6-^m{1bO$kMI$qa}HjB^EScQ28*rp#(WsV*{O)ecCtFP6{BiO*~_Wl$}gGoLJJUgKhX{dTn^7BH$_RTZ;7U~=^v zuGUpA@v&6Wef2d}sNK=nf(0X$G-&## z^G^J_Ha-*s_kQF5guD6$APU|3x zKXj%_BI>umbiWr%=CYsY*M{wrvvw9CDRsf7!k^4SE1Ajl)`oUw;THMc3!;Zpj(u)7 zA{$i3F-Tv(P8VBd%f7zrkW9!?Bu-R~NaaZ82rdG^WWj_2wI5_0B2uM5(!JXgo}NY7 zR`uk@ABx+`cd{wR7Kzes+IGSarI`{m6?zvHwZ?*V?LQP~W8CuzX`DEU#yN3@BxYM( zU`sk9Hq_YmW(L*0RQs1)B)*Y}enyy4036Be;Xgacllv@vaZX{5yw%R#7rkT5)pXam4kT%UWVYsY?Qu0Rl}*h> zX@6B$mn(yc@aA6wMi>vn;!x*1x&0f*52YW0MVCbu;YrBIKw1a_0wC_iUYRTchbu#+ z?!A(%5?jvR+g71>Xl1)>r2Be-wR<*yCNUD=>YJErWIb*sa*hx6iD>z-f42mR+H62L zt+?CrRpR{C>bYvX+Mr_@aad&2?#MO#v1s6BsUKFrHdGcr~)PSDRH8w9Bjk}dzSg>CgO$L2_x z(`kuf;ST1s`De#-p|dHTa9{oiG5}=vC=SwYS27U^zkN(b-@`lEG0U8PEs! z+vv7+t9>s|sm!j?h}xqTsepALdkWGRRT!+XvdNrvaC|lTdp7puTio15HPF}r$3=+I z^g>a^h!HIqyq2q2SseNjzpKUsBzn-QTx}Mm_ zkQ35HrkJ|XV)cd?L)@gO(v2(d+8hE&jx2T(SR`6KY1xe7?o7*FU-Zow_79ZsT!&I7 zOicREqRYm|v(r^h**(YQ%6(x^lys)8O>b(v6}Mi>00SXyV9egY!Ow6Vv!SzkS=rm^ z@m)5{(Kf8^VY!Xs-%CIwD|nhO%wyf3rZmoBYUyIQiu+hUQmY4TYFps%P`nxShzg-E z36`?ch8+eq@aF;#e*<%?Mkx(Oad#SO%qA$Qro$I>xOuwhWUH;2=Qe0O- z=$FBXLQ0e}QC^kC473-GTgcqaHsN!*{9?=FmApvaA!&`V{++2II+C^kIog+7Gq=)4 z%5Rcp6!TB@0}xg7tH`^@D+zoQ?dW>QOn zmQ;8tVNe=8fIj<3Jd`r3+X0ic@mGpLP{r|WMhxUafAj?A?MV3@^9PuXJ9&6KHdRFG z@|*3eSH!JeL{8x`y3Us<9a0m!7^IT$4ze}EsvhC`8)5htgOz9;+Q#*xjM?#*P~b<# zX8u6R)fy3Bs&uJ5+%|`*3|?IA#yG>35$&3fhNsHkl+&4kFmqClB=7$bkAJgDDPxeK z!sQBY`-2aAn7W%VYk|~q@3pW7f~D=&MtiODMY8YORv-@4CeJ@Kf6<)YYY1nvLtJdK zejr=u+OISvT}s655qdEIs{WNlxRac>0>)8%e!!H%?cFSBMaKpNY7q%*t<03g| z^2%IG6)CpbPSb1!f1Z{q8$nAP<)U{d<4!ein+ z$}#F}($b8%F;W5T*Er)O*7Viclk4jsPFD$U~e@Kwq>vuo!cLh&Ns_&?S2rQ@ZX$DR(ztU&sM7{*7|YW)>&|^Iqd!wRv(Fd@a}~ z)Qm;bL|`j=YQI(%OH&4TxpKX z%JJDw++&}tx#by~^c<2ZvI(!IaiufQmnq*1(*2!%um0OoFslcN;XtOnkEu=D=0pX*WKzv+r{FfONLR|G4b?fg- zdOP^qZIF0leH{)yBfrHp!<~3^XDXOLY9=g4$Js*NgxE)T#AC3D^kKDJ8;-{9Wh3BX zL>pL`^H0$8n4~(@>IQYx&Ec29#q7(w^g5cg;O$n!d&m4Pib^1ClWTn+y*&-zP=Rq( z(;wqW|J4UvJO25q2KQgnJ*bM@p8Zsg4tP71#XcP0m~~?Z+_wdoEE9KYJkg5Ot&`bP zBl>hrK-W!=2-_m)ijg7=9B00#9)0-$r1U9 z;6%rd96=d*S7U?mggAgV_Ga86mgQuVIB<)^FFFH_(S_ma;GcNVl4f8Z%*uYXfGb4!g}^01?v;~rK>=W z5JuyBS7yJ9!%`=lU>SxFj-C#s9b+twROT<1%@WDb6C5q}vPy5dRi z((IKS(t^-OJ||P@(mP>U%vEbq3c#0l{vJmkMwMIm*S#M!7Dm%ph#D%iqu7DkhBtI^ zhg+)g3kw_boJeIW{zp#Wy@Z25qN7aQ+T{LQ z_8@ES#tuo~!%V(J-W{5>(gu?yoh$HR)bxCD9jPCM)mQITrI=7vulLW6R9ji|#>G}I zdz>^^na0<2zM*~JVvE^lxlsPRg$BZx9ap!~AHFb~x!rIqTr3$s8jbB+#?%sPw#oLnzIxlE% zl&*e9cpRU>Hn^l+5-l9XG@DP~N6V2gj-DP$%dFWLlZt*F%^`Yo)7rO7OweYj9Y|qv z2)I@y{B|mek$~xg^S%G-V^_n=Py_p&B7)H(tS@2d0Eb}hsf;S?t*mrTi$8rKUB&}n zWtVV4!wS7WmD6NV@{6+ZbqjDWDV499vFObbYH-<}kzC$JWcYk$WnnTzC|`Nv5k z_~}WmlLqz1>xR`N3|c^@%e3^-=w#$*?j+bytYfdqPG;#kL<-q_UAxMhI+&xuTW31`9{KiWf!DRJROP(Pgg zHXTdI%UG_v)YzhaaUQ%JKVNUle!?KB7^T1mI_9%3_;K2?x*n@qfuF*V%KBsJOZCQj ziZQw6NzyEwm?zVC;~UZ(qh9?k0V+m}#nNIGv_=3d+6*2g%GcLRp5rH1FBoJLug!)6 z?QI~uFM;J36x7lK@(2OdS|Ql9@&z?5uF&scRN^^4p3cO+gXn9yjDYgO(M=v$^u_$< zb?c4NN0) z?ehgg*y;_Lt$bN%M0zBinyQGsXjQh|^=^%~Os6(T<VRomiRmye zk7Q*6Y9@a`Txw9%{RuVgXQ_Aw>i>C7lcSXew3=)rj0fdZp)v#$#ee6DuT|IS$sLQv zgJf+oiwI}(=hWQPL&xeeH}!x{rNDse6@bi(D?~!1`Qy$y7b-{m984dq`kw<$>Ip+& zTxJqjq5VEqIElH~o{xWRZ>|^`?ssxWT6h5I_`Rc1xB?efzDhxdp~7-k&;7zmlAfARqfSg8%gr$Dg3bNqua zr=hW*bnIkpuLeJm{>A@Qq5ckB{wE_S!E5v(>gO0bB14b3YLH4Uc*0wjD?xMYD7sI3 zb%-zmA913^>Q-5{rS%_;V-UA*0#(zOUuzBUsiB=ggZ2Z znEYWst{TodDErn`vk>Q1wwRmG3A0tTA zeVgSKCZ2Q`%+yC61@B;ke+xhAMlnW}8? zXc}EwcT;hIW+Sqw`;*F2;pMy3VYsCP*g~7g+;pKfTdQ)i`qS%miJR} zdRjBGrLs8}hsA6dw~gT${HwGTDpy>-l})4zW&+K<<+@ExF3`0X|1hse%oe$pANKWE zyAo0L)z3A1G8#3xt3xl$zZwF(;hn`>OV3yooSkS)4T)rn+(YfeyD! z8&3mncW^fykOyIjQu`au`D^|`ln7kK2UAqjLM2@Yzb2dFtF5BR42DK1KSq{}##7MF zQ|#_njX|^X_AGgP5{)m*q%n)%phfr^3f9RZGBtG0&)G05cOQ3{*8lrCzZ6W&_SLOT z4de4{{Z}c%^vO!c@tR}K4uos-zig35gg6rx)LI8UD>Y8f+^SK`N@|Ap0zzQ8Mr>ZQ z!hDIClBBBC>AEj_Z|xYm#sbe&zm1ZA0kT20oKL6_z_ph6M>XYg>Vf14rmBHw^i9Hw z0s~q!dE`SbZK%=Nb!MiqZ8D4yg?v)$*-{<=#801sky_DDVMmjbeHJUK$eXDHEz3J> z30kT)#1b(yU|>YDIWNvF@j^asU_7v~qjpk(nxfcgJYmiaM!cyp!c%H`g!|WrFZ1oH z+PXAcR=U;y$<}mfp+3YK?bBFvy_TbHMgE?al+5L{Zon72FW`z{qsL4Rf@+Rys6_8i zxDQ|h*{`oxDpV0eNxJU6cA$CFLmxPf$4qZ@)W8;-`~Acc$@0CG)GJ z4`37jNp_>x?a}<>rwtPp5qG+Cm`@pE7lN1g+@)^8J`)<~W-v4%2ISAdVvr?l zwVPCvv^C}o0CU^&aR_FSZx6u|b*7hKf6@)aR`kY1#w6NUrDfzNexrFpQ_awUaVEv8 z;%D}a#p6bc5oI{Y6->vY4#@i%Bg^Y#lHVzOoAbE=g2UAFiX~d9bxkXrPlX&$@cF>Q zM!ZV9n5MyQCZjj>rF#wUsu0#><#&6{;?Y~-k%Zt+l=!YL4%RmDH=hHn=9R|2i3AS( z4CB9I(y%XIEGZY@kWOY0$q#G$x1u#g4BHFZ_RIx=y!Q4=@n?J+`$aeD1I@9%8d3ZX zA_#(^gZKNK!c*4-Ofdb^q~fiiZ#IwHSG?i3Qog&JgTvY#6sm+iCj|{P`W&P3VZ{14 zZY45&u?k;eYNro-%8;`y4;#B=4tQ|9(SGTzXNDprE7_X8NuR-anDGIl(ND9bfp_@uOqmB&7&YvAChFF7|LDm1B~+!ec&g&PYjkx5Y6wyR z58H|95i?3kB1;D>A=g(1 zYB|C%Y8a}&1~z8zgo#Ed{YivCUcSFQgitY*HTUdamG&Fe}YgC@y|~@{m#jqJci=Urxv_F zfz}=z^He^$WusdnGwA_Vqw`FO-;}GCiq+9oAqOkB>t!%;gsrT^Mzd?SkbLIS&i(8P z%TttnC;1z^*~7lkwo<k*^}qafPDzht0a{;W zhOr)AUaJcj_6Gkr(|;!1qKEMx1*V88-pg133#1ZmnSbE5d`p;fJ~4ZM1skbtQ__h) z^kLv!2MAZJ78y7O$M$CD9q{?}(8&(;lM zZhHoNW4dDx{M;qekvR3}w=%V=U+~cTnPlTOaeu>+P*m=x&;Q_1jk~f*5y_gN#_Rjt zA8UfG>ld7CLHHZOveOR)S_bN@C6sZV;(kd5U*&Na#8uwzAl-3=Xyy&DKzm3uRPO^+)HaquKLTwYoiak!h z#W=UYKv2Lg;a*5zmmhH(y)Vomu$(FjB zB;73z)WVCdu>rCI#sAC|-V!^+oU|f61n|WdseUSVtAD(>B2cYdw-6UVpezxKgeq#e z$@!#z;83BkE`^?Y?7^Xz-=2ZJ6bCuUJLT3BI{z~SAoxf@Vzlzl7H0EJPhi|EO0Kn} z?U~s?Te{p#3m$G_v<=-nq88BY}4t%lmyqR~7dUIo+QEH0;V;gZB z+Uh?;?PVtu2UQmCS^ST#@G1_$RQ+zjA5b+AB*xj+ym^_r(`!&5ol8w));Ats>h$?M#h)_t3=I) zw_vSm=KER$K@D}I>g#wXUt&EKY&d(O-n9$83i(IB8r{7JH<45SHu%wf^Qo8n_s<8~ zyy2&?nE&yh`1@|H!*dy5JmEvow`POBGS92?u0J4VwSJKjWH&R+$PP51JJ@dk4vkTB z$2GY!=%%YmTa>vRCuHYo1M#s8YLYfm6=o*#yz*?Q-}Y@NZEUy`Rs-$69}8Gsm;F`FvSyy} zX$e^W`IH7=4JR-+0sDg%cqrS_gJhX(SLR0rn|%Hc_TDn6j&E)7#U;3VaJS$N8+Qq8 zToT+NxLbm|ySqa+7Tn!}ySuyF-RI1G&-`cJ`}tN))qLuL>b<&qtzJ(*`g@kxAq^t9 z{)qO+^VCxOav?l{Fh1LR&Dp1{G-kwnMfm=9EO45id6vM`R_yW{kfriJX82Wn6S6LY zq7mDnHczx`B>dge=o|@Ufx-tHX59_uvyg|BeMHmXi!bZ$Gc2U&=9}0ixIW9CYo+1N z&R>?`DvSNSjsnXw8ay3B4|1Li|Bc}Q-kDusDh6Xr!2ia(_%}ubP$~w%UQ%&sE&LZ2 z@qds-{&~nB8sYfw{{^3lUXG3~$qig%Ija2U`TrS&4s?zDPc+AW1_@+cG@{P(xy|E}o&c`N$=-zox9rIoXv5Rw0PAyR|RdwJ*{o8IE|<{En((l{ciwu@$~ zkLu``=YPA-%`|itSPbXO^p~8|<)P}Lf(~T=#vG6OPg#TB@-Lb9{Xrgk$$tw+M?Qk$ zWJQ2Bywd(EaUT3#_!p4s-v{>#jLRg7mug0Lq6vG=$&psyELYaRC5jgoM)!+Rm*usc zO(iTz?mrmGU~ttxel`gne!i6mtfcfdXklw#WaH8AMS}C^CftYO{wWE60?;wQX9_?_ z#^Hc}Kr1P?L=KjlBn$*JH^Stfi&L7TT1k2At_qrto&e9;}GYJ6e_MwNy;5YJ`}PJWxJ z(Cm974=2w4fca{0?Q;Hl0BNdBkd!Zh;OQlL8V$tze-}U+gV$l3sy_-ZWqUB|sMB-JXQp7mD$yDz<$%VVBNsWG++>Re%4Yrm@hn-9s zziF9WhNqQCJtN3>^7D<$rHc=Ga!+7HY4z}V3>bN#6?f+)={uQIxHsnUoob;Bx6qaF(Uq}ar^HrIP{HNaS)+ii`iIQCiPHJ_+E^}u4)bkJ1nH?{=<||O z;K2Kr^v~;l7J3?Ef7r@=Us&msf44C(gXghnnHDIg^cdMsFLe?$;G*LORt4I_Pa~YX zj?QzpkCUa!Rud>vj=#6JAM+MsFX_05(1K&huZ=dtVqo@5qphDH^?Hj-L^w8UQTSY` zL6q<5`kY!4PcoRBD9m;Lx3`rQNb8swuFTb`_%gtcy@=&iF=W)3@B1s*IZ!{0yiB#I z@La#Mq_VP4D)P{G;BVR`9jiW}W_}185R+gC_C$J?}4ju>*sZ%HQ^$ z>e1o*HRDE{@E}D zA6wy+{UOLdUmstX($uxqfic=!>$4BkGc&?mpf@*dD694QFrn7@=V@L5c+>WvV31% z!k!!--{xw2M3>NhHo&=C*8EXIFg~MY^Xt<+45$nDDcGO{z6NS2Z7#e9T@h{zhzI zje3ZnP!5v+Z`&Iw-Il-07Q|nM1F~9OXTWPJ`BYDzP-+CbHqkr`_qC9Wp$)HKAhLj2 zx9O^-E1+08OJQ#`iEEU^CRn{vRdLpG`VR&Q0cRI@a#aQcHvfJZne04?*?xMS8+mQYv6 zarWVc*WA*g!R|osxr@{jX(+l`xmFSi{$CQdg&R^1k7WG%#Nmz-sNXAW{38;?yXsxA)Rm!C$&o^xddAx!&M`ZN<`V@s4w zX66Yt-^6BQxI9YP!fjv;!RfU~k=JaLqFAeCpPmjE&wnkA;{x12h9%5aNwcz@1fv{J zk&0I>JVi4AxIg{Y%aFs~_Gbp*lD6r%9M8yWPzRHL3~luyFa!oWUrkf5VDz zf%7N>O!(aeq1*lXFA>UeLTn=d{0 zTOFn@HkB5v@&0Lfu!nYgs*m3OfRg9-3eP&JqO8v zrW_6L&_aDFQch9go%?Cb%$0P$=Jj6GWWVu=NV&9xU>e+2>*#!~m7>+5AQ)!2MWUAR z<(Vt7+MrblOvBF`Nn-eP$6c!XUDWGpoBG;Z`rFY=Nr9)!$)U$~q=K%cH}MwT(PJ2v z^ToQ4=l+o_n95QV3C0yZUGLFFM?`?iGlQQ$3!0lxWTu7V(knnjgR`~B?CtI4;;9h# z#uIesgmFGM^>!@bE9UU&o}=AYUa5=8%vF9BU(A=onett}P1~-QyfNd<_4`&fRK6pi zA^x+TTZhxVK4Kz1qcD*|($S$E9BfuQgMPq$(4yFDd%2%~3zakFh5F88KMzbRO6dSc z$MyHUd@kOhKOrKTd96n#iuf5cdQ6sSPG0WzhM+m`9y+wRoZtop2CK&P1eJdI*h*Uk z)1y`DCKBnfa2R#^YRh;-^e?VA)SoF}xN0RBq zEvL1T^JR^-yxP3?7}h$RLO$QTAgkZnEP+(3iTV1bGGhW%_OId!1|QejrDJjgx6G*# zO-C}r#ytUG68}s7JDm@BQ7L zSA6hDB8%m%_wq}-N;^JM8ki-Xe?T0r6eV}%6lLE;uHWve*ycAh=v8aB=Gh#+{E`W7 zq@KVq@~D&}=#oy7w3_#VwrRr>T|3G8wT-t(Ax-RDQ*N_q?=p^ZyWTQkVEc*Rg)lyJ z71*wW)58&Bk8=7xn#8QwAAy6l&Qo+hQjn5@_uvA2m3pcT-;?(3H0%sB=g07}8MraG zY|lMqr8qiHxS0OEl0!!>VCUV_SUVqEbpo|G^FDgQr9zwh4p$evaBXbh{FX-AZTUmP z03J}qmy~vhqY||4u@u50{4U1op$`;P(__e3OPa2e%AqDZ*?9}_oSXMKKuV;S5gH)y zyGdF=Bg=Sv#T`Lceqg>?DdxZekQ{`!50gh|^-p}TyQ@_gK)f1(|gfR%SnPG8=`e}4aE*KI3l|BVkO{v!_w0DkiYn*XU zy*G*_ou`#=O}=iEXrLFSvkQ;U+h$qoq<4)+UjG9hE?)~xo|dGpYW?n3C*FK1Zh_L} zuLS4KVF%Ad21amE^MGAu;yk<+31M~I+;OT7lF#17!Gq)dE|(SiQx1OxH%Z1dv1gKC zIlKwdf`XWfXR+qlX@MrXqK)g<#JQt{?4QtLmJ2^iJYB9TQ|$XiG{)7A_vC4FHsGg< z>Cq0~Vb=zMBZF*kzd%-5(<*W4vPnyh&)1@?%lu~;K|f@OsQ0Q;Q$b&98+RN2I4zt9 zlJW;)^8OL=W~(}tPs{$ZLmjp9ES6@M4NfOt;>hzDlb(95Q$!E*13ov>HOCb}?YkB21^jQd*0NGMUvz2*nbd!&&bzgB#~_ z*ku4l#ji@y_~qprb=TN9on6BkVny{A#%~VWF2zfNZc>Kolb+kbc{wP=>_7-idS!m7 z+DKD#df4lO1kkQ=LwbV;xXy^FYQ9O>HmB1wPzdkP0||S(KmEOx zY)(_aPOCK?WHwHL$7MCGz}wqx)|H**r}h(OAOflxBnQ=1sVHEap?zAvqtoJYrckDO z><16QuiIc-Go9gyD`rSel}rw~IG)a->8{=nwHQmtV*_}5zSnT^bODFakLQ|5+qqS2 zW#cGd&lWp^M${`QGFNA7G*hHrF{)jeqZ|TwB*1nM4YyvQ;8CbzNEp^Y7z#2y+F;RW z^2{mUO``T}r#&e{A6dESNn>TpI1&Y{;k$SUGA7@fFR9E68ZkCzq)_WS+p(_Iyk8gD z)*`|M?ikJL+8v&gs*rB9)?rKzZ`vkMA?gwtg+wscYOc}{_SgqG?222i| z)1Zwem4CV+=)|L3Joh46@uA(mWc6}=7f-5~!#+MAQG%Gq8_Ozycjk9KmowL5qb+8*oiB<`G%a|MyIF|mdrhu8NAj41 zGx^}K#1_Z1IssK-Rt87YMHUldM^dH+ZI(QzF&LGY=52qvr6fCr+YutzsUh7T&O`tv zTSEO(4d6w58`!cUKAPNPEMzLzDPmXLc2kr6p~Cfj^E+hjTnDA<8tjc35*bt0$_-r= z2B;)j(Ok;3soYw30oGc%y+BF+a~K;7NOOyvNYL^ECrg~w^1J4N#jSbCEs(m2t*e*D z{l)|Ba5w8RHpn96FW_KcFSpp~bLySW>*fG7;f!S>e)+h6Be2+2+fr+e(%)u+er^~N z&?Dza&ST!RruuB=&p6bt+(6%OPr{2)XmDmwt1|=pImsBu%l$ z7;~wCRMQ{_f-!-ftft*i&yq+uP=8T5Cwx9j@>z<%uUyOQ@SR6Awy|Vwa2QFA-gYyj zjrVYp)piw-12mqrOvQCf=9tYDZh8%zzz)Kc(Yek+V%J$9bsR;PJE0*xD&(Xzf1sQxh0U-4dlLS18PsMwCqu>6uIo>kNK=?^cD@k-^2doH>V2;*T+JH!c% z!Y-%2xva_qy}BV@5kscpO5JgHVhjwEtE0_x3dGuL=%kE4BHxQb-rF?3+?7nLYoL& zL*eEU0L1g>Dw69`j=2-LZ3#zuFqKaqTmufJ#E3^lfH#xTR_u7}W*5AwtIFx(?;uXj;)I0DRVKbFtK~url+UHQ zhjM3IK@D9M-7>ZOYzX()III0!IqGK zny;byYpqWi=nVCM^Q%nAOu(N`Yt5QO>h60_ z*2D$$Db9M1#0-?!M!7(9m$6ce=`!!t?u$+C`R@?zhPFt&b_p_33$e+B>2%-KK273r z-vBPZX9wBdcGkkY;BH8J>jHl87R>@xptKV|)@xWv_`N0Oz3J3JF!tCug|HF0VQyF% z%;w4@(&}l;jTfa4k>5E+*MxpQ7Jp|WLPsAmnDepNuP^i5P-=!2pb~u6%Uh`AN}|m| zA|d_Ea>TaK0M^*3WBb#M4?UITf?Oc2&GfzdtiKpc2B5d%PEet6b&N!}E8=OXp(HYO zU?pw3pmUE+u0P0&#RR#;n&FEFLEv)XswLNd zeP};VCcLnhACqD0Og|PBt7ntWa z3t$w(e#J{v+&)h0{13*%EjWKsSEqqWckVKH z#Jqlsw>G|>=`k%!c#xgop<|mx`OsHOA%a`m9NCUnA8G0K2H@3wv;2@#=I^+o4lh-? zqXIU$dB!EbXRW@6yH0pfC`HW4OU(%sWBj&`gG}1O>9w1ANeM`dRZo0j8m4^4NqXAI z_vJYnZcxq__P1-yM=YdhaU9CvR`|o3lK};qo{(H(FS4AEv~={b#*Ax->&M5@I&N;! zm3kW7LjE8F?vlc(cxse&j0hAam*Nek>AHrB^e8--?_&f^&n>r^DTjP+uL;dp7|yb! zln>8)ex*bx_vyT0;X&|6#l$PU3xL4CuXT3r8=5kLL^=?KK*p4W8lXjxUc2_sNot zO2b$>CNaG4D-?(q>;%LcPZgGwNhc@whf#>ERR(n$ zHh(t_HVKju2nph!c_CQ35V&apPW$5})bc4|_2l@H#h61-f;Bq7BOOf^m~TmiJtb^c z+$aPGbAP?umwKAl&q>YCKWHPGu(7W0fbRz{9UJ1#{avGS`fRL1=$i#JXs`WmL;Z%| zo*Qwzf(++)TopG+B`Skc^1&+-UGMGXE^hATci!IyFV?HmohFl)c|{Oh4Cc`OXi5s1 zsQwBw({(Cpp(7y?{hsy<6ikC4mg1mqgqE0&j)hV&xHXU+Kaw8&*r;ROx>+0ch8z_QReMOMiwz8+3Hd0<^I^c zr!5~QIw6Bt9B=0swkEikB%gJ^_wjIA$BtcVcg3?!Z8ErJGwauqJ2Uid&%a#hyfC92 zCFAb9A$&R`lAP1u{*{u0+n9I|>23{s!|DPAczi2E%-Xn??hbuIk6)X%Q%dk7 zj)`(I;~zs*F7%}Enu5$F;CCOljCwQ?%O%mu%aIZZ(F;Pm^xA~I7Lw(55T)g9HKzy} zb+>_6MA96G#L46gZ9Xr9NiwZ`$Fzby%+ju+ejnTlT|3JYdk%-S9d9*XLWiv%#1op>#7q*zGy6tyZcTb7*@ty)l*wBJyV~dIF$s=&Nbc7*P!1dfHEEns{EJ>{wjcfLMx7w-dy=jt!%m5XX zJ3QE_MvGdpaZXdp!e}|OU&U#*>Kz^RC1Igd$($e>j>`!=_hHNMTA>4no3-PY>OxTyiqy8X;L}T2}Pj zeLE*nF9oX0zvZJ_<=c+bBA>>3= zNQ3u-B}N{A&6Z?IjN{13%=(q(jrK^fQDZNaZGNc-9=_j_;ywIJ!pE={zu_{)=DeHS zz;S{1xylJGyNAf9A&q@ExOCdbb6dSmsSDkxCu0t@3<)v|RoVM7IkE`+rXN7~8S+&0 zfNDKK+S#iR6jIrb(?$AgB@z*eb)U>GN&!v>z&8NZwbOViRcE`5(?p zY+FT0Fg5%=|1IMojNi$1f^y-pdirnq;02sX(UjQF!`{-i+q*X>#}Unt?M7Ytq{HaE z?%Qfjqdcom^!9BScz2`BnQ71 z>U9~zjY7Yv#a+rhsWqv>Ig&EqYc@cGPzjMnKV6|fi+V*~avP!c#WLCs1+PNF+R>6< zzGihbOq*<78o;-8!JM9{1-F>b#iNHwH^MYXI}N-*P4d z)j^4OHnJ;gO9@q&OMlwLc};wL3#?NI%6r$D^c6Fg)1Kc6s<|=8T(f(v4^O{YxhhNd zTM<=E^`y-X=^RMpD2ABk>lL}Q1~e&kmUIT60MgjM@ja&hemETXx~5b@7#jozC?c*Y zr8A4@+(UqZMF>;<9+H$T_As)Zuc4D`#fk=rwO@YS^$El}zE{6=N8j^4nQl%29}J}{num- z7FPaknzipGDqj*>I9WH`IZ$cT{)ZsNYc8TwHfO|%H zdPBxxznql%!d%7=bSj6d_rFylNmx&p(x`AP*%YJnZZ6^4rS$!mbfTy%`v=i*Q>{nj+~x?g>5eu!kF09D89TVH^V>v|u< zX3=t-{LaxfVWHo*4WS~mUZ*fMc-Ld>IxTs}5w(!~62`80_bj+L;KHQ^=Fs(Gj;2dt zZp4a20)CqO)Y$8u#IrfH_MVPRvy`gA%9Qb-$M~}Jf9)`70y5p&bb+~(f)9*7*l`QL zpmpK95{c8NKO3MQWG}&PCuWVE4Ao2HYqIV<8pd5uYxY5FwtM$wWePjk`6FeW-)5ql zVUC0F>S1$U_n$+9 z@DN;E7Cj6X9h4#FwmJHS88c|QzY^SDTR2#G`87qkwR0(tMz=3=y6H15& z-DDXt7h>*;coc?bh+3#F)dD>aq@g7%G6NPMm0S}2q^mV)&@P;k#q8nZRf5<^0gOtm zcpwSKP$Kqn=BUS>4|kDO8O%37`xS-wky^)SIWp@rt^%P#)mSCNDIbdugZtz17u22| zW~v-AFI&0LiN_5o4f@Zc<^5!(q0kb#@@St03q4U>y833($ZeQHKC}tW|Lx8G2l5C> zqgzsb4>Jpd@yq7MmUXo9S&ER_{#yRpe}{?+==3%2Heky{#KA^jxY{C_}WWvG+f|*1Lozgkma8%N8VM!RoKccAUb{ zA?M0atd|BJ=#&sA4bj`{Qy!?Qa)IOFtIcA{pFAe6IC2cO*+gX3hl-Yn`Lk5bXRPh# zw*9Snma-XvpBZ})HT>?^yh1yOc^P=#Fv|NI*Ue?-p`%#}b5}x^PA;7q_3z0S*#tmt zCp9_i;npfiZBB^9o=+DGgRrPm#;UjVuyj(@<=7nGgd8Jlda2ksc=KRDHZMcd>y6u= zLxelKClzu_!+rJONs6vwoHKYuh=v#z#4fe}cGwc_QHOE%uxpfQs1+){`4Vw~*u_h6 z{chBZOtI?bY&4izG_nM5Vcf)q=i_ALgV@*|%*AVqh$+9iFhL0CU-~V*Ll52R1@dv{Tj+@E} zfD3N4Z~`-K=+!b^ zQ45_WOUo&w$qckn{F=h!j?;>H_RXl`&9kV8==tmM&0!;^mB?ZV~{#IE?56D!$He2pG(4)VZkYs$psme~qAS6)KqE6ED+Qjozslw=sNz4)^utj!mkj z{z4Tw0UF#fb`zd5Y|K&jRCrIAiy-`+9w#J2f5bR3p^rP3MUrR745>~1{nxGPI9~{6 zq!J_a56{bIlmVaqek7!h1ICqVw-|B(h)B>XCmZquUZHn+b9_KBM<+J}-^QUv=~-$fjPpGo4Ve{SBrj2XXd`VJ5?s)%9Kgv$;{l zl^gbU<3Z(ODo~8QNPgUzbZBGeowelNNtz!iNCACcZw!F`a(mcJiSZlB>g4lvHStqhBR1@%1)M(5i@3x7*Xjy{NV-QH2Ci zV^t=-rlc663CUV~*q^582|HpnAiN%A^lET+vGF^a- zbCx;lfOpIV@mBo=6Xu@7@~bQxQlR}$A}H-a_u-&j?%OkQj1XMg@86xa>HH-K#o76Kc`UZX(D-M#aWNnI){G;&l2ft}t9&0u^vNJbtE!S)M*K zYTf0sk%V@s?m5-Ox42Km{*~8o8S%;ZF0ahJIpUjCM}RE1V3paMfT-fUVm0NmE zwQ3>r8=3r^-zNh{1=2LH*lg_2+a!)017k^kl-79-x>CY_*;9RVAD%W_?s!l>(vS=0lSzP>LidGI& z5xikyng%xQ)Jl}p4(x>bV73BL1VIvU9yw>QCbk}|O!}G41KI?BIapANXG``!~mW3~W*4*{h-43A*Z6YbzFS6L|YcQ{~+sCvRyIqgE@Ldf` zyAMN3&@fDRyt<$0Gk=54fsWtbS>7p$I4Y0iV=zIxkFU55mvKR?xWo36dZtvCgN>`< zPRV5d^xwG+$Q#6=3g0YV!~;%?%g_#|4OrO@%E37bWpKk)=^}09y*q5%e~U*5Lt4g0 zEN?Ng7EkjL&;n7x>YHikr$yl?B97(qt0K9yXM-Y5(w}sOtB1~}MoQs$0xdw3Ykc*9 z)Aj|(M8DdJ{U(io$NJ!2s5HvcO}#efFg&`wNZ>2-3JM{6r0d1h64WNOXegGuB zrS!~w=Ld%RZ}gs@G8FDSLCmER#Z(3({qJCVuofw(h0L|~N7ki8xMXL82^v|e%gY8# z8PibWTgjI9_rXuYXxqQ|`T13wShC9WSLP{fwKP4VgRI`gB!h%(`akViE+@*480BSa zR@nLQxt8*gRYbxg#hRdOyuX{nzp;tIw~*Urbv0(lP1brQu<^zfHizoB*xt~9wSG*X zb6zs<;R48)noQG63OJ*5lV$xm|jLp0M-<(|74E$5=fK0f`LbBc8?6Bkt3|$BVURRTBoekpA1v&4`wu zX-bfgf91i=0WeD(FJLyascc-}KSF=2VRK#7MF5n{uxudm(B1Y<^o^lOu$@AgrYNUq_Oi;>{;tR z0W;sFl!A{_jslP`CF7cXXpl8f)uol`T0z$2D{t8WOpD7^@?vdjn;}DU$&ZB-X%8a= z6KLfs3YinYZvuQ?&GVW{yF^qE_h4bA8m4P~LS<8F5t7?ufYm;ST*anU(8+1Enq6km*a%{!|XLEkeHKxohrk2?v?TF8c7Tj zl0^s?HK1o^oqxEc#C6Fw7uO5Kk_ZR9DrJTp7Nu2Q{J1!N`4ZU92RaWb1(rKFj%c&z ztwLCJRc{!j((epO%}U{t_!{1AAK9`dkjk5i9%=dfQE8w`q?2TF-11)y@Xfp3QY7m) z%T1+eornu79r|dTaF_W313RM5O`c>K|8u(zx=8ur*U`Y0TfJX%30FLyutyUZ=Aa5s(#w}105AE~$aa0UtWtoaKDH8@7p z(~Z47L2o&`e;~$%?{VVk`9tOUN0{lp$pkiSaY5;OC<%*=spgXVe8SAc zwB(hrz!g9!mgnsuTU;=+Nu$k@1V18tOUQFNxnyzGEMDOdW-bI>rG7>6551p@HEdv7 zQXh}c{g@gr#@AqcQ7^FS)~8#!ko)^bDAaeTiyR0wL@b(Ih!2RL3oEl_Y6N`xs@FtL zkgQv;^y0y{;NHEC-47=`OS;rvh<0n`MQvosneyGH0zhsIO3uJ6IY2(2?XyD1!V!X1 zR<51CK*R~SRcc+_E%51gpWYTCuWn-{l*IG1FGikjI5taVlgG~k^fqC?t^7j~$#86& zkHw$tW@BWt8PHHqo=+Z+uS=R5jJP;Y8`W!G7MFiT`si0DCeC{Q805@o?^=GrBc>nfa3m@-*~a zDqN}aErJg0n{NReozhcqgHn&xq61??NDP7lgX64EEjVwQ>Ve@q!(y9mS?vVMj|bHH z?uU%kBgC=o4(I%eM;zL-6{~+fah(jiM$rtR4~2hW*a<)OhqS>Rb-DMGFTBIX1P6FegA|q_u7I}%?$Ke$ zpdmkAbE7dzYWpFSFvKRxpn<2@pF5G1i;8^kHE%tJ{_<2O&odly^O4>zMbT5!=+jU> z=Bcd+t0nm{eBHrz>sgA5Wz4nbncr?01nA5wPCjTFyYtO{Z14y1rO-hhoC&38&My|* zl1aZt%o*nq{a<7R{cpjxPJib}kR7EH)T*t19!#n2Q5=N(46}XJ>6rA8%uuNr#CG-& zkTlM)hHomgIU!Er(IM8Rexd}&+(jWnmMS>yJ^hUqNXDaEJ;ONP!ES%L50FQ$Ma*pi zcAACekr_<@lW$EqutxTgB!GJX71gc8OgN+iuqgO4hH8_IsKk6@{)F2#Z(%G? zbGX1gT0ym+yR1~NE-_ya1i;N&6*>^lC>G3R74D`P9Mc!Z;3C+~(?s=eEuBQsJ}%cB zqMd6kEYe5H4m}+Z7o<~Ok_cAs!o*>Q*M=H0TF!p0}OmOawtR*-_$( z6if8+C5JcVmQwC^WXhtkGnqVmoBt zM4$2ioLT#+@+gRr;(-AHoq8F=b|WUSm)ke}z|1K|mCRB;wH|kf?&3^fw8nXVCA)XRY{@bPTLFfY(luta z#$fV>Oj%AS)Y4ET5(Tsg+s4$2!C!2+N-JO-b$vIoV@xet^sTJ%)Epw;5op7MVk)aQNJC3haaZX9T*sW%dO@G}az3w%LQNNHA zAR*o3DPo8XHq3ZxTQS}pa9`3%DrbcxmJh3@En`3|G%T>(8)VAYEE2~`O7^h?q0kJq z0!T(y&5C3`BK=gvQGHGnmC`ug|89ZfzclD^FUY#)i(>NMvCfhn_@w3?cN5zwevNd~ zVFpG;z|6Qzf>gP*88ii?I&)RfCYJH}E3A>exjYP}^?^x@rwB2)FUETZ zdA(l{ttjT}u)xqEKUvw?5O;m>?kK=<^ftu#L$LElr5UnZDmyMtSy~_nPgy2GR}a%; z-=C?FkA#}- z``+qSa`MQb;=7YT6KU;xaAqvz&mw*5QlcKViJ`4Z&=}I??;V<n0i{#XGxl@Afek{Ul`7Dsgy zTqdES7(GWfmELfIu%#&Mi`=OsGbQchth|u%!xwnq32ikl{m8L5zUQPo^5rK8659(^Kp=b<2rD7YDUJu8HRIpObLIF$zDXz9tJQlJvn-Hk&@dvul4_8G{2&ywR+!OEHXgdZLMl&>!J`kpW%`ZIzcWd+ z$s#TW3hC7p?Ir*-`8qhs_}4t$@gyBpopFCszab78byzF47sL@SU)=E+1|nGp;M|AG zJFOHJu^~GzWL-8QnAGI7D{;V2X6A-eV*aqQ3O| zhf=b-Q_(Z;0Ml&hcKs*6Wkbc$|6&0skqHHjn|598iN!M>gX)<*pT)47<}g1QHz?=C zwe+{o#=w|}3)W1Pl@D5*9(JBO0Q812`LGK`W)@_wfO#;*efLZIH|$j(B)BJOcl zx`NNCwRm8>d;7+>z0mb{DdA5e!n(QtB5MYm%4HQayEXd#K-qU_M@vpc8#8b170NaR zNE7I2X0xMLfUEPBI*TSvKDE-|8)uwF-M~{{9rJkUP+-6tmyd;TWvt=2DOWNd1gx&hqBd>_3 z!w>QuX^*Re0{Wl`kpyWq;9*p{Cpx%}6N7y|LY@5G7RQaig+tiTVsyw%$3t~G(I@lx-&J-2xCXV63{S`?i7Nk*C&5nk&e=zy&?+e;RP(hIdA{L^H zsMA8k3xz*U=UC_wqAEZ9&p@nrB`27qGambO6>xR#9VgOQ!*5M(aL&~cLd9S4^5=_c z5)4nYT=v_b4N5L`FZmnjjobk=7v;r3aTnn*FHE63do`cUX7B6UFcrwby1N3zY|C#q zZ=MHl(MFd|(5SteX9Np|VZQq>HYZ*IQB=HZy}=tXG_Pjv9v&Q>-y$xek?gU1IVCOO zZLO5tg$={ECNr2za}s%oa)s^ff6gRmvVKFnb5DhpI8bbLube>Mv>G31bQF$zivr%? zF&1w4ekxu#?dR3~WFC&%N==i>0xnpA{(so|%BZ@UCfx)H5(2^9-QC^Y-GjU9!3pjT z!QJKHE`i|gF2S9HyWI1BGvCatJM*{q?%mZ@wO3bn*YlKIdc1`UNmTm-aI17B$N~jV zNP2GvCrszwPFkE6168|1NTXt0GGHD^=&9d(C4!%2oMfWs;ojbFt^&_Qryiz%q6wlz z!@!Z7N%TBY3sW8rknYDaOEC(=stZ105|1KgpG)!gB%YU}4kvHx40Upp{%vyg91=*^ zA&3aHF*)%L*{XBm5o}DCCaU};9(=(%ANV97x`RWn%o9smse3A79rf7tsfBFg(7_B# zhK~>g=)xGLaC)s$YCQ7EMLoG-t;CT`t!h)SLa4%3y&k-b(^;#i4q?Kyoi};I$n5DA zv}Qm-B5?+1Ws%JO?NResFtpJ^cR^p9>q=rAQ(91Gm`1^YVMBa9npp1dUfqD1m{((6BlXer>Wi_%a4ly5E9|x_J zLZM!6g_NxkO-@9M^9u8BCFCC38nrc-37Ybg17{of-|P7|U3~xpt6Uq1^jmuo?JhRE zBquW1>trCvnigXJB?KqeC&p^vv-&IAjR=Dh)%B4a`3Zx+GQNrFkhCVO@9zLA21$U(v z0?wxXwsVyH(@ii0Qb||9{j60<9}ylNO|r~zv)en(eyf{w3U2fLyA21;bdUD~9H@NR zk{58&XqyY4IWL$-hjx;oY?QN#$A)N$H_er|7tkc6u_BSa7*Lgn`!R9*@%8tMf7@j4 zRWcY2W^IRU5SqEMpD6o$}YHNp|xP&3Owp%?%waF)1~qO2fO~J zUfc#&-oBrvs7?<2TzH!N_u~jigUS&n9F}Bw9>sDAi6)Sk#Vp0LE}dI=%BxQzYCE|c znEz02)Ks8v z@Aplk#6L!|#CuHP$^-YhNd02UPGs}HB>ZO<0smnfHpJ!e&) z4}u#ioW#fG{x#kIdeIWEHXRIeZi;ooiC+k)a#M`dkOfN`uf7|ZTKYe~_>by;u>MQ@ zQ?SVYhxq^Ui~qEd({FRc<*&o5e1V2lMk{Oses$QAe(j^RYzd(Ar6VJ7%5=}5n16yc z*kYJ%%ByVb|6$sH57+|_9tgLNw-|g4b#h*{I2BRZ~cc_z#j46 z4c&y`jxTSXm3LMD-S}^r{!>3&f#CVQA<8YZ&;QS^|MRUt&=6Q%euA6U{5Jo%-2e5h z-yVO#{?P-e+QjhxN&nw+{e5u)w|eJ;5yq70}FONtWDXRE9b1Bod z5Pf+vkk%tdIZ@0$Ir@Wbmg|zA`#Tz*NH1}|arkmw*4|b!i2GpbVoi`Kyw-idYk|9D zzo`XiNTlEO5*>LkX}N&&V4=6Qe3fLmf6`=ZDJdyAn!t}MpUaXkTclv-#PfoPS76Wo zGJKavDJxMZfdKxSWkvxyBD(>^Fi`Ou0w84kmCGzVz~@yXWA{-Vu0W$MDu2JHTFh!Z zC*ARz7G!NILx4w;%RLfoUSQBi9>4d)h#Q!AQ~}_;U*uM)ISg2&sQ>Uwzv#X!jULH5 zo^0$~+ z9PiWe%P8&_!zcHvRiSv&!fwJktM6C^-V#MCyKTMZUvff@W{SWiPsM!%^wR_j23`!K z6!;D?^GvVg7!Ps;{e`pJ?~1%12#14==jyBqzp!0CbUWwhKtzdKCE)S5lTPWcIjZd@ zu>e1kzp>fe33Lz5SgxHBs1=JTnAN2&a{bUmbR}%bz_8<^d-id6eEt|Xke+P+b2M3~ zxtBlzxAAPzsqH7=e-r5J^fqM(Q3eaSvRnBjv)TdJ7w*UFaj`18ODRvz=->c=x38&T z^BzP4(=~@@m8N=vPg>nBHlqjx0W_G92w>1l%XDfoYg6#xXK1kY@pVqwe6QdzR-h{> z@(+SoX)9iFq-_FiEsr#<=c}OgJN#7jw4QH|EpIQ4k~4*EtF)Ny+O@#^2K~*TMa#9P z2iNU7;E}&&b~2Rolz+Bu+d=U8)Qn`$_eyQnZfzVKCDIV^N^tPYYv8!UaF%!LyUY$o zke7x+iNOd_%W9EsBd8)ym_hj`*9>)xH(f;*FTq`TMi$C-8~@0SK2hdUb$0W9}G+19hBApWNum=yh2565Cv+9i19yXCce^ zam?ZQEn zMn@s0mxe|ot2&eFKL12Wh++F*UbzY%H!@{zP1u<+&MB|&jA31ER`l^3Z7+r=bN+c) z0-BR}w}%A)G)99xTVwFD1?s?VdtYS)NYNtpAZK?PsKuiU#2~jJ`UfsH>ort^=`(s? zfNy3s>zB8M<_(|-7kLueh5^&Q!YOjESBil8l1TX_%6(>SMeQH(!!)P;Zm|-Qk_Sb4 z>%cCmici{fmWy`FWDJ#XvOgr>ndfOf(Owzdynmf<{D5%cY4!bvvr$;1hDIKjZi7%F znd5-{qbRRZS5ne47GJU^Z+|T|iUSxsSs-?`BUaX>)^<~ta(lRFA~N8zdt0McswYq` z#p}2GsmS!0<_^nmFK(@}ik zUS)6K3e4jl25at^(Yh6CimARW~$|&B-h{W{YG!c}nLlZ^Kif@~~AYm1C^cN%-ai zSzF4iORWkv`UPUj3{OXqFLot4!fAx=B@J$XT;SmD++ztmAolQT+}h%UX`BQ2&<0qh zS8RQ@yG;wG?8xM((Kow;`YTs&yr6S?yTY3N>15i#*<~(kN_*n>M^Gdp%o5<5g(|Ba zQ&vdYv#v-2e4Xc-s2(rO9Z6XvHe!POY41%|VDE!GcwJj3sml^VCUc`R88ueqBFkIx zGWqo+fsngHtkCpWKRBs8c*MB;8~tGy;6T!2(w}ImqkAv)cLWQ1xa6@*+e}Onh>ph_ zhr^i7Zn;tXw#ntid^BrB^kPW`;w0JM&{Oe{@M$*cL0F9?idKF2SOR-lU;>8-x9{9T z?^#GQ$2Xt%42wpcgmN@{HKgJ&#z7e+w5_+qo{&)u)OlU%&G<%5?fr{k9HpLwz=_(9 z#AIy~^+909Ds?en_44POQrA7=L*4GIx3U4NA;f4RpB_rj&a&?HGnyP=ZZJO@e1=-F z>u^jj>(j0#C$pm3UlL{O-+t1XcGO@t(qFM#XtI9j5A@3$Q|$RZuegClwJ(L8Sy9h# z=yi~Z^ET!lu*Ba}TWyG7tvi@a(ETm1xQgQS((TiL$&276!jg&Q1CQO3>^1_7FQP#u zq=nQ&W%|!Ut4^0EU1<-a!f>8@5|=61iw*VehgvIJO$q&WWMx0``;0<}_?RR1Et3@U z&ak|Tl*9-NPmmiS&BeCNge(~eSC^jmY}6#*tDM_4Wf9G5Rl0NdZS=XIlVQzG!&8PY zl&O(ja;KGEnZ`R*A7tCM%M~|KG6umkH-!j(=L_zn=iIh#Zg8~|h5Nk*tDz4~B6E$w z946t<{;VRo{TuGU^Vn}A5!uLh6$K8wwB;D!IKI))w=YU(s)whABd><@~k{Q|U8ft5)Nv zA#;QwS+?%?*uRv>of02g=JutOt|QK{@bn>PF37?GTx%#ed4m*sfj&1*Prt9H#qwq6 z97d<*rD}cRFE$UmwW-|EoYG_(O8nrh+VZ4=VH@Y`OR42rkDIy-mSF6>oItZ_<`Nm) zoquTyey11`zuQ!R-j!|v&zhgPeCdarjGJS26bC+XDf`%7K0^7r)$XQ?>)ty4^UoH%-K53FhT?RCCCqG5>zSRn)O&ycrS@Paf za}Amx%je%E^NrRSX1O> zLb0wD6$9Yn3i+=qvynWZA0*edxXtWtx!$#JrCr(l8{W?n>zd>Fx^vDuzMCG`U(m-+ zg(sFdxPlk-m(ICmEr0?=t5rOPZJvmc`L{nxf4w#=fvi5tab0)czj~d&CDdQO#8cW> zSBy+Gw^3m`vV>Wj_Qg={@G~X|qNW^zU^h`+CUcm+oT)BQ1!jJ2s{MO`^wJ={w_D^ArGW^Oq`OteE<0N&aXLHsiF?)m#UW4(m3<2LFRF5MLq7m`A1B z{N@rq_o5&C*|w79?RtP)tLC1V^#{NDA~iyWnTbPOtLXma z6s~I*P^PSH;QBt`OJ;V+jPh;mHk!hI?oCO5pBo~82JYnN1VABgfuBV=sbJfErtOPC zzHaB=Dnl}4FcFpc!a!UB!92Qy;*>1liyksf*sv+a^a3@2x)K7G^dm*_dy~Os03ypU z6Ip;#S-tyyNE30B?sb3$fgi2VL6G(nweM6Egc|K>Z~6E|p!VHw$8n5OYP14s+T-=d z^<>8CsFWsp&4$}(gtf=$=4@X{Y|p}j3pNv7R^3PR6`S`Jp~Y02FHAP$AQDUA7le7U zW6`IB+kN@3k8kPM4_~=~%5`Fm&E6DGdNNge6B!1y1WAnke-O$|H8gc*27+d>Y`;^V ziytS*G|>+i zllp$3YRUL)@NigHstkRp%pk?w5er85sBdCOt#L(b#&tVfV?Gx1@!;tCyi^VNpyxFi zrAc1AA41d_RYJ3+8GwHq^p0@+8Z$I+JZ)@rXsz`{sKZB(mnKE9LC^L2+LvZ-_1Pxs z6eVgiH-oYzE(HkLn~>k+YX9aqIwmA3-PAr+z>mqAdf7G$JEJrLMzP&khX*J*HrvL-0#t1a&AW zlGHc2p~M^#1Nry29Cp=47eB(!&PoD)BMLao9+~A85>Lxe%K{yx1_FG&?Py120m%lR zbAOYbFX!BqxdvVyidH~=*RL<`-b0-FN$LGGvE^7aBLVgM>?$P)y0&`Wi3VT5TlZvi z$H}>8aQ?7GM&gd-*;W=`t9>fXp1+AVe#7f83Ht@7p`6j@o>Kkg3*7?0>Izuimyt1d zS?&2>oKPByXH>be5$e1OSFEi%wir@?**dbGA`c<*g^zEKaLrC>S@* zme~9+z6Tk%IzCs6s5G;#(e>#DJdY>2UWcKS=&OqPg|;|9q#oZ9&ef81mKcmM0%Xrg zp3jq4u?d!{)`Uohj&e5WahFsWV$p5r`8^-QD;BG0E0E5%!d6@C?CPv4oAHn5vGEO# zw@NYHPNo-)ajW})BcH>t^%=tW+mI2b;nihDCca?%3poK~h;(bLWZG*%^dFv~%86`s z$KL<{%Sy)4!q!6K5AhAL^O~`f zVw}?!4W%}W{&v)UxXmCM{hU2?FNBgdo~@+xyM4W|sF-G9KR0}mOU{JvQEijJ|LN@j zrMo%GnAoId+waEXVMw_FbxD^p5F_vuR^NYvnlgnQ$50o1jVz0>(CJPxXnWw7c0>;8 z`5mu*&o}~#EE8Zx~5elJQbrlJn*DfeA_ z@8){fKGM^6SjnF2cfJA%x?)Wfk7=HqboTyzf;?3&vSu?nUFwRul;PBscc6{`0X|g@ zF?h#F+e6|#A&5G>>NNqzrh0P}o9Phe^IzE|mBZU`C68T56mojQ$Dj0Nnh>U8&UAG7 z697cBF$B>7o;CG1tch7Y;?p>ndlNiL3VxD|*XA$*t~}CMWZnGQ*Hj7DPf(T|Ma#^EGc}*J@9M#+q?TSnv)bOHcF1d( znL6Gu7HNlX2~CzNZv2d+GOUJ(i0X!X^I2ZHom1hEuhvGyKf5ZaBVpt5JGaX_>jE4I z55CielIs7Mz!>jBGZcJ;Rr%Vp3q}B=(`zdvOAgxX$Gl8YI|LyYd zV&oF2!wg3)CQG9#)$w7AKjxTVUd&F%vX_JQ+zQHZ;=67h(f4=jiW~*wJ58l?<)o&_ zsIiPCHdmQ*RO;WTVQ)^kiC;OT+b#!0R^p9$d1od8UHi6lI-g^OMw=ZmQj`W(P=9lh z70ci-*^y?qKMPI%OqMCwvPLfz94cdkN)c*ys2pt!B@d1NVIiHHRkL+R79jq;5kdio zZ%($4%VYCZ`Uk{pt;pFMC+W@EWRm7>B6*IZ7~2idw*bi-a>dz>^7QH}F8avEu4>jY zbBF};j!*Z)lSrnyYtj=m^-6v9(0~t-beJkb#QX(%4*n-q@-B;VhmiZEkX-^U(9`Ad zS6}1fCb3WNFdukA`AqxZd^;cykq3kh>_ah-h1l_w|Tt;Yz*uP96mS%YJ{P*6lVbkZOjjdTxej zh{O9yTuzFRAdaR`qi1h1^}%9cIB>^K>d*PU7}>;5&~_q~*6{s^2|9C)=%r~Sn(qT6 zT0l}^$YbIkvx57)V8}Sf5o?@d4+MY|cGk;bkx6;h(vJeBrLtyRMP71mt$ek&MNZ0u zI0bqln>&U^v*NP4|9bnz!f;fxwY6-y9-xXN;2J+5u}`~{XOWXrK!67oi~STfz@Zaj zm;~7;v551cqL%|k(|3Aio2mgR!vy~hC^GRvuQZ&&;p>zpL10v;MB_XxrJWIMT>osI zn0@0)wf^<<#8sZrc&UJ~41tlrQ#4>*tUSx=aulM#Fgeitp;acX#t-f8v#U!g?ABYm z=U@6a_UG6dk`GR3Q;ZLIsx2Pk3oenm0}i9*HoZ8Nc34Ja5xM2xBN zi`njysf`t%SEzXnhbwAQZu(2*tL`bw2WWarh?zt`6tQ0S&ivCqg%TI1Z&2{R4OVob zWcwb;-T{0*?I6-^WG%4Z8xg~++*c=0OW9Q?3>RD+qKgOf7{3#19@9Wd(~0V-zs;LliQ{~j*WDIxRSfNP;#Nv2mNvxQ&;kqSTyZt(oLvW z_|XK?UB|_YN<(8y1=-iB<~tWUz`yWi31(^rBsN4g5w93CS}#kAO{PpqaeNW)fH5yj zMu-;Ds`AjeSCUG1ssX3I{b9U?tKZM?uJV!ldf$z5-f}lZ6VSrN{Fs&&*m^sTgBGC* zMkU&HnUlxUPwF5@h8^blGjx}Fy%Ge}$W4;YFWKBYF-*b;w?{m{?1jaU-{ZVSF8Hd} z_Pg2SjwgTM{)Ixs>gLuZfJ2RzTQ&eHcA~GqlsoP- zM9ZVRt@1ku`n_jl>2-^RO_PfX;uDT4J*nXAgn8D_LZ8A7Spq(n ze_nZ}8wsHyUZumE$=+l5$}Iaq`c-}2yoV8O=?PP|JfpTz zCMH=3V;>(kH6Od`0{%|?lkg>K#T1dK-;>Wh>a1Q_Mf;!=#+7wSqIH?1I~GCrFHMM* z7Lec!F6dI;lQ|&7AA7E~p}qEE?KM)JQ?-aX z*KXfeVG!jmXza@{Vt?&+P)vRZE~4z*9Ate$+Y~sO$l`>Kr6ZK$jn&Kd>N*IotFgtF zUtz6p7t96i`Amn+-3&;4nf3cDoE*X*-ea6%Z)<6nK9hZICL2Uj=M-$=-8Y-P<3sIm z+qmbFx9r`X}XMIb!|H=QTj{)Bc_Y1not3Kc57wwAMZMy(HB)1?4(Yq7hTSSCY zeVwJLECbEEQAd{gUhEk^=e4g!o!+)$nsI=UH^Gh@X$Jqhy{N1n+edkB!}RzAhZ7vG z_a9n=Rc-x*Va`e%?3wmlHws#fC6oh%YxXz`X5Pwed@ftE68qF0IhgyC^ok+Of7xg( zUUb^t3R~X2_VrWwlgCOxe)*ad+3Vi>gw5NHX|6PcVfH>WEnQdZo|~tNfRX)EuIi#J zNLLq`tmq+EFTL+(fG_&WT~oSKT}f*>{=G?Ee>14w%UodVc5dQHk?EGbjN$|>AkH{VhZ3-6=FLJemd z?b;5Y&L>B25_6oIcAG2)r{dTcVm-Ty+-Gm{=`>~6ye2ZIyv9uGylRiUKnqCD2C#*^ zN|hnoQwdXP-xI?8$6`AZPItK3$b8Z+*LS=s6uXNxU&nc0(Yd@u$~x)t{IS;8snQ|%iTa*HPA$$Cgj`-FKP z6VO}P*Nv!dS`ZaWNJE3kYxQb!Ksg@a+*!isM9bINZ0Bw@`{Q8(!{P%Yn923zwT6EA z$vCN>!kz1qaZZ(_v-74KA-G6mzMEcU?;UZ2=)7_Xr%gEZ{bho2){x?W1ap(W-#f_?biBIOwI8;Y5BsXgl!2+uS5h&?mQpOq<@xZ5C zsR@OXN;8A2&(^-{ezz(Fm=6Oe;(KdWH9&A$&*+wOvj@ATdQ+813QmDIdBTh=nb?SmNAu!id(jRd~T0G@xv^OoTRa_IvJBp4yq6)|eD#E0p7{%qR zQZ$kLrpdvXJ~@;qRn};3eAlZ>$FEj+G@%e-D;hy3qS@NSO*%?*5Gm>X1zVP9(B5AG zoY0BVm^nu4#2+CO*DXw`ZTCG%7w!+ zrVX@NSHdV~!!(&#s9O;jXRvl6yYmv08)O|GQu%}p=WQxx?U*)-zeCXhIX7Q*Tz{HZ zi#1Q3P_kLHD2Tin2YU5LzyDKKfiuBvCa6g%Pl|dVvg35;!v1R%xRyc(-9_#4&Lm0H z*bc)$SF0*~F&fq7*2}Ck5pCUv4sAX7=31;H zRv$V#i85AvVKk+Y$W0473YDCyO1H~eqYxGY!NHz|V+a<*noB0Rr9vOiC6sNZWd*Q@ zaulfHBiQ5DYCt5l6~HlnOh<5@YfRGKZ|A>=z9I&<6YeR0cXjQ4U=8UQ73={%mkg%; zh+fou$g0Je(>z1o0$pUlD(c*^G^3Esx+V9wFV8cSnqb-weMgb2ABe5S3icth?;iwk z&uN~}Hf!UR17Zrw^cfhhEoAA9WyHl{{qfpJ#ux@WBZ2Pwdfau{5#B%+ax?MNo=OwX zlxO}SAZ*&c7Q>8kgr4Ps`BbE>WsTh(fWu>A?kgFx$K;LcJU|0DOhXJEEnDoK1dW$F z`9Z!OsEeQzZiWUkc7Jjt*G~-k)cmfxxI0D8`#pF4CKo@8W_?#Yw?=F?@v057cFhk$@B1c3 zwIA&l`GZ+h@{0nPj@h*qb2y?stT1*|OH$O4X`35cw`S0w!K`{W%PSSc-W(GRSlqa} zI6c>i{RA@)C3k90i)NISX*?Iph%*owT2ney;qo%O*4T1Lj>!%>r&n=I#xMutejqd% zhnelcWJ7!QwMx(!gyxAsP5Eh4^Tfa~jh(i9HuN!pG8e?q#szk~IB0Upt|aLz0Lhu$ zVojpvPt`#c*3jh^04LyQk(J}GoikAun+V%;YR=24WW{kW|~7qb50G4`7?-$WmgjH^9WnZ z^o-#O{hFp#oV1vX7U(|~AK(hW4`p9t?GQ&qT>0uZlsxu;a*b}}@ z01)XDs%4EnWlAwc#^@h3ok1k1#|G`YJiO2A`J#r zPSYR$Z1!4HB^%}=>5Ad+PPX(z%Q8u@RItnPrcrM>$vYg7x@jEh(|Z+0l}EFO#WAFrq(@hDXd}d~w{vv}^CkkUqV;JY%>!Z@px2Zxn~5 zk^;V^WM6{j;pq7azYBTQh78PFK4db*9G14MY8lJjDAo*7y?#-Qu4fa?PxSi1Q07oU zQIAh`@9l-UF&f+b+3r^dX4zWVR7znuUEBu2OAkl zm$nCY(R~39c7sB=IU0?1d~nB_|5yM$QCrqjHm3cjsHX4s1x^f9(N9C`iXkNGxGEr! z@fw4UqTSJlZfGR5*vUG6mh4kMN05{l?>7{qh~Ze>N5(ITTR-m5kQi|TAjs@ZZS#ri zPr5lj@EKL?vEm#iJiNnghn|a>n+ze7wkP-l((JjB!zT5@ynQtJxS0lu2r++=)@Q_= zQ}IcS*5Kui(8l6rR&W^fo~%`%gf>>zFf2NFZ}?En|7`nB-j3>{I61SVy{hz;P}|yq zKH*M~cguDatNMyJ`W5%<;s<5LuYQ*FZ~u5`*wVkeQHr+3+X{LKXV)ggaIiK(l2%JP zD~sof7tXx8AjOTI^`T?hddzIGdCTvJ#1F(F%lK$!-$^KKN-YNk&UHdlP3N`2kx8R7 zve%*5N5cvC35kqyj;-Fu(zQbQ3>`=)VJfI(FdL}u8tLjZOy8!p@uROqPU0l zr`fmlR5U~Ix${{*+FxLCcKp_^d0QG<#|z!MG5$J^dZ2pSZ%^iz~T z@~0~?mA+C1)UvwM`-wf7tGe@$4!#9B>(w0nkO@9iG8mnVx`^Z$tf?QR!9Dczk*pc0 z3bn2d5i_lvh6E{iU7F!)t)c!o_8$-tHRax-ADE8F*ZN!RGSEL-n~{6QQ&raC3@Q0t zyD9U04)FAsfH&iy8_XuCM;iGUzu0GeEcMn%-YtRTr;e3W(;+8p{;RT;}q>_T&+0Vo!IG zrGjD=w!k#zbOvew=Qp#gX`qTPfVQ+t&L++#2J0NvDz?`v0V1CkRj59F?YjEv`r8BsZ6UIuS79@Slr0`1f4^Jl3=kebfnupY1EPeCBTT)AVFP_ ztAR`9KDzfoJt?p(V893kC4!Y>py^kLRwqXcTTSz0*F-J3mYhtbt>Q5LEWd$m)cJ(^ zJ1m&9EOJqaKvCoP&C$HOq*l4hz(uGo);QxNg~#Qlxg|^Ao4f1VVb6y5PK7~u*bpnF zd$Bvcy(G821%f5o&P59zU)(C$?Vmwz@eVdRS!4N#?@_ZywO*je>LKQzYOX6)#P!YJ z!Bn1a${iTM0(5S1GMVzFXM~BS>MRQbWYhZ66c2W~$p){<`&JAOa`LN{$_F?u36GbJ z>mJPHt#+Hjdaolcam>S?;0ms!_wU7T5DZQc_9F7j31G7qWf!jsU8zurCqnIr%L!a# zgiE$rq-!F4t&OL+5sl8MG+H8^|7{bm!-tt!EV&Fpy@)(kxq6`k)EtCwHr1pjz=B(tmN$jg&Q?b52)m|V(@j3Yp z=9Gvit!vWTyY4jSGf7U2EZv%b?yt8GG}bO-kZyhB)?qOwRlX=4jOPwQFhwq-M$J-{ zg!6wh@GwNvM)8)xBKxB1(@)+2Mxx{RS6ux_ATu#BqBXmqjl+plqqcjgzF%x(6n%WoP_8P@p&JwkU4m2Tp%FIW4`I-jJk?UWky=##!=oUX0`~2TEfU z&#{=%<+P+Oqdrg@wuQDj9F7?7y$r>D*7?I#6&(_Z)=Q+qvViw+mhvM3!=#Q5sUup5V;McI@PEI*syhd`FRnj5chh~Mk|)WN2-uo_Wg_V?9(UtkS#KGA z_Wz;%txa-7v;ef%e8@I3Grh_qZt7Ao;FAR|fVJ>}<#mVuTbx*@l-%PE$$xFChuLZh zN(kUN@8wC)NugzzJR6L4>wkMN_n;*o7xjK|t8|L_qwFV7E}B?M-H6#$2R(de)ltPQ zyI)x`U(GX*y@^88vH?k@Ms#-Vf?D;|C#XWkSfYA=eAq#|d5TjYYhk&MAmHTo!S3VY z_5G7peQ?9U(-Ra8T=E1bd#2EjTi8i13NbNJlPw~KZEq2B4u-1ElYN_ zxp*0JzvYBub%F+h@?2^(wy2Q`rD=7p<^`$R(JxGu6o1leu|iQJ4h?TSzs%gUAe>ac z%@%z?yb0Lin`{q?K6e*l+BUhTQJl|qb;%Sh8JkZkZyUV19jdoQ$j#9DQ7; z4Gu6Sp8%&Nz_*x?NF1k+H>=W6HLEu&>QuaV$nY1UoeJXKrdMt`Xd$nxA?2Jt^xo7B zf|uyZDb`|4mKA(derTKbXezP$(1!*P17J10tuB$Pc$+!BqwObyiN;af@z$RbZN5hx z<=B-3u~h$?(bm`N-sO3jaly#p%`R_6eIzLLr5RkZRD(c&l*+Cc*@yDR& zZ|}{Ao?Kpk;aAYhq$~5#j)K{~Vu(=DOY*_s=``(`{=HHaeVTPV0(THN#vnq3yYF{$ zL2*0bt8X40zWzk$)AK{FkaZ`ir*r}x2D}vu<=u~oK@Sr{lxkW&)c&M5jLxRcA?i`d zj_U9;ByZU{#U1mi;YvFA0KW}n!1V~v`+kk#_Bxbh!@T5F%MFvw%gw#rgMrjQKkz$p81Sd|WUS0@9B&opH0Q)27QGjGJgrT9WYv zmif0et>QF=Sssbv1)bC#G?Z1Z0&>|Y`{;9%2o)RTxTB7gm8(f3yo_YDX5Y<_&g@Q5Fa+1wH$^qy1keaSF}H&<}pQd)&7>Z z)QbXq0I7QH%~c%s+v@5b7cHprW&T2tuR0SSio z`$js75a?}D115T$JVEhq=VHE0VDVyV1{lhQOQ=Rb}+~#d!iJ1@EEW>8p zfe;KSTwE(Dw~SWw<-4aZ`l2zBt+;z!?#VV+eL+(*?(g_@AHl9$r=rFd04hyqz4o3< zhuy18MJmxgqmxHRa5Ukci;7!{=KF+1TL|j7#R#kELcO}x8+@P!MsUjq&$h;D7|+nEit0urHwr>#$q4nwVY}2 zH7YpI7d~?_7yM<|cqmCyxjrfEHOX|LKj2z1E*_1-`>V}j(KpycJHkHG`S{CE#NEE? z^#Lm5-jK-4J070#P>epAwOUDy-}5;iRp6Vi3qcvh+g+j&xA!=pa&no`x7{9~h0h1`VP*r0GCPoy^6) z8quF#4i6yKJkKW)h~2&CvTyQ9sJbM=G{->mx?j~C7ta<MQUU z*Pbdtzx00Ue10Z_+a-qEhcr_?OlV@4Nd3UyZxx)h8Ch)fLUt|FgqP;0dOe)QuUZ4( zRF2$fF-x{%sPbS}QKs#yNu!3FM99~4C6J1T0&@i!Hhsu~ox?99^yAJAV7fBYl}d~* zS6qJ^YPIQOa-{HgQF?Iz18%AL#Kvh3L-(`t-KZ2)>LyK6PhCn7?G5GojfPxesOKX~ zleng&ogHE&>?@MJVEp5~p9#_ZL`&GD#bR|yG(11H3$Y?ylAYi6n|Emvs3)n%hKxtL z{az#@C*Fk0!Fh=%#m+(M?fj?%kY+{5F6KrhD0>){9Ns|i!P3E2zmoIHN02kyQ2y!D zW?|Yd;URfO+1n21c>rRy4YOkSMyKTD3dzA>tGkU#Y;yG+QB!G$C!){pDU1N)H(E@# zaMgPXc;cMQ3r)efv*}MVSL@SI(=N%)7hDdZu&L%-}!$e z#dR0^jqLEOdMF?gJfY`i^VMxrQ1&yAj5kGOO#yZwAinUDD*kDT2N^ z9Vv@x zCGnfV!zYu7T5Ij6tgFiq``4FaquH!>M_|h4ulDl@4G(3F;BW$35*zA2EO2Gq$2=Fa zSGx7`T`c+57oK0_aa85jEB-Kk8-0{z@UqO2L;6D=X2?;-%gw`kT@;CKO)?f#e<>Hm z-2z?Cz8rBPtM65&zcRvPzlLE-k^vn43O}sI8$HPS!xF|yS3WY*4Y}h?WWn$fx zwa8}gOIPb9g%LhI$ynh^RGJq>GeJYsu}89Rv{gKWZv~lpH;xYjW&IqTliXF^wnt zizLH!I{Vy7qT-Zx`k|TnBUFIdQ51b~j0#~xcToDbY8&qt0O342yV>1)@`YS0uZ9#< zh@2o%$~Bn;&AyE8C~r8qKO?4LrCLpRgoz|E4gXnK$d#zyiiZCV6P%!xc9>W3os)}> zSn7+T^{<2?cv)I|9ntXmmE`79_F~Wsi{B;Vx+mLYe0??d8Z(e`6m7Uld&A>eN6x_d zJ!b)^ZWeu}C%fg*w}X$x<<|A?ErpB6JI>ty&)$FiW9yGWne52`UZJ(^>u-ZLEku50 zSG3;kHzwf{^&h+X89q~~0@(MAC$t76ztmJdR}+xv-U;9S6qaO)Sz{Xc!LCaYYFia8 z-==>zG}a%ho|&>sxKhkPwME}dzy&0%Kry!^(*l1p86#QzGh zaKyJ^+W^5myK}kqCVz6?)hx<0m3@NTPa#F1{Q6i6CQS6Xc~ZIMIdcX0n_ zU$Z$HIaqlkwC^jEc`t`sf?tPEg6+=x??YBQXC%Ef9tp!C+&X_7i@YCpN>;ZaKw<^* z{=uJS0P4HAYn0G2t@4-M(y2~34doi4mkV~MrpHNt<2J58hmW>z9+LKS2JHwYlyWFn zZQ2c{gC%Y}A~q8O!%--9Jg$Mcxr7Ch9)teg9&j_3&1wdRQXvP!#LJ7~&$RGc0;MKH zexX|7D~mKZEdO?OO36YpmQcjUIE48;*{)FO{)^g?07u00UAKu+IQ zSK%;-u~MZ#{<0(&O65w*V)6NQn)@JEQp@XzJg4)$2n1|A>~^6-mx@9O-OJV_e3{8Q zJoo!@{f_qXWA@deFgaY9mRH*w`a^WYggbHg+OsNo6beL0f&g!?SAzwdC&0>5f1(k< z7dL(Ke9DR`!2JGT_^TVL%y1rm>?m+63ttc*(|HLC3o8V?(4VdlXLXUk+fS`Y_!-oB znZ<`f2Pd);l;(HXXmrZV3;sMizs-~?g3jBg&d5>@MGuR!yktgf>XwSS6|Zq{fIo`o zZs7CPxqM(D?ESA#mGy4!ZtT0Z5|0g@Z(YWGh(yybn7tIu`{-ZNm5Cs$wdI2*>7Z0{ zzT1J+aJsE1Eh9e6u3#LoheS5G!qXQkJGLxeRGZi%jh(h`!8>f}%3_@o0rP4vw{(nz z{b$yP*XhXXX9MD_C!XyW_4{OI=1@LNg1NWGh4nRKELpMpryI;NeIW5;Qnlv{$WF()5!Y@bO(y*;{)_W68XqXFGO77<#@VaiN*^5*_>$QsEV zbXvKc(wa5aYJPkB@Q=)hnW6z+W|w^d`9wAcE!M^|?fJa8>yQzy!vQ>g2ii_*!-_ig zyoJJI6P@FzKS{&aWL(hlr}0=~ zy|Eh$(D-bTBZg^Ux=xSG5Q<%V?(R+asnt$?NnQL}LoL3xP>Ha z1HTV{!!B1X?W?iNls_@+1qKBu(IZa%c@jf%VkGqMPmA07i$=<_Gb`#KN8*`!Mq6FR z=l?fO%c-!Jy*tTr^x^NrtrFS>IegZz{&b@6(={~NYw#Uz5Tm`j`d9`zD!Gn5 zDVk?O6UV44K?f4T9MMC91|9dmkf- zF()rE!458l%h0U*0bFB!(DaTOh?(}Kh0$_8!wV)CSQQOh!JCBxUU zY1?~9)cJ7Vrayupb!C7DIz%maA0*6=!9#hy-8Xx5ZGTSs> zwn=jNs_88W`s2yhP4Tpu5-5VOT$~wWNc8CY9Jzd}KSnCfKR5zwtgYidl!iG1_}=V=6e08<14tD3N3H)qfyK z&Hd8U9b{O!`nWOXk9{xu*3=i_w;j6D(`_LB67PQcwmxW~0V(cdKg~F38;&kjTz@}! zTG(oSDC9<}zLBV%0H#e=MIcGN(6W)Yp1UsFlqwarY-Jp!OU?}4+&ZlY{hYzLXW1rq zT1WKEN4$Q8ot=7&#fH^Z8$vr4SI)I{6rgHK1WI!zeH>>|akQ(byZm^ya6I)AGA0un zV25=1qVP=WN*1F%nc^$#5{6Z<7q040G?kt;?dj@sd^j>+#6pjB+*DsT##D*(IO!I0 zBIq`J&`45p!LvcU^Wr5wkJNHngKLWb{OvBw5uMfM9!_Hx7kU&CeRksEV`sCGgd=~j zMkt0CJzlZI@Nt@X8-aj~lGI<-ibJ?FWw%nxKvLUu@3-49YXrbaKTK*CxtG|p#zb16 zBAw&fNCU6oY*}QOmEe5a>>QEswsoVIynS5L;%v18u6H_Ymrw9ybF&0cU6zJEr`ZAin(a*C=ETP3n{ zT#Xq&7p@C_-KVR00t}uz+CzVRH^v2quw#8BXylM>ql!h{#ucpLG}I@o+xmhuOA^!= z_yBZhY5gRH5&~B8Y&ZM8u7D~M5UJfJib<`bFwpFo0e$RR5d-<d~)#xG(>gk<`MpM3#nT@S?`2s(GpZbu%}`~OzBKy0>-Cw0ey( zG4kMuZKM??tT`?8apH2b7saIK+%*-YYC(LRwoywK3Y3JQPgfjyA$}E#UR7nsXKw7D ztWX#&qZP|#3!W+Z(9zmH6g_`j`!axJo$;bnBy-z4mfmJCpVwT2(HmC7Cw>y_4LHRt zuYwmMU4+IXD6_QNYnj^LEzHIT+VXlK2)}E(^e&K#TI2G0fuhrDskCYTp+TVp1WCPV zTQ3B^L%ifBSC#Q&X=-f0L;S-MMz7M3wKozEU8sWeS@BNe$(Y_l0)`YC70E9FLa*Bo znbgt*l^lI4LKnh(b$MJr^DlGC2&@%N*yZhn39@}MscQ6Y6wbHGa4gzI-KwNkNL z(Bf0Ch~%FnH?Z5xkv*3x6$u1@863WopavHy(+`tEqd|rG;`&J_7DDXG0tFB5H&f7m zq*lnZ={6DY!ixj&cpHb?UiIO7EZqgm2C5fnE1k&z45iZB)hT4^pFjvAK(Re~SU>J` z_z->w)>(D`2az=Us7g4Iy(p23cPIwU;nRa)?=hHDqDxRjTrY%{I^SB)FE2jcBHqEx zSRx67R)UJ1mFME@wJaB*i@o#7# z-+%r0$Bigo(&`Owgzf+LPycn~A1p{;>ORndRsM6z|7xL&05U|oUoZwf{$CpZdn7F+ z-WG@&)#d;A(|@!Ozy;}F&=XY*`v0|iXi%CcF~W0LwT7DitK0u+0p11DKcqXwuN41% zMgRHfUk%oOg^WO2)4}@x~c zWz-m9)@3=r^nXV6A1y5Wgao+$7uk~Jzaq@vNV0x*7Co$5v5EGQ^=A}mwp4{RdHRUW z=C|n}qv2386u8=0z<%5?1cNG808dJ{U_AAGbihZEwd;c^fcZ>OV(KvGKVs1Z<@bgN zc-lE~@%;Quw;s8H@dZ@wlld`N5#aJg1>W=JmHF z$=+Txo)RP!aCcaDWGff*?)3Ddpd}FRxfPzf`2=p>Ro2$Y;nD1K*VF6!>*HzNm<5}) z_E5J5(>a`%r)x%b*fp24m6Jx4-Poz1_vpd#>`!9H#RfbQ$dOFl}5 z7m3tY!}|zY$Czc12ESdg!JvIKX~!H5W5@`}Tll@N$A0nVZ(||XD(HXE96W85F_r6` zt(#T!(&E6@e7jFOb{ZeL^*!HSB;3S(piOXsaP~Yp+ysNavpUby%sFe zez+v&5S7T|cr#M!`c(d~Bl1fLeW_LzcV8r7=>BBJ4P>f*=2EM%e($=YS{3nS%HVXw zOgxo2RDqQ5A7cq#4CWY6ea7qkAx?;uJW$!8AF*Eu-fjLC4V=rimV5tOiujCw7T{hx zaIUGrudM%OJOkTrdFW|r==_{Wo+#t>nuRL`z+(ixl-t_f-?w5WiHsg9GyFI%g7*k@ zCGZXmW_#{=9%7aKOtBZEnnqyvtupI_-f()$Ip@7(>x4pIgoH4w5ti!AelqUqpgv_U zc^2F}PZ!)8e@_$qELYH_;TzHi-z$eNkbv#r4-9Op;qHP*P=GGA<1@K-Xb%1 zvlJ0F&WS2N-j8;nMRs8ivB~)<+{A`r%54SZ;->eNiV=Y*>kuDl2Q9Q-gxV_~uCStP z+^D(PQ=^9>jzvf+T)JHBeTu)=k^eR5s<@Ec?rUY-MG<-t{)|@55=pQeIXa2u$)pxfJYxE1=tNnQ*X%7uI zMpsLDvo=?-!CzTv6DNL+tkO^75>8j%A}N)+WXk9$SgPq zur}odFy)vAzzD+thOauDUTHVU9fLd+u1fot=~^RI4Y-^S=n5t)WTdW-=Xxus+Pt2y zM5GelS56rZrhiPEudFvqU-V%Pz;2>;7&-22;|dsvmw7+X_mAsi$AHWVC%#PT!A!2V zw@kPgPW@{q(_n_5PTJIw9bqfjYXA#-Y%QFm>1NsL1ogkch#E-!@a?B^033+m`%bc2 zq*K(F4MdNxH15g78M1N14Idj&%nexM2hN(pwL8lCK zcUvySP{V#A406I_4K)tm9T%7c1PUJJRKA%UIbR=g@q5}VHGgn-IxDG+!}~{XpIu?f z$gBHpI{HCJoFF7;+RVDEV()qbyu1k;Af6eI{x4%*MJN!I#i_qYL{98LNU#NSo-7W* z0a`!5Gn!P@Tr1(D!Mq3&cP{4iytm(Z_M00SGdYhEdH7kt>uhW%i|G0L0+x#2BiZ(# zyWw{XffbmsY8aN)!2{K%({m2Ijpys{EBIdF$6;g#K-}cidtt%%40VcJ3sQy;&t;sq z3iwhvjk2a%Ju5Ja(T<;u&)kA+Ao*EoyEcMh@~P5$9k1g`-Oy7tx+;`3PRA31Tb+wu zhqdv6IBKjRqww$uiCR^AS2B;8U9nAku1U9BQso(?(@9Xmm|Yl5qKFFCu}@UPtKUEh zfP83*_wyu6Kg@OUIJTeq#&tze+}h~2>&%DwEYBXg$_93iapcg0`(eXK|C}${RXfLN z-%vdk8xM$DFD?XjrN4jxZuXXsCP4NVxR$R4QfZ=;W!44Nt{0oxqIJ~9TSp6lmlL2| zz1j7&25S=MGPU&?BAUi+i31^;FD=@HyzbJ+!z(KUfrz_etK3ahXMcRKdNZBRz`=0H zMCPBhtA!czB&>KX*JqFBlX+bHzT!;ghzM;8hptO7gddoWNyL%P;WO0+!p-rb0W-PB z62UGv-3iv~AEV@1>OFVR0jyM4=3puNvo^OmxM&-nKYPBF;(`}D#gu(4%B-s8yXU#d zQvw*8Ly2v|(6zrXRV^Y`K;x&gFN95P?yIw$$(wkA7#aQdv1 zc~Xit81FGdkal8TkWMG6#s_b~ev|~Q)VTccz@N%!#MCbZv%60Fm^wU@D{C`5tr_{> zJzXb;8EK!k-!R1nKcvuF{9q#$MN{8pe&m6Mh&^717nd09TX=AhOc~JG%Z`g&hSt3^U!DA^T z9^#`$ZU0!UsQ~m?Kt}qEmM8Cl!5^r1qM~Wr7;$S0k11@;?6oK_aFr&KpbrcTlvcJW zK^#$b39nC>05zw=)jvpppNYpWvC!+xTw&@$hSSb`aA$i^;*!Eguh-m?s-tq6p~wF7 zSrdA&y;mUD_$o5u*oIaEcMOsoBgW<@>Si_d>&Fkp*pcm;nUG;g#TSZF z`gyAKcO>3&QOwuSLc{S_-wXAiuS;TK9^l+lm`h`r2w86jiXN){_ExPs2|OS5i&(X@ zRK`oEr2Kz>r>)RxtN)srKphX)LQlwLr!bO|;B$ApfKYMwR@7pwuD82Jizf}g`4v2@G{>OUEM!fM}jR5A}9F1~yfCylz*~S$-ba zrC8wJqJxgCK(|&ca@U_Zj)$F$=*dlvxuNrbS=-N7!gohyu@r(TRq8s^x$M1;!j3G| zyXC69jarje(>?RrAtrCs0XR-a{?*YRaC1UUg)8pvEYDztIxA+2AjI3~KMG#GZ=2DOK3!-Se=2E- znNT3T)=b1+dTS02htuigar^X1D|7r8k`IT^20+a#*=qZDXOZfiOBF#X-$Qu(yZ(_x zN)-&m-LYD;BDxh1gZ_#Y+fdZ^*yEY-Rc9#C z@;h~aQ9#Xcy=lJ(=zSM*O{KydNA(dX-s3nz6okxbvybFm3`)8PC4}eu;N7jMA>k!v z^NeYbQ)45pf-$PcNmzNgbLav^zaJN=xRzJAPythw11NC7fSKwpCn_&FXF9Fg0LK&e znurVE&OXtL&)n9UK8b-~)Fz4B1bnvW>rvEo9!4gv@G~b$5Hu|{sK#VVBVA0D16Sg} z_iAGiqkfj6rBjeWO?X8WnNf2l(pq3}^%WJrGPG%3RIQ5OSHi5lK}E>DCV8NyhY6$W zS5_@fM-wbyq5k?WJ`cJ!k@20?O?;o6*7C~z z^bZgpw@NhK^cY1xA}8Iz0jwO0uinQ+3v!0sh~-#3`Ln;pYEyF;0z|1Ma}~Zl?Aq%D zmUEw$n05hQxkc?=OtkVbpAnhQcv)h9EEkC7tbz_)FaX2vRf(aK$fS&=)0q?ClcJ-LMWW|L~h5@b!B){934{8GS~LTw+RGFC$e}yWRZ*sJ)QC4p|DwN#kJpJjU4WZ%+tOM49;wa z1jgx`h48#gaB2w|$2~1=;O5J%4%9QjL6-`P(XA zrD(NLLBhzR*L0fpg)%2^+Z_~M!QpMc(V<)6sL|sl9j;qqEkTy@L6phrs~Vrkoxa3M zgJg@+y-PbAH&ZWKlU^l?yix3^O7yPsFZ*+ZJ-%9ZuQPkwMO>TNTbl&#iC?;~FRwFr z<^atSZ^m@+%g=cKj&A>N9)fPB?|Ju6*CGs}ADY%vI=|I{XFg;9ItIe7_$chy1|s%e z@HIYumN2_n*n6Omw}~3CUaLY}alb`X)c9sXE{Q>3l9{Q!G;2QFTX)13(9rGN%xhIO zxkau&xHc@3G~NG-c(JI`LUM(eDfHyr+1<^6i%>tJS)cIVK)|2M5Z_s06|eIsCE8nJ z`<5Uru_v?(h^8BlJJfYKHC?kYzvQmzZ~@4i>86M=dq0YV2qEl7Nntpl*DMjEf}5T) zv!?}DsJkPuiYMEp&)@%=`&Ewu4qYP5eH(hxPrek!op&03m-H(kR^W(mKQv(u!8wf1 znH$KVVAj ztE7x!Q_Xx&`anAK!p-^kiQI%uU;|DA4(jrYe|3nJluzpcyYZ=aSn*P3i1Drt4yAA+ z-i{nL9-iqA3+iZG({KS(rM$}!(j=eE=6)jsRl|bHD@LL6dTuT5NOBo*dgX~r%d=88oJE?tgUrJ=BxD|xLwMy73zfE^r1D zEjeEwGx5J^hYuVA{aGzXxh$67F19Gt>g_SH=w3CIl*<)9#!*DDSntN1-S!MrBVL5? z$#zC-&ARp0Jq(NtXz{ybw35n2gIC%HobKXWtELSEtX*Sc;uZ-}!5O04$A~MX3$8}B zwsk#}I&5DyV_X7Ruu^frV4gPHt7}cyJV#VRMi(=eZJO+>Fug8rKa7NjhAu%RTCtQj z?P`znsqFb4$FxtQAkY%0!&(l&(|isY&f6Zwq{(n!-9Ws2nr%3&%B$JG zY1wMq%|5R)@<5M+)Z)FX@gNpJ`k$$H&-#TPmEPMLp0F}_Y%qmLvE={2uMAM&T>z!{ zL8;QX=oHquvarr)8u;Bhs@fbQ@&ehEQd;4;nyoJk z_2|V(t7#zB7%?OK*OA3N=nB3|Y!Qek0IMobvW>;faBGsffB2z;N?V$DiKf+Gf^9YKI=qlmCY0R z1j5u(Us+}r1G7^HG6|A|dQeN@hL)eWtb`JOq2bUsC1maeS(Nh5=B^P<}dgQNiPW zhkdd)mKrogCZ#r;)CM2nGq2(lANdco>03A?8KUmY;2eefC28P=NmZ8sRUJ&mbBOhg zv_$H28zgzpdDq$_%)AuKE{_@JHX{2|;yBiF5Ta~xR;3fD7;6y653w@M*v8RfO3BX_ z&ZrYkR88Jup6``U7$wB!dNgAFqDkQKOh22H>l{`bnxtU-`~?lP!?8_h3+0jt+w$`Y zr>%snx6z#{A{c#bR@hmbK<-oVf!UPxg%ACNd*-RoKjN*wz^XwjG#`G3) zSQSe>=d`sRdZ>F<;0Mr->x5TJedq-yV5!OrFAVdz z&6mCIVB~=mx!~Rzh>=N?zMFiT%Ntbf*^G>3>F}%<#K$u5Z@wqzH+l83!ST1~#|80aP4uKQm_}HZpH)I4fw=a>^S#SH3{Z zkjViUt~d%$qC>ZeB3up+_~=wRP9FC=``6m9>;;r~^tq#D3ENN2b$x=?UX+O$CzWnB z0Vrv8UPfI1fL8IteYJ&ecWa^tmbY4yB?#>;csLmEX+6cKxtxNvuAF%~)fGxS1p(q^ zdLvx|hd4tAql&rjQI+ew3K|y~b1T;&NtZ)?d-|v_{S<8pVlWcRWgpvjpbBnDsHKF$ zZyCX%J`+nb&KikN5K#>#B|1(soLw!!Sx#=YHeO=7VdC-_RG4g+vz-`XwDG0wE&E^Z5N`$#X+3f`$*C%cR&2 z21mc|>2~858JD`jZh_PcHl-ggH&DUfzm@+eBWzHYq!-eFZTl1onPg`}IrBg z-&JUKfP|;o!{Uk3AN^%yu;weC@tW*mE8D|huT8dgY4^GGe%~LO0*3RP##dj|+N^m_ zSFZXT6q1oXeF_Kn|rVWxC=czxTdeywcv7uUxi&PHgk{R|>5)P=7 zCbrRHyZO#gPHsGmF|Tj^Eq&LfoU7)-_Z9{GQyJaQAS%+zGLFer)~>bBP)R~Lp4W!k zF}aKY_eVu#HFA{LPNPyi(spDF&j6l4al>AX+mSQ7{dHrA%?`V&rX?iBl+5hZyx(=rs^L>@WA|06+61=XY4 zL`0>02p3I9Ypq5TyVhb_fjNW0f)0|JAgSkYRskwUl`~Y%)tmSg?v^iwFYqxyA^LQM z4U~M`Sg-5ojMVWCFs$*=>KbL@%>mzM1a6d}n($@!s)NRYlzqSnbGQZ~TQW>%>jQlh zIZb5qIybFCLWUG4^yaLpR^krz!2?)N8Cq2>$?Xx-fZXSwzr{j@Hbs8Wg>6}J&M2{m z?-k9e^0>$%&sJF=%QKtoD*5BsI&nePxog0};myCd2*<4T;TrR?U@ID{%Bbb7A}g ze}QI*#=>fttgFnJxU#-Tn=d?O$Sw&X6y!G`YN?UGgy7Rh-fsdn^L zfpt-kRqu65oId^S3*u}GX8_5F0@)7sv+w>G>Au87hEw!x*3Y$RHzY!w{TV5&nN7}^ z9Ch;0Q#EAis&16%s-ghZ(}NieVliCwMBn<42=kS%wem8{jLZRCX*!>3sdj!$MI?j* z(S8`E$#rScN|ItMtt5FE^mQ}`Km6rl3kbM?-V#(-+?3nML*=wd*z8%w(7+G1k4qbs zT>8r|d7kA7VKHGKOwhLgpENT2!+@sh54u**NO7(*{=LqH{-= zm@^ei{Eh^yuD)OlB@Kf#;IQT|O3$@6p#uf7Z!Wvc4x`M&5YYN_lzM|0rKAJDI^{nW ziz|O`Fh_m_u-E%i^UnNX)4<>^f>@S6)Jj^M!Elw-y~j|}ii__4*I|G~&HzLsdOCcy z-+E2Adpg&YepzB^f%%|-4kp=l*7!Pb5PUcPXCl)m58YA=JbVBsWlgvNpLzZ9kfXHK&5jW);RJ$8*RNp&{wf-v( zF7jX<0d*dF7LXPHgX)_#QJHW_ZJO{zj$mU2KP%7JI;Q5-s0pY+YW+AiXpr~gq*#w4n_Xoq%qE2E;VQbJL*Tj|`%_Vd z=Dn-sgjq9#2E(03_IyP@09o(6z6hehMk`n{K|9N2T${g5R7PZtJo3=s+}B$r`U+$( zfK4Y4d$#sOEcEEOQ18|@>t!VL&$&AqGIu8yf?BV>fbbG#O)5d=R;|g237o@|hb!J1 zy<740cP6{DrK8lrN?9|O^Pp7Pv~mbdcVy`fpFjdW#0s}}!C9$y0m8&wR%we(O1W&z zB(X1~+^}y;got>XY}`0cy&RV<)7*^&XO}N}Sl`^FB?rH>WWDde36VSOE;GkhtowJ5bRo;in+2dpT^Qyv7(U2 z>2zd^?kcrvw2YBJJMmxWb=yRn81qqRQ?n@(+_id@Ckf~E34;yPI1-gD?+&9>Xj4N^ zVqRN49}s#ald$cIA?%diM@Y4Haofq*opT8Pjv*c*aR&Z29s{W!HwZpdCo}BG`4?Zl z_i2)xy?Lq&8n_&~rn4s*ebeO4lLjs8aXaYBK1(6=KzsxbhpZHGEOTR?sy5GSqnaCU zFx2&@C4b1i|5<1ENPw?ViRe?b$crgCe>ZdX+TB7QB0XfEj;uVaMtL|s=jgTe`c*5j z|Af-g9?8A~0(@_c(5(!YR@B%7lM2p0 zZoab-C3UK=GZA+1YcW%BBy^CzUqg230fyorn;f^T%A{esIbI`J+meaGK|n+Dt*bt1 z*_WR0*;nafuD`(#Fj>lnfYpiis8!Eks`xA=R5VUrYOc%tD6+>3A}PoYL*@z<+_L{7 zP)j6dSH?q?IU5TWG?a@iQrhU$(Pww|AiNN>$H-A$)2ub;FnoD00NbQs(Q(+Qf~ABo zXs)>Ur4HeDHNx173Tkng&~|J&UGbguCxtWRq;Sbc18K-oFJTBxtOrFm`>MNY?60nA zxBMWm6W`tLS8}Xuh%Ri|VJsA;eUHdjKhH#%LU%>pm5A-3VlB2Zv{B$hlS1#zUbS*h zre!2(=cR#sezSL5f8>@+o9{(Dg@bIT-1G4kac=tJb75;+7(_J<@&0@#JKd@BZ(Y)X z`Q;bL!%knaULn=&!vDO zHK}Cs_e$JhGavRB+uP}lt<3rbR@R(E4)90VW1d<8daUmMNt;)82K)6>$U z`WM>0UxH%eQ}+*QOn#OfgR2tkcY~x=GWpK??+Z*sWEHT~s8zVA7!vRTjNSevqNhEL6|E6V(F<1@l_3-hdFptO?n zT~lq%kJtMm{#8O^>uPgD4CWp#jDem0s1RAV*E#w_Cm|u>HJU7NH3`o?44+WZN+($7 zK($7SMLZ~-Y~^N_CN)1qy!dKh5shTnzs(KHSN=xsXbgE}3D_VJSQfZKsVq;r+`b>a zrJ4Ctm*#hhCTNEf%Xkyhn{{hOIcH*s&$A7iUeQl$t>dfBsg_!uXJ`VCM3!H`Xvus< zFr=`}SL2an_F5loErT?Kp)bg;lSgRYmGj~l4pAmiR|)?c#`&E#z?(hWLsLuLZ(X9% zSJCV(g%~o!sWl!@#~%|8^x2E&n4~=U+|pVdS(b!P5sGicmFt1BT^&~I-jtxi0G`Q{ z#z=mc4l&TCGLE~eOeO;iTScLu(lH!Yn~n`NtCH_jCriy?L6j)B8V8ZZ!nLDc`ahlJ z&2Zt1m9Vmal#|kycttA)J5U)6m&8jtoeGyxmZT3=6raoWZ3gl=#j+3q9kivqSwvay z2UmV-f1MSs=W6@4o&=+j7*FUL9m7>$SV9lPY(NfE-r;T4e+pEweFzl5;5>K=G8AC3 zC-xCDuM8`e@H7o6W8*2q#`BhNMW8e&<)dJg4P6~>6_FQj3Yi76;Xe%`SM1W%3McmS zxbFW}OYyoAr4Y`mtE5f$&< zxn*Czlic#P`v59dki7!o6eP#yFPST?T%;q#gc`kSXh4_>uE5_f?BAuXrQzK zw|;!QIW?Q;TTaSox%=hNpp(;Vz$Mu`o1fcMP_6YpTQev;RLI!7^gjLGN>)j2&HbuT z7KMBE^ccVVh^bt$Bx7B^lC*+eQ6Z_R8g_##2=rc|CKt$6Z}|OKWSx+71Od(4!iuhy zeRd%bGg5eCE^U6(kFLD>m=Kx<<$gKyrrwhNnuGy+T^&?>eqhQSC2Ta2A(&mKQ6@zg z;8K2(-n6O%7zQYEP*I#|0?LkuPFNVQmm`*m-2z)S7l8V7fsBotf7WT-muG|%r_Yx2 z;a(q}GB@bTfB$CSpv|DA!>W^c?@Y^9Z^o6Sk5LSNHPos||^B33? zXh)*z-RR6gjkvTiknyTe$kZ(i zO!;qWr)Tv_U3ZM4cyWxE5#dB+-|_K!x4ZQx$>0?9a__>iQ)-0=X)_O*N(xjVI5jAYB zP3-_x0~y&X5o*XT&;JCm0IxGY=1g>DK}6C&j$u~9NgbLpX&sZ4|FOPM;F9&u>)*4(Xk;Z7GfgH!#5`-D(`HaI~<+M#Gg*2F6ke`LE-lFB}LN z1{5Y5RgvT>RjqGth|agZ#^5*27-?jsLAi%0|on2OBn5>8!5yZRZ{0>i5r!{9$G$ zvDot~9~lmsUuKVaUhq1t$DU)qG6oWQW^bJ+-iElQBv$6Y;oh=E6tnTZLacIs3GJP3 zx~m*6ta$JL@`lZXmDG-0JKBJlP<7F&QI#sTkc)mI2q==T+e%Mx?iP#eZAMD_!%z`c z<-y$o3+$lHU!K}4szUEUB(gS;DQnEHGR*h~u_6ebJzxO$GgZgSF+9YZhwsU5@IeZ~ z5=DiBsCmS z8COy$Lw{JVrOSb6{LiD>tOKJ#4U<&vnTxU|;o$91Dz~L4SNr6b_#UAGk zWm(mC%c*ph_NhC(h%)?HllWEv%1vkjZ;>7=+v#t4 z>LjS+$pZENwU2;YlzRfNAh3E3CG@%_2h^AbEKZ`3JoqVGtQAvgC`c+}Q1aR8h!Eg|rXvW>$Cvo`1f~S%kF5eUY2HH=zV@px*JXB!}U5+kD(U8+* zw@{)G0oIcxRj;NnvZPDkYoxg0~Dk+y2R|zzVzVqz& z@;PeqUh1xvtvAR$Hxxv@XRF;TxM=-Og7`_48w?3q-dTqpU)Rp=+p#sCFi(Bf_% zr`a4JEO>v|Ymt0}oxegWNNhKNFXMfAq}60t6)e6qh-@&NkvdUs7RVtld<$$}LeY~u zPVqSgv29j~%_IoGmdY*cyPwST?e68W-iz?)YI;VhSGTyFWos8!H12unuF=?U5A3hh z;Aybfl+Zt+;z>8|p7;dG;}LFvm&RdR%3^?o^*3XN-?0dFSK&NAjK`fRKX*;Xiu^PX z&&~HzQ@lIBp~yS*RAD~(PRvliCSfGQR%0dT@W#Yt%C5wXmyYKrS4mPL#z~6n#ei@8 z)#ZT%@ z?DhxbA*^zQW4fU};d+}hLX{h2D-v(fV&+%sTlcnE{1U4s;pADGI^&gSnux{qwE(q0`IQ5e;|w(OxxJ*W@at)^8?1{u5J8lb7r?^=RtOQWX$Vx+^A7GM*BLNuSbuwyffl)vU=L!!U!(DAc6$-g72p249Wx zi(&4$*t*HrYI?6#5{Xc2=(3+2)0-1hudGmeP7eqgbtmu0>mh8~?$?zi5QIrxz;J9< z=FKmKLxC$gfp_U?rccc3wsk*+$Tg26A4C4b(Id#&H0#X-a1`>CB_t$vvj4OlQY^qbpj6-kR8Ov33r$3?T*z!%cf<5gD z`gMV~;|s>V=4|sUy{6r{sRwT5nh!{LPG$YrRM%*e<(T`-f9P6avuE@U`i>967i|cW z5X85_0+~oCR@!6 zKJ8mP;nb%y=tRnZcRoQx`ZTp4?*mor*-SKp?tfTe0`R6e7z>!|r12MC8YSfKh*;Si zxa?=b%1BOqc6V_IcRCO{9~|#^Pgzbv*fFKL+hov%W!A9>ZABNnUa9xg5!WZU5zQj8 z<%jWQ3?JAlL9pFG_f`7TPL>g5O*HVgV0OXd^_^i=O8I&KMDSBad)s64J#(r=YkY_p zoxmen98KK=R8y||uH2o%(n~Vr+o(kxtOxyr{>p_aC1i`~e1q&3$jHogHh}_$(EWYq z^MU#-x9h6}&gDu-nN_G;uZwi=xT?&*T^h=o;ki~jH4>jQp{Qf!+7C{P>M2#3I$NfI zXN_B3cgih$%^Tm=p|tdS{$#(jpisyz^u90Uk-C|EMAK`z=2dq>rRsJlw zkHKNXR~|+4busy&+ml9z4w06j>5{$D1Qpc(bl4kZEoQxqxGQ**%05Zf{Rg|g9{*RCMcfml|{R>T?fb>(IsWRH!hQL)CC zb&gmHXQ4z#3HcgF>&8B2rybr6CpfXO6*Qsk;Z%g)E939T6!kWIo_?cGjsT6~SaSZ8 zYPTCJXM(l}sRqJMT5B5SN_m({ub1CvJ<7*?c9F}N%}rNUX$grf}ICOG8S_?P9_{uXdav{H@s033|h?(-;3~>=6dZ- z_{E=$8rH4ew0pq7Rd`ZCjb=UL_#94p*vZ;*3|qnm z3oZovrklY&^+C~>x6{r6I0>5M0g}vCqwCDO>YqJ2`Ek*~gGh?{qoJzowl@TxRF))O zn>d2Hol_mkx2tc^bZ4DO{Yj`C#-2SiQy6~qr<>g%vQ4IHDJ|ivk)Y&2yg2jU4{Iz$ zLhDzW@QuzWx`gf#v_EqDIW%|KjwzwZ zqZb4z!vyObh8VcI`bBL~1A1*mYV*`lcq}-CoshX)dj8Dwa*7z$h+%16L}HA-L}m1t zoCUi!ynSnbn7k1wtvuNCmjw$6>g7Q2izHj zJ~iw#^q()Fca<<5dh&f*q=mfh*S37dT2WWH5~QS`H<6sR-NU;Mv?hOxL)%UTC-e}@ zF1tnJx-EbA>tjgb=t=Zh@)GxYto%A}m5KefWHnZB>?(M5FFUWQRGW{z*JpghQ2LZq zu7+8*KfYP%j0#qCd7g;zTs`AK{vHji=LwylGt2ti8>*(k=mAN?o!#m>==NB`YS+NF zmQe)uhL4NY!XnvHkTKO^DPaGGDfogiTs*1VKRm5 zZ>KisV%uVlGgF@`z~S@oc!K9Hqvf9hyi1)K#hZ(Wx@#AK@Fd(|WtV)-hVLMzOs7QO zZutND$p>UQec(_{y1IR^xRWnklI8|fk=NztCBeX9-3gW0bKdD#D1~or+aN;(*hRX< z?_LR)G0{u;)?px(n)`afk+FY<#|MS zZP_gSRQR^-lM4$9bHCao#BvKRf73bt91&_M>8@t9JkzITGI5r9Pvl_&MbvxIdl3xl zLK_I(s~x5^nOHx8l>{BQd5X52&rfA7B2|SoF9-qzDlGeR5jO_#$1K0KHH}o8NSxBa zq`ukQ$E*;nysWMqx2CY2-IT{p;#;MAEWWK|ti*np=fD7(X-Kjivp+oT=ET6w4Sv^d zQbUrR{m~@V`OS7%skvhyiDsOD=MyQ-Y)I@Z?!kYkyS-(cm0LSnCzsi1c6?E-@>3_Ve-dh8N0A6UA@_APmNQ8* z4=~?sDZY-mERID-bw3B%bByj!0Q$+`8CWZy!XVp<`-iIYFQ?53t)y!x7G7zQ_oXHX z(}bOZbD2lqo>~=#S(4bYu!j>voRMhsq7?QRUrRW4Ni((s<9`3d8DzR!Sw*PMRV%vA zaOpIP8{hL;XOuzXb~Da$Z;4ml{sv?vdmTnE5n-fY?sfG(Jn@j#xHTDvLZZmZmZ1q* zgaerb)o2;;9nhe6*4if;E)XCD_r)bREQ>7`Jh-#Cy9N)oIDDJC``x{HQ{Vsh z$5lPGwY9U)^mI>8%S=!Am7Noj=UHguksGnSnSE09s7L7>Q2 zP0n-q{OsAGsvWw?(Rhm~{N7}Cqt!L}((h_r?1(#PSA;BqGpzEG7DZ?WZgAN{BYTODwJGCh?1IfbpG#6J>P6K%mF1I4U|ZLc+@+`@eoxgOwjq-F z$e8yXI5ZJ|Y}~`Jz8X_d$?{gANpH8a9O93z@R(xI}FnfPqz zMTTb#KA>vl-qBu0{0?ZCLexK%IV66&y|v$DbRZXh*=Z}Ak5v9G(@b2Wu{lO_rMUxL z%{M-pbthd%M=6YKtf2U9~38nefk=iaptKH`j7Pnk@>U48Oa$n!CX?Yy#VtaLpH zC9P=v*A;m1>SeAivSb}on3#F%>AgmtmuSaDF+^pnKQ)u>YFVqKN=?cq>${83q{`Qu zOXumg;F%M8+87XXO45|#j^(8y8J8#R%XDLWuCHzoB?A)QkIuZhF`!;0n=j2O~zBWRmXg6TTJosDCq$h_XQNY69Ix8uhEgUMU-h!(y5MXKqYshEBQ1s2p$TVt-t%&)WvA>ThQ29xLxKE@NA@H!SxiuW=A#fy zPv|KYOk_`vAN!5+skcNcUNgRF$^C}KdGyWTyXct^(EcdL*UvQ^sxXHo9vR~8%qI4{ z3P4OLjQ!{(>X8~#t*C0u&8>lLmRPGq(0W-L3aM6hK8Es*DC>$WnVbzq?oGJ2dit4A zW&a!jj17Q_7e`ROl9T{GFy^m8`>a&JW;Zoj%SO<>6??jpHX?Ugm^d1A0-~Z!mxL{{j>qy0gHt)Wovd&u+Io zHAT$hxbS$@U!!}T_-8uuvuYID@@K6PmfBi#J1J2s#7w%!|IEcnDA1%1yNNmtMbChZ zQ;S$!^m$%;^VDth>HJhCcrP%3ymE@=+oSuFpggSK4UNq7g?mU(8Y6(R0+R%ABXung z$Vi}ktf*v|t)6SjTz!CZ{%f(2 zmYezhgou%3Su+sU_t+q_4E2Syv417j0M8oZ=8r3x?v3Ld41PN;(V+my!nSO!H#Kv$ z;JZx}$6Re52ent=cn1SFRq}H}afL^2%U=ksCge+E_WRwGbUcNC=D<_LRj`5! zQMMAcuJu5tR%*IRGf`U;f&l$e^Idds1Uy&sg@T5<)F<%6sKOJH905I>2#P*Mf%qS; zWKJ&HF`!NOnlL6~YXFrb+nTs~DvhHCh$><#<5TL?={NDjVa#Zj_p^W>Q{u?YIn5Zv z%#|E^Z;Pa*CGfR_CcJQ!i`jpmHW33qHj>K6Om1#kF6nJWO|He3l)nOF;Lntf9^INv zM0h{=h6b}Y=A=5-q%wzQVF*j>eODjoBU4o(mz=tyr z0g^(k#LGxS0ibP7Ch=6kMiX96gG%y$z0dYWh%2}-zA56mr=n=ZePa+v!7q2A-WIjD z;r>_Dc#?f?;*+f++k3s9295HU<(VOQ+Uxi&AU%v2<%Jopd?N|4_D=q*%%X~^U7=7@ z{K|W6ijl##NHXxgkn!utw2Q(pis=&anhks@04QN{W_#ba*YL+Aelp4|3k0Vr&ESV6 zXobEFRwQ1&Q+)<&X7XMpSXRkOG}_BiiiWCrjU3^en}GJu1tG5<#ous$qtg_v>~kP6 zrOgIJj-9Dr2;lK5*?N)QY81OfXI2@4tOm^rKamM6coXFM~U8_N5YI`s-Ts7naqvXqd%+QHzFw@jOG`MXb*X8Lg(%Z$+ zbXMh08mVvF=4w)Z>B{DZQRU?{`syxnFXS0CrQe2btQ5*sW?_&EX{1L9Pt5z) z6J4x7JH}6AaJhi_^Sgs zcM5|E=ICK8@CFC|lD()_zqg(TPBTYmVnE~__vi!LAuctJDH0>kW78GKRC?1*gVzU} zeIH7!_l9oTS$g}0&mq@5FN+f8j$=i$Hh#9$_D=U>uI;bT)}LF^MqryP{j7?ZrXb@>9s0q%W`v0a6}yR+ci)oX z`7|!sQ1`7wURk3BpSFZQUDKsB5Vn0!zcV$%bap$1qNVDaG=?z;3nbX{UjF`wT{!^b z*j@eXSJN}hx_iY7t=qPDb*}G(pDL5nl-#1^TkA(__ma^!H(Q4N;%}6Jr7c(0(>ip& z+wx-jC7<{V%S6jaeY8gBrHdhR4+y%&IXo7j_=pKM;;@{p1QCJIUk#q~3mW}sH@#C) zXafPxou#X6vE2%HN-1spM0qb4kF~;unRKh&3xYo;wWV219ki4QLo-{pyH66kh9Ufn z;``#ay(Q(>&WT?-!l;!-x=55Ka#r6a+EsfYR0c?HwG?dE=9i5p9e()uvCpcW4rl=uQoBe8`3Y`(Y#WZd zz0+cX&6^1dTJ&rnViUW1X{2 z*wl1RVDC(vCE$yV+W4i6i|A&>iZ!E7^gSADO#S_a%7}kx}#P9i$lRL+buo zh4~%1do3NPE*#)(X%{Fqbi}R$ccL}kNlzF2tV2&rYm`|ye-;79cjw0MkA@)xi35@A zB@Y+cFPw^Qh8Jq3uW?)Lcy>PPSrA*f6S~wQl0SYER){#8=S-c;TTa!Vmi6}9Oh#aX zY{d5=@8*JKCC0bZ1_R{V?B^KXB_~Q&?eIlaxqNBWbb%kqMkE>?rpzDZTjWP z^Ye!@-gBxuIASS&o%o-nc;;E^NUv%1dfnbayt}&rGvT;YP`q2Ofn{FTv9QSOvY%Oc zR`4@yfoYGW>df;Rktbesoh2N5dx&#S{*|(zNwxdw=Y#K(+n)F`%FE72)r%#EbumZc z7K>SCJFVW(LdQ@2A-{&h$2fW=a%!ZpEz z?z=RO!^ndRB0IP1^Cs+aWrR6kfC#*d437Bm>U|=S5Q%;4?5ENeN*sG%t-!eEOyYwD z4#+w_tlYy*to<_u`fO1I`QAvS2R-^Y=S>&W^3g<1K|sJL z+dEp@0P{qx>F$O2a#xb&Pqn@N?X2b#HDW`1cU})D6*DKfTx;F1q+dVD!t^my5b(`W zhrz(kFi-m)K7g^Y!JE9sYF;1q)GdjIq(aJIuBko8^`a|ga+&TNTNSVpiku(EB3;s; z)&HSvcxxdIAgiox`t|-znE6mj$>I7@E00<#SFzpUj$-3wp!P$HwXpQ!)aR}z3`TA; zt_Uq%I%c2V?`(FeoWPU6&T^;9GpBJfFOGLRAyC4eBE_u@S@pe-ExnEghdd-}n_k>c z!FEJuj=W*tjI<9lqz>;mLvgwyMXT_qMmT00%+zpc*vQ&957@5$o-HT#| z5L@we^A|eq3qRvC$$h5x(0RjEgr04pVs4pXKYd>f9MKb$l)C9GN@7kE$SS%KC|Pj)*y}=;c?mrqMOomxWNa!rE{&(WCC%|)`_a+ zKv{>nCh9l)BpT-EN(Gch_X%5$b}>AcfH>cbI zri;Jb09mio-)_K=j_fq`D+Z3KM9rFGi0`~(lq>DwT!L|MaQ5*0r(NP}(90<~tkMMY z&9UO+?EOYe_Q55$z|{BrxllRLiS(O#dB|sV|47!p`-O`3J^k48t(0@lW;AA~6Fasi z3WQq7H$rz$MymW*)y(tAn(mAoTH6nj0W6LK_uB4( zI_Lf4eb;e_bK!4pm`qsq_&IRBqBPg5MUecL*~|W*Za^`LyB55SrC0jwUMhsZybYo> zU7{2iEXHU{{?eb7fihUkgxTEsG`D!*l(b3M&n85T&ZKU(e z6Xq+k=+dPNPmik){TZ8P7L2>iRf$L6zU;Y`+%@rDiAbSv$mLwRWKFuz=E-L!-#$Rm zcbNhn5caw>L_laVPXKbdQ9hP-JA9??R{O!nXH$jD?pbe6FxhttFt&q;)q(}x9rVNj z-;BMt!0hz}#`Air4c=12e*Hl{qn^avO>(p7qq#mZ&8GKwcw4|hoToJ<(k+ptyD>~u zXE3RU`GkX0`&}j`l-Z^)VT>IpOFBC|qF+m#-7k8zEKG0)W{ZM?2I7};&meTB6j0ZN za`;8>Ql^cNrxnFufGxTf3W3cIHX33pM8q0`+lZN6uouk#vI( zPh)n&lQdIUl=!*y*23Gn+0zJt-qCE_EzCBkL!^QrisMIIB>l@fkqhzUKXoHd>wy3F4CkVK83JtVX@IY3%)|| z#80t3H^f3jM|%wm{9Y%SoCD8@FP-n==t9H2x|&(+ zF2KjeY3yUnfzj7Xr&V*uXbAav5R-#php{A7Rkj_pEN6Vc?aKI+!=zWOR0)q+&2^@s zY>9=Xpv14}G)k%9BeT)r(OaqxzS&{U%cI6mq3dOoX)!?bFcpGWl}x_{D5?T#GY8}J zBcTwd+DgN1S64i3UMV1EvFYskwLfd~7s7k#}ihno>T*ypF>jTsbIy6d(UxkW+pp*@$=hH1Bk36R`?;Z|g&K z>yGlkDMBA#fY|kH&|{Y^90>_GrrE!6z9kbV4Wf?MBKZ-(augcYiM7+6DZ-#+ zHOCc&W1@VS-tj=?flx-%hle_{FNA=@cZIW;G4&#+^_=2bV^ZEqaNMwbckCDY5|7BI zL!U<8iTL%=zvC)NAJgYSB;vam)J=-ZOtl*fsnPQuI4@U^0o|NzrQ|ndB7siFO~M)6 zWt{H8f%HfG7E5yN4KVQvVB69=|)~*i1zn zdu`~NnNM=TXreTxbigjJ@>##OWEpf%`E_4`UCUf{%EW`HOY(>u^- zISMpId}v{eTF%1*yTdrwHP_w6dX&erX^m=_AbPNtsdA=}6bP&{DI^tw{}HZ<;*J8S zN=?+s;UyUzzevtpCNzH04+2B3P$-tPo*ERABGz-4gB>}K6TL2D%8WaN{YH+Z8`yHW zM^LH70^F68LtM7vJqqu|`mF?-uuYGKt)#3cTAZIDv8|45nriMhT|{%+-Pm_BF#L9v_X=U`&0EBFd82XsKaaJNp@5 z!qqjT-)WUv7#mC5+Z_RWd|x4wP?3Cq9#nX-2__Y>&^Ar)@&3*9KM!?^*2@VkZ|7{l zVNcD*M(U0V3nGfwbXhS@!-|QNCfkdd#itfpES2m(W{cmKuZIeZsw7ZOg+xa&kQVe; z*b2}0Pub=}E}4Y)9wb5dPkfE>ej2z57kBItn4SZB5hpl2tyQ;$1k`Uo5aGAQU!-52 zZwim?!X;6fSj%mL@jKBg;dSKEhsfvJE59O?7YWt?1N|bO~y`s-K zq#3sJpAxm#z|qI*XL<^bxPy3F;Q+>o+2gN^4xNpdbu&?7M}&5BJT@U9>6Jn)I46z6r>t=saO^e;>uVk)g@141ns z#jOu!6YAjAPwTghRpkWR)d;4QVm3z}Kf zs>(um$JQ);iH#kE=|WrBcFa2pU^@ZaU2{$20%k{Y@N>d7;v<#ie0HPfbvtL&Bm;@^ z#$fv8HyVXq7}o||Cz72r@#FFf5$SwpsmDM<>Zj!#@8{3PJjQqL5cQ(!t(|{C2f7`S zGfD(a8$X?fjlY>J=mMTnATCeP{?EdTAF@8@N83{ z`Dv^6ejxABbHpHPZ7)Xvz2j!B)}j{l+egTVLy9WwZ-k$tvg}4$!(ZmgMc)HVooz0( zG2K(>hykoKPW5t+LEBr(%QFctiPYq~jP~M&iYw{*AdxBvlw4}==9%ugF|!(29L7J; z7zs53r%(2$4xZild2Oa{4##OG?wJ(mDEVqFzS(tgpVbWy?24CdQ8pkGu~4KkmT~Zf zZ4oSxJ?}fxyH4pB6`)|(B61u2`8Dc`iOaYTh0}e=O@%RH$9z-yYW~$o70jW9z}wom zLgV7|iPD>|(^mU^J{0h6Y@j(}OFzQGdFo+)nglS7*p91SomYDj&BqPj*u5X@&fI8Z zY(vcA1}558Wy|c0x@pt=k%*VM9G11Iwtl@lR$%POBKkl~c_9q)>e-!owy_zvJ(KPl zb$B2p^VF!%F5pXf787VEJ#EJKl3$a(xJ+3(T5kBYq>UC6UG~iSX3nqJwZ=P*p$p+U z8g9lhV^;j3kmZWd>o{|m`iRr<7;Vy(p;`M>vu~o5-+pZf%5p`(v#b8d*DcC*aR_a)cNy*w)o}5RSAjXfD(8E<8A<~wC;&Is^_cC;dYj<$6)Ns) zk{zdL-J-PbBco0g&yod%p(p@DEAHLH`*nwI;T>F0x5Zl0gHi&RVP%JG`I2KmV3(;u zbd^aP7^ngG2s|xY?;MTDpO0wBeHQ~9ZYZZnx*Gf$Lm}*h*OV^Yqh1@+U_B%-(CQ5r zP;evOE~8`yHXSO+pE%4cp_f0i5iocvHXKmM?xBnVIDI~sq6ts&YxYUv!!<>i?~=ik z%rAs@5JLJ>fbtPn(2)P@ES-0m^SU=pg01nf_a7D+(xR^pZ=ElV!d5>CopQfST-}xoj*?Unyn9@DOPsdVmN>)nJ>&@e~ee$EDI-2+B~Q%*Mv;0?syNgSVrk=-jeM?fDS0Ly&iP~K+T)JhF%8f>mx^= z?kDlQbH3$+u$3Low7ujvR^Un`to0*xOcrAG&U`Vg4uK!{C|_9`Aum*Wamx5+4tiTk z20uQ(p}kGuja9(fvp82M%$EP6rUE}ZPRJ5}TjUsg_ng3@W`m{J2#hc^V@@%gVdFur z_e{Dzb+z{_WX%IDMzG~)1szQknk=6}Q54Bc>C5?q34pd}M-@y#mn}m*7}1>2kKi8L zyMc#8&W4A}`bgbMHujb$e!6y=r&!^RP`@1$dtT;}*QYBH^0XlAnYCEj`Z5IsZp(ulCkVJzjQ>F|9GWV>Pd6+k(TH86@Z!5Iut|?`3 z1ctmej1`Y?M9YIHJRTrI(HJ=vY~Cm|KK))l=idBagHIL(UMjoPTG&mb+H43O1@yZG zl^Sokty+xQayuMV1Zae0^@)UFRt(y~nU;STYlyilDV$g^YuRl&hN(#uVpwL5{ddWfXv_B4X zZ@tOdvm05rz^9$c?}1+?o>;(oJp(QGmJnsSwLiq1^Ah8OyP6&=APS#pU5qzKaqf<= z*-pyeu^`HNHQwz2FL!>Zy2Vdq2c& zwl0t3y9`X*jSwy#?y7_T5;#(cayj04{{vUIKUiDxpxAhHqdM*YH{`(o&{jxd>4~nH z0=n0AOUR2!W2@!(dl(5w-AetoMuZ<~s03Q2tE42QHl*@uaz{h4PbpaI8d3LxlR@q} z<@1Of8FJM**6ylcY!un3CBb9k&RXaE-jl|R6gVDfWfyF{ zGJ7q0S?Lt&?a{5;!P&-iN>au(IzBV~nakg2my)Q;S&_3EWw%>xq~t`HC9HJ0OqXkG zfu0%*L?RYc?l+>!ey}ar_+n)Yj{wcxbbuQ_s16O@Ep;>F8#WJlv$71k zXby{zQetz(*tEPsPSl`@FE;^CG~JIDm$rwTfzZpkEgx`#v@y# zTBjoVc#f;Mv5~nWqCR8Wexc!utrXY%HSZcM2PwRpXU6%4-Pc)!vSmU=Azk`zfyK4G zeDm6nJ)N@~oZUr-Zw-)JSK3$nJ|Rj_e(7#+rCR5$RpESH&D-?_xgxaI0m<4Jn9_!S z_bd)d9S4Q%&%N#Z%M=vnZ0@xR2d!* z#b@|=YyxK;uHxU41R6$NybEh2I*pbn48=J6)|E7gDbX`aL4QnlVxIlv`3+Y+LE%XK z%v?UR390k^#y0_qnHHL1sQQX^Q~AnI+IfnwdSAyD?=Ph`bEsFJ`!bR3zITck7&UVA z)9j3W-Z*gbCl5wXZio;GlQMhjwuU<|kUV~Dpc67RT<)5Fb&2ig*u@7TQW$M(!q!8; z<%QO)j@gcmi-i1W1<{jso}A?$N3pp0UbStnZ^u$Tc7r)Uyg@DvBB`!BuIVBT(5B*X zzeUIRS4sk<>|{}8EZOqi4&ce0b^6-`*SRI(#&LJoJ-!4#O>8fU!U^{F(W`T<*W3_z z@Q{u~AYCaXTzQvcKCfk2b=*4Nc1&s}{f%F4SlW*=iD`& zEb{G~y?!l?B`xDtQO*~Oqr4LC5y0YRdM3;`^ls<6IKvK}JGI>mHZIlqdMP6Gy7S#P zWbB}%Xd9XQS1-oR^}~4$eyd@|p~+{(v?xVKI|j`c~P|IC2)i zue=7|Uz8crt;zlILoAFC_O;etUzt&D=G9L}%_G$O{?VZ{ErtD$&6WoP-c-F|V*S>i zTq0Q?1fFw<(|fys@%`#W=WTxu1BgT83E_z%SNgQ`L__=eau#arB9fP(l%Sd|Bv5YR|65ux8#?H{&F{Z9v%qwOQ_!weT{ z4n?O~&fZEdTqfikzX&s$a2(rcJNbO};rvs^QdX{!`id$emHtc!pmq_wqKqPw8G2cjBUKjDr~j5!JI`HA@$`T zFCPz|iwHtR(-R{C6rS@T1*21%Y?hp#9}GuE>>FHCOV+E+XN$1e8B!!pi7l+U3y_=> z#!tQS$3|G#*iE#_)OfD6XR$}7SIN4}73)+8qqe@J{py$VvRXQ=k2NsfT|peN32azq zen%t(JN;!_>$1PAP%;fspB*n$keTNZq|lZ^tkYMqp`p_8Fa{E-Yx09=crXsNM9lfd zqP?Gy@#~w?MDGM`qztV}OLW~){-hQcud|Jm1Ljv8J~W{qKU8t87jD(tFMEuO`dD;k zwJG1l_yF88d@N6q1hP1j*aZ|R%v|e^VHOdZa%AkBm>f@xE;=Rz`uV~(YtU@Jhmy^X zOBoI&*f_^{w{SOqAMnmU6dg8DSWb5E1=w{j8x0R&zzKHA}8vnhnKCq182HYCA5R9HD`yJ_c}jaU~nnxUAy0 zh9Dz?0VjZGM@_H1f)9l&$|TbU&h77OIJolGCBNMi4C%N6q9R%E-qyq`aYR8lY@fL< zl4$3(9e`h1nTx~QvvOrm!eDcHO>0cz3qQGv;b0muj%j`wu!o&N^t+6*(dKfH6mbeu3@7!=P48x}bvEvg zghDv!XiyyXcRQUZX;xzaiZletQZu}$0REPGV3V#mPtSn!)rkd{&6S(ikCIxP&HyJ` zLvf1bs>~C=0dM~uO*H8AlgB^HOXsbARbb}TI+$ZWu>cQ~!iX3+3N zeSK0nKC*xq4!zp@^|L%b)#TXNleCU+`M|f`b;b)eBb=?xv|t+p5F6|%!<4x*gZ`dW zmMtt|c8_K%o3iQ2dPHo6P$7W1=q}y4dUZrNH{=D4*_$`9cikr`Dd76iNk?tXSMR64o=Pw<0($G(vAR3zLshT_pnkVkf}5>-2sFB;7y z87@>=>-K?5G0VTvIlPHIWT%i67xdGV&O?w!4In!r>{a1|B)rr*R@AW&0+}c{-1QN& z8YWzX9rNRQ&OOxMc-KC#)e92fgm(lc8EU=qZeV*W#@lSggVP~QtaoIl*q($NWG>EQ za4O7(LISXYs4(zzGsaI@Q5eQ^t0kT!k85IOExQ8tDn09~F-&07jJ;l`gIgB(^(%x^ znWRno=mTh49a>vw0{bE^_6pPSs*P?B3as-k-{_SyRg$6(iqN8kGrshCz;?X4D7CYe z*(-0x1bLRxGVDc4omv;>3g4l>&s{qeqt^Th zl+1%Xv)R5>U}B;Jbj^s5+HY7F^rq6x!JQx6(joz2jng@aAAr6HY+CP&tXP#?2 zU>}|5lctO_GIu*gQ!yB}x@P&Tb!U6r8r`;ZhmtXKI2cXRK0dcX^kQct;-uUz>KNdG z5l~b`5~KOc8Is82`)R!=Tmex)aYU0Jjof4SS!O zIi24->J_hz)bwrX6JRl~+y2b0!J&AKjh1^O@lGc$y^iy5xqNW+ow~y-IKM9^SScftQKyB#uPDA+zRs@-cv$jf)L} zE*0WS{zMdg*ZVW4E>Q?n);aKp-=#CW;NcX0u|KRMJBO1sRYxwO%~aYq z>(zjIgBUN_H(?WHn{U7i$1A+$NT8?`+fi72lTa;L$t=S z_lR&&5U8?+e%%KME5Al;whK1$5<5Tl!%oHNjLh#|bU41`6ykr)zz|ZCPp+EE74_VD zcrJ91kJu#3JVjnakk};LmM-h6{#e&yjpb109nkRD-qsH2I+ z0M$i_7YLt8`Xf4jCiaftcf)@@pDksO5CgrDJr;XVMyBk&7X{9FX#Ky|-+xm?3V_gk zrhaydigrfU8j)zXRCwsqvtXEzP>M(GkM!(+9x)esBypYwzjhCie|GTudx$xrZ|N#b zyyz#t(fsE#n(-Uud$jc{F(l+a9?Dc~e@c=e5fvefe?a*Uh?4G)u}pJs=p(kD{5LB9 z`Q@{vGy);68?j@)e?s~F9cvLmi^#*QH<_4!0zyL0A%64>I=cU)YyE%F`A^jTw;;9h zARR-->&TI>7$1DHJ)po3waA^RG?A%_#`&A34;0Ah=+J0#)RMwzTtR}aNL<&)%i|WX z9mF*!@B#AinpybIRE4UMcRV)4I;WPYGY21w1HV zeHJtytoX8&EgF#{)ykgz?Hgt8us*-@NCKJ(qeO6B1Yi2UX^!-)X%_juD!_K!x5^TJ zLKb#-a(qysW%6*2lAGtBhj(P$6tOrpIW^`sBpo|6)KSWJ8M24-m?E z*9oduobG{C7t^*z*A<`K>KL_3G?OqW_~oG%@bbt#2F?Bi`{~br@b!OkpQ^%&D045I zxHTbI*(lfYuId{m{!sj^ofETGX*MF80N80LjVFhVY`)O|75#5INV0w=Dn*6W2w5n! zZ7#ti%oH}Xo+eNk@9(VU(pS6Pd=zlnMbD_m6H6H@%xjwEQ~^0jG03%FeiZ4d1=3sf z+>g8L4{H9l#X#&SU&A(hzs_M~5PmdKMmSJ8_qe6tHq@jSh!;76W(%r1Enu0WJ!T@g z^X`W#QxJgVowW^c_#|~*s}!K{a5yV73HFirf==*;ewFlZ=D^1d!A68thTBs+2WwQD zC9<1cLBhkF%xXMfqo*1$_g5K>J`#l7QB)(tuf~!^7*oeX#_8GLy(=2%mE!t%FHL4f zS_pTLy@@u8sGta~8x>5NwX3ctg(A4OE& zQ_1jpso6pkiaWln$E(`pA+nk%@$}!~2kCR~YpmQ)=Pilt^-I|UkK8SLTGTh@tEpb5 zHmOY>zK=NWhw%*rbjEIS8l zn3S~a6!2kE#|X9E+%p^xLH9c`R7$P$N|MKf-3|ZOMIELi#6=y_Ij9w1MEL6tnX!E% zUrm1a{(^j89PM*z-dF$`KO)0mwcWUveA*P}Yk|Swm}h@+&`N^;5czCJA)ET|(D8_2 z*VTV&4^v?=22r0Hq~V<&?|YoZ5L_7kiVr+TV{O_9o?B`9AtkG+e-F zsI5*M^oka-5MhnUL=l-DlPjCf*MSSAj~^FY&#e}kL?`R{4W)wa<+Q=Vi!Fpj zWr(p1Z8q^6)f(fw?v3hcz6I_|GMyjGENOg&{tdT0**}odJNBZ%{H7_*dde^+FqLXol^6N#^<(=oRPB*D4&|~Eq%q4H zH9T2txKWXk`a*egd2DiB;o|9a`6k9`t5>NciJfN|WB6~eza;h;BVd2fY`)m@VRl#R z00rO}AK&WaATUr;>uB7Q6Uo^yiu#4Bws4{;b^gC@c#x19qwv{h(@E=VJcB;>(|eD| zb*5(LwmXuj%i}%U;z;dAzvjDri6)AlMk)T77HQtBjrQ*;W2V6}*)tSXxZfw<@%?~h zx9F`#?2P^bT}yH9ITYt=nq2g{x=$9ww%fK`dHtzN4P_GDMktHVCCgwfy`EI8>%=Ud zg;=fF=Y*c7^W9a+S%ErX8FS5=Z&RvX$va2+RK7il``{!&~V3UhxQod);gtc%9Jq3MBYu>Osn^84kTvx;X<_14K`(j{u;E{2F`zq z{`&s^+HaH9G9uBw3o1CX`Jkk=-C+*N7LV5|62b`0#*V-Cl~F7KLFEh^@7_$B?sc^( zXU%sGe0f%Fx0{grdR(ixI-JBWuTG8LxtEX_8>QURIYk=j9?LRw-XOR9|3Sf1AO>Rk%IH`_~+xAJBr zr|Zwamr`GTg;A3Ir8FsV&^q~mj6bNXTltsdY&4kJJR}wQRBt_$N}rPuODO-oCRnLEk*@+VqG3y~NHlv=KfQtD)lata z*8ny1pB{Y`&bOC^cluskSxl6>W1bwN>8;fI1xy_Xjs}bJs;2WHG8)}4Hsz2Gh&(U* zdp#Mx{`^29?sihWLu1{Ea+)rbTpB9S_t#sB0^gU;j@s0WQhRfuh0p#rNIp@w#o=Q z%PE%&8t_k#`Z znrM*3rxg4dF#hJkn%}+;t3&nEznWHP5ugnpOFI6ILlG^)m$LTE<^HSb5j(<-Ime+4 z3;Y`uRz!cQ10W`SLIR{Gotwvzn1Z*8Wy#stO1< zYvM%O=I%6`=jD9 zGIZhDKmPgqMPFJm%02BNDKmr&_~*Z$nbxEJS6tzLWYI1pgc< zmYBa-qW7P0#D0_`KQp}p*B7z;lQf7?erCD&6OO;X5gJzSHR1{@;Ge`ojPfzy@J~2M zk6LjkW6n#qa-jdBB7(3_{`J%U5%&KG`+pq!_}S(ER#71K0~y*O9T9i7GuB7_1zjFd zzMNJmoe#76e7ba*lKDZO_6CzQ0kK6WJINH?pNr2dG$P>W^oNZ2L4o|3E~ZqwHQRRi zxXv#A@_1cg=+$JNL-_@bYL4VZbB5RX4!aSMb8@|@yvB}|Y_9dNG7|rfK9C+ceD+5( zy#aEmv}EuYuo*OLFl@k*w52gAm{K@|H*6cHpSQByYZ?OYSiMsbTZ)W`GSoE6iSJ+W z6ghaC9i3k>Qv4yNez`wteQs(25uvq#>sK5KXAZN3u62cdB3bzEsD6LHO+n1#lVB-U z%xKn+$FbhXc)^+sEK%1^5p-w~zDUOI$kUzdcT1u8mpH@5{naQ|JNey!<9Iq3z8e+6 zNNW|>9XSJP*c|h(-M(qwxS{Z^*2{8Oko9Vw?qKa{*7LcZ?S`7|@yNx|ghBw7lEytz zz#}E;zCU^vdx7_?S8QrB>Sd<4IFH@E!dc4fvTq8#m0F?OL4!qBWLgW2&9q$wY|CE1 zYArM4Yrr3h>T@y^*2w35M6K5R)A>ca`C7X>sLSEVeP*3=VcDYDRC+yJh&hq1g}v=m zxRpWaPld7|^Z6Ux=nz9LgQl#yG}Ca5Hk_GrIx`NirzAJ4FPE=6%M~XSdz4+i9q7=z za9(IO-VzQym8~#UBr!raQ=)+-$g}q0T#J}5tmQgwjkz+WvQ|#`(0pN;^;K%o^L&Sq z)j|gt>x@VD9Lke1Yx0&t9TKMDm3YUZQ0D*_5X#s!BP(i0;K4FyddQCy9o&9Woo=zmNTT8PBg&aJb4nf)WboG`n8L1@;^K(aAo-!B(F7I2ix5JD$;e z{#KP#_BGG?s<3&BkX(^D-ms54aGNZSE&icq-gp1DVuCeu>}~PGj$2CeRzhbqiGp;R z|8ZBCRR*wXIwNsA*fyzTS|ZPC(}knb&fX%6?fYYZ0b4wM@q1q3a^gX(4`kdzCPQ*o zTpnK!!oO203~^WbZ}Ib;BcIG*I$&eux# zrgQgritvm}5KF<5ggj3e_))+7X}5i*!gAT18;X$}dS?Nl!D%e%43xZyxys!)WP!SV9oZ-ld|bF z9tT>#GF`g?&#fK$e7B)jYGwMwa>6C0u&*m|HRA zi*1nWJSQY_MWisflcCK?P{lDjAgg(=V6e8F%xfeQU{tJGsb-o}Hm+UpwFuchDQd^c zS(8DIyCuYC9H?Sfrg+95!;NNsr4rK`prPHHG^%Jg>El^ni6~q1ElXb>$`lJC1fGj( zAFoM31?&;oD61=!?bUe1;xvT-ez0Y@9I`q}la*4GSV~|$;u20jj(BhaMswnb4=7%b zsU9~1nwS$V^sLbvUON@o0T#Fs;g-3QsK*U^BbQ%YJ{%RC7iJ@u2OIo@I8|izuFw_+?MUl zq&u-c;zz>NRpKi-QLPO2n5ZjUoW?q%0y~^xI0cY~3L1{Odu1OsNnfoEz;@LeK0Ve; zl;FO`?JrR@H@26mY~21ifw;=Pg{Mc2$T0m4mL3oJK<#Kh)YJDZs)^>osu|KoHjgg! zfT`fB5DCIZm4^2bfF42bximSn1y24gSTkLJb@~&nEkm z5wcG!b1 zxDS3j6^n5&94~uhy1M1JjLwporWtooZDwe5>a86MmYzLj?iQ~zWJ|$y8_ z72&Zut=*OldLOL@rsnn=5%Eku82a(8dHP=0Wob44GsShayr7m~m+m~657Fh(xVSvSViLh>`n4Lt(FFtCZ_MwYX8>&_- zn8dAH!TJjRcrn0RRGV8gJQvvTTfJ;Ux`~;YYi8Bsrl#^eI1ierv=Z2w$6(6)A6dws zQ9oi~_toZN>CE9`c((CBeY#=^4XiS_deZaw`@w19>q4b;D8NB2_7`>+BHkT`k)Kpk zg>XKX2reIctCqK>Dv#knmJNN?7xFWK>coQ_o1$>)PAG&a_T+Hw@<6@+HCdOY$0b(1 zW!Y~33Q|vlxNmkAYzAn#A>I;@_A4V#M_xer--)7(x>Na7X6{_88NHE;4cTNu1#CxW z%BZJb>WXoXx~ghFqk7FgQn|I*CUmbK;BGDUC5sF>W<7WQvB?9K(Pwu;!)>0xaLmrA zWobw{P~_IF7fv2jbV$^Ox5VjEU=Hg$tN(^~kcgWM_O!dXHnhm)pvew*lby85ZtM>z z83O(dKxfHoSZn}MT4}umQ|7){Av@LV`Hbzz-ctJ<^&9-=e~)G5(6ri3cmd^wfZwu+ zq%g-)8=X;HBKD~5C0M{l7`4qU%R;&kT)|GRqRV7B@*|tZzhNt_F7%Vk5ex9A+SOxp zsN3A-|H=|*cmkJyVN`ycJMuGX-0%K~aJzcm^a!jwMxWORTqb&OxkMce*UxMIsU~yw zblJbQ!b|Mif!fozAZ+LM2!P~OY{mq%JdKXCvLdEWhmL8g*WhOB2oM}u3k4oko8$c@+e z?$#w&|N9D^w<1n)_Sm%eX*YPx@^r;qNqAE8tm_sqs<`h&C4e@ORiMTtfd}zwF90FW z{`JedPw989H=j;#ES7iB+8@tsV9bEp2=2OyW9RJ>(|TC#5Zzyk<0XEA^Eo$U@zLbMWjBc-+AZy%F zo0fXm{$R97-xqzn9{Fn)PUZ70isDn>BQ_2iMpDJ+;yM`DJB)~O3r!55p3h&tEiMmc z7`z6mSz`J6+!?$O8K-NEf35Im_~p~=Qh`q%{6058?e<1UHY2N8-{e*fdS4+4XVCHb za4n-`w9GJkrL9A3S6jkqXt7+Y`1NstK-%-+r)eE?tPBhc-lZuL4rdfID=m>jjr+Xo zgtv)H18I^_0eu(e31ZO7?yt7ije7G4=H7iy-hZvm`1N9MqVAU{ zf^M9LHNR)}^bqOOlQ*$8K(AR;`|YxzS!bh z4Ex8+%$9!cQ|u?0bCuoKgYv#@kK}hRzAa|&LHVwHtuWZ%-CEi)L+fBu2KfP2oDBsS z`6ogpZ8U%#sYWJ{3{U+RNeIWX(-oKgBgg8veS_6(d+-(Z&Z9?&GJMefx&8T9;N% zFfO5;$M|C@Fx$Cq+S1!@m)S?kAsiaqSY7^k^#0F)yPZ`6%S*Vi4c;{3xGd>w`&HSg zgQ3_UvtE|}T7f@1PAhGyO>lkGNvW`h*wwRoc0un$Z`Bi0m&Kt|RT^pSb_`=f7k5`6TQ$myrFzCo-pn zRgs^N;Q1#Vw)y4OjWaIS<$Zoo9BpLVFwHMhjR4|Gq3L@UPIO$39FL^a;MU}_#fTH@ zHJMKv7CU=ZfL|Fqz84pI1&eaZZusWcK|MHyYTWpfPdDW;z^f8r8X&!L6hLo6NxQcW z@Bt_{IztYyMZ1-`5U8O})VN>4De~M3A{CKed^b+WxF%W@W;(dm&@J7zjcLSsEuwtG zePlwVysB$){ko8RQ1I3X!8ljjy?0y==mw69iUw}lDN{ye*PJM~7CgjFJD>|fnkB$j7fx}J7z1F%GF5P%j)R8I z6j@+`a>=8LQUvT9`jY`6EZZ|Ovb%=-NI+6PX~GyXn<%KeOsM`fUk@R3n(uY{P}!5} zoX2!dESSJFydgQQ0^OswKbrL*R2|3xMnuH)KnNYMFRB2kJ_r{!t^1U8)8>a6I88P@ z;<{4cgV_B;6{Pq%M}xzOg3L zi|=8}%cfo;qaH=nrmmA zRFi3|U8C0&mkl3T=adgFKg%g|qpjQq?f;>oJ@$*T^B)ww{7pfHJtwRt8OPa=32qmk zJ>1MMkPd$;CX;y2q~wv7LAJtDf|k?3kCldy6WW#y9*Jh4a9x0cHt+q;K&*bV*xaby z$A82oYK2`UUIjkmyZwu+JMOZGC{ll}3?A4YW_>j``!rK@x|I8Rl5gt?JRVaW+-%ms zYFP(O4zDClWv}MG8y!+gM1MRmRsmT){`f$9#B97ta0fq3aZe+RA=Wd1_BtT_%%?fC z@1wyJU*j^ki*y^ax4XAlI9EnlXt1AnF^;9z0*D}dtM@_?@$lEBIB^}Tw7t;X2qr75 zh%{<>*9rm@KkpzsSq_}#n`0eJ9CWJ+GBHn>2^;tny}$Gvq7 zAuE7Sctl{rj9CTU--tdG=-FNJFY&68v@X!}v7+^> zzM|fS_eT5iOj<5~L*=iC$a8AP-<=fwa!ZG)as}y-!$CxRi?-+@PyaUukUZ*BdiUC&rwFJ7#&|#eH*{1RNk+uLZVk z;sV?_$z0-XKSmEa0^IvEN=W^U}^GZ751|(Jx<|-hGpvn+- zN+9X3eBgX^g=YWSs=GLryH?*g>zR;)L248phV7Po+1L*x6_@(z&o>8BA~WSSDECb^ zR$w~h;x;XXrcJcWO4{uktR(4<9L1(fMAYOXM%_J;d3ace@cPJ`-W{&Xxv)-D{Ld z>TFR!aNA0zAqwRgxuZb!v)!!zIn++#Xnpk|;EMuv(CceF zkhqYe>LXHW5%o`BRK?%x(vc5}PP)Y^F}HA+#}={Bw*jnng&=M#ZoF*6HQ-g_iBqSd zZXN89<1OM;o%@X$;Rlf6x;ZdP>fGkP1;Rod}*@7q@A7QH!bfD#j~q z^;c#3u2J-=8p?X&fsj4wgE$K=j4hG9N4RNxPWN0#s^J?5Y{Z0l>dv5;lTlVYnu zyU0idYWQAId#&d(PJW2gYTgt^)9exO&8c@Iq#HM+O^Qt4*l0{OE$|*&Ho&xhkV55q zI5t((8p45&i`bgkkUJNRite#wXl-~(dZ*Qb@Pm>GU{E&Q{d;=MrL~Aq+np)@A$j6~ z3o)ejJiJOO?I)F|Xk`rL+3w||`omQ|uY++Q^$L%LAiQWL1AhJ4%q3h>AvwMbPCSgH zDi@>?vqu()IoXId(4;)cMyyT6JKzCMAbc`BG3C`k*xK!&xLSRLd!+P#lD8OBSoe3d z>B{!_HJ(~z_L<&U=PYG`yJJf{mgingwQ}t*joJ+b)t$2?gh;G>tnFBfI;7e7i|3o5 z!4u_AR=3wP%r*Z?TyTE)^B0%j!Id5W(Z6E-kXA84IlhB1DN`o3zObV4;=aCSvEYXeuLR=&rpwmaRp0#e zL1EHe^(abPi2Nj~iZXp1b!S09j#^idCy~avcpfPY-!fhCifNy<**g*0U*=3mQNfzj z=;#X~aPq1_i+5^e6{*u5b6yTUhdv)&8?!41Idj${$|oFV+i9Fsr-4j-=0YRCt}^Mh z_1ov%=%p;qhJhFNb%UmlS8fv-1u(@sY-EZC(vj*M*`m0!wNsd^wS3dco7tY6eY$}^ zAY-qJiCZMBx>w$qB#WGM?`m=PYQT8dqQB@Ga4S6fVq1kr;c@;wNI_uAL}*%6R+X-hgB+Dd%ML`lo;iQG7IdNAIviq^v81}JP2PbODVv7f)F+Xg_&wWQ*u5h!%9YsRb8Y?sZ< z!F-Tcv!LWOrr8lL!|~`@_Fd+YgmYwx=2I}LVPx!S?-MX~jTR$&I+O_VfNCVHj~&jQ zHd7^YX8q*sA?8v+Td0z1Dy} z87`r=rn2?Hdcw(MC;3*oLS4AEjVpReto3kMJHOAg+(mYEQHCpQvy$pj<#1`Z?=eAa zR2vkA*W)adJRL6W-F8`g8Iocqd3jW5#S}rOn0C6`@V{4_cv<2AXfsB61~clhdl=_ZpHq!c!1@jWRZH-!Ln=m4dJN*Tvpoyn*6>r; z2xmxeg;Ysuny;cYFaU@I-AN!gxL;@ zGC5>c4}IZciV358Cbj`+GsR}dl?m}UqHckr{so%#(_o`4hHoALmC-DHy{rqG5Qnj} z&;BGVz+`2SjQ(ub5hhefUd+HBWN7sBe&Z;gcIQ@f!Z-&_=#lI>(d|p94XJoc+adHa z1oBdp`cl)paAhnzQ8RSX^H0h>_h?MVIzpAtd6ciQ{FLHfY1Igb=+oooSqYC{=DsQ7 z)r!+8EX}3(J1#KK;5kRsfpJd6IHV$zJqFS{1$Uv#lx;hn38#``*d&~=R}wf;)vQ1F z>_Ct=b&X$1LlkK#248%FlX_Nc$-pPa3acZBR~0yXO7l4%a?s*n9;h zP04`-G^FCQ4luGtO%Lx@`Mz%aX)t9z+f}0Mm`?P+zc-a`SqO8`QQWwSA70`}vkO+Q z?+)t!F0BF*DS%f_QA>N_tRu8G1rdT_t>XtaA3IdY1&VE?LG(~q#m4#2LVuBxhwbG| zpX}0F=ud&JzzwA_!twA~8^?K}JL*pE@b>*@nMslPsFSOx+HRtg2y0cFK)Qz39Wct~By{h2)~8A|=z9b; zN3Xm|-6}eT-Vt-7(F!}d|0eoHD=>022htDzPvKOrFAuqlr+4qTxwj`76i zQ|P`r$sjwer)<^{JuZ%8g!Su(G-k;V&JEXms$PS_0<3DWMU}Y!vyh5+u*q4p@(kRW zFmJK;4>%0ZMc#f!ob)2EhJ_Z5?;K9I&1=a9@spkGyTkAFx`x}!Xb=M;*e<$bD-Kf! zTqAGzMx&Sg50#&_KWTP9c;ncV;bh-IS!g2cuYC`lsl5nl@%e_D_38mv3IDcr^F1AK z5;iizLz49nMw#dU`9G8Xr}e?v8@3A^Yq9RKs?A;FB3($Umu=g=vDb~wItdG&>COrH ze(*D+>S0Yhrj`6bG`m;%JQI~YeXQ6p>X(S}S6v03*r1ch6i|}}%IkQefpx3=U3Cq| zaernBy^TcVs`NwO6F14i@#Bdz+KSk-jg>9$Gd5qFVZNa^3Hz^yycI4ynk)9`MIh z24kHL<4(26pbg1bkIiXD&Z>K(XP0TPA^#}WHl;Ue;5}wlg`H7`oIIbrBH#_=99%z# zwAMio9Xtxu+A4A6bR0ZGtpV|lX7F(@H4cewGW_A!s%8r6xFmA|)OrD$ANtF!_icK` zY58DM2g8z8kpBxABwv7u%MWjXyT169OMg{7nr7+1&uhR8NT4{*{v+H%!f}AxvB*^3 zf3L1H=9*z&iqKMRcN0L(aahJRgFy!&lmh?$R6Ym^cTv{hx;%uGseG`dko_%rkou%+ zpmz1qOn(JPnu5@Q6=*NTFxX{=-gR8P&}ds7piuXOQECH`WMHixrCO|?s2L0nx77Kd zoo0|>TfL`O6eL(qxb8BU+oeE>OJjLLG;eh=5!RKF+?N0d5AMq3b&U8W!EpW}C*Tlh z+{uq(uJ5-E*UM1(c5dkhUco!o!0Yj+r^g88=0?q4Kl83DgY|@yL>82&Se2khgKOgj zy4|GjvKhZ_|2n}Ko?sYtE_KaBr2hrzif%*{0iD}zF5v`o?2gNc|K_;cC@{t=vJ9^U zo9A2*BZiNiT^&W`c7VG@!=|+r0jj>Hi}F@dR=ie>n00AEkPMj(5?)}CHfptTLjJjc z@u=-6fApcOdJ))BRw8cyksC zB;2EeloQK$eUr~}QDzT?K?S^j!qec|J>nPQK>qRqk zSdWDj2Cjs^WFs1+wb1JI!-X?%oA|I%vR$ zXRN4oTp@UvTP~rQl4tDJ$EN&q8ZNz9rBw%hF;t2A=4u-tSr<5!BUsow%+X-5qf-Pu zrVrDeIm_SxRCOt~JK8}T=+JGAw@DJNJ3>Ow1l|Tyd-b4_p}!NRM0rzkZ+2aLHWTbY z{fl1yLv;p+m>`*kj5I%&!6C+m{RwHwo=;cWqnMc4CG<4ovYry&v#V&hJT7xdr9}J{ zn<$+=CK$it?~@flMpp?^rud6wdk!uX-+fzEfQUJ85QrKFA?WXOfp1#jfFgR3;2OJo3uSve=j=~EkqW_^usPocwuAT2-a z*&)u71%HxbeKv#GAIq8{bLUIYbIAS{THNMK(+p@iS@L(jQDe|E`Fk9jEt9licO|Ct zEZiT~YU%p9;;!dHQSRMzk+FBq#< zk)NDZ=Z>EuCQjA6$aPg&H-72=ilQ8zpl#1%wR7(pPKLIG0V#H3AkzbYPBLPkQHX6f znyPcg`Tkg^64~5BuTa54;q7hPJE=Kn@yW0K*n@YlWpk__0h!8v4a_V-wJG5#1*bs*)Z0uKZV>z&0?jTiRDs| zEsEF6C&)Wfgwn*K59G2b8*L;Q>D0lj8Xw8D)@tg0zO43jOK^yPRM?$|h=Fs|_Oz$E z$HnmpzJ(Bg(Sb^EcQOkdh<6(irvs=uJtqSJHVLhJ8T)MaV<_$S`ryiv8+_S7m&e8sL?3>}V%KG9l<@-@;rr3PY!_b|<%LM)(kLA5K zKhjj!Z4B|EpjMv}t*Yi_{Mcc>SI6S8TAdB1+YM1?fb%aaxb#kW{9{e%py7_o&$#cy z66?T{FC5BWyoDFUr<}Nk_*JUEweTIPxir>udhDf3c7C$icf1cC3S<;QX+!IFX7;!| zUKl#5M7zJ_;K3P6o4c5HqEw}EWYvi*eoLqRi2{&M8=A&Jb$B?5%%v!#xc^niR(pJg ze)Wl?=tIb7pyJ^IQqB8f6usEHnEQ?m&sEo`m`e&-eW((OC?RzU0KBYoa6hK|ZI~^x zZ->o#JM9#X3#Rby@z|(Cf0v%4UFs`3$Ji_x*lOB zAJB^Tm@+@khqsowbOSY~)4?~A+uo?dZnaiEreIfT(+U&{CSZQMu9LQKnU`@~sV`sN zkBV?XV{fCRoJU__3zl3T796vU#i8(ASc`&_`ho*xLBvB%Acu`BJ_%{mA)|FW^hSBQ zN{osxa@?zO2I>_Oj?*h(ikT$QBJP0bFHpOmxlfw8vu8l)&tw931GXM}c!73U zLViv9UL^Z%Wrqv^EI4T|doE^KrNw8dw0UTfWTTfXkxaoX(az*mcehqyLvzV7R95gh zH9wg0E-m-T@ew|TXWEs141D17VeFU<+BdZd{ZT4{L2sd(!H3jL?rG`JB5kIX`Rwoe z2Th*66MGGf7HVrTyaOT;*DviY#frq8tC&DuU+PJ~)W0?SKN(@5c7an?)|C>s%83|P z9gG!kwEn~qR>f=ef8qez`O~{201pLjN5 zcbm6%BC|lH3w%-Ju=S!#NFyEjM!f&HwpPr(1Luj!eWa<7QzTYvS$VutV)t*!(7FaU zH=TJF57~_H4m)0kTqyQl2&*0 z|5UD$UxqlHLH<0||G?hynvI-i1G4kUfzSINgmwCL2X07!^uqJMmuBb$-HrHhZ7-ms z0KZk?VlPzNi4c4(tLDS2KUEn*Tm)RMNrOY0Oooyri_@xCt%c0<0-J&+FVq5*89Ol5 z$NzsH8~Rc;HG0^TVqsPL$mQ;VKQlfPA36*r^|pH&JK4JvagyMZ3uQ%50<426$8P78$NbSw_zQp_JR% z=Ne+i{^!B}UIFg^S@HkbD*tmh|FVdH+4;X)mCqY=D7G@g-gISFw`)6r3blLyH!yxG z=3jP(&gS;Ns@0E0kYfsU%)DP3l(S6gK4LGAA^HhX)M# zE$pExj`!O~Ug`Fpux1<-E=(l$<~#OmHNWnNc{T0F5{gF1IUDKb&A;}{h&%fi?E7zQ z7$9)|a%(S_%)MI)B5#QvA55~ZR*wq_#V{Bg9@I5;zUNqU8+&ciD%QjJ?Jz}I>!or7 zHkwm%Yh1}lK3t+Iv{|t{F?{e2Q-5K?kUtkxLRltgsl-^SaDVttM`sLSR(?U&nn%_n z@+8dW)b3<;Dd>VwwsK9Ja>8s~{&wO;A6oD$W<9Hh0(-U}ieD+cZ~lr{|F=ryynMt* z;8R70*aquJFAXLQ69*jQYhq%1Vqd1>8wM45d(Q5o zjN?b*=lw{dJMoW259|0lHlJIh5p_7(ls4l1()Oz`B)gTULXWMap)_oGi?w5wJpXS% zKO*onq~@80(=5)vc&V8Oy|lJ--q}JvOV2F>jVfjYNCv6>i`v3t`UuyPlJrlsm=I5V zjo6uHa$EV#zSG0(9(uQ4Cv}JB)bAdur+=GRNWtDc+!2_S;QBic|6gx%L-a4Djp^j^ z@O7JqE|+!0E~Q>iG|dl~avxJ%N-fqYfc3Y=ozR_WoIovs{U!Q_9p!N_Y8;?gOSquQ zmD0Io*NYPGYuVU7ZI3*6^TvHx@VP_LVF&oWd+>{e54i)Z0x9)5oF_gcQ#pGgEB?U# zYp*ds{>&S1J)HmXvB=dhZbi>;&L!k68OxtLTrA021H&`b+7JgU^VvaPug5}h+Nsl! z|C@XUU@6~!qV*56aEzW#m)j@;w|OFJsp2i9e3+0tsxwbNQ+tU^645$j6*{_XK0&=8 zl%ZI{yLQHYr`aM)L)a}CAA^wq|Gdx|bl3xh-g&(u+0c^z5Xl6isr{;Lf@mcr=?TFJ zuSCg}6aLS=e=U5zAfl{K^O1s?8@Ofxik=|DlC@t^7ZVSuEc##}(CX z6#2Uc?DWj&b7NKNb~is5L1jwFn|4S_-h85(jPPZl<9`E(-%GP8{*3rnFMu}+zm+7G z=WL)itYs!^1HuJriD5FX1uhp^BHS81$$f&7%u|F)NyO?E(pIKNfv|tZz)Bbeb5=BV zcXA%E9@=@&UV9n~w;q9b$LQA|1MgkluGsJ~%{-8t@bs;#C>-Al(OkOv!^7&#k)=LgO_y-a-lTMP;Q01WGW9;>`8Qo&%O$AH z_$UMy8?9!_h}$0QkO&;&iGyLxW@O-Xq57VpM->Tb+{+BpkGRXuPDz#?TZ-mbaTj-c zlFkX_>cj~M<@+YwkOjv#AHih3kVknHs7r^;2#)*z0nDpu2(HI81goa_hG+6eyK0*0GId-n4O3?A+xc9GKfI zt?9=69nt^Ci2ixVsG-e`Jv?i5?8tln32=^q?gP5IkNyr9|9g-`fCdQf|NTt=(*WWB zGdcOAi#?oj!4?KN@SAaqgE%u*!+*EL*f-?<_5FPY53+K$S~~8MU`l5!i-?ig9lH?) z=TV2G4?c@oriMLHo=TTW7LJP&fOb;+e0;=Gpo6V1Nc?cQOV`H%*>O?P+~{q_9XNeg zTmT4x=sg;|eL8mCO% zkm%(7NiPa?ll5i-bHBS2x(m(*1^w9X+L@CH z*kf_;x+t@${XbP+E-n}L|Kz+PPEd!^2(}kRyz{&W)kh8G8w0w#wc+UVMu&sIPzJb7 zl{m%{`QDG#fS11|Xqb~4-9^y+HK}&aURQcu^jZTxc~am{CYcBvTqkwHGbPls?b6io zYnS=7%S@9x3!}APgf#O9qGx@Ar}Ubi1-nWYx{v7@b^O@1F?sEC#Oy`fWI1io^h~$M z&ixeX-YLK5d|Bzp*wIV7!nfj&qjU!M`upB1@_T>X^>JK!08)C?fS+_)SRBAnwuh`_HRPC`s>soW^#ktF0@ivkeuWFQ$Fxd%QRixfPw}^| zb%@(<2#!K1-QRXdNMAY=j8_cA)#*`I4V@s3U&b<*4mj8q`YT@tdN1^3GzNmfm1Fi20c50LH zzAd$3mg2SH7;cB?MQCKbj`lVmL)HR@Rm`g8hHt7{QiUROpSGkffnki1BV;F??+vTj zXn~$^y~t%~ut{_a*L=NI?T#A7eOyM{VJMtP&b0yZXWw=f1o;i7e%N%`C;|#@=@68M zp=ntu1GqJC$@cgWi+7&m#0%5Idc}fiLZ}-?v*Qq27qUEJIpI6pN!cEn+xR-@>%Kr= z6&n8GW33M1m<{?HI$p|~PQE_m71ASXtFe1{Rf1Ud+HolF(2#~rDRa*+1;a`;7!ESt zlMB)w3xCVUyNfZUpL&-g;)DRfu>5D1<7cW=MGe~&CWZK2zyE-R8ic>SCfHD`&pJc# zOMjQy@7YKnKm6SmS4fxH zAYkZXoJmJ&alYHpD5a17gfEs-n1wqvNuap&wO!F9=x3?$ynt< zWa&BBK^zOJJ(L}~Q^Y!HUitV&PA$&jLDKE)0k*9a*KtY+Q0${PuAgbGtfgJ)%^4&` zR$}(5GUWqCJi;ry{n@7QK`U3uYNoPluS~TJvl0>EPo5DL`x72bNtNGNXg}0%*iZpP z^qJe0NjKv$V%WHue5bysd`EfgR7QrPWw18%cEm4{m={%6iDN5b+EI@61)P(IOx8>|ie{YCr3})1{}7EZp_-)0vgOQ-%LAVE~{d zl4p2%POSMio-*LrEtUFYE@AZgy5wEkqEZgroeK8HDUUX!Tk%@~+wX9Zcxpji+D&c9 zGwIzdg-sU4TTcwZ--*>S(vpG*Py>oo;E}nNyV#pPGr{Y|T^2!Vj!EVBry%hMMLT`{ ztf3Zt@x6=%{hvMY4P2@aUqW&84-??$wt?o(|Jb9gT_^-?U9O?+c{G$l-K8h}{6CdFkq#gNeyGlbsNoxIhq3M+{mV7&392O*W~uzkOXeq+)(>Vgx; zK|*JLN*AcqK>3IXJ*G7mK@anesq+(_!=_m{6{GL%_2HL(q%mH!pLtta%S6>7qb^C2W z6xhCTS?;UpHldOXnWVa^hBqlY1x81V>t{UuzCgUbQE7!$b1)5zv?C*LSN)ML+mdhn z9{@SkeE8w4G-71v_9bZ!W$%d;{6T)$`->8}e zSM%wd{Wnu^4qKnq@PJEsqMn0Z#yt{E;-=e`iKCy1KJVf054FDWk``(tD+H1vyNmaR zn%ZVILwnOXrX74T0gM6gNlQ>wW8zHTL#qL6l3QtHPh zZ>}fGa(Di5cusSB$^MR-#BJJdput?*aEtq!>+EM#j+FPk-c;q6 zwd)qUA>WOhsb4f&)5ZKHR`<3SjPlfEv=gKfg1TL+uPcG4+Ans8nm%Q^>RQKsQ+L9x zvD*QWq^TfN#rxXF0Xo2Dl*TzyCh$Q?WH0y{vijLzU}Hpib|c~!3My^v((5vmsHA;^ z8l6W-ec_NA2!EQEDSG zETR+AZ^oaR8oLqBp_F{v-(K0tyLe=etJ$C6e863ntQ4>XJG(dU#C9-vqxE{jyxjoR z1|+i)%9P>p0oe`s{wJCS=6r{o3P84Jn%D#74zrSPCrUa^ZedQst~G4bexZ)Lwmaz= zB;2ZzlB${ws_>Q;N)oKqvd$ZeJ}06wT%Y>Ns^ylmg>>={ap_ot@qDqP&++O6(04(z z>Bj>{CEFS1){SB9W*>YypTSiS(7IEoBvG*0T?oL*@t9Mw{aeN>e6}wFp(_49y-8xP zLy1Fk`yGu0@sB2K5zfZ^$w}Imbb)b$2{-Xy9N=u%Z^mPK-_<&M}+WW!6qxqmacY#ueK-~@G5o3RvJ{~A_ z{2?uqdQ_I(Ne|R$J`6`&{R_RQ0X3RqKPIh?O2p4!0%|mN_e6Y{jxN(5Kx?^^5AA$Q zj$YOS8sWWXsOXVC+J5E#w-4@xpck`gyIH$3l$g~Dju9(1Of{IQbK!Y=k$+om1*U4+ zlLrbv3zbhy60_FPxgx%t5Ot(c)*E)T%&O2XuEU(N25ucquK-$ApXB@O zR8h-D)LxN6vJRlT5~|UsoeG!ujAakAggtK0Aic~~47V|@u;Jz5;gLbS$<5KJNFRr9 z*B&XUty^(_q%+5#poM*5FB@Onf*Elm)dR!=qO@Z7!8LUos@$*aS`tfDtShUwfuZS(y@jPxgWS|3(s!>-=7 zxB5$t#xFUEe>OW%>!ha>j;95$pK+cEZA(s5*feo|SZm*zly@7M{Zeo-p&0UpWOQXH z)np=!9CkT{lNPNIw%4ZgcuCZ<#^=6oKUDi*cEase6>*hhQX>eO#Nc=b2~{@(~{}|_8FCDr&Q*wAY^wE-|db>6NSBe;IOvAoAPp5EbKVKfm@INrT(a1+esp%~l&vxT8fBN!L?;_SJZp&( zzR#a=D9>GD%$IP*&@9QC8rQp`daFK12r2;mN~wK7C>GYqqt9N+YIs_YQ}!E8A-rd^ zXak%IxY<7Ux=Pd)Gtn%N&gGu>|4xH3; z4ZPIzwsw0wlf_mR?GK+w#hPt58_LEW+P=-aQ+c1@lni*Sp3(a7{yIw8(&k&qiSm#d zrENF*NUbV#i&;v=VYd}EY~(ZSX|~?>^R1AEijb_3%~Zz4$TZyZrSI0;QSz0x6-E-} zR7NlzFZ@bHci~*ww%5?R?QO|89RMSTvMjj8fXb7n+t_aGxF*GKoP;mC#SJkcE3Fd& zaS+P2@?mAUUgm9quj80%??frL?YzN5os5*x)rw)Bz6)Z1zWb;B^wNz`JY&zyp~~x- z&Jg1$X0uYe*~zfbU(KmsXb#`Dp_0>j!)<;ke5cn|gp(X}a*PDXp1jFAi#t=uJ({@v zd|W>toFV;y;{4}gDWT!Is{ar#DBEq-VW{UERMOYN2~r_*dGxO}{f&t=p zgrwy2e9jcV6sOd%8a?zC{R!+$`G^^Vis&i;(i~g-M0lZFB6H~a*n6am!RY|djNnXy z@~K$ee1*coFPyC&245DmWRyRFK+hOEYWn-qCNKl%Y`&`*2w@_3^efQQ#P~p8~ zb|2iNcdy$FBNh81=Z4jITJ4GsAgV;~{}$0mc@W)R#qsn06QoVs{BGYvYP%wl$ig8B zPXeg;!W19-B>Js|zDRfKA`t!znLEV=0(+R_xTE$a5)v-OPuaca&>@ zE)FdC<{y{Q#NbK_DfBmbunwRB4cJ-^9(8MuhW;W$XET2fVuJM!XySAXAB){kJx8rN zRZb9`owBjRbok-VnaNPiOEgsC{H=rPy-m=^SKAj-lPwDgg2s4yeX~lNOQGMTcl)FT zbx&Th^4!gBEHKFKL@irPItFLfudlBfj*YGATwt)TUonB?u~tkz3pSSQzd*SEV(27J zr~QQ|h73)c)Pdwm^J`xQMK2-*80Nd`zwD&>vf@cdcC*x6Om<^`C09NA9Ml!*5f~_% zF|97#K54e?h}17 ztf4p*tPju<@LJ8vtI}?9D0H|J8l87weyhK@zLoHXMA-i$R-QY?Nbf#Xqe^_8`tvcL z`qUzHg4ohLiVf|6-kGJjn7O8i^W}u^!k%*%uTFRMkGgj1v5|J}jm(&2u{F8#BJ^6Z7HBS@8+RSNi9~SJ1{%Vdd}iIETN}{CFW%{IBywS-{oHZ+3=|$3#_6}xK*1CyZ?3DxWO!GxLXF^eCT&f@3%11 zAZU7=RB{}Y;8y}g?K|oHF-6R(kqAdQQtx+uXXDc0G}fH_;W>RhD17&9YqM@l_acm8 z=2Qo!vl7(gcRyM-WR`SQP*%Ow@D}wJ?&nbO1bfzEHA6cnv@)F|4~Ki>$f%GRi0FVg zEajBh@2?~-ZYJ zb2A?~1^2jb8vIQ4Wa}YeH_QE;4?c+AgXq_eOCn%qRuX{5tQuN z$6|hE!^Uy9qGGcezC8^<9BPafpJOVw3Oa)fHU^KXG1wev5)l3!zo~Er$Fi?A@o{dWx%ck2JGE2Sv}9?HT;&jbO_mnz>JB=XjfM9 zGaN!e^F&wd%UFTMenTj}?p)*PvmSq{!0I{@K;8Yj%825}24;7_Y}x1OHV5hlQ6lY| zWkRnG?=P7a-p+m{Dy5_D!I{-n3WKz)g=HS`MLs@iY{?2!MDt@s8L<}94{-rvJ`5-7 zG~N?1J^Y9e=bn22;J7^=Tp%n3o%Xg_t6Lq|)KO zqL>4$)WBGD)`)nuSkPmvn#a;qybPGxWbym){kPm^cY<;JtQ&$}06Us)EStboKz5%( z_}KAj@AG;EVuM?Wf9Ofm*wPI;cc0DZmQrco>lz!lwhL+5^$vo}p_--2=L&zn9$?$#_aHj?@&(!T+G5g_tyJ0Uo?bq?;F|9LTn<1?~|uA3XGUu2I}Q{a)nC{0O~mUXVa zZ`j@Ev3_X=cH-@??+1$&EbV;Zviey~k&suDlfwXy!~F?&sSYYGF6%#L^HXZAv_=qJ8aG%qmouHhREKQ%dawzL0jm>_@W=M9KSim9_1yI?p zg7Tp{p~u5WY+;z!1uvV!DK0B;4;6I+<=9@8s7TajX<)nUQ{(HEDw_O5rBq9Q& zuz>0D`^+5{5plbMOU4jV?Lr|OLcM+S#t}$^!1=G+|JPuMy}?byfqBpEaA#pP$W1nA zQ-^8KF^N$w3j~xy@DP$JHoh%W!M}q6v`jW5(*Q6ayw7iOuzJGA^}PF+0EN(fN7q}BtAJ_t3XP?s)UT0qa6_y)bd=~i~7Zc zdM)Bs@9!5*A5Lz+*ZSE}e)nJK@VLC907Yy*TweFb`NIZ!05mgb%qOzG|9zV!Lnb4A z*86@e}TT1qS4DG$f{-2kkP2KCxA1L-c2!2@oQKF zdyZj)UMTB%MXP9;@SE)b3_I&Hd$XcQfeA0P2iAel@PhUD*kdzW(r|Y|2 zPejDe{gVnyOKyLM7b>Dq1UQ1Tj87DB7SW>5%g2RA3KDXaQ}b0C72qct3|!A&&9Yvl z@Z4mJ&h`2F%XhMRh9wn;g8m)=@V|VlKx`E4IblpYUQ9uwV;tJ((RYZ?_BMw(T85@? zn>Rb_3LHm#U)v4vOn+!r`1V_kK;Xvrqcf3gN6f};<-SUhkvjV#uW;q969<@bJS|~$ zNv}q`maub;$vt4c*9R=nAap84SJ9*QRVp<#I2)`Ni<@x~^gs%X)M2fad{xx7xJT77 z+j}pnqJkiOxm|IYw66NGqFZf+!py-D>#%k;_pyJbTfWs6no(sM?#^s{N?mk7;j%lo zR|Wm#?PfbT7kU#zC>IpzwvTO}6#9=P6(}xFEGeFL?}ZNr&T-N!z3JSPMNweBF_*xk z>rIYBiTz3qP2CcmS^~i?#!%Y0?thI*`&P0vw5p{&kOIPxPio_C7~neWTLNVsRLz8} z>Wi!$#r~~zhx+mGl;pdF50%Rf{Sg5%zaB&i<;eIPer5U?lcTOIj5v*hyAk7(cPgxy zmKON>s8#Ra!C4R}59`3aDObpAvHw&kX1nKmwe#2NmuVs45L(gPcv=Kyy3?aGq?CZW z-Ad^#HCcPrN+Wk|jd3zOJR)t0;h46uPR+#xiVqc@}({qGP z|3F-e;U5_$N6{x9EEcPkWKO4ZWXgs?NDQ)AsJjh^H$BQUgw^COIpY zac$xMusqT_&_fx3xqB(5pKv!^dFZpg2n1!Gfp$)o2jDs9C^zndK~rU}t0iIMCD#Ly z7-Fu?;a4JN*0HAPL?SmJ(ItDXwR_QfVRYGK3Z={Ez3`utxyGEuU1>~MGG((fGY8t; z$nt4WeTc|IRFqM_u$GnT)r_EfBO|{G6SQRR{uVW}=C{t*Mbd^eLv<)G9xY!;>5!sj zTOtgNltYwm^{)G!lQj?`ICXnJY*|!RhLuuN9M`7TVFvTF!Ohh7Gtr)2daYh4VfUhS zvNaGJjF?z>ad3!rMxj`i{O*D8Sx`n zi6t$JTRxE|7vZ|`TYwW)zEt@m{Ovbuw^}_nxGW_{KDd;Q@aA%ru{0Kr>dbYC-KHrG zOKe|>d8-O?3{trl5{BDGf&*io{Z7Al%AK8^tW{%Jojrf^$k%OR8k7~w>5tI;nuWlm z)fRgMRmw^-5IOD-z)5&~UcUR=h)E={YIc7d1KwqSXr{89L60{=$Aij&yu*4q2z>_I zMEMu;lnhHw@8ti>^pUfIHc&Rs^+ZOfh?}r3w=i>ovEop&9!7|S71H&*i(DQD!6j+_uGb@I!11BzSm2Uv1)4|Trm?|l=`cidff%9;bQi=00c5jf(&LqnwJJR1?fe|<=Ht;$y@Z3z6 z{GedrF<*a6BS!KYbb2m51`0LoUU=^3J?{OgVf*Xu$WcM%&Cp;x4LH5Q0aADUgHobR z?fxyLD-O3s0iPqct|o;J=!QEj{&GO1<-s!ml$6h1?kUjK+N~g6%$_P&CKCCdYqFHb z-)VDte`f}yF2_yx|L*|`obm)GXy!x(?rJZJf9$P)`8R={!e1lp_`d>F|9STQ>uHhW z|G7^@TZ71dn52L2PC{fOQamK$YxI9S+J7J7FyWujRze1|G)?{*#((B70tz^q5wHk; zi2pwE|L2E<2T1zFId|&!Q~%oq`#)3v3j{dlSD#1~{~qgqT!;T35BXOppi+&N+ijno z-{+mFtup}3=LLP{ySf}8lP!D%bF142sq_9EjETunI)@hnomT79@nQu+X=y30v+p4A zx%P5`J`nMT*e*MYCJuz=JM9D|@TylDzV!L>{`GhRJtcsfYiW8K*!S@q?siyBo3ln2 z0)s9^le0fox3xfZITzQSA_^-Q*s3fzC#Ob|ZwvV2Y@i?@AeXPha@3K%L_)tr6g@q; zLqb9T$Wr3sfDD+Mt0Hid_sSFY@`CM+yO3fP5)-R#|SR>3K!rvlK zZ?#>Fe(%?q_&6Fh2Su!@K+{3^Rso)lNq~Pjo z&10tQL)i1-J(wR3<$gyDN+iBEXOFY?pUe6gIf5;*MyZ6-_vZ4Gtu0-f=RJ9`v+F`@ z+~;iI*`-#cjszMU)Hgc|;-KGMPBw^O0}gsY6qbPWFsu+IN!B;SiX)Z`jzWAA0u);2`QiRBeG0L-T$op|G2u3L{%{fJp3Cx^sz28cDrEi4HodQ(#5~2+*ViwQ zp1iox=feMIy>)b(0(5M3bFHgi40#t+2Q_j-OMU&{AH{Xo5E6|AiWeI!bunU3fAs{}I(OCZ&QBSP6}7Y{|x z+s8=eMJf|4{YaX`#azV-h|loA0~lB?4fghQ-q5bb_8^YgVwd^M{#xK47K0c$0xhuw zhjzIfthUyHRP?H%2+9=PHkguOyO+z6L?LUz>20nZJN7LnBopwCU+3gpU_pe zB`wlp&ZOID5{#SOem9CB9)JKY;@#h3&@TQkD8LNI%o=d5eQK~YPmYG>Ss%y?FfjrVK=zNEgC+I{y!R?*A8tuMsfQdsY_e&jHQ6$Y*I9pQgeB;MKUmTf z73BY#@KGyvSXPz~iv$rZ57AHSXkI_5t&!KZj=A%K07^sPv8K6+LwL4m{T$-vfw8+S=L%N^92kuE@eAB==Hr zn=Gba-E5ar9EKO)*0{J`AIl}Pft7}8-6k;SYDU~PMy4Jym3yTuruB&*?oKx`@b5A( zxg3{EORM!i)Jj|QaFT*B_137tl2>K zw|?6fqx?R(=cq_^XQ#vZPf6;pa!q(+hX;a(b=ZWZD{&ra?GwR%(K10P)*k-n=1|Be zwHtPqf@hB>(xuV1w`dJFD?%W?)A?gug4{EV-#NU4{7y2xgQY@!J)sFFR)rrQrf~-+ zRV~9^=ZOMuX1*cs9Ds~fxr2p&mg6uxq ztK=Xwo+%s_U=W-sCRstJvAjp8IT$oN@)D-{sa$;m)3*8!{7vk`YTlqo!RzMviEOV% zZ`!b!ToRh=UBKDt;&WoBcCN5;BtxR#>n;tj%qpy)|8sGMg8mc`g?MFi!A)UM)hU}+ z0@JoiD1pTAMxH6s#Zo>X`ln$-4dez!#FgJqeo9!GSSWAHlSQ4v zJoZMuR)^P}b~*$H$}GgWu8tTwL=-^>(Yc{X&`Gvk2sAjnf*kdvg#|FAAU71ZJ|fh( z%LniWp1Y9m$OA!Fn{XVNn~8L!SF&uc=r+=H65oxd{1|N*KI#%FRH!lLN{`|0#m!W7 zJ0Jb@J)qkf#Nas^8YK#K;UDY}NG>iS{glG(YXlP-H+-$Vzfc4n^EZC7NqigX&NQ{C z7rmBQ)mxQ|qAcpS9c7*^iwA`HdxO@h(gI$%_?nz?Lmx1%OPg&+ao z>+6vsHJlN;N0Vc8ZXr&NSPKgVP*waGiIb4|l6P6&&`Gnm^Mp|@Py#|wTl-unXEa%{ zg935N6Vw5cA^poD+Dggiv8#uy3GR~==8o0JP|C@)5Za`%)k!l)WKI-v=)ncS?@L-I zQ){iv-s|MCoO8Fb!^nweKU<*0#mkA5)_YtuQNw|Gr^fYEP)`Px^4a_#&Suk;8#a2T zVrE-Ceo(PltwHt7cVby~<@P^P>7abyj^TlN8q^zA_8T^;IBbHpvE^kX*)-J;M%U9B zM9P@GW<6XcbfDAl-wziW+(g3cXyW1kDNOsvc0q=8UMUT4OwKb>P}2buG>fdJ z=#yDACJpFHqm9jRVfKO4gO5EPv_IBTgn2dGGDvuB)ohn~4jC8e43saTB3Lh*oN{M6 zjLO{#Y+C!cL^}oPNMP$j&~omqH0E3AkzH7(;$7C-oOr`kBEs7vv|gD8dX`p|uR5{% zMUB-`wLd^u{QM=05&3o(J&R9QxP#^)q@t=>+wr2J&fkN}Fy zvW&TzLX{xti~Sckb{av7T~&4hFq*75G&kO=(Q9|)+tcbcD*GyZ0tFQ+-plaf#LouZ zP~aavC@K$I!AMBgkq*7lRsFUn#L9{*4v0xt{=dF47Qw-wncXa`5Wh_xh@Q|+NokVy zoqsH#DBRbS2I;>QjGuEar)ofciPVwDE8uSwcZ&4P6|CKY6>i@dx=cLdGhzmcFb&!; z3QPRg5t8-qVT2>9M&GwS!i?&3)q8dP-o zJ`;~wSq^sV_j_qE7U+{t70!?r;xxFEd?;kAOx@YYwV0Rqd_>#!13Se4P%@hVTEfS3 zZ6jd-f5R;_&{{_{-09niULor@mo?{y1(o|7s;;fS?e~$C&CfxW4&yB7^i-uJ6}*g${-X<}%X!#apEG(l7#GU}6t7`{C-}A2ZV zDgOTNqGWQbcyp%-k)$QKUeDX^NhFQM2(Ed{O5fxv^kZg4T0+#VOyqHY%uG**xF>h0 z-fe<%n(NreR5}88=0>SzXo81_gmAH%pT}WNI{Wv6LpV7d#qiz*|LkJpcV6P|1gdLk za+S`RE_NXdds4Y9tvP^7gCh^bDQ>w!g2doQK-;u!h>pg>P?5D$=^i2O{&3Q_B!Gq9 zub^Vy(1pHIz0_U%4AKp(}G$}pA|3x?4Hwc3@ky-_TfJot(~VG^z#)? z(gvzCuE!};e|daC$Z9}DUn4OQ2d60wjmXAnL1Lh+~-7MIU=+cS2dd>W@K}=nnngiAGz#CMh>Vr8gTd zNJ_27sw~Y`iK5a2-$yNQStv_OhgE3laDDFvaHP{2?PHeWD&kMm?D>qxZ!=90SZThC z)Ks}&J-!os&f}rVI%*0OB#WU*$>t>|2R~k{L6F1x!DazH@wXj*wSXRq0?@J?&lMs4 z(V?*G^Sgkunva*Ca%z1XpTaNNEMmQ3jHiZ9;VlT3Lqd_OgwN@5q|Un=3*sl&P)}(W z;bLJVzO9pG@~2FO&^SA}?#U5B!82pv=VTm~-SSjGRlPCO08k;y3X`tuB&2J7qB^dn z)Wnw#e%f8~Fl$GY5!Pc>M_070j9(e>g_ATGGG@FX9I=*;fv?e4yX{?ScPMGJ%EC&`V;+;0Dt3nRnOX*UTp`Ldw&8C8+F*f=4sR5E0s@of?@0g$y-rkG^`Y{4 z(F?x}MqoPVXU zA;gjJxBkrP@&2or5}%U-SFF;%(=845>GIQhX{Bnh71~O|hlA0NWgU|k_dF}{CfD=^ z3F65!hW)yhK>3NDBXKNBo=gCy?WYQ;a+x}8$04LV(&V=27248jlS34YLet-7WC&%fE633|OWlVL7((_tN!ByZU62Ua!h54^=Ff%n zIvp@LOa=_GbcQS>x0CWMxrWT>(SK~*4(OpwKw6z17yyeA*wDr4RA~|#D$_WL$6`E% zX6MJ99E)gXVV1YIcN9yz^IizLyE_Z6V|6_+6w@2U7;I)F8cHaKF1!DBeuF1=d2=KB zJHz;gZO$$4mZnG8*EOHQoaK*kO8NfZxuhjXa+^u?ap-QcV*4NdC`UM4wG`&dsd3d|iY&p3+gq?AybLgXr! zGoMZd+-A8n37Tbcw?9(bkhM{8G7E8~LW(fEn0}%=7XFxsb}7U0N3FiD08_WFtMF57 z*WT#$f>x0g0mRS%tNcOCO(sdE%2^~XkSGfz zYIWEO?d>S%INGffH2G-+mUL_ZJ1Ob&dU-{rG}Bsxw=7bTG+cy_rf=!#3BFK1|LL2) z9=HQAunz)u1(D#A7w7&QF&$*ZHSm|;$_xqv3<)FbjFgbk8MHs!eFs9S^}aHb>`Ez? zN%H6w{2e}nE18&~swKhMT~3PZ!a6%R zkxO}bc@k29VsR=1GF_jiPW*QTmrzo=4E31+I~T^fmIlU^6>*P|)>g*lyk zm`fKF^s!QT+nDlfBEW*C_P{s8Ah>;p605G_#g>{q@TJh>{8FwQXncuT@2UB{Ir*(% z9gznw1meeGa~6!J#nmOE5LSr(NtBjkl0f90Gf?!BjELGsVDJI6wd{_jV0JHuD?cYG z_2>m8&L*~7e42m4!5q$aJm-Ex+Voj$H>Ig$&ZNpNn}X>tuc7$RrU9t0e$nh_^^x(i zh7Ainmj80W*&WrUa=x|zc0a+Y5@OQcFFb6jjYmB1psFh+tx=llNg!{pDl+nPaTOSp z8K|5%g$}S=7jMx>55k$sOn```zP{z6Ur|6zM8br95CFS#ehDQg8&rEJdL+l5feSwmNQ!6j?Bk(DUnwzn6ZS zRHxGn0@gehL4MEe2mq=do6LjPA7`Wt3&NGf2WT#;GBa`D-#dGuf0)_W1R-S`{GLD! z^vYech41z{L3BM`6>HAS%8K%B;HcCbbZdl#Lm(nDB=5+}*Ge3ad^)9_N`1K#VYt{D zvGzi{ZW0Fj)MNY?<|WPk2OApW&yc4vMXQ&=p{6YrPn*OY>q_i#6&k@$O-swN=)8(8 zf9UzL?c-bkpt7}ch_)Lh*?2s0=92j2o~^;ddWf22fW`**wAr&~2JPh|h0JK3&;p{W zb0J{b_kdpOnE#Ul7v!FS()u>(iSa2c$*Z}bkShb#hLvUy8Nz=~)6Vt|q}PQ`B3+PF zj{IqDpj6s>5efHp%2+di`5E6fX>ht**(cIWpwh$++|(SG*t!P@+8Fba-1U@jiY)_C zn*Lc+Dshjn+oQnd;1P5#E|2o%HXa}`a)d!O?<31p;@gYKsEi53XYa;sxloOZ`6r&o zPkC;P&%zX*JH)e9>j;_6W|b8~J@UNzUC3fy+%c zT!54s#%Uc}NOLZ_x|ViOZVp6U4jJ*}Q|P*#jcL4&?83~_ITL$cF-U3@38|b#lCyG!21z5`c^EyaDvql#P|;a`zqrXyy>hmJh4|4yvp1;`!qToLc)wic;qdOh9giK&tGBLl&H|)6m z*j>|fN;jKW{p6=#@~?&Rf^KEZy~V{XtRqy4Jc;pjOewUQ+Uy+Vnpl`j8AYe>S8fZ! zs)9e6V`AiRHDGnj_7h;J>yrvl<1D(wD<@Sf764#)I~S3-tH>hcV|H4P4Wv8Kl?g;P z*gqsp73h-#aUhdf>`MRQki_Sucaz z!L@l+mx4d?T|0jre)(@W8Wlc}8%_IpV7=YP@egc1QcA-_pNU5Y2Qhs#qfMYBX~Put z?vlM!Gs4t8R#IwJ$7I+YHZrwX8dZEm5{r}`BG%_}vb7!XrACW+>QWV(U*>E&%ZZQK zq2$woQNY&MECF(LnvYj0tG-ygF%==)zVilXh%DLg*>r`;nwadbCH~x?x7#O6XM9T7V4BL$H9sW@4yJ>M-c_#t zI_t@0z=0$jQ$0k{#fh^rCFZ88lf8CAFwakArqY*HmLKKMtUeECS zUeEX{JiMZEybBU87jgR3oGKeIzSGArA<|H(ipGvle8o~ z5gp2MWC_dT5>-spHv%9IhcTPV;8GCp4j;rfY-3EAQVzVTNa4VA^nZu(30BarzyNr5 z=2;(eWPyj4ody#nMPbT6O0`N9R2=*u&!nkK<}X9>M~@bP2IQ1~gA*bB&2ImP+m*KZ zLvpkK>LUCrWcv>%Cj9LW<4pDF$^8HPRFn)z8W*4(-2L~|{4Z%70_3B)`$vQS-cA4c zE-LOH8b6l1ZuB4F&c8f#WU4=GHH;wP^6aRlCa^&oP_<7tf2J!#31^U2+KlcSVZh|h(mngt>d%K1Ly<%(p`{Ncor}F^`Xjs@F`b;*F zl}7V?*D+LF)_+mXK)?$*0NT^{1M!5*0oWbtMg+(_6WgXu8kv}&2Ebj){|ga&6^DLh z73bt91q})kgScJNz%;V3c}DAohiOtDI2;-L$T#ahO_*F|HO7n$SAPW!+L@h*S1QnQ zVCL8p`g!%KqMzp7?+VqM2jLTzrl$4?dO&*adM^afd%DOBl}qby#HcdoscimeLXgj8 z)+mZ~#11q>2<+<<{z4AK-RkS>9~a}Wm<|f2ksX;F0qIPRU6bib$^0J=5XCY%xO2ci zN^&Ds1VG6owSG?&KP6C`<$AG%^L&3!^B?9qa0?>PFbr_c;|H~hWJqJs%FyK9pNBC1 z##mP{dqBV8&dTq7g>rh9)DL8)gmIzxibg5ZwkR8c}UjS$mU_w|$Y(70wTN!+z%wg$7?+@s-+)|GeIyycJn zEwL~$AW6@CcMKv1i4d{;6tH0S=e$SA{{FQ+6Q^3Q2fI?e;U)gy>XF;^7( z7hS3(!f}7~k!t_ys;tc~x_@n^UVh+O3V2G_^6NWr>=A7cBJFjm$(+OJV1M}%Q0(^# zX8hwB&EyK0h$ZsdX4oY3_FDhIcss`a`lsforC6N2%#BQY^Oz#z7Kvr|&ady{{dP`1 zqu>>EGKPN$hC5s?&5KS?mY?6Pb7og5Nm~S7Zm~@97OLQ)u_k5aEEOiFo^rL}QT(_1 z=_PdPYZkd!S_f=LL4m7(Hki}sl9}7Ec93V&UI;?ShVl^ z0L9_Pg=5173Q(6YeXbuH#=y@H3Y7nW_VoAz5)aaUp6%RMQc~Ab}Ue2pk8)PH;rThL<%? zhhOMFTP*V~dGuw|C|Ybsj5T4{Zh`Fj;cOWZ|C3OnA$tHKd$l2#G3J5#zYL$W*`I-5 z!zCn4pyBYl{KioeciywgdktqKFceSYlo`6bPi|Ez6D6r{X8tI6iHjc_gI{eh5n@q~ zb%xl!wc#j;k8cmy#b0(@4*~l1(G-%1M4$p4?s2ou6yqA8LPA2+2G!K3D-9HqrU6vO zl#N0URa4?iZOa!xvP!g5yF*RpH{_5AEl>tvzq4P%mmuiJ3&>@##dlAs7whio%9ow$ z!1iRq26lS=1odz({}bWT=3fTqKN6}(L%)?r@izFv%T?M7zkq2+{V}eAdDtMy7{GD?guSoe?|~#rOPE7wUmp|Vzuv@Mi7Yaba zQ7H@2!GIOrL-pDQl!Qw{_&i6vM_bkkg_hOzex2ZQ1mux{p))05WNr5pMMucZy2R`I zgHM0FfD&%LUm|dXijWi-*;|8DusEr7%Z3Izv8WmNIfYg|81~EY4~EwfDiK>sQtPrq zr7$F+sjRHoz>^{D?)lV-uK~rP#H6ASTplsub~q{^nQOKE%R5t+9z%VEm8oM$3^qrC zcLrT&^dTXY!HCxKaa^D6ZH1lj-b6^={a!GppS0kQUMv-uhiBe3owg1f_@S0B1eF?v zIm=ZW68b*#TuhBRUi#Ka%ww@L7<9ZCJp6ss%FFXC7#q+#AX3L#Nol0sFuDOOFQCxD>Njla&V?%Q|xz`UItrH}< zM^R!{q&%D{2Q^c;DEH`cFH(;r{Ka9b+=+gg`{42@5*8LFTJXzUe5MrG=y-6%t*SZR z{4&?KMW^+I`uXMd7*PzWLLmhKQ5uxsPlVv_4Jn%Q5z1`&s?Wv(G4aj(DgdV*p!KOw zjZ0dyEgtWYaIjCabl=Ft0mdROv!7qx-I&rYO|}=3YW;=|e0`H5@28KVnVRLx()^x# zh3L)dl8WtZ3FlK3BdAF8fg%#g?Su<+gG`_;7AO!R>*rTM)Rs4-n0%rD7Z{xmc|hu; zH}|fmRRXKNRs)TI2J4Ns9YQ`SL;%V&{QU+=Chs`F-+WM({oyMUKGg&Cu&bR@p(fTb zZpWcEH;{}8iG;s>EHN^>0KktZ%L7`24GjYOUZ6q4g(az*kbb81bB?LodL@ye~L^?#& zyMuf^m8`zo&Kw3%D~aLzcnQO50qn!)axfxn)zZJjX%mgjy4dS>fVkfKfh@gtPw+AC zi%zogV+r$me+)sNuPR{cmLO(C$-A2CVzb}pHcviQ*>fzQ5nM;kY&=ET61v1CG6Fgr z7{B%d*^wFc7D9P^E*)P?e12c_^Yw11zzhpIV3XdN(nTU(6hERO?GvEX%XPmb?Dgqd zWKZ^ai)=x$w5tc3Ic{!Dtx^jFs7L?@Rsjg~N&dic z(D-RP+%BVYq|<__&N{xIfohp7#e{Nbkjkw0vuy0KItf-TSBI$9{K@ODJvpZ@UxL5! zG>P?tJ{4Hp+3@5Q5*9yXoMbnx zw0{|m;*hVAUb7CzN<~rncUIa6`|+=;k1DiTA~-`9E03SILP$SKi3bS`#TPspTaVf979)2+6lRaDA2s0t+S zbhxBf+~W`bQh2&;Ty&dMERVw$K`e@nqG!nC{YoyM!vYr}jYlgk`*6Nq*_!Q-RW|)Bg{V`^ zpw{5alktKiStI34ml`xI3nlo;XsTpah!ImSI_ z(thkzL)+V=vLQO%^+O{ehQ%zQumuT+1y@ghBV|5{H*xj}`z$9&-x_N#v$F_JDthUx zSt8$ik+$A<473RBd=}gcL+k<%x6@)zC5NXy@L!wD5CH@&+GIoBtEmiX&1~rs+r>>* zyvjUhuHL0KdBiJK++F&>yZ-E_0<@S(8WBgdqEeMyqD=)dOJ{>0ehO`d{`%->{Cv5D z{cf@Uv24K=T_Gl?E~J!a*sLc}&*LYuPL7~V+xV!G+mbEqfNj{@+-Bw5`A5-mm`eEpLdgG-FT$QG?)h?+UGHA^jC7jn!!)dxlcfP_ zxu9hrWlxrq7cs}NkfKuH73rF!p+^hMRzblvJ$lEqp)PR_m^Ld2Og~T6q^QW|DkO-} zZC14Mo9F&H04BdBmLan@R9T>e$C0CEwf_93DgG9nP1W^={xq6Hh;D^7_p12vf)u+S zpsc&$@(VJSbFZg}tkFJXe2 z%UY@culb}hq^MM0vjaj+q@Chg`9uPX6 zj3kqE%VaVvx83oCOdN4dkqqDz+{W+)0p}q%(LNO~+dttI5{aDL~?$ z(1wW(pbPKq|C!RYa>gj)(hW-8Dq-ExBF_NaiM7QoWi5i<=M0;4E16S;7N}B`R)3N$ zX1^1jf)cH)M|L7G1Z|1G2>C`M$xmr-E}noCQW&OAT3+$(d$2;q{t?n|U)tu4O(@EO z{TCt@k1Uij@Q21(L8$;?blp7nr0-7rE$>hj;Dh4_`6Bg&&|ve(MFTQuC7yUNf$Bixa`-V_epTl zU?DtK8yV)9ZnDF}iOW=aS;W5sF@ywMm)0KdJKQKtnwTsr$F_&8UJVgVBPNHq$t|FY>78Og}m@)msj7$8=kM5 zdzyq)JT~M;hil43Q5E}JQLI)T`~4`QwIFo71O3Clpp{EiQm5B(vRD5)#yY{aa%TI8 zsODyIrwaieCbvjBRKZ!Px7*%}g{jKz1f^LlWc2C*rVnSKB+1x@FWnVO=4lyg9pZ|M z1#k}>rEBh|VO@-8wxd_sxNqgDYUULj;sCQcKKb8zRs$uty`H`N{=W;VfV;O;IC-{k zt5%+9u|0d*?YYQCc;43Q+&5OTV#Z7hQ|d;2F^z0los+_+(r)5bqh`fJ=3G@{MqYhV z#Ph(BUnkU}-kGbkEb+jw`7UO?wrWmeKB$-uNjFyKZ)%>6tp**Rd! z;lt`yhU;-gEDeX*uWA9m%64bpbXf0}S6m%h*LtfRFGlI@VOAYe$oZ`F@!v!0A&nDWyu&OoysnokN!d2LaX<>N~M<4Ln0yT$|(PbmI)vz zwtM%H*{a0h_Dru0K9*T2xe->_Yqlcm+}Q(*s_jMShfOmo?IP>>Yw%0^%fxbB<#TNI zgv&;UpA>K*NycYWPvlFgtY8#91Jf{ez2fi%2={&xcE5}@!llzEn_r3KSIWh2I_LFF ztL$Z783(@dL>6ng9p7qu(T~t49B`D9o>h2eMvX)?{aa!!Bmi1mGDq$6c`LEEzR0UW zGLJJ60eNN8rVBZ|n%hi|Gq+)@BB7uAh zZL!Z!S@};*l6m(Eb`f^DVPq|3C=YYN5UcYO4~)F5ks@Y%aXJKhC+h*;TwQ+)c*o$Vh+Y)^f{pIvQz!4=!(d(FK}qV^bD(LJAkiJ96H8dd8`a(mKVG<4 z&1x9|=50`#09X&U2|@tTcscfzH8!~U~h&Xt(VI2~JlSN0bb&kmg(7wL12K|2iXtVDtG^w=w zeYy_mw6*h9k?(b4F2}>-Nzq3bE|F0Wj-j+1cc?PAqbXZktK?@uZLV`(5;*OH@YyY& zX0sWOc~g1o*^CTf{C*|xn=*%d2EPJfr+?8qlyZinnuOVuk}|6HD%qPou$ZPP6~K1p zqO$;1msAdEsCnWpyLFf22qd#7X-541Ej<1@7nf`K4ZmQSF<=K(v{a|Yn^#u@Rok1p zQ2&_IhH_*MpT#SK#eKlc%P<30!AGaZ@(-21oh~LE4k)y4sBW)Z_|h>Fm|9H3X47(u zA>*SBOxgC^Xs{tephuy6Rtym}6iHUmmdpmA_7^o+ombq1YiHU1{FWnH3e0_0N%l=` zUSOAs4wO@Snch_O@|5_H3Tj?Ng{j%(xE}k?-;ju5ji|FVp_z<5dm@oB^TDUc(MxQj zNQ6hq=T_oBSL(|xEUwo{4w=ZX>`>{6Fe{{vfl2tJX1Iz6xtg>^W{P!|oHeX2W5ySw zR|4Fz;<7LS&ll|G$)7)_SDg+v{nR%_hlkVi<}fNNrBz*a=FDHOi=z!)Ey>Tu!W4AX z&UoEZd*$7ZD-E+TH}r%mw_di1sh{NY5-6=AP@24-^q*@G*dFH(6r~Y>f5)|yY_DT20y2bF; zA`^I>rEJ7vGE97#xmDY8!mu_kxw1O1A`#QksX&_2Q0H?$Q%)>h%n(J2wW5EHJ6`;b z%NCvla6ey?vxJ63S1G^?d?dogwjRr8z{VrZE;C{|v)+9H%B3Qk3YaR^ORLG*6HBJ0 zkKA;C445;WbB^GPbl49J^y0|WB)~WrI!1|wAf*NaS*-6&zE)J#ze$A!=!}{37W={* zPF#o!W>SY$HJa@SuNFhvF={`v&NpQY4TaNc0raS5Y$&EpUNOSkMPGmJxo}A-W=I4% zk8gvY1lNWm=yXSfp9`yU zP{~}*ghG)fq_BcAKNYLglf%BwS2|cz2PXQqz&-h3+6#VW_mJw+IPRD8iRtk zSJrjw+ObhFtKw8_r@|H6wr$(CZQH2WwvCEWv31t-ynDB^_xalQFPUx3ImVhAWA=XE zS1baxtwS1E!%5_=f>_Q2ld`8_99I8JSL1@KNnlVv`jP{XLAd>SeaFnRRDWn+XC-Y$XJTt9?={at|5Ww!hnPsTS# zxnLU6eI$(+7#$t`XqR`-gHD?Y_mZ!$ZCp-hj^R^&U|2ze&QPW>bSqbDV_l|IPb@OP zs_YWUC9F`=PWfdn^}dmeMyuP73!Kf#GbpHT)8Yq`wnSD86AHv`v8F{67gdE)TTS5umEPXE#LRyS;%a0w&*;4o^7)AjSuph!;ZF7V1m z93yHE>3Uo0;VzB&F=#f-c~D-&ocMLWmiW6KhFm5cX~Xp|<}Fa0x)6>^D_f*|y51NY zrXuar>RKcE*=-hnL;Ih!4FZ@)xYgJ)n(#WRwL&Q=*vI-(KycyuIfy>Z=`0SmFgT<} zfuE$(4}vTxNCx8=7lA~xK>0|#`*dVe+p<7f^Vo&%QV@YpS5Q7yWLH1 zyCFZx_2Bucs?2%Biv-OH?WC9z2~pPct2a|xH5LsldUcM72q7cN+1a0@dG)k6;zpFa zis33~Ln=V@8K|KL+wv-AaW&r~)Ep4w8$PF62^>LTJs5AjdB>7x>aa&bQwy+AUaK!sJh+#ZV-F)lH@K|!0v z1#M>id}e3LRhtY^0sJ`PsW8b*6pBu7`F;{CIyhBhvuVJr0FkYY|HdS4NXooNWC;Y>6aQwVP7Q#AAr+MQ4<>cW*}hkis(HZh^4;W~CS1gGtIL}?i9$yTFb(wO&YFIY$>x9sYDEiyQ%O=u zNWtFGFrnPIV0q*0m2%NhxOE-@S$y%Xn6+lB5}m#i4^>pt&v-FyC83s`UZQ|^#k^tP z+|897Fu8NeR{1992)gf?1~l>7-4=*6YE4Qs^%iReW$J|)(+&$Jlfc<$33->YpG7z$ zMZ(E6hBn?h2pLVc>r)oun5)S)wFzJM-=z4nG0Lo@5p%)O*mqVr^r>eYk^W=}0~B?H z00{3=E6fd!9v@OA%4F5`1TSs>jNu;nKVrg~B;0mKE>hWrK484x7yjfiE$P*>u!s8l zE-|jk2A#qtw85uwKlNYwGXA_|=2We0DVhF$H)&GED>hjyorOS`R|+6*c%a4#CYgv@ zNidhizytDSSz~$R!OOL$x4n=MJt}+jYH~I)ezVn95#8e4jUJU%`ef`tJ1*1V+@*^6 zO4&paHL&P*4;Km-9Uz!1^p7;2by2R!Ta0?PR6tEI1}7<{jaJ0R&9lon%`A){OI{0k z3iohhvp5CCWiq(1I9*(u{&N@gT5b?tchqUnNaOO(-{WX@xlL3_#0lk#qaHT>=sK!w5sas$e8Vj4?asr# z-xCm>XGH^Mb;Y6I=1 z`H;m_@_9I1bSqh@9$QZUaL#ya7-$F=J6Nwz(M{`dCLh-~XnNm%*jHA^5ApNN`o?L1 zZ~r6y_Ctv+r1I4>(wb+&r7HU9az1C<9K^3qs!XE!Q5NTNHMsYItkmc<7g_rOobsVaFcTl;bOnMJUCC<;Jyd3_~BjV7PP z>r8h*=X}o3gu|-I!s>-o(rqTc?GbPoK^%oBUp>4UFIG^^fB&E$*8J^-aYNYf9}5%l z_pG-6it{0XGSRA}Jn8m~^+n@ynTuE{y^bPfmGA6Gz}cW@_KJ;rQ=FI9@Wg+hAqqc! zz<=P95r|k5tQm99jCmj1@~FyuKYoRdI*>vMHMfpXs?=6c{XzJOPyMJ!R1fqaoax-g zTd(`Z%io3s8T=vHaG%8OTF{r#!cp{&&!UWIMklR2%q#XdW@wpPeNx)eaU9B_*u~~` znoHL?h35ABu#fgJCV1hu#8O4Jed+Wjx1Im{N%oi0E%M-LsXA3LYC6cB`LLe(D;=+} z9+vXL(hoVx{M@v)mw!MNKaDpx-lnjYLFFKjn!9ff^Y4XKMQ?HUn zNq&IzoX5HT3hDi6dT^(3VCXFjry%?Woa7#Oxg>woZiza^%T}UmuX+nGdoNf%kG^Kj zBb1c7`l%FdY=#&hqw}P{$B(J1-fk2Vs@|xNrpmv5$NuG&v|T^q`S}tiVX3%FZhXqk|D87dwN|I2=7Q;W&3(MED|q3EIsEXjXv$-Ct(=qb?M~?@ zAGg!;&w>nQ-~6Zvc%Ht*d!+dVGpogYVD@G7+`I?cOam@KxzUD%2oPV?9B3lW+fXL3 z)Civ}fzt+m=W(7qXQT8Nc50)!<0a=m5nWW!d2$Q zGC0Wfe00{P+S|+0vv>Kt`n5BJ3`n`O2ic+4A@lUSOKX6+L+y07Z9T;p@;h1Rtubk1r&)pPqLjpAKy9 z8k5~H?(UuwhI0rE!y8g%%#jq`T^A521%$$VR|MFts_#5so7BPBPu9Yo*^KC?YB(S4 zRK(}?Etyh-a+>ALsohW!Ff{S(xrrIb*bifp*7`crx82#I7=ucHK7~}T{hR#QvCPD4r^VmJ?}azk57fdVP%-N{Jpt# zL%CFb;Z^=_EMWusoO=K1w)dZH*Lwz`SIt6tgC@qb|1x2Rhx>^G!{16D8!M>Y*`6|6 z{>dGS{^%653zdeAgzeGERlzZ`3;T9b#5o;(V$T=1+G+eeqPjJk>Il$gCp_+GRXe`w z7r|f;Q5V}F4aQQ4(Wvv$s&Ik!KZ<~t+eX0VvmVzCG9R#Ln%o+0A z;krHFKv8x6NgS)CWx{g4`qLvxX}Uu+m`FgXFK`ERSu@o&ut4wl5xNEXG-e{}hTfT( zNDAkk(kIwa%v<38q-ads?}UsV!7=6dIuNEJI!lganb@Tcdk3PU1!0_(L{A z2|Tijtd~VyLJo3nU03*;c;Nu)mV>F#8Alai%Dg9%?H?%%J4fpY?uo(E&0kz#B68>8{Jw;E|HLfgk zAO8sFHrzvrZ`5kT-OVQK`hy%yJJ_>>|0Fb2Pq6^D=*%>WU>C?C0KE%{FgB6NM5z8W zv#}c+5RL7dMLFYlK4|3x#^*;v$@_h}ef&-<^ltCf`9BYonxrGkFM(p2*?LRl3b=(G zzKlP|rVkdxFlgx?21Z7NcLxT-aOcks3GOr{n*LJhOo9@go^>rPA$fZ5czZ`ssdT!* z+MbW$J@7yrXCQQIt$7;eAAm9n1za`B;JT5{Mx!Ryo+1!miu*1F3+A;8p*yG5t`dFb z073+}cyw__HB1-}88uFGc0i)_{8ch^x=<3_WWEsQa!KIt?|=RJ<)2c-8*BRmsPYG~ z*97JmvAIa+$%g6N9Y*6xI)JRggml^^$y6Fp>sk6%tMvJA0mrV=qz|b4?0YSvvS+Ew63nQ>Jo=m7*p|rn={T=saresgG>Q^hv$|qAnvUmBK>IJH$HH(I6k0Uv)5(zc z0K+p9Nz?KW(9vswh+eyqwek*;=Vx2fl%_k8}9ZYH3DkrxHeZ^uO^ zlUZfWfq(Xbh>WA=3aQ{Mr7X`Lo0evpvu2t;1h^oM zn}^8{?md#I^yS|@v934U=Io_%5o;+a7qwwBh@NFcRpVw`rzm+@8#JiBGC3dwj~4=jxI4Y zxG5n-L!K+mz#7OhAnQM}p8|xG(1!0mr;BY811p9iCAntGe;3@|N+vn|KO**QJo)E9Rq2b+owJ9-|7dwi&_rcZ^-giTu z!gf;n8_7ySIAH*267<`knfef|DXT%j`8gRyx$QX;a5V;rTM)Cg%-;|(%wtuqR*gBE z>P>|%?KWL?it9*eOCji0YQrO(q-ETpL=aOHMf`@^UZ5v-KvJ%)Ql$eQnOgIWY2ADN zV^RDMBudKPQ;E;^gHk+gMxkL!jwHn|0kI@L5zb&H{&*(4_P+ zulvN6vsoWl^B(+RC`>{Gnttqbz^0_6ybiWS|GVTOjr0>Azm=hyHyt^Q6Jm_BX@Ru2I?O_rQWViwWJy*Hx4Huu5Tq?#jFU2wPX0jpLXtRAz0D8 zcaY2#09aARtp@UOU=dA%d=J1`f#`?c{5v=lv2d2qBKhP99pcFBv?q*rIqC~noAxrv z+xg@pNuA%5%;qiiO8!paG3Ny-=_ zVbUvncfOyTlg>=FFL=B;<rD`>pwZ;eNQl)ZyhI363 zEGco#z8TO)|d28{g=UVuUrK&8VK&*LyUePglS6mv(& z=Hl_=aC>H;(XPj(h>mwLUoJwK%;o{u!~ic|xY-ohglg}!wx{qJiA5oFQ&D;`&q{US zm%a=T7wVzA?RgDCE}IRS+f&BpDE8K6zeQCD?u|jOi1PmNA$-jsfin0nn#?~Js291t z@rvX$1P22U`c5O@nl!`OV@p^jGArV;#4|B^a1sk8RkB4FewUNLr84>#$LR@DylKzxkVp%l>N@_(Y({*u-3=<{0~pc}3NiDB?l@pv=e`^PpGw>D zasr@fV5n(ogn4!0T;tzEGf<)ffY14J>s5EXNAB!70C#<+#!MpSOJP+5pfb3TwnEjC z76+`J%8dntQNeODmx?nzi#X@}2gi8!^Z7ow9njGtA3kD9@FCM=z61M%*MsJ$82y)W zr4pu*%YNG&m*rNkSw(0pKDezd0f+Ams!zEhUzu8?L-})mHFGaNz#vE63U(@RU~@;H ztu-@@-^w5xe^SvHl33CMe$3MgRo;;@f<7HWGI&x)S}N{cQ*BS{nV`944uc5~3DBqq zgNRwuZi18^B>^uK#5DPUSSAQ&S3A}>89!Vc;lMdQg?sdlIu*a5C!^MU82*TM{DY{ch%54DusLs)_z}BH1{d6FsB7$LvEd$dDfB!hS0RZ>O5CljuSeXggggqE)a~$e!zUUv zIMo5Lz(t{C4H7XW{Gfq8_d=1Z^AMNkMaXK1>9+>fdkihd?ygv;| z-gGA|n{PD)yIq@Kcn$(Z`x42OG$HI||615cq=!`hT`KtCLfn_^yqLSp;C&FmU=ug+ z88PN4f%{Kwxb!OB_Z2pH-+53dYAkf>0-m8aJAst5QCqmc)X~O;)a_Dan{%&lodzp1 z8l4uwltKxsrqOV3lW6dF8}0>Pi?%Bw@jDQ28ZDNWHvo{B_su zS9+N=Zy?k&uwLq6PDmQ~T!wNzUB>UE&0UHF%_BXWui&(~aBR1w4RwJ$(&$WJBokYL zm8`n&KjTiI0=fVa&!`i_-VBH{-FB%zI{$8W60=aicHzAiGy$2JH^L(`GrDF>qf#=O z6Lzl`?i~K^sAH-$mdlfJ?FPa?&9p&OYbN?M{vYWtFmN&M^G4qS{AY<=N@oQQa!B`E zUItk4Dh=?=DnahO#7y+ZVb3sbV4sE|L?VSDv>UGcK&>U?jIF-D$M;5@#d$17dV8QR zY~N&UA5yN>WolJw!0s0UJj`rjY;ZMI2@R`73NH|HE+kikR@@)}RyF(yH z6BdR(sIxsdKKaT}=txg47;5iJ560CKp2*e~95SFla4uv)))&Eql9}{i`MyT@a{x#e z5?prGUJkbyT<2Y{2x#!O+iLuB3ojB z1`ZYQBOwqlLZ+A8nm`l}VU7Iu_(MwsV^Mvf#0|(8ZcG-hLSo``1xH&ObpHTGk`aJ~ zfd^vO=#eG*e)b>EE71Q1pl`u`_pCjz@<=8BFGM>^~t%HUO8mzjdj6HSK(^ z`zYD-v7ltBbgEz$%O5<`JU(JfKl^M+qEEeLCn2xA&(Imkk5Y)CX%2IX#RgK=Bm|kF zrll^$i{-8>YXcj?dX+J8;QgF$Li7}yh|)@DGL>3J-@-&8e&3&v1dtlfU7!3u57Hx!4drVRPso-xU8m5c_8}?``d7`fq-35C=5g23p!tnx=}9T`cSP zZ4XUP?BariQ(z~}c+vkD;{R*`95Ws?x_}Cv zX_D9fXPp1NfkEt_o&960T;lp=e@`5j_avQ?jo6NT#J~Y}{!~u3_B=*6I-SLX<#MrJ=n?>cdJL5(2`xXQgwDW+i46-18>LW*V{1O; zdzrP!NlqxV+r4t!y*aOq8(K%Tx~3;WN5w>%o5RP(DfVM2mqMFQo>$rH<(u-){qbY> z>KHi~9!p}@T}Vg>gmyg4tZ+jPvs6;G&2Qq&+2VM)SP?pn)4D+;C!c^+30PdvxoR=W;d_i4i>TwsctK8~)RNid7wQ?GB5+Z&&}(D(2q4LM{K7T8Sj|MD!^F3#zOazhK=Q4{#`-;Tkf>xce*2>SlS2cx7u3?x!C=wYs_ zU}Ns-0Q>PIJF^!%Go`MgZDz_f54g_H6C@y{(LYu6cyL`-t zlME>fxSR!+LV%W+muGO}=fk$<)4Dp9%{_$Zc)T#YwAE<`NoP_&-%>ST>jbXoFC2MB zA=)~g{(_s6g=?kIhCn@>lOM^6FRS{=a!6S^XFl|t7$Az7S9L&9L$J;vp_TTRGn)p# z;Nal_(iO<`pJHeQb6SFKKNo;^f9^2|rRC=@mAG*h8{au3Z4ZV@KQXVX>%}H}K-%#^ zSf*b2Gfm(J+1kN*CBGWiGvfiB4d`R#`2KMA-vwtt<+49Ow0FbxDp;f`f3Y3FZHLXS zF`6j(KH(tW0N3znI1D5fnPSVX{H6)zYQ8*p&OCAFj@b#=PGqn15q&U&fgg4fyJ!3q z2^FUu<#oTqc+BmZktude9G9caa}U6vvrSaQTfE4HZFv~_r9Y#V;A z;6deRBFzc##xZG|Fw}A%^!WV#3cthSwV=u3b&ScDWW&R2bJ%OzJ~l23sCo_(E4$uJ!|6yqvqlb2}OSn3|wlV2qM$VJYW9m zm)s&7kZ6`lNYvsSO1FD_JQ4x4D1r}!B83D%!tswM+2=m>&|r~O5^hvz|8%>##YoG{ z9Qe>wjbHN>rLOSP^@(9*HJ*k(INwFshma8ft124i8z!m^|_g6WL$IdHi%$p)sQ- zpsLiC(5SMwL8M%v1Vn3#OTLkrEYyDYxCr&z%Q;D!5j~W;Nd?<7`Z6{f^gpTP!jba7 zr#V|4{Yl|}9&)aG2uBn2RO>B(?0p0SUJp^^3YJliTqjhvU%!t?v^Ebh&tcjl)%kyh z3hE`QZvT3I9$R3rr~*GPR2oCAv#*9%Q$PKSR@wPwVBDkd9132nAsehp;9FN17kWNt zL1p6~WttNkOMj2YlJpX$u-z~;JzFFX-o2{lBaZglYZdMJ{TJafr?OcRqz3W?w8`ng z+)(LM7GlTK?*?A3d?=UU#W60}y7#=V2Cby304reZWv_2wB#zBm!_DCfb7qG0i^t~> zw&_QGRy4Dtnq}Hzk9tCEIyyK-fR%!s@)s|LfQs)nnd`*FlMdjK<}_cgh6Xkxq9(v< z_eyS5&Y1$Q(xte-&L!IdoKzt2OB9bf;G)M}pU>+Z2I#?*%kTWe12`Rh1rSQ!(O7CC z0!^cNz)Co~zdgB)aqzvruJJG*y+QD)yeAhj`7dQScURA3t#ZB(V+2ijZtbqDd}9zd zh5*M*@(VCN3|;_+W_!=sZ3(S2SnM9=)sIjya}$-feQ)-bzihW6vQ7H_sOqNiV@3p6 zd4)G6vYxT<^S3ZCDDllzLi_gi6;mnh;s;OWJJDKl)c<8JYGez>wQlSi%C`B2iVnNX zIp2GISlm0Wp-6psdJ5Tm#%{t}e>k4v-^JZJoT_|HKOsCuH5!A%2OIN)uMgYjd|kM1 zI*oCAa;3EIWrIHdrdPP?v{U}Oo>Xnft5f2IHM#)X8omEI1aLJG{rxKy`Zrv|L1Avo zJIHY1Fsnr0Tr$ZQ{Y&wLICVf3o!0Bs@(UJ(`uwL-g-)b)kcl+j0P3+jl)FI9kN23! zBV;R^=(j`v5FQ7A>_#6E;&0CL^ zT;YgT+s6StdOXa;;B7#au}_{oW}C{qjdxa&fwQ z568QVpDRb!_AMmtZlguAxMEmw2s|d8|3hX=9d8Ov7V=aEi^1vh`&;T^ff0sLDvc&= z<#L6K`s2ka+&}0F-GMJD}^%0&&5hDgmH{1#DU|BD2xm9 ziTLyDg9mn#82w~A+JmWh*jtm`=DhNRswUMXl@OQ?N5hV8LEU5Y+uqQUcPw(9dM;*4)ufrwJE5Cb=dyq8FlV0j zCT3t>jUk;Y(F4zn;RQ)EI;&s6VV2RoT_TT~<1J%;-TFnkUI)J(;k_flh9(3%@GG;p z7xQrvGbhdLbnTAN>#lm=A}yF~?{H@;7rz0;5YW4S50N3S-OUwyI_+ZL2Y=lT5f*s1 zAz6?#&*j4-?+vu-R=JrSbA^Y1(fn2Aa9CNJuJ@@6e+mCyj zS>?FmZiVE_k#8}YE7U-}puB!=m<&~(_+$uvoqXNnzy zZ(gpoaz|HO>SCHLuBh`~0k5pJmGd@t?)y8}^s$8RAJSpZkN79}qe7g@`Da#t_dVvF zobs@OesO}L=>9P1pb*n;Vk_$BBe_GkemlbqL%M-X#6Lk(>&$7QwLnnN1WdB zLYleRklLvyex{{WWWi!-r5=zwTO-u?goF(33$K*jC9B!%{O}FL`kfLKBFb-}h*l?K z+c#{jBkA*jhw&Xz^>3GdX6z18N??Vxo*jkeKs_s1P31+0Wya)L<0qPI?qpB6F0zi7 z$l^6cOG)09vxubQQN$m-ZwSTqJQ_U`_V&y~(i%^RD>)6U2XD1M;^0?&nsV};owyoV z1iMyIAKvJLCfd5E^^B2zs9tB6K?A)HxEd{&qZ(%&Hw7bgT4*YP)Y)ouSm!N8x!ipyw3$=@|r-FyKYKmYSJ8@@H?! zR0LXd_)NV(yN@zqdRS)0z%v20DNC$6y@*gWL6WXIu+D!ZXs{PhL>}aP!*vESn`Cld zaHV0hn*jjLG{&anix58%a31E-R@cb@9x%VyCOoFYO}0`#qvRls^sYyWNiAm~jciZ^ zgewJt;YahL8?c0+HlFH!Wblr%Cw>2OuqW%fVz7_( zrCvSYCn8b9P2P~*XUeMfGgS$$o!Hofl6xDQ^ccv$fyrcu3>T?ddjrndz23n|lYR!q z;y(BW(U@$%dZfhF_wS}skhk*8Lc~+kr_vSDu1sV#>zg9dB$X3co=*f2=z!GOLReu9 z-T9{vtlS%<9AA*{BV{b^mG;%_*f-zYa2Fa;nANrGPDyhizu&yIf%haTth-#0M`bmF zixDO(AZk_F4qs)qNWa2HYU?lMMDpjaHO;kcN9)IQ9q}|i-D}t7wnoBsudmPlzCVgd zo8s-x;XUW;z9eBewl?fR-L&(jF8NgkL&Wl#^=wVfU6<#l;ay2_o;6*YPC;|m^VwVF|eS4cPmk_=eo!Rftap!R>e9v;|uDL+a&sIJ^trnlrU0bd*1 zO-`J^%z3=DRsEfo*>)4GhTkk8xi*XsXP@zEJ{xWMl z=)Y>hI|M5#habr1^8j6-%S$tfHUmd{W5Y0I?0X^V9t?B7atKt^Q-AMZD zMhT~OA(<9!5yIV~o@x4oq!$Vorf&NWQv9N7n`iIDg?zCfQ6})<)gnZ^{t2!g{&} z4r-mqfAd9dhYMS+5<|yp_Q_=%`y^4C=OHRmse`zUbs?jvygRq^Ok#R*OKLb^?%1;Q zwzM}7Kv?ApDaqE0$`{p}$BHjW=&cLSZ=QwUcF8lSZ-hE-em$7UBeHQl?jf`KR64r` zbjb2Gc-@v4$1++QYDNrriU3 ztLca-~S3 z!7P3sq1pQws;6fW;@w>0xJ~xkjuZHx@QJA*f4!o&$t`iGy-uFpCryPq2Ym(DUit5= zur&fugTf~(oI@$Ta?8rQV9ViDg!S35Su5Dpa9|77P5DeTl=mA~433!xPp_%aAcw|QboYdy`-o1`Gd|Dx`FQJXp2Y7P1d98*?ITl% zRI*_xWEKZK8p8FbSL+gzGQi;@t1g@8AZ9iP#1ilcjG+$g?eb1dL1%OINxXJ{IbG(S zg+r=yx%}8biOCCjd?kqf*6zI6LJJpT83SUTejugB{{1%;xT#hC(WFLXQ^cBlU4ip~ zs;g~^ZiSpoTPUV@Qy$g=&BcoSgFF#6i3KKn-sAW$X^X`SoO)*zb2f3D+3NIHu6r;I zvANc4-N4xpmpv~wv-0GWYVZNZmIhxv7$rdgm$gBu>~s3qDS!ND#OUbt zSQq~Rv-D)-H@8CL1@4wdFZD>a@4HLq>~dv#pd9u>+F|?Wq$^kH*1EfkP)ixyjx{W^ z7G^$b$JhAd%To|MrC8C98uvBT3WZ3OE48jO90M0-=M20K@oI6!i1|FFSNzjeIQa}U z1Ur9TLzk7jU`Q$R{?;V6>JNNYTH$s^37pd@9Bm3!iZ!I&t6Z_M3o{$VpwNi;SX;6l%~yQX&4kX#a2PIrt?T(P zy&B@AaFr^|jkU?a&#*Xq4`ol74YlpHrSncE zs`B0Z*f*R0mA^ZH=(tW7C4GE5z-;rGZ#SGzl|#L3kYGng&*ydAvGlxU|6alnLgzJq z!k=_=+VPX!W=|)-#|Ft#xVXYd@L8B=78?@-x}LF$3i+tzdsjZ&aCRv{8@{th{Vh?< z1_ye>(s(iSGoeG9c`xht2BEa4S8&y$r65DEwqTEeY!{dpd$N@9za*R9hbKONU{T)M zz@kSQec;)%d*_<5618jH`_m*_b1|^&&Gw0s=6C|=zct_H?aED;r0`S%ytv&j!{ub2 z@IpfMjmeAO9L#h`lfu!=>ItJ5?Zc^6yWa4Tupp}7eEiz!{;a?pVo!%3E;yI)n#*8A zNp5DxiCnhL#?;`+0s%){e6sJ2SopZZ?5Q7Hu17Tt%QmpFgNU>D8fB`bGhi{#BWN}r zb&kh7)WVsv2a!#m^N!LFe;jMCvuU;W`jcywvhkP<(6KNv-(GI4?_Z-Mc70@Od%e#y zLq1;GW%dh545qo~N21?Ydw8keSZnF9PTxqT^@)G+Ir_Yj!+3kto?}?zJ%tacZ{;qG zk7&qhh2bjy)$D1iaHlov6@K|bjVSbav(J&#tY>NkJ#7oiy$WKIcqYifU~X;RTAF63 z8V!A8Wb2Xp+vr@Tp~-cvRdSZ;cH}!KPZ5iRxc>`_9cvvbOPf4N9Bt<{v(bZhBh>M4 zqJ#qqpANh-7=1OyE6lGRh2+@TR0^*~FV|3F{Lm2vIB!R7Gb}rc{3Z_hSbKXiubsIw z3Co>NP*AN?IAyi13KwTigjAx%=&-QeSw5AM&}H}@A9uLJkfgl3GUeKM2GzHEq|Ic@ zm3G~n5cVBfW*r9-ORc%*#CBsNb*&05GMAjdkeDRe6;@`VD?aTJ4!ghI*V84oWGET9 z@b2#!l}llVfVeymFKW`6wWcuxaZ!Kl<+ZqVECp9}316ktU*{>lE!Zb#8!3e=tAUbTpC5wdV3 zI9_{B@VP%~xm{Up|JE*Lb4Uh$W9^j$*&)w9#Os(kwW1$jK{Ow{2L>F5 z9L#q4Jpj&ch^NRMnzj#NX(59d&7vn0?~W7&d8?;RaX!v**KE38`?C4ES*$gh{X!nj z1u*V|#S^($6KlSP`Iy!|4hz?DX5yx$O8F-aEcG|+$zPF)UvXYZt#Y|RDx4h+I>1?} z(fu9IM=UOeS#jIcmX(w?IOpkYlw_4~5SDXg(J@kmTo`7J`tJ zy}k$jZRazSq znu0UZlgVAmFMNNqEMkPTWxR>2LUS13CjAp(Ef}68<>9%P=JCh3)I`n{+5#HX(}H+1 zNl2z78v9za%1T?G(Jt`at`=^~oDwO;QI1LFLTb7T_V@1g?~|9W zW3N6IEYFF1jWy7({ePiJ;4Md64k}wL@{m^(XG%W5c{%=Ea5Kq%N_a_*fDXHL49!K0 zWWKC34&~IF>(!z7WTe8fi0SI3h$dU*=rP7M%m0RUP`431-aswtrv_?qj*ki$CCB6YdGyHzP<6y zEg2(F_|Kf)nhP5%XuY{Z3FFT+K6>isyP4d{D%pz3yM_XHCxe%fh>_ieZC+lvb`NV8 zF_RV}8){K**DGV*IwdyiTcMNf=0puvK|EUZX_ZlCrDz&y22vJuo1JcW)9Gx}&+{bF zu&IvL%BBk^D;RW)vA*u1tKI3FT#JSJF~uyGBo{t{YaJgqA+fm>jQf(}z5)LEV8T_;5FJd6es>Dm!J!KU z#qhdt!`LSIxY3DMICJ=bj0|*U_5@t1ECo~TGY&smAUKLP8ydHt#~QEF1ohnAL@^r) zzz_G(joyA@u#k9+Db8*~QB0c5U>e4dXNCKdvF-NjT0qOloFHqPGAN>*I-wD##m64s zW*@7i+F+&DMUq|e0n==K$VylODG*FQ4#L^b;~V*oN5p9aQudAJ0D|;|$sP2)6!$NL zuRi9mM$>UI1W2gBr@sgj%q^Z1EE)jg`rZx)KFBN}7=i*PXGAxc*%lW**$AizE^OlV zhEQk9C)6b>AVd4zTQ}`oyv3CGlUHeC8WKD`mr?t;<=deuj|qAU#@n zoJco!WJ^wog`M}C5me9+(&u~OooFS9$){4elTTZ>^n#W=)u@E7nHi;@o*ETeJTPkr z?;}L|EkRFAs9W+w$ma}VQJ7KXv>Ru!o~1n z@~C2_UzkH2Tmk~$KFH6|aV?4|ng_Bx!ptXXpH-Ws^-zvqGJYN+fUX9rN83>C&MLCU zPyTlr;y3%;SD1#LEDNxg2UJ3ZVInGK4*T4sN4u&Bewo<5DiuDl9cxbN7$jIff`P^c z7T8!)A&KzU;?MA+0IQP)=H2E_R_aD8Zg?8pSYz`Wz8PU@qKhT6qtXoTB;`aNsnIBpJTPaEZxE{(^X(`l+3`EQOK613pH$l3ZqdVSNDCP;P&Dr((bA|qUWEQ z1=X3$WU#Sl>!%~8pLSlCrq9ody497ph)e*}C?ZQMgQ65!XaRv9#z{Hll%0BS%`_gz z43Y1E@o(@Aop|YLafqHx{@y#yunlOb7oowLGK_WkxotPowq+4BD6~@`)%iv}@Gp4L zSd+1tD|8bO=G;!O6M8tUgk(92I1nQEv)eJC)aKxo=riJU)f2C=5TfT618R3V6iQX1 zdx8=NUmDGoXKz0-jAV6vLwu^KAcqP+nDd4D@aK;#^mUr5tyyu&7!3Q9PVIK{&az+b z_p*B`I2N4G+J1sPO}qJ>7r1^y!K7tjmPiNFKp2B>UbnnWpwb3vEoQj_mcBIUG7N|m zGf{*6GT~V5_3m)D8i^(ew)~5Sz6JxT+`z-nW?%1i-IMqIl1MNjj*TOPD#rn8SO;gW z4i6M5pXUKI(GvBCGC929Kq0oDUoU@MQ&Ui)S!)hwqR8n)#aJN3n zwWRfC73pCF5wC&!6Nkyv;su8F4h89t*`}`#hTf7Wu&8sJ6|TCG+6>r!E&`H<6)lyx z^Y$Giu*@#}D2{cw%#Dhz5pU9(>Wh-e8q}W!roNO*UkY|{Z?7o|-faTHa!+KVam8<0 z$#Rvqp_5;U`XY!3CY;We=}p+VMxd4)DHNq?&qKYDAPjHy`wP;uEgS`^!G6Te;vC)~ zDx{VnFF%T^F}@soOqPw#p8{)~IY}!M7}#%|fXF^GaY@F8l4sEOo`_e_@Jg zir@XY>@a3{@9s`+o;iDli9(rD1O8f-6~_|ZPE}`vcXD05OyS&KifXd+4F1y15ez-^ zNE0NzH484upG$n&km~cKao4667I5@Gb`rCvgT@vh5KHsn8qi1T#V1<$?Wt*LCiU+} z_kek9z-Sy%*99kzLW%cOr4?5g+Hi+6pxy#UuXhu*VSz@q92Y!;S!fskGzg7qG@>US ze0?RsWhRE;&k^|^d6A4Un7`{v*%FbjR>LC^QNmB3Y|))p7ep$4b##Tpuw}p!N}|AP z*F^X^#48kvj>t#F(2}3i;KvCtU-2d$aicf*G0)DyUDF&^6i|ijSV;Z)p0KPev6%C& z6Mn!pTl|3bCrvd^U0uDeD^nG)FriV-cS@r$$9AR`Z&7e&Z@M{IDDi!kr)}YfmDn zr>s``MpX9X@<ljw;Vu;OQ=u@KRS$LUvmxWLWg-ozB!)#8>y zp2Z#x%;x7m{63MY#JuSLPXO!>6Y%tyxE@3L+y*N&`=?C<0*FdVij7D7xU@M#FI_Sv z)AmxPy739W!}o2-zg|mPKL^Ix~YLO#WimNc%t?^a8Yda6I+n|J}5l{n2K#o zzKp`>SdTi&4r#8Q&Z-SNt8UA{yjFj{n(!N&ARBOEJ_H<^$?94U-w&xvtDaS%F(&-> zjD?`{t5_BRE>ZX*De;0VfnnJ!`Y0{ddK`-3k-V0wzN1#%mg4*eu(}j3$amWimd-r& z1_ED|)!Ij56zD3*@~%c1Gh~3<*DuKq{V&9kJ#^$4jGw65xU?TW6ow8~@m=J-AP!+>kO7D#-FKFuI%* zS%Ce%uc>q(@SA0*v8AwYV!%nhPYS=baaJGM?=Jxfu0UnPzSH*r@l5z8!fz=AcHA+q zznVgT3iVz8QRuw7eHO6(SD@S3Ael%Bu?ezrh_u3FWfIr6PlC#5sg=~!6gQdPzIzYF ziWY$*2lgiQa0%*P9Db*8#q@As@q35}j|S5;DPh`PTQIjWQR`o9?%%6NH<&zOoLYHO z9Oxp*(zyKQKSc^TyH3+Oi5FxE0QTF3#c@uRKsD{q^ zP2fK=yC6Y@G%h^Fwy5Rn=<`d^<$F;xMWIXRg$BvV-a zg)A0c;_6qIa`G1?zfsb@`QKS3YX+pPAKq+~+7iDAfi_bH3x-Bb=D(%>_!P$`$cjyi zr6#f3#w9b_tTjinV)6$a-mRXtsw}?_A}sPgvIsl{LuPGb`Df8bo6r}fB=)tInidb3 zu?03GA|nwY2o^+5wv>1+H=!B7K;$?ni3M4Tn>)5wBWV?_$As=n=yP;Wj_T167GQ`W z5*V}9wr3{uw4=KPO{SBYbP;4}4hZ_e;sWt4ip^6dp)QVn0}^MwU>L2`!l@eGeB5&(mAlocSCJ zT5i;urnJ<2?s!2qb*YA6J>rl?A6hd|1MWVd7({u0Wx^^6twg-0mO}p6EO?`}d14jl zD#(r+Hvx{HIK{qmFPzi17O^SYa zL6%U9pI-BVO_Np6WZf<~q4}V^8bkIUGz>0Zy~ec7cdlR7C^w{xgbK1F=kCJLITzR| zIbnF5KTr*_r)Y|?J4be_FIz^L^qqT#NXM7%zQ(^-EY3ZzsTFINv~}jf@3bKb+BY8wL|e5o9-`K z(=x(`E7@rN!X*OQ76uegwt46}Fpt2Rx@>{QV<_Ok*t={txY*Z6% zR9ipd>!WSnggVI2U5d!-wEmdZG8z-L)WZ2R8N66_8e-JqMO#kG)`=~%et%~+2SQKA zk2-hz$p>Lhhb}ybt!bi_>55uhwcBhqx7_u|XuVE6uXRB!PP7w9!j1yZy9h|Peg~(= zYb5tcrC3|9l^tZ;i4lCmziUVI^l-9c{d^yhO|~DoOs~~lgf>wDx+BL%hldE~>$S4I zT-RLK=Z8WapKa=>#TX_>YZ>bdpKl(8*==wJS#)8l$DTw)<%_XA9TE(ARBZ)MARlK!hRdgl`NX4-*lBF8}WK z3yeWnb=h-4$S2hL#3U3sX)=>CI8!u>kSX|5qmDb_gz_=K@%kkG}6?w|7zp2@qXW1^RcJ89Uo z6+1_YWDpV(6IDQ5Co$7v)M8q@$&vUznYQAfTonPexWzE-2>#-R^t|$@*A#t)CyMvR zJ$&?-{keUQfj;IdB;_yev1q}?E9}CLcIn9;{G_(oG3gI%?Eu; zq{FgsB_ss!^G<9*mO|t3ebco;R78zA$Yr2bQD{dWE-8s&$zu~_sU3fQRL{r%x3nwS zWAR6npv841y5>B;3pR0(4JX9&gMKOek(k8iU8U=6jnF5nqR{H_z{+7G&vtxo6*gwQwc; zJQDMl1k7&(ESM1FHYhy`agTKC9^VBN+J-{VkWeWl3Ptl{Y=IboD;7c4dqW?g9tn!N zP|)>lLK`oaP8lVSHI1;$&yxoRabCG`P z--X}@hlRGDOIoV66(1x-kfjhve0vgHLtkAM#teOZMLbNbX^bwwVSH3BJUl$sdUA!j z3bLoqoDi0yfvkjc9qSOYn2hgS5>nsGFOZ|}y;y*g>rcFn z(npYe^ZBQ+a7Mfc4)H$ZhS4jJ?rlD_4{c`0mw3ereRIU?yo9d*O1GKHzGD;`MQ&Y- zmR!PjE@QP}YSX68XbKZZbE35gtud0DC=?d|4telUx9`{Al8Z<%^LAH%CZ&QbB8&^q z!{a7%7*Z9KPe2za4=kk;%w(H1X)z&=xE$(lYQJ@|(a# zH(y;1tVbL+r3E78%|VlxLKuXbOhU*{19wNDnOzw;f`CjkZwK_bBvdfoWR>rfoV5!z znINFlvZ6Bt!34E@3rZ{ABL(YqH8f`-*fKxAYzJjBo>;}-2j zKhA8h>%=Wqoy=BjF_?E5oI@rAQA#Kg&nRrmeMHqGA~WDIXzEJ++n^0TnFyn>0c4^> z09}+vMCU;$xkO|Vy3w%@1{u$fA({f<8Y1puoKI%9i?MVWVAYDr-5L5Wg>)g4X)*Pj zv_UvO3a2xscO%Aox?d>pIgKR^{X+rBi?^ICmUl{tetI68YIRplUvN;pdVbwAP z#KXZr44<!OIPOc48*?z{#9?BYpkT1@%P5Ml5PA`KD|fW)vab(yb@ z>zRA7X0OU;jewrsVpts>xPhL7*Pni{HrF1!gYkG>iO9@;OfQvxp?TWWPy|h$;vzDw zA~f{>;d^v7i~6)`JK~q=rW}{5CSFc=_8u)H*iE=6X*v~QkoVMctY*^jluorPi8)U z?$j~Johx<|E;cDW|M|O4g1|E>BuYXXHm^GvObb>6Ld+!-VGfagqkP>Ew5X_npi4t} zOe+r&KVAW(G=_`=cQ8;TLfj4i@(BF*O$6g?MSx6kiPE*2ift=`X|6IX91qL<^Y8by zt>C+LFgr3zml@JE84D)4$|8`F6>y<6_76x^tPU8NrH^Tb*Ti#CV+eb#dNz!$^MH9H zdjym!#>|_!@DPah{|SUrOvuJ!3ckGud^Yr9S!DKW)oCG^7N~;YQQi>t_A2<{+$nqx zk<_%9@&ZpU2LJske@WsInI{`(&Ie)dZ!!N_EP4VfoZ%WFF?C8f6of}XM4@Qxdo*C{gM2wN zF;^HLbPqy-7rHjB!q$bXBL2hmHOyXf402`92)WR`%F;Y7TQ3D704TZDY&&{Wz^ITj zt=xoeKMWKR-NWeHPq-Ttb`dwQ;ndYF3_fT-`co%XPvw+gIGC|fn zX~D$Q2wd!+Li#MJpkz&JxVHa0`z)BJH-YJ{l~}p-B*;&;W}Sx2ytsHVG)LaIi@i^! z^%Cn?Y+6ixcENj}fXiq-PvIV2FgghjL`#6KgjvIzzCU>RnccV4u1Xh`+Yey@9bGws tvKSFUu{OH<>>~?(O6BAVIBR%o_#d&pvU2Dc0owoo002ovPDHLkV1kh)e`Npw literal 0 HcmV?d00001 diff --git a/src/vs/workbench/services/gettingStarted/common/media/Tall.png b/src/vs/workbench/services/gettingStarted/common/media/Tall.png new file mode 100644 index 0000000000000000000000000000000000000000..174f64b5c842b164c16ec09476d1bfda14f488e0 GIT binary patch literal 86220 zcmeFZWmFr?w>OHG;)NDyaVV4)ON$hDcXtRa?(SOLio3g8ae@|icL)Rv!CiyBJpXg< zdCyw+%l&r0JXuL*GPC!d%$~{2-m`y`FhzL@Yz$%y1Ox?o=7-KZPY7j1XbUr;Rf)U6>Fd_Ii?wuD zlX37#)-%{~{1LX6>WH{&6s4IFS%$nFdQS5#7qOyX`yJt)tDqnOg5uY0yF!EK-Caqm zS0A?^&@H`Dl6W1LfSRYf$IkFq(EunC<<$G)vjQ;b@93Y)0|YYX2zIUCTK5il&nWe~ zHD&w>LeI8@#^3LB2+5Ne@cInWF@JhvNQS@?*%NDoFgf~_hao%NuP+z%=ON`Ly4ZU| z$I}fAPTt=&ZC{z`Oy?;_zBNkU%VhlS?2}dL-?n2(;B8B$qC!J2+_V}8KVP^$*bWUP zMQ;E3oA4IBO=I*BN| zmal=8zvBm@NPc#(ak>Q3))^##rfL12K90uz-bpm>V>m+M*ZI&X_$HaN`>s21=p*A; zc;x#lbk$|r+V{qfUP@+v&DP#P*BlFcm#Skbb<^oWF;$K;S+xc9w*`n*(h4df2XHaS zufjCo5f?}apx&h^XnB~IMWS9U@OT$<3jpZtt|)Svwt{@~I7;5qd7wtEvL_%S1}&JM4t8@m}f zS`cUT6a&8g5sUJ*u<-6{&I$T**;Fyv1(_z#N_h68#dGX;o!F4a#4sm?o!GUb z)N|1$UtKbK5VQvjPidG5;Mmb~ej0yo8sa#Bx|wJ9rP(P1rRj~vZ-ySV4Ga6R=I>yp z4AL9o8&ri})>FndvNcSK;OGIzGth0&t=cWd1HTvY6YmpY$6H9qvrx|4OY}w*1*G&C z(Lu`5Pw()CUwgj33d9WL3AE{!ppG4+(Z*j5{n=||@X4Osp1_`=CTdamkkSS3UWz7; zc_?XHE}Yt4(!GFs+GHAW`opxGGRGdPR*;pb3w210${_W*vcm^=fjhRlPoNN9L8amp z72YpO@5qgrjj@e63R4|2r{zB6SST`;uFY~SbHZ$);0wx<(3h(&%FY)k^i?-5 zSuU?tb1#cfWl$qgwJqyV$}dSRzbhY8WKd*K;VE;`J8Iw-TNUP0%*^jlY*&74hVxzd zUA|hU!tJ zWR8xbbeT2WKHOfJ2ASNMJly)uS}k2IS}g}oB+l8p8&_7BMZ073D@CqCCs&%4H9$j< zVZ;FWhkHeexu&V;sqErTndda0PQP5C62HYCbzNKm3&FA?0zI-l*ullvo{{gx`Nf6v zvBgb)18eKGo+_-=xej>CCp00PqnajdGtH}Re|x8C){IJ}GKb!(l$Excx9q)|QJ>*w z{a7buaxrExN}i@Nx;loslRmmKDxjsQO`~1$$E@D%XQ|;(BjcZn8ZRrcrt^m3hO*ig zYq@%trt#V}3-6v+4fZv7i>k}IO=8x1)VBN z>Z9xREg)vkCT&Z%31zgr0e^xeP^NS3dx0DA=23+O8%j*_P7q5&v!QQ~c z#^uIs=@#YJ6&Am5bYS)v$Bkelt0$jS*;L^#XfFUcSesOvm~3vq4dDD$4Uqmhr5lPH z<2mQvS>MbY>%>JUEF0(o)B@hO17+(o2D6(z4U(I}I0ih6o4_H^`2D&biDS#dk+aHk z?;X?qfs2)`g)Q5o>^s@sZ}6XKvV0E&;7+~ z8ZH%0m##o4XYrboFw5SeXjyiAG`}=(ws-ci6vC;LK`-x1%wsL1O~Db<8g?HJ8(8^! z0QJ0(x#Qbg+bi4yu(Ywxn_gmgp&I)ybPN6rI<+>@+_@fA&{ER!tb4Zh z_`bUcuTJ1hNJ#Y3>C#uh7JC8Ls^fu%*xGvmPt!R`fX)7)__)Not zu`96qNcgQXKxYn1fwf2JCFw@#+t663T>9Ae>eYuzVMY65mYiCfh^M4P9e!)5bvtOx zR_Dki;D~mm^Z3nib0@2lsYs%j+7k0-)q~!IE8U^Zecxm9KA(rD^tBg+VVMC!RCnUl zpyPby^Z00KF-fc?cj9M`W$1KP z&Csi*-*tMGtU45#GTg5B4+$4XMAXc>E$32UJv2-iT&kO8YER9 z-SX!-=mOkj;X3%hW+C0i4QzItvS<%4IvJ~L^0(1z8|(1C8sFw2bKN>w>*P4fdf-2K zia=Y!UE?41Y#+Q|(A{ zic})tsIc*ot*-(RJXjEr52#91LOl1Wgn}W6A}G&cA@|2r_NXO&!Cmv8|DdkFDI$zO zoP9uewUWmvAefn%2)B(b;^Dy_$osiUyHO{6wubO)7VA_mPZ7&X?Q@5r?JF?yuO#pW z&_@xg#=p7OJ5kY|2`upJ*yB6I}Qp*tmfspo}7owCh&FPETn`N%5 z>7*$q%WY_D&HU5I*1(wA&D!pT8UcaVjr%2QZS3@u(#_h+#*y2NkNQ6p+%NfmiUHJ= z{~>X*@T1AsLh<5?6?5{S65eN zS5{_Q2UEZ|E-o&>R~7&Z3)2e)lcT$h(@!@h8^@3TCFK8+BWmnu=wNQ=WNvFi`H$S6 z2DZ*leALwcH1t1@|N5TBZsz~DB^$^8?$%2O0sqthzA=9V{EzGxR^ER~xfRXbjIA_9 z&8>}X9ADbtXZ`+__doRiubThc;{W2*`oEmtzJ2}vzghoR)qk_{0{-d2|LW0ysp~(b zFZ$xg;064T?)fo7PXq2>hJ(~xR6+G6MfzuKUXm{_Z=e4w{U`67;H%lZjesDCASEiK z>V|ljiIzgZP81wH?RnDfT2S(?&tJ0X2hkfPLBW_$)2i>p1Y@X`Q5Y%1$y62JiK5^Y z+^oG2x<5NQ41INVIX*UVMJIX&@E>Q!#T%^+dBtbY^vEIN1R@|&zC7R9quBThN`U!< z`~(qD1O@Sa3FcG(LU{d4FcANjpu}#ZP|ZK(2uP9K|6#zBMnEFV<#^SHg!l#l@ip82 z3n{{D(a(slodVb1zr%bXMWLK5LH>{I+?On#hoK_l3+bB|!8rd4{#O-m{y)x&(`;Hh z_(SLZavV)dSlp+MJps?m=0DHOek8&<&yO5}L;yW?S1S9>^emrPr@=zk}kt5EbWh!7S0`^ire{c?SxXexHA__Jky{iSj~@%NG9bGX+qugCFR z^sLLkr-qW}5d}>EGD};{Yr!1bihF{gLbA&da&E7Ed}Ep9z~#B&pA987_`3#ItuslP zXeCCuy7gY0I_j98Q@uI7@%UEV3x=CKFW{H+GT0T#h#%H8U#36D{A2j`G~r%zVB@iX z1nqf2LE=eLo%ZZYCyGb4<*}Es)qZ$1SPSxL&o*J8r>?sF!?VU0F^eyfW7y2v`CJ#g zUr$e3nN*dVB^V;~&F6%ICOJa7ybxu|PoG#{r$rjrT5I;H7yI zsd$x{y~4{^$c!lk7Sv1|zfjzt-dBR% z(^v}Sg(o2KiQg$WB`C(g3h6hQ`In_{XPDeorW{>O3lpSza4{%&-D5ui_@yImi2-Ln z93qwXb~~o`_E>Bs_9-`t>u@G(kBSMZFTcEHtu|8qmAa};>0DnY*Gojdz;3%GmDYMp z!>3OB7TZ!g1_?3m%n@h$(3x%*YatomYa$(zp6F1ZK#Y3dH-ZSapTg5_hQ2%EcknAC zP>^9CF31Y`m}n0j zXRSY36r;~#Kuw%TmQIA3P{hZ>m}f#dPgJC&QlZ41Pp~&*x{m%)*&tD|J8klk7(aR< z9PcU@iuRo0f{{t@ZkKi`Z;~Cy#w&5xMJA`xZ`7#S`;o1sKJaZJO%P-XM5G zX)}}0*N^-9K8`<&lV=#TJrt+-Jg%U8KzAJJFz)$dYQIvo@TaZwZ4XCQp-D6t8i}uT zpMBADetv81l+xD&0PAp*McS$))L!HSaA0M3M7MZ#M2_oY$>TX@CojDg$@(Jrh1XxL z@qk6UC-Hh}ICbx}01c}am^SoB6`5+*u(MXbFomoF{rNc}v{ZEb9lgAl6)mE>o67gp z0bF8RH(_I++)E#7z^V#MCQR0@X(>gH&1MIY{kC@RFVDEw2(FbYOOqdqGuveip!4ZfZUZaf#(7H?QM7_B3T5(6|d1vL$2rxst6s1A!l8UZ^QGbFV7TGAvg*@e`))$<)1 zK#HOhBGMu{E(P?D=|p++6xJ@|&K{IR6NA*mr-q6T(B8LdtTTa)Vws#ChNK+A%h9XS z#hOm-x!Pg%Y>m!%!!YyPLn9%;>9hfXH|NA=Y=0E5&M{?%z9%E@l~v3D7q4j#dJAk! zZQMteq%@u`&oEmx{EK$R_&vsDS!8R89t2(9-W~0T;caQKx0^*)F2u7JguB{9^IZBN48ST#a^Z%W{PLu>Fom+ zWS*zL9dl)HI$lx5q5XIjVccL~uI6(rpq&F_0xr6L3tUz+<}( z%*Yl(E{Kqw;D^R>mi8e{S)($1o3EIttcOKa6HmhGlZdRi#h~ZKd1McH@fQoyIkXVO ziERxg3y=i9Me>B;9BAQU-j!#rT{iL1g!{?d*jfJh?snpF*1<_}vCt-AliYaxx0E>n zhqMbhR!7FjX#?QcQD*RBn{YSk%5fUySd4{#?i|>~ml8h;^yjs_@JLqUd%u)S=+RoE zW2Az5gDD4mwHCvoMGXhZpr34@EZq>8*$&&M_SM+Ush2H(UfdtcW?+5f-Z!RCpevWw ze)X8;V@#9D;~QIREH6Rgb1d;CUg9Wf&%p{@lP%3ZDRSg<1+?_IeA2lp4TZ1v6ST>~ z3Z0T#@6XlA;JQK<-OQ+DJGT5{(KxyTt96*O{;Rkrj+UB$oESozjq5JLg8G=wW5wV5 zNh3M391h8yCXl%@7HMO62!o0k;YTtswWouX@mzP+q9GTPX{=1vwh1?T6$=v-!(HbF zI$VIPF@Hn6qp@;UGk53d8(nKAqfyJyq`uu!VBBo4h)Uab+-&2QWOH-~G~WI01CrFN zyT?-VwQTqZsg?T)t!dHHVMI?@im+L~C8+?+=zw1k1U`=+E93Zh|1tqiez=BTTKQ;u1(I*T z1iNdWpe0Vn372n9o<|30B`sC6D9|^#8T#u!U)Qcs5jDloxiId`dhfMM@$GVa(ZuDq zP)kW$Bba?(%{$6N?p54s$qyhF}($nI|!xx)gN-rwB==_ck{7y=cfaTkn6X>}Yjkfv*qC*k`&4vgO!WF`d`(0Mtx`~03c!=&W~DA|X1l3Lua zK9pZ2t-c$+Y=TN;UNYCH==sl@XAacNB+q`kyBNy8&)j-TMCuZCfDO8KSWPPBynSPz6-mZ6j9C#W5 zY3N&=BOHWiiGl&LK(F4gw|huORSc;*qZ-hpWbfv6!rlA(iYR>Ry+#$k>XhV%iGbjJ zue)O*JcjMEk3f;JOKtSa+s-_UO9F2khDo?sdJxD>U$o^RlOIx+G9=SY21d#(zY@Or zVyaW6R<&|(U{8J8fAwxx6T}$@o|bh+-k#`#Qt+%ySsS&s@{w`5gokgBh+F#Xzop$D z_m(L6QK>O|Hek6b{}$f#8y_al6BCe3IAVoiOZ4sg!r6P=f``Az^!P4O&2z3O9ba9q z3J&Ofj`%*>I>yb}gd;7*&GdJ5b!GA_LO8P@!}!RDW`SSr%pMz8cuMV&x%7;coaZ|=v=yOFquw~*&X3X08FW#D4D z%Dj_JS!i&hA11Dc#~Cd?iLd%ts(xVhQc}B%OpjU?&AvD!L=O=t z>pf1*iRgLM4UOmqgfb|2!Im?Nx0>}xC)6gy4c%gxOyNpO$ASRqgGDu_iPu%j~<2@kq~1eB>4nbId1`ygC%HxDL9#RexW_ z8Hbo7;0BKk%s&i>?-H_IuOhA7EOlKAe@_t`8C{uB&7)A`7~SnTQgLI5zl&^WQ~bLW z|6q5YBSUavbI<6eoq*K%dHv3RwncmvjYAnGq_E+)Jm3~HX*(ZrziG%Y$-hq>a1;&~$E8!R!Q0&g01D-J3)xzZuxDPZyMWw7g$h3`nmbFiZ8$ zK~taW3%-lL?-R4I)5e{>6B}7`$R$pQl)>cA2n7`{^@-)^6E`J_JJ^bJ^YFeQU1d#7 zK-1uv9oo~?7Dlfpr(qlqNG*3$oUyRG*Y38~umMU8VJF z^@GxQbT;q8nNa8b5I|`h5{gEQrG0SAS6sFux4gH=z#TgS+)?9JHHQ=s*17 zmM^%?S><;IzQHd9Zvy6xlZ4vsx{d;X^-!Z`Gpd1d-4AR@U2~ZH0cH4Fu%j!Xh-^;t ze9(Sd_JqzW>W0dPmH^L~ugv^rSswcZM;!7S<0Gv{*Fv4!tf$OpGQbbuOJE%j)0lie znpKD)&HW14OEcNHA9_#QHf*XM;n^=NjOnye zqj3;D`u_YC(0U)tP(3KEn@UA9u%w2+=*wFVj85@U6KxN$J|oz@@|-|X=6&nMHTYw7 z%`n&9v%04}TM=p1t@l+(ByX`jx=xd|tJCgn*kUmr1H~m>{8L_%ZIl|*eMRcDax&~d zxi9YSvv*p8lRr_`;PmM|ePY4yJ!P)SXBE?NmDm=&y~(Nd-rMgAkm4Nxg@AKXu+O(l zlX3m>&H45NLikyLOO&3lEu(%-9Jyy%jdY{Ee?#+YBIF0l2xJ*7a}s$&cj7>~ex(sk5jx}7Q? zH*m0DEc*yKr*AKY;4;HK*5`lEMzu6#Sq z5wDgI?PvO4Xw5r@FrzN>KBiKv`VnajogWI129w;r6%XT=uzEQW;>4Q{w{3q?J0TXVP1 z=GIA<%as$Ah_rr3kF#kORlh)rcy*Y(+8rU2hZ)bEtO!B08_*g_tRMtPF7pF24B+DPP@iIFjz&4jYt3CA&rs!} zq?Kz+_Q({UJY^2E8XlX*;t=ig-@dj6*QessZYFj`Jm(fj#Ro?aJMgL_F%i*GYk z@nUh|y*hf%k~Saw`=nYeUx^~g4yQ5lNM*bu=eW;Fb8#_NYc-^S@W)KK-U-HV3{LOO zQ`jmonXe)xs0*R`7)DztNmjO;FZW6qZ5c8^V{i|hNIU1ug@(RqiG$;VgkM<^J2Kob z*c|QWQ0Oj2M+-)@hl&va$@!C#kq)5HY5(#8rk;%n0?Je^N*O;xe6w_CQT3okiY76p zp(M)~%1X_>pIETc(8J;)b>1HpA}clADLA|h z!=$t=GEz$7^K^Wp1aUacsEx-Z0kzt!HOKw|=$&SQ&nNmuLRK$Qp+O&+C_&do;FhE> z{^;HZL5W`I3N5Y2gbA_@@eiWg1Ikik_`8~OES{+ zg@;3nVg(aH48FQi5pPEL;*ICey)n&I3(VosY2gdIRg7#^b91(CZZkwYKXtw<(8GYs z%@Zx84xO&GIzl_~bkJ(1p$Gdr#kfjS(T+@N8|k~J-)-v-rn3F|Mp&8DWh3;Rbn;mR z;fcqpA^WpsQX*)$cG*!bJn~3n*5P^^vKZsH(EKcNSWHys3z_&f$jsy=TFsDf6SyknO;-rtM4KfC++Y=;Hc zJIq&l|t((H*wkPxgNL<02Wg% zl`WGSB4{dO#B+w;Q!j$5ykPB4w}W^dIX-&Cvz@jTU6h;8xPH$e+|&Vu=h0My2*+Gc zqorQN>L%}o=y+h~!?KTDIya^WPrep^8``JQ^}R)G+peO9jo`CG2?F|Snx?negu9qT ziv#LUE~y7{nLLffNlaPM?C(V%o+(eCl_f-fsp#JAc0e)-1YAjg==9Hjg`J-LBeR*J z#1ww4$K+ma>_&faKR2rPni6oj7}F>o6t^9MlqE?md=qO?n#ksL59cSnsG)xfxY}3z z=Hf{C>sR{UXBDz3NOIw=zo}?=5mWm?4s*oA3Ew{Q zK`uY!V?E6vS&JgY3atys3l>=qC-Cdkkv(m3R_cEz_EGv2ODGV>H1o5UPiHs`cE`P1UwK!$-R zLiQg-^}0Cq8-QPj*B8NLz+-t8hg7Yo(~R7dK0KAxv}EAGcKY%I>t1&dCcQ&x9PMt% zNk{nFBhCPVhxH1>YW(4f~CmiopW^Q$dh~+0?uWeZB_8xZDdS?M5Fr zz-LJ$L_sglYA;T)Rh!Ge85Bk`9;wDlW`4Y4ymu{JijGtnmhzm%>6yBg*{1VBojD`; z1q4Z@9#-IUO~LK@?Q_DiU_F-(yg-%G(!rxho6y3;Rb9Hf{WcJ53r1Q16Sq>8(#G4( zYWJ8)*7q%E@e0=&we5Ja$OzOD`6XzHAA7OlHEKf4%GATmCYe5e@MgO}z=je9qSWUQ1po1MAp;5CtuQOY zbmm6od(sH8NEW=i6>?T##;r7v`%cfqT(+UN?h1YGkTO9EUboO=P-oORm&RxPsE#KC z-3-hsY^upL(d`G}97DQEDdI6&7mD()@SyH*Yk$$`O>!9d0j(P|H%j*kO`knqJ6*ot zVwfbrC@NBCuPv92%IFaFt>Tw=oX^ZrfiagGMuG_V8jVM9Sm4S)zSb~(c-=ylB3hL@ zX3Mi@fcYq$p_)km#4~w+q0+m7#vbf1IDiLcXA2MSX*AXRnxa!_vp398 z&&BVn`dWQJ!+=j7P<8Vf#)43HLgh{At}|37Zj7bCp{N?3?c)-JWo= z;rE+lDTTVbw9Y%&8;y>L1Ug6M7c{lDN1O7eo5GSKKYp`~QX{*L4ccg%=kR8&4}yUE|5?*vqbZy8lXBjUVIScnfU3 z`$O%CUzW&#R_N8^i_NcJd*WJ+ zVJahpZ8P$@I5S6&^d+tr3yzF?WSrD~y9R43$k^QRjM7=y@Sj~0SRmCXhJpZTd}0YD z9PM|v0)FCr;VK&rN)mq0##9eKZwb>LttY#V8-2=jl$JqHs`Yi8NLYWI?p6{#^L^U6 z+1vyLT=A!D081`uFK`HnR@_Y7u;gfpHZ49G9{xhRI!=?CLAIwK0UkX;G=F*2!V7Z& z%Y=~*D$cwg-n)5DGZXhBV^SlmQP!m|&kspGW{(rG2r5=CNT&@X0^UMW9uGsVg6F}s zWIcK+=&j;w;!Ey!QvSqd9zXq-lZIzbLROtJP*sG*e5l&4+<;{Zwvo%p0`8hl99U&< z;+jbH|J=P}CvFtF6ElX8^_o~6P&;u5V67>pc$cm;>s+}dj?RL7K$J=`kbA z9jfvgNgLMoU(AlMNN;~dBfJC!(Qhjd>{Q%sh&&+qdJTHO52Rfciz)LD8D1siFLW#k z#qUrQ33J8G!2Jj=&0z}(3mMpSyIC9>T-V>M3rsqtm3i~2#dG1smxgNWiN+zOC&mOJk>6S#%hJQ%_b^$x> z;&=I2%&m_#nBFhvU zVNW=&O_)F7CxN>AK0IEPtquL!EXpP5*&lsNYD>MKFcojzV^gU6A#dEjwbZ*o%Z~;e z=jq&SosdOg;F`i>!tluNQ_P*ft42-V%>?U}vMC}vke}|vYE!(stlwQ&{~H5gYZVE> zRY|m%OZ2{gWkp^&al4;lH0f{Nx)tzfb_iP7pk^0yJ$!Y6Y9Y0E;wFtKL z!Pr1KoQ_lf7d)B+q4yETa3a?SfqLi{F8yeZ+5OgF6FW-{|G)9c!pAQt-7lSImk*X) z3wK?*vnQqHOvQn3%%qxh0>Jgpw_@-Foksj{hmlUG_mcVLZ|^eU!5ZJSFEULmZ^;T0 z^*at&U_r`XJss$?SZR+qoubr_IP>#{yp|dm4;`3}b5L6>YU&eWbvk_QM(WWX5GWU0!WKUk8?FvE|!Y&a7SZT)Bdq00$C=E6xuG5$`D_unD)dI)-|PM zml_@}Bu=K8c6*&#AvRP#H=}Cr>nBe%DXmouC8RKI-!rNZ(i*{12@cRS>^uq$ZiW(t zEX{>RepKQ3+>~K>qQH6Gue6eyH&C=aC=K104JCZ+rFQS!$oH2hqhEm5(<)Ux#ME7$ z@?_fr%EwkrL}kH?)`y8HH|kp6^xHQ@@^hwW%=%c9N6xiMJ;!|+@uo|Br#o90dk=df z2~n*eYk}sV+CPetF{t$M!PZ4wZv*lN9Yz&$G)|?vB-}kR12tOPh2_%O)K|Ve?%l28 z?6cY@htG$#j!Y}h3H3Hn-}^Y7zTJgCE=*UCM3sH6=1&XpID5ty)ukY7i}Eo=j9Vul z<@%&|A1uN#_$h4Ad)(F}b%#bsdq%(JU;{NPn!d8WOE*=!SsMeLb~5>sDs3upLd}v_ zqHTU_?PRmMnAzzp-{tVF_5LDmri`NZf)mxAwd_un4@=c0MeQ5@o>hLbPXI1y1stt` z)hdKLY%?>zq}#;sg4`2OA!DVdIjyX=Q%ctRHXtpO&WRh>)pequF-pKKr|45BCC#8D z{N=s`H-NnKfk|LVcB`3zv8x(-I#<-ySJR=f^kz z8`x)8LNXqGOLCt#F7HO_<5x5BdxNH`Y;g9^6m1%+pI>9T7d2A+Ao|!T`yIFHy)hm{ z|3G1~z1_dP##Iy2QagSZl-@zn@`aN5cfn!y;qwZadN8-STM$|z3R`BIpzw)# zGJN5jbZ~qk|HhOz-b{krPU-g5=l0vXG~f4abdXNn4Dzz~m#Nkp;fnPlr)fQRBg?*x zYIhsGC*BV;!^Z~Y!!*n|=n?m;!cE)Q?NxE3M#!$vZT<{m9j@WWH#{pym8~IhHx!5G z_yR>dgJz!Ugjnc7js-c+V4Z2Ijy5Om7mVeiY~9G;_FnO2c#h#5iy+6k5q2a9*$3MEa7rY6V>6C5nlA)Feu{K9JK`S#w+{w zH7r&u`RwbSl+C-LY6D*#QyQ{IE+&52xEeU0B#G9w9@=+%frfB1J+5S!I#=Hu}!`evgTE{ zLIpv*2kAeMj<=5e+u-ZG++(Xh(0!2j40p0;%j7(reI|c(Tne_gSn#w63{2=2$&Lju z4Gx0y)5tmuo=Veztn=eXO}(M}YosmQOTP8G;(eAb-Ldo=qz9 zlBbTXIbh4q=gy{%mW-q`8k7^(6T)4(W@lbMouT7DH;bsl7n{`1lA;$qu>5^7;n(%e z4^A;ck9AIm4<{58M3sR?|uZ_*+8pive?UTEA==6k!u z%i;Y1-~SsffLrRs^P5rPP6kznI{Q*r#6j0<{A8?I1x9ktlMC_CK9xD`x_Z0Ya4?JW}sV|oFr#vdwI2riv%DUJo! zH{>|@@3q_%uRgbKlwDNB{{zbYROl%J^os%jGE;pJ2Rk4Uas!UfN$c>2*n?CQ_f$Bl zmaa~mDV->htj^>aXy+EgNxefu;ua_sASpTvkc9$Ef4hPw>V%72T0I0-k@%|Q@GN@k zM8Q_TIzIi#!V3*izScF2zs1 z3|57R&6eAh!wLXAqwk6x-@B5-e{)>zNFi+a6VuGny$G-9!C0=}eqT5q6X@}*DJFq_ z7rCcHIuK1!tWypywCa6k^w~}EAMI#9sm!t6LG~eOyawe?ttPm-U0z2rRk>EW=t%?RyJRkB;U0RK>ZTi7=fA7V1AS zO-@T|9WE2^I$xjX~1?o3pT4(OoccVLbx$j-B zE|BW@bpQhb|4VK3Ko;+{IwNh?%cuDteoySb1$}!eZBv=|ai+}uqG04raSCrT)`5;z z!cIt)N3DNa)l58xMobq%C$sjdc_Hom6Q0Rm6ZjATz*LWWJX~PoW?~cm&czR3v4tO< z+`DkcnG^lv^?h=zL<`g6*}VWg$ix~@LZ*l!Cw=LJ^EBF`41qiAiR^wyTl-qV&S<_G zmFdi;R5NuvgHOiUVy+-J0L^UXPv>!yUNfFzQ})t||5Jv9Z8}hEfIqJIz8USzsYv0R za{Y$){pYS#<7D>*uEl4j+#RO9xxewtVbJUpl;uak>Ma}hpT}7;q1A%Eo$Ft5kzS#l z7w|x@s5~Pe320hIHVrs0>)^}f17McHZWCM%mi(p@1k!1ZZf!bdZsgG8OWLp&8c0qa zmuTfQ*e}{Q-e8bMKwww>=f41M&pnw?Jm_yIjh;N5sQ4F1_5GMf_%_+WtVxr_KRb5A zOS90MUbpH@+7p;HMdZ^0uE=egXL-QQQM!Yo$BFwwmqWaU#W)HQb3(-ULEI>h=f{33 ztF_}}tV4}wY;9)96KdDk@e;P^gYS6np8r;{cGv^G?W*3wZgVd>>@DUzITf2lmjwHy zU0;o7@xe$2yiX5_jU( z2=}9UxdQ}0*!efQZrInSYGj-fz!U%bd@Zjk(9t53Jdg($?Zo$n;pV;y$dK7~(WFzb znRwDM%JqpP8e6M43bPnFcw*MH>fphrD>uf;*!1}fQ+}yUJLh9ImoHaL^G`*U7eBKc zci=X?Y=}3}rPW@iyPphxKu-4@hFQfQzr21V#gln4(wMF6%)aXQ+?!I>XsRFXt9cC* zlJN2+1#wB!;BhmppOeVvghakCM9~(7ubj|{Ne!F`rZUUSp@#l~hiyx+-f$5ewZ9Ai z5JOTdCWO^`#vQRbXHae)w~Ci>jS_(B4Q%Y;djRq*`P$5i56pYkske%%PQ$ve>B4R? z>Jw@t2XY2K+45?%7i9Dr*2KO+I_jWn2PyZnkLv&V`W2e2kNnVnY8G!7(f@*o77H6; zn9uN}YFqusqR@_%u(CUk2^O*v7Dm4uog2t#(@*`w)L*gXIA$|%k7wrEvl%ONfHeI& z!dmjRUsBt7y=t$LF$R^6kiV+prqEC{|rcgx7*oDg7zSb91fF@TP zjC2g{!@-p0^4B~w#L+&K0$#P>kdQ9IKQ3^Vj{ab+CjT|*c!w)lz;r9FbLSFq?I zVbd=oJ|j7hg*Q>&OM=$Do*i33EWten%`H%U)BSPlqc21P;Ek_4NO?ig*Y03D=6XmY9Es5TVze z9vEjy(~Y!UoN{a%s|R|iuiq}oD0z*dZ*0c!u3{Q*rzR29iMhiIXURTT5#AJe33rjz z<7%@>`Z7w5k6>YcnAIH~nTIaZ3>w709GhaN4&m|kIHxXrmfc{-I3MyGaG&ljF~6VP z@8RRM+r6(6th53<>zX?D3=?Y5^NWNpePUZkTzDZsYGvoNXk2TP4kQu^?2DZ~mB zw9(*hehJ}Sf6wej^tXA-dt?Nl|Gs?)&-{k#=2{8ZfABP#!^_C>6$)%9*y`+6u{Uzg zB>$VR7sfDPzfUc2&S&ILM*k~}1Bd$D%AMU7l1@5a01it{~ zmsd_5U{otCgRU03#?t)|g()G-`Ze4e226F68+tMq<~q;)YI%`r*U9^1{Tp^3B)tQW zmukrKO>ic7|KVKksi<#fX5X61c2`&IEEK7=ZP&^eAq1FanFE;Ax2E;-=907aRIOrnG!l?+rCyx`b#UT%r0#c#fJZZmvP zrrde-bcdp?Y($9}J!r!ORSG+a!&?!52pxkqg^Y!ydT-IXN1`Czv8 z-~gl6{B_hkN}Cz6@M_-AJe|BS%pGjtMShtTp{_G|A)PEey-#R|9xz4u(8bzHn#0#&vo}Qkbem(E^bF4vze8DBHabIY=H)h^{uPvBx z>w*$*%g)tKv>jx<*o$=Yq{M8)`CU{26UX^I+i`r@%A7%e8kQx z@~1?KA(jifsLUq)mT8nWWl<0AO4Ex;P?abijxz zyLL3Wfx53A7NvH2@vsqFaiSIhc$vWKON5?xMYha*l&t5gu3u+mbiD<+(VWQGVjK&U zaeVcAM^cGgR&k|<@NviA#1c9{QcAgJo4guNIIc7%zU0TO^r3+iX?N$K?$OD34?Y!R z_y%?YryfTH_4P|8|FoXm`p6Zn9U#nu9C_Phl>aAj_cC4v&-&0n& z`L%_}v&?JJw-f`C)Vchv(R8AiTKAvKlrd}#tq0UUkrB1U`R~=K54i>E{W&Q%(K1}U zkTubmV2`JBO4zrqgnK@JX36F7RmtqX#r#b_h-m%tf%ww^@$wY|SN-CS8k?=lqI<`H z82p?)Dv$qSky;0<2C0d4qW7u(y~TRHSaTj439k?s$i7^10}pmfLA1S*j0`?1Ze@sK zN?wDx=rFaP#eoI_3J%6hK#^k_>+>Pj#Uh9_y{^?Hg3K3CP3*v>n=HKn`SFa((!?i?D zqo*;#nxuTsi@i`QUxDFd^gU5@P}CjtX^5VuV|Aw6%W=5cEuN2yuU)Y~uTSqb^}fD9A1>B)=!LzE4D90b}}+e)L-w zQeS~Wl-M8**hPx~0r4>%QO=M*p=b!gfC^{I*iA38sD(HW1Rj$BzdR~EA z_}Z{Um^;q7%9O?Em>(`Gx?a^T8oH{#8ez29}Dmr&K`t zcQrRaFDwsVeXM`gNq~_`TuN7iY*fQT5m;v9$yJWGbL2Eit+8+7?lpoxCD4GV7zgOe zrAJz8C+mFK{>b{cY&Q1p_vVyTn_fu%#dHlIjLg;WnarctYMCX+G=U96BhP<-y;ICu zd!CnOY|hWHiQepa!&~p<$L7wC#^)9T66So0DBQnG2)6=6Y7lz>?LnFZ3ly`pYoD2N z)e6t$R6vN0!Q4- zK)( zz9eSNGUxrCanN62boF?ybyrz&OVejMOMFi~e&*zql3FwzT@LToc@5ltU~b9tn;$2X-l7R#&k^X(Q; zv-k=Lk2PyE?^6N}jjY(+=~lY*!B#4BsuW%2A$*t4du*fG;EZpz(i%2bC?_i#fnMBE zu_@_xci=4U)J*;vjEIX7Gfd$2%jvb})tcmTr7mKwSXOu_0;5R$wRIW!5gw5Fe6dW1ZNJ>L{{IY`p^4K0S@$H;H3v^?YSktx`%WSL@c<1pn=`Hwb&A z8+p}P5WYUKirMozq2XiKeQvhh4Gt8Id7}j{UbktzUS@@=|4gp=Rd$wh;r)JU@?f*0 zm;N%Dl1OWUwAN(7?)5t9a@K8f$fa@Gyk2_r@ysb1iTedP+FRx5KxlPS>#)&L=U-#g z=O1)-YaY#j7ksUifDIq&q;Qv zbRNH0Np8!&3+jv$&U@#1m@gC$h(`yCB!pbs4jl+InY1ZT!$9nVK) z1mi_mi*HbmV@^e(i9(!r^mgg1RZ12Q7ETXtotI?3IT6fOv0z3t! z9!_ON6o1`)Q|$uqak)Qy=Y4%CSm;onj^(H)WxSBnX|D(ld@khi3|NuRVG)mxRVIx7 zOg%6GVOyw={QvQ7K=+5BCsaC07G)8Yg2K;iXOQTvJXw&!|vfb=nEm}b`C~l0A-GHsd z6}anlPWC2re|(xGcbWC^0^>MuOux9mwf3;zr`-Ey8Z0(g;^7n+|)^-2zgx!lB6t$2|qu$Vt%jt|&lJ*)H*)(Ro66>c@VT=d_fhXZq01_H-D5N|gNchr5 zCmX@3QKHS#U3J1czU%IiL9wZ}8jYt9n&=0Pv!(90BkR>-{ExmWoHDYCWCo_}JiGT7 zJM)dkw)UTGd}fNk2T7`4UC`Lm^T(Azd($6Cuh1o%6$zWJ`RP@cl=Yg4yFUQa1zVuU zRV=9DDVs#BptM;R#Xf+HbXy4tcAC{a-MxEF*6N&}r1N=0FJvl{vjFK7GfIX!vA)r2 zGk)vpzMAWpa%N7+=VX>Liz}YZ0&^^bGUjYi(n8w5kkji-o_PM7Px>8;*N2rYii+NS z0V07?RrydviqcT{p{l&dSq_Aou{YpVd=V}gtD8q2ZS6mW<%*J3$Cm{B<5RgyMLRwH z+I2Tvx9g_eUOPRH#j-~#5aNNrM6CA)C}}Mj|#%Xike>tub_M*{6Ehf%w&C*R1%Fz`)E8v{qgg;7E9n+rD&MR z>&&poqJ8470`hGM?oc&G=1Nbo`)8Z3o5tym6%+5hwnMc#sFUV0>S|nBH8!*1jPXJZJrss8^6$yYD2U(5FCaprLdm95QW`rWgQrQuS1Ug{>tJ}(>UiU5QVWa@?yU0$1xTAdbuRfa8OGJC?d9$# z!h0`WHZC)D|LF|*QFS%`y zcvMPvm`UCP6w}bZI5G`2WWXkMT@|ywC13n;m>T`NlQ*!yxx3jtPYZf=%6YtMh1$BG zjWhMC?(t+lbsBXn~;G<#JSUmqkq-LoFwA%$aNYf}_{x3V z#@}0Y5X&>{`Ceu~`y7O8GW9Ab%x62*b+acuW!Gibl?^|dT6ifz0L8SCZnU@#&AnQKk3U-Qu)xtm91 z!~KDNV1nNS=u(J#s4WEFD1gRvwbOlj1xISP0Y=}wQJz6QeE7w0@^zTmQQ=PS zRQWj&BR(om^6}Fv7(BB>E;`Gyb$s9Z#EI-#+U(Om=*@Pdrc3}nVeZgI+31hDq=Y7H z9Vtl_=cqIV(9lMpXYNupskw8f?Hr%n%q?t`b2LZClKA*>y!!o8)eD+;)$1q`(8Rt4 zSGU>h72;40JX=s^0{&>r3&w2{mU3$@q~_SLa+y%R9sKxcz(?#>b)g7 zZc|w%mCfHYb3X>fbrCKS)V}UP)Fs+F!SLlq82 zaQwMOx(XlRGkT_O;&mHijJ`a`DG}pjgqDHSv>Z$9(J7*x_(pSrN$moj#Vj2|^RKh` z??i-?o+2)}f~9}soVVa@fsLConz3&#litkJ8Stm`plP)yc0;^UNHyVbVmi z%1vd#S81&Y@Ds+zB#z=A_$@w;ZziDSE$mG@ENxPlYw3QE&xX+zf+~wi57FBvZtpBq z&$B8zyu{k*+Uz-+Kn$}74lpy-TT;v0RA#}oG1Y*Pat#(s?linMVWT_&zm z?p#Lb#8T<=Ouif4k~GlwN|HF&y?-xVaE@)OUrv?txOfzX zlYH7>GB<73d1<-V8AVVPGjnLYPI)ZaNdhj}^<4HMzxHUKa-LNIyH^1K-Orzg(Ak@c zy>-jDSADrFx(zGMX3L6*K#e*!k$eV4lvF$}qT_K_p9Z(Rti2U1Mk}SrKk2%Z9MpX$ z`2OtSzBfZBT~pRX^&Uaon%8;MGVp7GaJgh;a_-1sw|g3y{};buaVkURLW0@6NvRI@ zvHdj89G~f}*4O8`q1E0yocu1$?<>0OlUVWw2RWM)6XmCmYMo(tz`2^obMs5?!+M_j zb@!EW-CA@RBz{Iq44~@b(Qa4;#s$7z__+FqsQU5da%Bx~yWVMadq77Kk+*`4E#RSu z4LAy{W4%A1-$cXgE8QxZ&vYfR)ZF=s`!=hhuiS@fa2Q%I`-g4`uzGUW8QQIG;eq~I z#Q4tX8M$>&}^##@tQX;$S3#9qwtRJ7?%L*&m+~jEi~CTbIJfyb9A^Tx*xxU#Vrq z<&tD+E_BP@U~P-@D`SaKAtYr@q;9j@fbw=HitEbiu?>41ru_k>E6=Nhfrss$ z-D!mzQDu0M-ZX8AY97}B*LB0Ue7RD(K3m|3Q2y$T&!X7STxIx1HdYqMEM1m*mb z;afIDniY9N^&ecrBe5orfQH}$08_vlv)xZ!Q z(;=D2^wyaYcl{|>9Etr{%@QGOTqN_l%MF}nLuKLDy5em=Gx--A^{ogi^kVcwF4QU= zOWeUn1R}S41tkop<@Spw6RTdtKQx`L*x}_DZ+}6%Y|@*~V+M6Ve$1Bad(J;|Q#HsH zTJE_#BT2mtxe!W+CWFZnI&QUh*7jw2u2{K5D0%knLeagW&G2G7L%(cMwh&HluH6?u zt|&*Tw$Z9pAMs*1=MWMMAKmPd{@!FtT}VFRki^>k8(+eggrRJuG-u+KbAjU zSz$4j=IFB_XbgVhc*vd^u&EPf1=}doGHaAjCQ3m}Oq1VP>Gu!;8vpcFC% znnr<@LF5)H3ye(k3fknw|H0+w-6ri)vO(fo2fHo*-d7jr*KZqO=WVv=b%Sa|OVVaE zzC@+idbn43nH5Y8-gQS3cb+`!Ve`De8+7)Hr713{MHm_*FizCej3t=;JPlUT`8DyJ zvs-ZQ^fflF0Y&kXUj1}MvH^Mn%9 zJ9_ICL^ChY0pLNp^ zropN(^(A;TqEz3)BS<}#D#sx6E+1>?G*u`N&(1E8QAT^H(%0-~WN> z0VQ;b{~7^<$>uA7syRrdYj?f76{qs~d`}FcOoN9%O%DeMsb#bY3ppM#=zXSKRbX6v zO0BV3sHl(oI~RKkFrr zbp&|UNw+(o8QR4lWJ^8sA|m^alH`0qBhBEe(gd}7wbswEOg9l>VjHD!yD*qf(KZ{V zwIIx8@2gh6-xUL=3eGD;jJU56|G1P6h@Lmf3I)A=E|oZSUIHWbq{87(50l-Xe~wc( z<0-DzT~cz%S1zunqD=}$KWgG}-#?j5Y#m8DmNs(0cY?tnQ;1M_-$aCs7&rH38L-4H zb?oZll(c1-Lv?E8=$!}+v0pk@S=?raCuuHEK1Y-cuRu$wm|=eA>e-?&WlrXF7G`My zrp(H;nk+WuAzQ7-|B$(PKixNEvYMf_e|4Y9@vO#@Uu{S$4IBOrsbok}E#@(b3r4^{ z;+ggaUthj&+eyJ+t~)Bc_IziRy>rEwa#N|eQ8TcFMEA7-8g_qw zZ-oTjXeEg<0nU(EBjK<7ypGG3VA>1zE)?wT1S*3xpLa1_dxLXx0fuQ9d3Oat&9lA8 zTHS-?2(#|<^6blHk+I(keGR%@Y&aFNKT>_Tz{?x*!{OofO=q|PR7!eu(?)p za>O-vJCQ$a#a=%AMpa2QuP){7KnOgE8Z&q=K3YDBlsivLrfYu>_i3z^8Z**Bd;BsIkb6BfCjZp~@eP-+$>DoIVecE*A!Ufs&WDH$7AeIUG!X0gYlPxs}AIccdr_QvWBG`uemKcEm)wh3mx+k79uIl|wzA(x6VVgjB54r^~(X7`IJV z-}XW(&Ye}H1ez&z1ziMwzw&$W2cPgG%0Vjk3#^xrs>rB#awrnso!^^&Vk7IOVDj1* zn?pJvwt;?rPt21;%~GHGh8vSt&Yl)xPabWnq3fwMl|%Q zW_4#flr#2nnn3$8b}d(=wrlvV>2;gA{TQec>$AoK^}(lmSiSmO?;-lSO*uw^;kdV^ zmzVBPZrVQ_tAJ8 z?8b$F_;$Rzj94&w#wOri7wl{DNUOZq{ctu-TLVG|ugxbITQ4nr-4y=%kU5byT7o>W z1o8l&4Js?{!O-}w#qhnqX1;jdBOtgOS?JWAnzy(l$2}7`nVhcQ#RMJ;We0g*Bj%HD zgwE%n*y`obb)+0VU&Shb(LY{<$?ZnC0tEenZCqC{=8{Meph@B3 zuy-g7BE{g=j=koRkd{op{X@D-2Oq*SGnXYbHe9$)kYTOU%2R!4clsu&F4z5(%xnbL zWW4<_ux>}6(`fj7*J*ePM=qP5I9DQF!BhTGm9Mv(MsozEX0k7x?s~;nbxQyx><`|JXXkxLn>Ri@(8;yQ{)-kyjwM zjrwXdU(Ysvzb&ype}4t26xftWY$hH{7~`iw>F^I4r39WQcvet&JXsQ3m)e?*Jxdjq zP*k(ef~*tsO$RN=z6OVC``C{2G>O=my?XUhce{}V^7>4Rwatsr>0Um;Nyb2eLa+jH5ryCO7XoOS%~XR_;*=C2W2MrQ|M2*UcZWH@1W!||17tmOc%o~#_B2q;06cx0e63Vjm&erpWrn= zf<7=*lJfsL|H!*#+7hMUr%~nsk1&->wYEyDtsq;B<|j4lbNwdM=r7)h2#W=fxOay? zcdvl}*XFQ^kCd_~7@{3<;CaO%he@)1WpvtmtD}I=oan^`A*0Bv3v1UGK@mIBli>fp zIII5%91)Pf!L(yj!Tm#Mt-vnWWUWQ~N8nIJfCNsE9b6RjAAw^Bc4-Dw^M3@+{~v)n zG0vs>kHArY_&Lw_{``-?p#TXS#3lkdskMq7 z6G^4HqyptB#bz!=6|GspJdg+qqSl}9dp=Snc$GOD3XgqgnMR|Wu~BulbO14Pv->4w zGP4_~I&##Rbpkd9f}eyQ>R`*tPeU>M2GjvRSR%tNR3t>cN17?H$oy5K=BDnT)}S#= zX8e!h){?`N2_ObHX677{FvtKWWWCKu6cWX#m>3CemUv#nC?36_So(^ z&c5e;_VO+`4jjlPHMt29(HrA(<@iIBnz0anh(Q@Hp6dz$N9ZRmpY6AtKZ(-(NW|m$ zprW=iyomG{xjq?Kq><3?ByfL+i8$3q(z{++J(aDvjuGp9~*8K_2GF*DMA4x|uKys6jt>TyVnI0$DD!cveI`RE3ntOp1 z`Yt<|yNh++AkEbLABc<10Alm!ibvJ`h_P6Vj$8?9zu$JT9{kAVD%BtcZ_YIJoec1% zmAQJI@9^o4Ibc}zHgu{Vn)=eCh1vhzVKkzIIuRui`NFS4V;$>8g45q94fa2%n=zH|#76i$dlZ05#shfW#-29Wq@O@v|-zb37aTUr9ivxoSR zYsRsNM`+Y$`XxMHmLnsU^US8pUMjX;_19)l;+NcspR~^gu3tQ^cCqoEGdqy;bQ~rT z#(aYOowEtxD)NzUW^~ssp`ldy+@=TKfB)30%;leWE?=NM?LfM>g9^FUqQ;<|@|Y&Q zsZp583VH3@Dlpk$8BDDqU3#Z*yoqs$O>_sHWB!8purHd`ECt2a$`J4xC=dSwbDyV7 z5>kh>*wkbW8^H?@^7iHn9471YGf2C6IdyP^tmuo)))Q`;rlA>gTc41LET$xw4s2-M z*X>Ros4fXIv#K>!g66CGrK{+9ViOjd9v8)L_(oW&B8Y6R{)K0b>-o2D-oLUS%5Ib{ z2clXyG~jPosp$S%I7&!SkfLAT3T>#_)!$!&Z*3K}`%_*_ z4ITFkQJz4gu1S78j9LtHa$iMmnJ>J86> z34dsGfl&xyAg#q#atbUZfHosOOb*EEZ*+y+FC-KLad zsnEd`A1%uMMeSZ053yY?IHHwG26w^N0Jo&UH~*8z?FmoYi$ou?pR`;AetLP6Kx{>$ zyk4LuC}IsZ4y%kd_qy;9rR}`5lE>;hEG@+uYwFX(DtzwHK4E(Vw8|0@g;XLHr~w|g zUrYwQr%HKYDvDv0pB0k=S`3pa{vn(uPVr@uh;Z=&Y@XG|0U5IF_B0VU zYf1yXJ0nVZ5saY};5ocL`jdj0?}P|SvG!SD5~J~V$*nDZRrV1@(+&(l$$a2NZJw!R zY^XDKeW@wsbf=@R=gyGs$3kLbQv`pf>urk6Z?fuJf9H>5fdEZC-?TX5nQG6kU4vxV z68!!n#C;E)_tz>a|>umC*Q;zemohaV^GfXzlOda;v4y z&v1mMN6|s)LyZ3BZLH`h6hv2(48w*J=TQ$z?`qQMDRBxR=WMu~kp}sm$47z38MP!u zW+P*0mjEpk=T08K7oVQJN7OnDLps^$rzURt+hNC4#goTYLoul7c?nB*)jAB^-z;Jdmj!-!?2)0UNgeWr}|b%TjIF*4Q7JQ-`c zs%E$zt;Kx(dvk$PG3{LQG{p2F? zUjkQ}el4&KTGbgV>d>&(YMfog_IIUX;jNRe<}OM@`x!2jb8$+%gj=c~?o&8%F|AcN zIm{@=DC0Bt?^sPyiJ8S!=&z=$QW~1u>{nMq%>3qDtY0su(&6^a*YcD6adsMU>IxKc zBDWf|qKu`#yj>@V>o$s855UGHu`8PKP|m5M*rK%Vx3;wZ8ZQW$EqXeZ47LN5r^Z|p zN7_;-@1m@D7G6#?e&|haa1#EoVdEp1L_a6BuKZgPIW>S8Y6Ru}S*}*>ogz75bIBon zKwgxMbuOcYMt%g(UI#rd^2wO-1h>l7X1;!`sdlx;VpiY1fmOLYdLNJSkZ)+k@Ajrm zfolNvS~MAKkFAo*OhDdv$+DPKt-Jw4B`rp35)?Mw%t$W$ciw5wc*?7;YL`XLf{b8S zr`ll6pj_;*Y=)=?rCPbWNSZIIiiUV9OP(hk+PlIz>|(M*dGL4uIpq$6-V|)qBQim& z@L&sm;iAcjqVV+WdP_W*rP(M z1_Sw9={{XQxd{3T71b}YD&-a4-(nb=Q9Ct}R1(c5hlTy&7K5Z|LbkPVnvM@))W7AW zF*;GuN~0hzQCnf(gT9b9F!8ZvD~6o1__IsC!(4GZ3xsM63FSwXS;a%X8~s4 zJ6NVwo))XqiZnk$qj zYh*SQrcyo(q)oZh-T9@tNrhe1P&!Qm93w+J31|73hSHRgRZWnU_fDw4_Eg(jhaVfj zdSIVOu5~tMUL};@zlTVSPRB$-;)YqRKc51pR1`n(UuacSo%sR>0r~nW8Ar+fKe<*fbRe}cq_OxhSHkF_Xq@$3 zTzEUyP0kxS?y;w@uBJ-(I>5P^K;cCpAp}w49=wkyoRYgdTo|!hJx@Fwy!l%j<{g}$ z`Aw!cSuzAdAdD5JxJY{k04#|#nYh+h>4xawR$JuQ{SiNo=z>;&C`=K6J-1J_RTHP zc!fst&x^YWqV(6N4z#57BUHOy)p=5o&OM+knRe+92}jSJ?|U2bz&xq@r-IlpG-IxN z3%^EMp3Yg{d)#H@7$F}}I)I?nw`YQAg;?Oh$~vZ8Gp%R4d&GiC=;%UECYd=x6{88k zE6jP05V8}?6np;=1Q4fMFvO!3dMD-645wo=K9f(Wv-tfSmQiVuV^bN3K3Yk?C|lsZ z!Rysm{Yiz%Un^|&i)ZO&HM#<@;W0+B;`u^jv3`E1B#}cAB>44|)s2WRUS({ze)Qn? zggA~{sCBnjU;|=UQ#PEwt)&{Gn$RJp;T4b8Rmk&O4!5wjOkk|ui*{4ed0tNrDM6CIenD%6RBd}5!gz@(1pI!g$D zSTxg=TB*$M!H(6mMzvMEcsyS3dG^#Et*vH}=#0pQqS-G*Hi;k~Q{%{Y3%H~8bJC)W zDe-F8T_6D_RwlFS$4^1dh-1_ZAkZfVl2yH5M>GYF%BY)^l_B`U)!?!`Hq-RJ2xdzC z_4p>gUpjRvQ^)xodKtvUlvPD&CzT9}#e6V)qc2l^oP3Xdsf{q;^6;<@R2~-@R*c>p z40$BGJk>5yj2|>iBG8+s{BcVJk=^-?xf@X_t=(BttqnLeJ{(SoK5U^`l@4iWQB1QE z$JgLm{VAGa(O9Kh3^@@R=uaBGNWVh; zz%b{UBH|_4>tJv@<)f>zZMcOpd*6E=#VzXI^n8gI$9)GTGtD`a)XM7-?Bv8!ziyLy zWPI&o)K;wJ2w6&)EF;l$1CC7d#`{z@rETy4|ANJs6Jzi5TS;?^ksNN72rMf;zr(r* zuVjAk96o5Armp7&`ZAjbf+2D@ue+4BGj^*84cS{4GK0lF?68mhBGmKmAlCP%mEFsz(Jmk5JHauz}j+t+QHN^#yb<)2=?SN2TPFjHcz4&2j!LR|EUheF|xWxamE7@?g|+ z=5?4jnGuyLB1G$-@4!TZvN<<bZ=ublCyHo~c{woo9&QAF9$+azi&36CNgBg&lO8WbD$y=ZdK}Z*ZNuG&wf99|HRVn-k%sd zoU#TV=wSEFcWV%iraPUrMhpMR>k}NJ-6e>fL=(*cZfYJWPyu}gGa6bTwxFmKjWv;= zDkV0GTTC~P3soc`s;~5A%+$7R6aH&lN2v!Ow@T;Ns5aRhO-lxn7m_ElZsvb(jK=wN8bLq!&g74?f63$Enmci{&f-})d#)g#D@J$YwyY-OVtVJi_PJk9N zl2v{ntOnkfiKK5a*P*`n^1cVVpILyW0@D;#yMdas$kuVrYJ~9Cb!z0RIl3M`_>QD`QXr_jTIOrx->qMB_R_q zGhgzWotLbU{gO#1r?acE{3W|m#MN(TIR?=cKSWipee5PODfy^syFPAUh5GwbiG;zv zxgm>+9yrT@MY5MmB;*Y%9U+(zc@#IMa|k`ARqchA+r@oeAAo4CvwDTQ29X5Ld6S(g@zCq4z&2nXKuV$v%O(n ze?-T_fyyJ^-NC)VAjrGyz5R3;wZ0KAX|L6H1myfVH~}C4SC@bOj_<1zFh3$YMJ|Xz zE7(`7mz~JZ%Fn{~`K{OsfH+!mzC@%@`u?4yNH35GbUzWqKVy34TswVcQHTk{)#t`x zI~0Lh_KJYQ)|fkV6ZvJkqrUG8a-w$`JtXM!+6H=XC@7||maPY)3L!dU(qI)(Z?`9n zm+^b&2xrChgxS5J(ByOHphc%ch?uBFOwb?vivkJ8_mh2d@_Tg9PmH*$r48ZmKP!<# z;cu-hC$6B+_Ybyqyr6 z?cDMGcN}t}*noU|bRhK$_cWlAH%r05exnGrccfLX2|~0g0I)iLk0+W$D(jS> z2P!qOnAu-y*)m09v%|_|a?u}3W^(*Uq|-%kw%Vo}(jbYoS>d(4hYKd*ObD3IjIXP% ze{iL=wFkhN#Zy8Ziz3DTP>uh!OihD=7wfQdzFc$jJ|r!XMT2oLmIRMR9^R!-T%#Ab z9|O+MDc`cTyd1<@%t1zx;=9Hz}RC&3S_cNi!ye%T_QPX z`c_(h!PUS$@^)(bpphc=Nb=NJt0L-s&VKKUr1I}=KVi#_mTH~wWc(nt_=MsKkS|{l z*=}-)SP&@W6X*cwr}>F*34v>m8M%lf_>_K~w(lc-sVc-{A_4!piQQ@zGgC*K$gSSc z_O;(kB7v((V*r2+lFo&L_K7dY{}3_;sU-M@9yWQ_G4gPIEFc5=w!%-TzfxL<7T|5M z_Wf+J3=x=9El|F@+xGGe@mHHWeqdl=Zs0m7MO4fLEk?K~@U=mgiWQL0&nBSP=?Urn zj5`>-n5TmabPCL06@J$MS-U`ri2R~P8idFd78cIaEijfTiX)RmOJ(zdYka9HL)`|N zWx=P^=mww)e=$i#SOtQdtk^TTAAalfzNi`38EjOMl6E@Q>b|)WC35YA^EaeM6IAO! zS19##ABkOTyqY+-LgCnc0(VIfkVx2qyBIHo?ASBgxowhH#DS%hOGEN_!q+F|a(3lM zubsBBcU;!<^sAV9Ga>|i2u~nT`sC+6itp!%WprRRRs6}@W7s2wF>F+6bB#!Na{~{q zg-cs%nS-;IIIXWB=3NJ|jv!j55e2m{2}fO7@N>uW20p0g`mG-~2jvC*J5o+};E(Be zLrF9tOqI9?5nksX>j&ntgIrfl>$t5B&jg+BkLjR-Tb*vH-8l&L=H*2NUwF`rH8G_C z88~1jGj{W@^nEASql^AMZYNXdQCsrCu!pqm9`W7}XgS;CEicoBTt1mJj_6Zmpac*K zg4K{{%EScPN~65GmEF;rHg3=JXH@3Oy$c4rUh9JT-ggOvMVItRJl zWV~Dxa#O2)IP>6xfW`iMOtN>`mbDI-E&#F+NVx|bCKZS(jXEpUFr$Qx+;f`R zes(rt-xLG8meWGHB7RhPnCs8e<6HJSJrAWpVbamha%YfWxd%xnQyUN4(n!*YoOwvx5#*k^DqJV z*nvZ-H0mp#SGzBdW!rXGQb|~eVwsNE7(g@GfL)|Gm^H6k>v81(gUkX^$^6J77$=3D z4{<`!1?XF}SYC}dbv?~A$Gsa#3)${l=(0Ifq!@^jDheSbg~vIF1Ah=>Jxj{DnIXzz zz)6&Wh7Q4ks2KcP?Pun`;afu-ynl$nld6suel!E6#%$^Q>jm8-gm3n{MzyMA- z08R0HH%i)kcqZO;sJyAxdf)hIkIErlEm{w~s z&4+pE`if`R7zVKl6i?SeYv>-mDpMLe5UmGf&XveRue00ex66me$ZF_b3qKSQ{&ONJ)6a9vaECA6}Qh32T&DGr7eNY2FAMUbg?#1#rC^DaOV3k zv*QiOh?#{&tlT$~kf}|?JsF+YaoVhyC$w;gL*xVh*xU&i@^3)i{MD)tm5!&`0r$m zW0lU6Q)aH_Lo3s>cf84_vq)C|nkC`zxHNQ1duzEYXSeL!8LE$k_`umbnhkDXT=-W*3Qz#QKcfH01W7j7As5y3;LL9)wmX~QV;q}`g{M=l4 zl6~+yaR4NZ25HVZC{>;v@d-i4Lo5!~*UWPAQ!#JyEiTus=8*=Q5o-CY6%g1ftGa0niP zYvbZMhU4L&>M#)ZYL5(f%w9~K4lC{5FtV7_(t_rF8LrdUV$22URX7CO(ip zl}T%%)F{UL{s0w}k{I>ZIbFyGb^5zQ%>pg!wUka=s5eav@mJD!p=Y!xrCb5tB*W_J z>I^z0Za24+1t?l&d>fTy{}!o@P;_kU!QCgs5Ml11=Z6r2hNF58PX7|GC%sCyQTMKy zWCnF9u1~WSv0BO!8b=ve(*Dl_Cy?I14tKus2G?GT6+`wvQ(PX-edrBVp}KvLEGiYp zB`$uK`@LH{L_I28V9myh!WcuEU4H)jAzkV3lv2@PnI$lHf3eA;9E*%4GQV~H^y|3X zR0i*%$J9F6*Z2gpm3~0ekZt7m#GR@<&*L!YXtj7<_%g&m(<|22n=@&C4L`z5Dw&EumBInUaXlK; z{fJ4n+zcFQCulg7IeEl9`LSd(I47S{`FZF@L}8*pV)#@-HajM6S-R(F%4h+H(J-?( zj+9$9cd)-xc#t()!Npr20lHnibXv}|d>$O3szb_Vw~Ng{#cJ-Tjk*^>^iKneB)2v~eSgW;0N_yIlpojWN@gZQ-UEU#{fw~P9BZ5FKkb(zI~7Adr5 zCX83>w1`$H69Cj4(PdbOc8e6|6>WWjiYNbqfJAI^OS}g6ss8uX&i=`L1OF2p!>UK>#O;U!xj%3I^rJ@j(b@G>zRmiBSTz=%%Y9{YqDYN91D-Az}=6L3p_c5&V ztp1Tx7eRelc$HeIzhTD726e1zN>|%%9r*D$>yaoW$es0C?xRsh(5U>D?-Ayd;t~)L z0B`LQaQZcZ)vAGA#@*{iOU`Dlvq_ZDK&8VauI&A^=`T_74Fc*+GMWJuh~s4lCusrx z^r*N|(`HHj>R5+r=%)8IB&zsUyJo|qahCP>sY?{pLDf_XGN!nS(>}oSq}MBm!#AJ; zm0`N;h781!ln&AXbtXf>z^)6#5sLUdVbY_B*jgkn7vn-^v2t+@*q0>VPMRmaSdTxL zfizPiR zO};zmSjV#ft(+$c+~aS5?qIHfg?vTTIJ)9*kN%mqLMOv;OtXH_fVa)tT$q(h9bBL? zwKzMcAioAfWz;MuOM`2p80BicPpL+ae!r#`F_ypGpJu8`uU@i& z`laM4mg3wG>Z2%3Fspw1=M?FjdR<3@WzsGkQcR`5Ae202L;oJKLBG?aY%A!)>5}=v z5jD&WchvVEm6(}d%DUkdGv&<}pg*aMRNaVmIh16N8Nc4wC!P=N-D#(<{bT7+ifZ4Z z#92hagjj9+9}q}5PSSv-trsIGkx=t zvafP5(t)op;q1Di=6jO9@Pt9~JM-N~(JefZ`s2;uNN470rAGm?ViCTObR|#+X$p3V z!(lZSsF`0f5LI!$atsD-xD1aM6nl1=$JrSezosV$FpO`dCvP;Ha-V8`n7MM>FAerK z1ar#>4V6x3o2C`vrFjuJKt@$PohvXNCDWr`G98%H@lbEWZa2}T>_Mx6(HoUkvvRPA zWT}B7A;9{Uh$sHU$oVZ^AiH@NE5TABCDTI}@%?lF{^&&jOXo~ zCn%D)ehsf==P_^{y=Dl{zSo8;$A0t~wVl@`X*B0#RP+s|rb_zn>d8NCdO@uZz$}F% zR2Gw!IcNA0pxPBz+69ot7;6W4B3?}vb(DGTdZ$N;f;*+8K2l*yn&)o*fcMxs$?;m6 zNjmE1en@4ORm32IRVkqt^csF78xnWg@s1{%MAITVGtinZe!eYPUF&dW;z^E%rA3|D zzn4AFlVb;h4@BH|ZXGR>HJ1uISyW3XVbs`_q#lq7*^%#$H@135ORMsX^a#PKO?}8o zoxbWl`?M|A8$VJ*qMdWv@4lN{$CE36qRD_hPO(|)E1>c0vzv@8R;jdbHFr#pfS1x2 zto2}DNa$0NB?em;aE@d}r_mX?EYvhilqU_tv}Ir>=#l?``}R1~ZJ^R9V}h&oQu=Ae z2&UgyEa`8R0^#jP^%7TyE{I`jlcIVbZr5W0=6=d=Y7U;22?{hDBrdCs=I8&0bf?yw z3agl}D7yt3?>tjK=o$ZK+mWX&sF^(BK0i&Er2MmI91FUiFw9eBJ}wcyp!Vp!C*= zRdEvLEGIM2tOma?SL<;B3AsV6-}LnID@}RY>rhO9EUNJ8fJyF(_+Z7S-xQnnC|SIOBhY6 ze0Jd;U$=SfIaYqsx86b&-jQFRM;RHrT?0@(s_Q3{OqL6SQ|VrE>SuO0Lc zyYxbb-9HGNUB^2eTyAch#Hop1Vo?{jnninBS zy+W$V`c(;)eR^4VH2y0^=@)KdNzK@~kx_xqN;$liD#3;>hOBQt2!8LQU46iSt-be^ zWPB)>Sv(U8#Zv)R`iF9zY|BhR`lzZ~wCIEp^m!JeL;lf;r~m5_1>E$0M16`+7zU8`!Qocf@W6R~9;v2XatUS!SkL z%8A><1j6f=J284?Yg%74a0aD-ilMT8`w`i+=b#AD_D)@KNo$cF0rqBEbP^^N1I*X0AJ{nlIDOd#lR!L}^PR*Qm z0;fFI+DW)OK@-<|Fq8E&sed5$v;2H|)*^)fcx8hqV(@hzVhiY-7@`v(_H8yf0Ao#ogTGEZhI%Xx4Wni_&b(P~L!zbto+vVkE zxmLzN#w|xXY&$8B`!=*18IBM(qMX~8{e(o$N;vW;g{ejp&ytF2tX5%o3@fBIjXvA4 z(&DaMBCZ$$U)$STW99LRkiwK2#$ipln0ZU=b}~z3_r9{E@LI%5G0SDI)&RR_L6F@^ zfldP5>KVl8|6w&S8b0gE3HMJdCwyAPIxKNJOiH>UuDKfvEg~7h`t@2&u)y|$a2ayp z7pag5gPK>qiQ#L+h~*k|EMPu(W|jn0uezDd79Hv`Ict5<#*ywIpU&;+Lw7l-^*(Ba7;wG+-7GaU5!A*dw*bIK@u?KAV9nDYY5K+8Ux8V+Azd zPDM0^w218d4l@&TC^Tfdnzxv#7Sr*im|kPZAX1`(*atk}q`l~UJz8Mp(8be6Uo?aU zu)-iX808r`SuZ!0((?cjeh3Cge~ZoIKrvz$l)3RZsJTYsqK{!`Mdu4tlXWqK^@)up z`az!~0H1xX4{U>y)`>NmSIzK4KAUDO-hwP~jD5WoO@E;l;pgncK!j*X+WvDly_f*S zyLr&mUvAqSMS{2ciyMAqGQJi1_ul*g5kB*42X;x9Vc_!9+!I9^bbNhMueha2d~Who z!AiF|%c>5=I+*+8*D<~0YY*4O@7 z(4~Rb{St>=qKVfUYL}fh3fNkni-bV*Xu=9Z(X0^XC=$Eh_KEnhX*}caEQRoG%<>}Q zKY+7^(q39-k18}r3i2~1>IiphU*Uw%_661t4FcJvpi~LnHc)8qv`HREtGFv-Vs%_|Hx%a{0cZ+?=q?Q*F-Xs)TZnJE=U8p$i~qGd)nkibJrWB!!KUsJ z(7OQQ5|8O;dk&|xq#A6T79m$U7RN1H<4!k|kz)zTCAHOU0yt6aON2ds)@y@*eR~68 z>)rj90+)U3CU$-+@Z>Fr;wVli>h#^SID7+hOR6Y(VS=sIDpgDK`*bK9HS?O!q$NM017cJsB+Ai~rMkBKf@y%CqXkdro^?5A8=NN~rO;F&|H4c_V z*2$)%L$Tj+^GTr5biw{G#5!CMCs&sD_G~>K%0Kul%X4dNgCXle&5#h1H;(QjeuvOC zqopN#>A-ALEB77epkAr+y*0KJVo^CePLauAr%^|n4Zi*$=fm3#3Zu)SJ{CaQ#7E)FGO>zyfwjS!Twh4J z`{xCXES-qtiV=zQvC!=_zn(O4^Q4zSEl1Vp}(FQHLg%2Z4upj(zln??c0_vb3@HnUykHzr&NMUGj=od}I zld&srT(ENiZ?$eW{^>%+80+30o^lv0_qy2)Hr!}sS>VpdUE%{`j`goQN7yDMB!8{F z$Z)Lx#=yWsF07|hEnXx}7IBosBxt*E{ob=%v217Tz{1lcf1YKAzrfdNRB8Wziw$;j zU|NIH+wN4QNBL!;f{igweQkP5# zg!%82y6q3Jl6O#DpnyyvIS)GUKYD-a1JE zH_$-ms0i;sn5*#smDfjhpKs}-e6kDROnjPniN}Xke*9~+w$jyyI%cQd-(0+!^Acvi zdC_t6#VOD~F5Pw>stITY(O9J2*+NJd!SB6w}20_J@(4 z!tlCd8`GKVtw~PKJOg);vWf09V-`0JwmRtP|0MRcp0Fa)J{P7iGY}vV2+^_EO34Tw z96!Uc2)rX3zMFhzQ9dlXJYxmEW~a4}pO(TOLkcq@7rsF&B7BWDF!QAf(V1Bm`{)2$ z_@wtZo$t_EA0y{Ovg&LEH|vELCjGy-tAscIj*GU_19U6*{(BG$Ny&)(Su(%!3Z$FT zyCwyRnQ8=NgUYl6)}_n!Z7GX4sXg9SjM6&7t;>_EdZ${vcQ&F#EO~mz z{nH|E8K(S1d(XvV|3B@3%S~?V3S0#g*T~|4&aw|SAb6neb=J%Ga{HgQgH%vKbqr4O zXa+PPe^Hd0Q~r7U)G5a%z%tH$`+0}ROx6=B`N|;*g6A+QEE}`-MI8)_*a*Yb{(+H{k{X< zU58$cM+0An#$?&5(4zRmQ&AGxy59|s6+t#U6xb?ue+K=|+-;PblP|)vSsKz>GA$L> zb7>ToRTzH2Q$xG+7CE%B%!n#?)+5>T0Pe%vSPHwsd0k2HSj9tP{%l3rbgb59Q9%JH z1Ntmkk_$1nD0y7STCP+|SuD~PPSmW#K3M{ek7NJfXfoZBVxm-}r3em`lKO;>KdFnC zGIF7lLe<`6a<6+l!DXgR0Z=Y==Glw7-mv>O%cUQGditUU1^!725dVceQ|01$m{8m) zYZORje5a#~s|bRWi<}35ECMLT?cQE4m{z)sBpRb> zU-^RKZkNJTMX_8PI``OB6o5OKSFWvc=q{F3O2(xzFdfJujIM|1BRcM8D zRl6}EF)9uOP`=8y)$D`!h8b}9bTB<<_2>3yK1?$48=yP%xEj)Z$szLs5Ml;U&JYv| z6MN8P-6rl9kfU@crnv)n8z(Q=Y#^;T?NGr?Op;#zkRR!G9ig zOR_+-=P2a;uaR6QacmNs576y>>!P@|IpwGE5xLh%Ca@Wd&Te*NgCH@ZskSIqZsPp$ z8ZS@r*t+MHZFy;s>LXdx`G_jfd;HH1e(1y}ePtDwwxu>@SN2;4+g+UtiKhPoejYcZ zzX~pn$ivnx;!@76GU@e$58NdX>qeF0hu_m?udBtT%ne(y}xE zVys1uBiGA&rY?55?BL*z3c-UT(fuj~p47%F7M8HLi&SKFPMtmz;4|~Oc*Hf1oW~D4w|y!D<3Yhke=IBvhU=)k&x)A&bbASw8L#6nO;E%^1R zXiP+QtQxCNxDbgz!Ul??`gaWvu-E=3k8R5Zb4e+NiSlkum>&8kaNWXsF@Y5sTz(ii zSufU+5Xu-V58NEcr|}%tut_4xM5~2?)}vH2s3N&Z4`_+8WyfzRMy3`kbyt!H^7k>( z`K9IoI=|s`At;}?Px}Vj&gX!%W}uHTi7k@`IUvS3ad8t zTW=qiiHUIMj1tkT;v!|!jD14^ACY;nGPnIrQvkj=JoTj=IiYJpqb^>AvbxqKJOqg3 zS}Ya|o`IPvuz5DT2@tAleW0H=>0?+<5`k8QfP_xFr|9vCOe#_JP1Y=?+DY!>5&i%y zXtO!$PZSRFa3#(3{8JH{+}LDGJ$#22kUe9+2pGNcoN0hISiA}it83Rtz9_c`n%+iX z={QsIxrQyaf5Oy2ox%14>9WyBVZqL-b4V>_zQfAs(s*_hAe)J6#wC6)h|^rc$gz3) zs)lcLzXwsXpnC5_9K)SyYn5m7a>Df{16t-wSq0e ziioDcZw5)#+pdLHc?QPMy$XT+_Q#!ldc0@4boYG`c}3I>uH9odRT(>uSAcSXxlLaO zbd&2B>ACo&|!N?$speFTMw+`lpy??2B~`3np{AbhQ3zdA1GcY`9>^Cwz_LzlLJUHOH^ z0MdEHiKx2EnICDzJe>ab4-aANIF)q*Bx@}p)=6|SPl|A>ERF#|tsFGF+(x+{q=8zz zu&k7v{>>yFVS>o8*)?e?Y;#_?lCA+a9pqZ?Pl;;rbf!giZU7d=rT1^m@kJuOv2vcV ziH|-lB34nS2)qymFxGQ@@cqrHll>Q^-7aIG-ih_~XxJ&Rpf9F=CnzB++D|$O zNsi({1(6~`OliMi%_8AFq@9gPZ4NBp!B zx2+iUU6gtWZqh2Nv0#Z?Yah_3MlKV5dj+ah?ke&|`mEfLC*iq>wEl-D47ow-7&7sI z=p;kCs!j zu6v5UDy0?|vMt{rg|@`LM_cpab}>~;-u81%w+$yNp|Yhp{GVbf#ANf^gcI|&x)cs& z5On>`^ZyhbUGHX^wCglBHjkM9 zR!_cPpm&s(#;x{#l2Oho89_Y4_1pw2k~A@OBN+-1>^4VD-{hl9I$s22QYSBL+?g6KFry)BIS$g9%D3lo z>pZxF-#c;?KA3^W^H`C!VM;<%2FJKda2o^R$?eX$thB~M6T|yy!c=VuMy$S<@;Y%# zUorK3uiU<~A3j1KuSDyh&J?Nt(;q?yi@R%lpYUS#Ck7W(cMb7OtQe+fa=8jx-}VlN5v{d)`|u%u;pw> zjfdMbPj5Sn6x$V@N4Wy<8K;@Z6K~U3B0{Zh@r6xp*i41$G(ZkLvVFAzHWL}pnON9 zM-)fOEdSgvLZ-}O4oPhNfn1C4I7m8%H59X@^hG2&)+Tvet5vjikcE9gfM|I?x&J|&dALu zRJ(Nb?^@KDWVyNa>1%KA`jXbm9M62!++Vm$bD}q$`vy|6$c;`kUH2JRlGII<2Re}z zRXb&KbFfw|bWpXeJ)~70#U;L3x03$nMZn`Ez0KY+6#H-Yj%%ul&|HPqGz=!LC%$`P#y7RNq^`X&1lWDU13Q&{XIOpwZnUH2rBYvP1$J`L3Z1;NJ zA_ZQws60n0_J-Y;Ai@()vdp%<@H7b4Rg^98ZjOn7Wj0c}>P~;onH8down-Hqrvx6y z9cNX-qBsL|-=XOjrPRc65eM%HBA9y~zx;O}vSSWg{H}vLhA%_peHk!Hzft;|rd1`X z$0RrAMu^RD>M%(K-KXcNpm&Dfp zJ<_)cD^uSxWFCy>(A1nDGDwN@aYiyHXGk6^Eogl4dh~f@+nk1+)zg9g$H1hk`!xiYp^)GVJ3FYqNh??-?=5Az=+M2dweBA{bA?IX%8MRe~xZPj! zkB>GUAzoL55PUgCRHr5?gT};RZdWsFd7$u2zI^hZ+p`i@Ch0pq(l@ZK-QQ?SwcHNN zE{z+7TrTyr8WqR;hu)L?AEf4HLt|*J5q$dde^A@2|5(bE_COC@5MWC)RkG;dNvCQ# z1e*{}uQ>m6PE|Uv?|kep{9_*#GF{X-kM@Qb7b5oYVRcBkEZ< z`=Im3Tl_-qD#iEGWKPJ(P+(S}!tc0wSxpGh?9@4`7_uJ9Bw514nc+G4dLtqy6(0wA z{qmCkw;KuzF&*P~tSOEMWr=Itd}B`(rpj^0uRkQe=IstanN z{2u-q#-DxtD*sn6fYlxZeKo2qJo`@@;zgjdXc5RPvxmigRE;z^nYN zi)MIz`S%NYp6h$|TmD=R6U+PWX&o%E`){{Yk=u0^_sP)YPwzq$?K_;T4fRMbo9aF% zrH$h_vkAAi}EU|Fn(5)$Linc zM7~$;-`OqXpn!R$N(|d^e2TR*QOBaKDvkq+^}b0| z2^Yq-@RC1Z>h_w1XL5ut3GZ3|C-|3@Di=N&JR_<+Rq&{1G=G~wh#5zuczGQpm! z+^AJuh~UdwYD>U)Yh5@pRh_D%itw0n+ZWx2a(fB0#z&I1(&}0QbvhFwt|dK481J$^hA*(e03gX!Q6Oa*mp1t>V2%?z(ukApt zMbf1TU>l-E1-y-*TjnUR5X>pTt#g684Z>VwOpxJJ)^85>h$M17JXSRLdfjM;A__{_YEWP9j&K@>P5 zQ^Z-@sR=^t&#a#9N z>89`S&SquF9z<&HfoYfZelyZ+ZBF<^K1YCjlpw3SiA&|)-nUDJdNzLTVgLsfEg-S* z`QX-J-U5HM+$z$l5Gn_Typ*NPc{QXXCwbo=Z9uGZjI&gbOQt>+tyN_$)aH|a$*DBO^iv5`Q*+^53MvsNZtROZ{=9Q>-h?u1}W zbJYI_#$;rj?x)s4(^c!I7eYtl_`|F17b`7+9~mms__tQ>rb?x=0!6{Tl3OVQ+6wz6 z-)4H#VeimZYjcSU2r-+W%JK7vj3=MYL75i~1kj%O4shknaQ>sM3SR>)@22jIwN@u* z?=}H4uP;U>S@s?}O^$jKHRL54Ec5tuj4^#f0-L>TFi4nW^txO0?}wT9C=?h|kBaME zSfEH)sOb`MN51DRXWyH3#L|-~!u#!%B%1MH;X#OBfKymZ@902M>{o3jrqP;eLeV!UM@$0=1?65IU*;N#z z!l4r~)4Ne5z%=b=Eq6qgaQ~eOYvoy@oqgpW(XmCCV{ei*OQ^JcF836m-?;_(RcHX2 zEs8*A#Xil?IsD@9gH8p@SFm;&zhd-Cd36xM}sX`X4 z+Q*8TJlZH8q%U6U@`+lmNI0!H#bKuTi1W82TUUF z!br5${mM(9T~4KD+99A+{ds7X7A3Ld=e!=#KgI<{syMnC*P-jiM%l~c2d>nAgBdrjqS#>;6?snh-4A* zHu~F+wS3WOeo*4>wNLy*f>uUR39_jEd=Jr*#f^et9Pf@5Oe1f~ux2jADA4yDlhwB- zT@zO5_WgQxrS&wg>|v`9>Zy$`>9VMSff=Qx=7V2~LF$UhVLJ`lYDz_!mGwTR-*Red zrrLSrn;&%4GLtVHkQBUA1xG3^53iFrO1g8u<=sk*L(OyfaR{i!_LcR2_xmc>_;9fc zAc#0Agf^2zlUhS4PaX{liLG%NY|x<3kpY!0^h6{%VEoMOklFVw}Qy@P-rl zh~}2PWw3(;RAyI2`KDFr%9~{un`&DYFlCjS@-L1@@<9C74uH2w6CfX+112WNQSjrN zvZH@qme`UXd%J}wl@-Np14|+mfitK;+4U19@uQzJfLpbX_EikSCmsw>vZCCf{l1lh z{_hj&AUALnhT@l?$*xy)!JAPW%)Y2u%ofi+sXR2;ugi03xHhXf4)ll|L<3Ol|Riugk?TsY4jPI zVqhu?xVHx$ku8%Vn7fE$uhILMuCn8kua=`$rdS8d z=YHen=MYa+rKLyY0&U<9%{mIyRh zIZrR}7^ZHAr)?%UaWIn4s)*p5 z)hkX3eP@<`X9)UW^zS}=hO1Ea!Dg14H~AN!$0$)5t#vp^Lei9|u}5Nw9p(g5uPBL- z0YJ^D!nm}JFZNAeeD%`TeOHCJyn=$*AD4RC4V(gTe3{=rMDqlKc1A0- zFE0zwuogVB80KgL)+N=%Zvx!nF@zVul6VhYK{f9?@r*v0WlQWGTFpEWcmQSqpAzY3 zc@0JY-w*#>9&^64KkfkS@1KmH5<^rVp#k!>LQ1DAg3~y5#5ZQH(|o!ZYDKb`bpJ+~ z?jAk`v~64zED*EAaUsx&a{hQDZ3An)5XYknV^y85}8Lq@XIG*`-?C?>b4RQi-X=cs#u#;7&W>mvus{K*To^7!wss10sb6$ zmaMpu0w6QmNBZKaFQ~<+@9B-Zwy6&KIo`@N%q3n(^7~@`2sU`@DYTzO`Yp}7p{Oa4 zMU$Oy@dM?eZ~SZSB}sM8Epu0ZYlDm-it-jvmMJXYuAZIh;J^~f;XXpx<0(w+M1UdR zu&z<%OICYsj27uvv>wxk6~v1MTX?3?BsK=@A+PL-;ngzM>u}eju5D)(p5)&t(5K&t z(sE$Z&sPRmqpzy!eSTP}3k7wCtFAl^aP!<Dd#qxa+o3R4n zCy1*BXuq)m;)L&kgn|Thy1BtSUL)lx=NTWIx*iiGB0yqGp>-O}pw@{0Pzc}idNo&F zSK%TVt-Qp_mTBxHq|_97+PF8u%|S7h|9n%3XUs`q&ouBV%s_IN!3%ueBs^zHT{{>Sej;g?I8*o8f8Z`}%g^H0e}Ny?R_(DPV2lM zP6r@C+ayw3Bch54#xT>uHp8Ok^lYXQs* zbvZ7+Bbw0mXPIO~nwMRAlI}sB_yuYSj#PfXRR8ahni3H0$mwlwyL_x;pfXSMZz};1 z&lVIrc}+MAm|EZd9;;-Fww9l-BEBz(7I+M2aML@uVGrh0%I5ku?UO8**NO7|Zl(uo z5Amz4c4Tia#HVI5=*I09Cq8qr0=yvbF-XUfy;Hi8lY85_x}AV(#}tA&QKt#L;Tgjg z#fbyTv0kWP?r_vN+u?80JE`S+BxVv#gU0J;5Mxe9GiC{McO(Bo-Fvy*5PvzE;ZL=b z<>p77(Qw3qEuoY|9C(F`!jQQ&CA}XJ@wmLi&~GgRib1b!dAXRrf&ENOOjLSgogLhl zA0}zV;pz2T$zkDr%`w@4n+H*NB5$6qMNZhQPKy|x_b1c4R$}xqYF}j`{S!Nb>6G(C zdp5g_4>Dap8%$2xO})Z7T=-IZtoxx8*e&jIr+>BKW2(H5qs4NXD0~kI-Ti^9jY2_@ z@IVid0PsM(sxnzz)w);sL)G}t@zoqY<+*72!c*akFkGU`CeP18nn?;|bxq=n#52KNdgH1Q5HOm{)RqNSn#$ptZAutjY03Ol)w@#YZrj$d)>nqyCWhkMIYD! zA8{m+YqGCvgFf~&y()T+`_FqUogYwgX(fb85EUM*!~v)NU(~IukR_xXou$+=+!g*J z0PJ>R8LX1a`6dN&D;c>8BTAH$e@Q>uQCe{SA1X~1zqcEx;d2MmJ1y~TA>ld%q^#$o z(7kWIt1!4^FTM5FiowKS2KA@c@@;_JxX$HJp=Mt`e;)WBC7zZL#KF8>55`8i@mo~= z(Gxnye`SVt{nRp-z}QT(+?l_I_$IFOw1)^L+vtFUB-ISqSFf^ZhBP&C3UvELg)qdH zX~+Hg;Wa#_P79le$Rwn+F3A*He@Y+W172ofm-vZI0)*rEM6x6={azkX|@dWACvqtn(R z8)+l{oCVOAx+Cn$!wdL-8DykPG-KkPKwMlq^yffGJXHDVGQ%V-0K2@FN8xKlrRbJOXAsEmZ7Bb z;Nv+$QD(gqXdmF?uJoy-G|iGx;8dt}H%fw> zIK1NXGYw@I=t}k3oLq7H1p}NyePpQ*a6w(@G34>d=3Hww)h4%g5!u@O@^h4&e7iyw zavc4;+4NNbpI`3O@NN}lJ17i@{aFPNOS~TRASFzjyL0>J<_n~Gz}fZoW{yf#+53>! z)in;s&(*-8Br`?K=0u3)m_qVR7?8=$}V4JBu|bf;ulhCFXLi#q8) zWl+ikI2MgcL@ka5Hf#O9@~sCdUj$KT?`VAa*%ai+Ju`#Bj5zGGB7wH$yO{8v`F^ke zz*S*7Ps7R}IO4z7P7t>4`mh1*+UmnCm+8EpqjCRy17HxYz;}U@UQe1UA#+KaQ-G^~ z=$RaM(K-3Sn1!mzqPBtZ?p=_XHrzK76RI2}Ah5Ymqj-@8Z=Q^|0DReTFXr+vFm-EV zXpmdhtMN|0R_1@yicAA?8Af-KjhsJ?Cq?(W#EGc_B^z(|f#r4_JcI|6{2cW)QW5yG zmTySq0u_!$pTjP^6L;PD35A7|>+Zf=GE7g|oPvrF3o)z~s)|{R@^{;H?+E3KS6z<# zcOlO0sa+Lli{)grVsi$v(~{yx<~4V@t7{QsV{r1(%2kruT!!Sv)`<$Zo`HpKwMEF?vt*wDCM3JZ*b$eaOx$AJjmqsYg{ zU;q5$g4plfhaBk2yGprZwmK|Zyj>rr{1yZqHI6{Zn77qwtr9$UQ0E0(+dz)o1Zf~a z_CDV@MAcyo@WdI7Xx3iNxPv7&fZm@iJCs3QL@bqxOF*9KRPcnkK*?2Q5nYyu^5wd{ zZ4G*JkhBqI28N&2Q-_2(%hz`wn>K!AF^LLGjkQwCjY@R=ungtwLbkMtOp~vi@cJX# zvzoBS!f`DmFd~GxG16U*0je2YMEe1<>p={T#3GZEEmoy*!qKFa^_9s}>yPvARQ3wP z@lPGqqcQM4MRTG}a)o^S;NbfzVe99?S&>A>T7s+OA^#&+5s&5N7xyv(x`c3^Gpe&KwnJ)8Js@6J zd2tT@iGA8&DNr>MofQdG5*|-Cq7ZTFCKFnB?TL`z=j7q)AdJ~k3U*XwVI^HWEJD4L zZn6H^nVs5JKCp_D>Wb~Wx7`{;zf~%bFoMDT?!$lP&ieg37@JucR)KzlokmwyO%hUX zl8U(Ny3T`-KGedkCzs&F{^9OO0GDM)+}NGcif&-K0|wC?Cm!8#s*V=M=Pbr1t%J!u z3%5~7lWg;h+reQ;Dz#fOVuP)x+5(Jpw~69OQoS5-U;^;^7n8WaZ&^?v7zF?STx@~azvOtH^rI|Vj6{3yq3Mlb{?g6!wEoD;z) zA1W*luO)W8M-t3(d>U9Zt5)iNJ#IH=c!%u50-Zw9uHc<$E#PL^DV;%=pNEalbKe#Wf_Ai;F-Qldc`EG>TJT61Hq2rV}g+lx$j?2ghTuvV53nf1RbNfW)OQ zAZbI_LMvPbH1Qk0$*5m>-9sq5=#ckb2`GN1e9-iX-#;($BC8OQ{;JP!qTe|qMwM3r-jstE5 zX=rB`rcb>K3;?41k`l(*1LY5MA7@F>WV>l5bxnrqnURor2UA<^IV@+PGON^>GWqA! z=ZR(+_)qocO~SY+XejX!iOvZf^;d7{09qGwWPq-hqg|}O+Af)FdUd$( zmDtB!|Mb+B5a~Lt4Nz^WLcEBbLfLy$ry2N6&l7j1Bdu{T$!1i}(5o{zjo5V1f>>gx zL!$k4Gpj-4xfDAu#dzr%GP1!pLdZ~yx^1i0L z>KRYb%seZMv59T}7#@B7)6XbMlaSJ+T6_C`CrhBwCh6smNx=3{ZCh$Bs}Vzp!>x*U zeJTFi=l3|f)J%+Fb#?%#Sei1S%xU4-H{0>k3jxat>rPOC9NOj>hJf#0#&}+?7qn7D zukU7sT8nvGkK!~gPd_r0a13S~I*JzWy)PDv32{m#FzS8uOY}FEX*Jn-PFkc4_-bz0 z7hP47bfNh=-qloA+2+~6IxcPBVzLmyxX&Z{CG}-qOOqHCK=mO`wfvS;ynh4pWb{D^ zEQQqbxDYN#*hAtVmg^iLGfyK1K^3lhP~GQ|JX7BY zOkbG9DOd^xDN8gUTJlt(wwdu@O3H{!5ZxhFG<=g+iwD6X%w z&$iGfh(AyeFQOCl`Qq{K69IsXP9+_ZhV0~Mln}mTpj_2DeM0Uz~7Av;|`6Vs$3ZE%801Mx)#q%daP-z2y*;dYM@GaT9j!P>pj-OM<9 zlTvoBj4nd9m`?lS(JE7c-ImeishTd}Wo7$WOZsVB;OrO_dC$KGkvXfnsgS33_R zIzJC3dH|j}Y`>;OifhP|*NNMEtIyKGXnsY~2S?Tv7Bw)wgjft}jJsKi5aZ}`v|sN| zr_pqr$I#=zhI|hxdt3uVo8WxsmOR~gV=eSXlZ^6z_;S#IGvh)2k|$#WfLc1(Ez=5%9!`Ph?hscqRQfQ1_&8{N(3>S>r-4u7lwfk zzg?Hs+UlOzZF6r?SbinIYcWZNEs#0+pLJWgb)e@M1oJRtiY7N}@>=ejA4kY~9o6SO z>^Il=FDR^1jD_|#qjwxZKEH=19KYm{IN-19T_K9Y0hVFZAmLJB|GcQ2KWX2O#7$#_ zY%JWLs3vZJRm!1pE#$Z|H8C`Zq)L*8M79xw=7*&13p+N(UCI6|V)6jwpV_P79XKf( zBhOm~1QiOUH#f1u& zpolBrDZ=&k725RMHL(&}lRn0x$e}k-XEsI{?v%JeJK@DniVDCA?VXW$#o^Vjo0ABh zJo0J+rh(?FfY4eNQIM^u`R8O;%c(j}z-`Q>c;7*fX|c$S|2j?z+mqV(cC?O8(GSom z4^er$`vony%rJA0%wbF^=f$Kf@v)~WKibr#=e`0raMR~8s-Z-O&+9(W-{sax5;hx` z+y6H8y5;(27PszT7=x#2g+J+s@@Q{|PzvU?c7kOoO9<0(7~oB^Odc0{@w;kzgCPj^ zW3oC$_`R}$gi7yKnn*=t=xXcWz{txv+8DC*OS9V;w&`pIvd4Fpf3$Kk(7(IL4PGRK zYC5~f_wZCzbhM3`Ea-kM9j1E1*L4%VSZsn_21#wLWMPcbxFBNqXF@Nf1b3FFAQ+uo zxM?W<*LPW_%E_%#h25Q70c5W??>XkMAeG4WdUnB47hCTUo9pvStjg&Ami-0W;1X&P zs}(k?XP%;o$@9c-7PgD$WM}yUHC_s$`LaM)S7dPf5*#K1qCv%t{5GgiXL>}7CIHd^ zjyAF`JOEbQyLu#&Q7RRpI`={9_c*;+9{aFZ&{{DM9%_*CBr02)9q&_6*OsVUY{z;i ztGo%CYH*pmC6olb7+?PbKlw60R&1h8gi?%%4Fx+k>mn?JP>K@^rMIT9DCrXNU75So zaa_q9r(GLIm?#lmwisbZa^cw2G`NH5!dWnMczFuSNqT=+YSnEN+AH(g&U0m(*GAuoht)PXamcbx){2v)#uW4Gkq{BTQEm zAov^j_mx#5?=no6jH$(krbEf4GgB;Fg4r!b_Ad{8r(C7D>(F?Sj0S3SP>-b zHKXHwwWw77^yuaK=E50u=>^tnF{n&vhlkLocrgwurd)x>1{n;LcBbCr*~7(ITWxGG zSu1xV&EIe0ft9~XV^zyuolS`D!IEHgX!t{G@w4E%MBi6%+X|tPyw^%Qgp9ujQ?Y`j z5}7pES4hC{7EvB^xu5tuP<^;o0hmn0rq|l)X_5k;!%Sp-fj6~^ns~l+1pHC^Gan~ zp};G+H{jC?#=cEQ6>Uv;IloBqurU8+ZsIY_|^dC$>x1TEW#J9y6)|n$?c3y2;YEEI%S1?NS z3QElHQJGEvKtW>&Qp9nqOv=|6Ta2*4PJm7M+RN07+cD>-_EY%p(>;3u%JhTcYT5Hw z&Grl9InuAuHjB@N$PdV|u=Ns`v3Y%j09w_wvQsGbnTi}eMZCS+C6PXCAsq+N4OX%~ zm{6$CvcRGsK-#)taLX;^&LvI|lW-s`cWfZyjCoe!0J_~}3@VHOL}uXt@)^@v6fE~- z;bAxqSQTj>gq_;6NV&@k+k&8ONr5Rh!-_&dzOfMmc2H!(Cv?}r-f&;2*iU5F8K6hs zGW0e1>BR$4BcEZIge3mhj9T=;Fntc728|wY5_SlpTm8SIn+_-a3&H{@xqlb)J%Nak zaG^qd2s3=h#1Mi`cn4IQ?Rj(bE|J~_b2OX1u`PoBJ9czfELxL*ze7w9Eae#EA8bwX zKRd+!4U;=IOUgJ~;R2uU>H7u$FqDvks>zzXTo!LVd6pU*%WQkx4V=+ML7|`f2dK^w z3XED^@`Nk%z0v#S)Oz#=1?QgN`H)v@vxNn{y&Pj5?)O3jIcx{)EblZExy1dlWCXbq zoxBa+z{NO}ibbJbD*}2-aproE3HjmjIv-MVq;jcHWAXX1r7;;P%EKPwm4fA?3{?DY zBW=qg^?_A|>BLgAF8gI|{N<3z5p{&Q_5va}n zU1Y9AN_C{BV8#8JMYHFvNpg$73Qv_fU!)g?Xr1aaYEWT8?_pVYo8NENIPxMtc12=cA=6Kn|Mx`+;S!>$fM{aPCo#V+siW4@guqsJEX- zcqQk~T88sQzQUQCq;8UqaLXMo$lc-g6TGf3T|DeqB?`wSDdNyXZ~lE%$lC|^LnB*# zlijt0_3b$K9;ykvz88$k-ESMnxKqBw@gdwH6c3U^*6cy%1W9BP;q}Ggf4zAJE%d7= z-0tj?+l6^y7X~YM<6lN?rPvuvz+prog8g52;mH|RMGDoZEVMb>jSUkMJH1|!nyj{A zBkPLAfQffQujz2{tQM zGpr9vg&ZR#f;VA5it1(2u`TI80)7uc{@;k!nLg)@{7A0dtZEhNyb^ZS-ntSPdvnKb z|7ogH;P-aeaJVMVqP3*?s~(;5@O8t^_j-+KsYSbE7N?1SzO$tl;;Ps82=q5okuQFr z12uykBi#OGu)EdHb+tm>$p#Nq$Tkiy6Yx*0GtzWV=SRL@PL9wS^4qkG!07B#ha}P| zLWldCxFe{B7qbt)zo$W+Ii`q(UD!>`Q{?+hEgqZ~OZfs3>Axjm1SKavY3a2F3qgx9 zfy86sfy|OE2~ey7aRC21ft}6G-8q;A2buFLC+ipdzu$nIJXz}L^ID*q;f#DmmrB;$izC4t)xlKF{nMeJ%LK;=#Jq z0Fm{%njI8K1#yLA-75JuT4kb{NpK1KfM9ocq9E`kpGGDDQ4gjc#kN0jA>MvX=};** z{J<6uyEQX5<5hFk=heFErBJr82*AX!j-L!ktBZ9ZaD8$Z%}P2FPSn4`Hip*W`uDoM4{(B zkw2{JxK+@7{(E1F#%0W1@7?iN)0sqsam-1CcGl9s8k1#BQ}QnFC!E}2m$rwU_Ujko zA2CPMpMJf3eHa80gYAsxm0yELwa6AtDs~7`7^xyfCjm(`@Sejit=K1i1;wdw;|xux z4&SC#fmzG|M(?T7i=<28%AzBvW*E#`C$bL-=7nI%WmVAdgDDh3gYfcU^Qibe5lZyh zLz&v0q$9&G4XvGT>KU8#?qM!HtugLi%#_h3uqizoxPVP9vP;%2LkTs9XTOvNTS#}WY7S}%e zeT*tnB-G74uF~uoaC`g4B5-QJXDF?J21PDbmKHHl;*&Uvof*o}sivALZC#C+mx(8p^P`1e+7N)P=2w!|r% zHH4lQNa0>;Jl8dnneZZl?*oaCi*9o#J4dw!K#Mu3%lV~P2l@!~8kII8fh*>Ti0?5_+R}mKWV@WQ$!byfJYtB5XKpsR_s8qPMj~5H_bh*~ z2vF{bFVwBPsZpA=3ZJ?dUbtg#7oMosdQ*>ET@s?vv8hY6BQ}W>O>iJX@7l{+TkEYuTJssaK`UXp=x4~CrYRn1K=T9`L{1ma(wLFa!A6E$7 zwLhz#vuLq8=Pj4~y>yXA!}pUy7r^z>tr307H<}wg$MNQgArVF* z#4i_SNsMfLRy;1if#=E3lGZ^f*#xg8!DB71nmv15-Exp)*xk5~m;j(?f_{QB!D_03;mW*xTpmkq3| z?F=`tRqSh?5=g5@sl2d%p~*A$n%mDYBX z5dCLorkcRGP@mK}ug$gAGJcCr`d|ho{!wZ7HjfgJxA#m@Z~nxURQt<(*%xT6*(s5u zfSiKQxnKUGaV_+CbElzHs}jP(WMW8WHER5NSW zY$&)+Bbb?@DGX#7>g9eNA+2@$txf!ARHy#v+Z=W; z)cZ*Wg2e*mTkW?oy-S&Z@*nGVN)#>yRoU4po9uWqy(uvp-tTI|hrQGtb|^^7uj>rm z8E1(}DRU~W-E`$R>-FJDjkX)t8N;2D5i9 z^FP+y)XOXNMrv&oHK=cOko13~P!il{*U1x}Z6HdBvGn-c;JY+qoM5cU%^D`gtLkpG z;IydLWYjnZ#Lbk~IuoMRl<8l!JHJ=7^BnM+@Cf+7FAz&ve|OEMSSG`NfF$B|=EpJS ziPNuy{qv~zNpx1iu%PIM7O4>=O*Y$aGZUU=`99F9Ul(4nV zwqzu$q1*y~wb+|7J*DMn9VKitecUFshfZEg<>dA1`hn9!L4(qFiWZJbpK-5+S}rmY zHNcI^YK?uB+Zx;{h#DJmkZ-%krL|C*d|c(X(sTuTC=TYjD{ON1n}bTw>V>#;in85l0D)F^}IiZIb==^AD(P zrh~4FjO_`}#PTredMKd;XFN*u`_88TLb|fy%5(`)Ap!fBT5)@8x8Rh==ihk0BQ{O` zXfIMw<@t|3OaI6wLV4CpX?$c-8s-XsMm$wz*ZRPti$_m8FS=pb8!IF~#^9O3ZhE_k zDUc19l6hhq{u~) zhrKet-2-d~B>w>wpLowBl$YwqVGc5B!nmw{O96;_L=(_ikpodLNLG-`aDkB7A$7Tq z7Cg*>1Ogj+{FTxB*V3ys)i&-HZ5H9x{Y=s#86!DLKI-nG6MPHBC6z^lzFLwJot7-A z?z4X94XKG?AxP&>??7EI%6XquP1r;K%K2CG&SeBva$d$;w-&eZWlZ3=-3T?uCKo>G zanOl8EEV`wt@0-Tr@S!o$}XoRA+#esmkD{X4RCy2BDQqqNY*{?>fX-8&6hj4 z;BixVS3Fhq2epnb8&JTn&GVjf(+7(t5w7(GNosPFcnrOCRUQz59g33OYaI%Z+;%1o7-&p??Q9ET5V2hXE=pHR?lNEknnj- zv}@D8pD$GwiQo*l&~iK?;fq|sqsfeXu%m3Ap|HY1;p+0>#14K)Q*-a7GihVa;KRow zjR7X-R$If7w5=Am8l31&M~2L7wSN5&fa4pkMisHuZAKCGaAv}0IC1}~5IbK5h4;Wh zT#WVNF!A8SMvt8GvXGJR;E~F0d6mM7=sKyI@4Aw#|M2UPIgwh8v>oSmSTlS!{p?8( z<>j`OQ@){{Ys4{F!JujQ{@KYmc=_hUnP5%nv`}Y}1_?f#V|lDR#Fjmxj}MtqGJ=r6 z!y`WJ?(8v}tj@76;d4(0=IF_I-jYbh&+$A9(c~VawPsO|YauY^VMSNkGz zu}QASK1UBhK*+z4 zWLG-fi2*ijX>fUBAv}(gA3TkagoAu|tby`8MXOm-;S()P$KG?N=9K2 zKdi%R45fn~4b(;fViBXIwZBX~+Id(iXby)}s!77;eAB;tGO0-dDff_wc)_E~?m@?+ zseB|enG9v5&0mirjH~b>7WVa?y5;JK!NIGDL`w^wyxhp?-bV@^pKrkw$u+o(?R12J zAijcz?(*XcrKS_jYjI>W7326q9u7M2dFW%@{R%!42)(iga!#+`gyfND2(|HYDi>?1 zL~P%`32K9jG&hje+mf(!SYLg0KB1kr28`yhx52s!Dj@s8o@(R2JcPLXx!IQ()zEw` zv|8<=MmQyMj|p6r>(el|N~DkO42*G6JyEovMRgUr_a%N}a!Ky~aBGVx8Xz}O^G!^9 znBUVzZ@wK$N#SOE3WS6RbY5Ja>;|%|OJ; zupC!Da97Fib~MGv&Y0v=nb`PWq}t-mJ{%$~X_{cObx}EXV)J}!d-e4TJ0jIW`0orS ziY5R7Z#ZnHr$K+pq(&QuQcL81(f9%@Cqpc@5=&o*m3%$Ralc;%9Ju6He*b35(`62P zx)KQd&VCl{gvy036_KWiFO^wyq_*2a@%tznPjM6H$!I<72?g4s*Q5L(7=n2*%Ah(g z3%aXtIhvA`mP)k9HfG~6S0^84KfhvKg}b{-mnN!agP@GRwV55s z#pS+6V)2q9b87#^_x{M~4@etLc#eX=>0*uO4l(EQ2v!ZE$Tx8{xc=yRJJoenwEMW~ zViK3^L8wD(*F0Dsg)J0ONg7CPw<&mwsj&%5i}Zv1tir77f-R<&5C2o&6!OX^)qP}AO2+7A3XHQMto%)y)+qq zAziLRP=kU2|I+Sm{nI0^$!^Jo?%Mn-CV;>Rm-Xh*`B<+1oo3(=^^!VGA#-vo?Z)M_cqpd`}JB`~4 zf(nSExoo%xGSzY9si)F9W`(lf5WbzLurrs8Ff02I0Rw+yE@M_|D3YJ^m;6sH01YuG zuwtwjgl_8W!cX~14=EzM_tV!X;9`IM>I%FD$*^%M(RZlO&qw^f=F!T@4~I8UcQ=~? z>?eu#O~rH5Mh3N-dt|rn;GlkZ(Ih+U{@_DTS4q)&HlMwF%7KI&KNxhG%it*JjZyn^ zOdt5!S{#rKAlBE3Mk_uOb%5Pu;vCHc;S1pQeDkNBIT_AD+FtuYpH+P}g}`Yl1u58N zsS$c#9{%R8(63ut@X%+o2la!$oMOSw?+@uH2#+MuiV~SV>s*%chonI{{h8yVS~gGS zB)82j!Y!7L!Z&t5K1RVnw12-oZs!mOD}#btR);%LfoCVA|Ex`Qym$Ib34nle4LTRW z6!g0=XyPaEBt}nRD|?)wc$NZ_f3rldeueygpIe8t)%8IaU7NK+c&awa_?Sjp zpM>f#cC4;Qtb>bM;S6VSdAtl?dTS9p1C_PeNae5kxast zF>fAEQwZTEH*JKCYcH06pYif#H)+5|W|Crgx|xGrLz1I?4jWMZa8dj8hT2=lRFpm9 z3nXQ!%(~h$_a@46p5pjE2biMIDPNl%xoXb1vg>9{yI0!cAio#;!eEDlgH>D@6r?{T zHtR2?Z`BD&r8Df$w>g{->%_?D+Zd3DOM}ND$Pp*KL`Wc4R2!A}*JP!XrNzXOKb*P> z{gax=#ZO{V_dkJH-idi_cd%5k8!qW2n95$-G32!Q$gq5zP>Yf@W+%4mblwOP0TQaG zraMB~zJi+~X(`M~-z68uc}Hy0U~03n7b^6Km=wh{&#Z#p&9Tie^hr;oDg|C<1-J^o z8mPRfsBT#z&$_eSiu@_Nflpid3_{REDc&qa{Vrc$@&ZtP&YFeb*$@4 z%)Y!J%sMEcv5DQw={X6G&#k75Ht^LIw#N6gQlAEo`G}xJyWUGUlaW01KW1$firzUX zx2)**u_w6fuZ@t9SXxIe(N;!m;ad;$lb$kIdX_Y+O6C*fe~v;wUgHNo;Y%7Q*yLlU zgkrzH<72&Qz=dUIh&T&`L5Z+Cohd}qYIIG(TSXIYO158s(UVI^V@rorki7jq7~*vT*_hNW61sYF;0 zlk-fvolZ#*%E?_rt>&3=P`zBx-8(qb{3n{!qRv;CN6REUX76i_SB7*o^*7iS6(tdi z8D(E}4YgjIUdC>j`N%DQbv|tPEWSKBlK8SHpH7%B6d?a}6Q$D4-GY+TH5LnVKW5?l z()$gdTM~5}ECXaa6UT_f&S`fk@&_ej(ftIJ{F;+QmF@!}m`W9L8H<5yZS{J?14H?C)*apot%i36^}{dcd$;=I-QprVkzG91xj@ zTZjY7gT*Sk#3O?d%VB$E3?!szs)48mC&ig8K@y26tmK26D7)GAe?|*He-01dFNRDR z-qU1Wfmkc7B8b8jQsGXz$aRx2VhF!ak%(py&AYWK`*>WSt1mT?I__d3hTMc#0As+R zNggXMq3OAq#9e?`X2l`bMH+}MH1P2mxIr&BoNS9i!N#U~xteWeb-lE#K+hQd(W}?y zNi8eZ-Hcun$Pw^}K$W=tEGnzD98Ws0Jm`V~|4PLwd(r!TPjFmCBrjQWGy7~|jfiZ< zBU(o&nR$;Ze;N{6e@+5hQzXQy(vxrsPHL*1CI7-uQtxlI^ymJNrw}r7u3VO?i@Smj zm6(3-Akan^$c=T-YJ1rzKm5X!CXXB)acm^yC-V%45l_s%4TUV_Zks1;gR!aY5?xk5SDD#mP?1+S$Pph!(K-Z^DHI61h9H<* z9r6ji2?^g99SZw)|#va%guj4qyIOG;4>KtX>geXK*~TgK71R4^@+Z@Fjqg%8*#UPAOa8# z?%&_OizlUH3{d$rVXt zId5(ICDbZL6H6C6M@N(#S^Rq3nOp<{C;6Q9xx+mFUiD8kOemg^2W~f<`V}{s;|6Cl zt14ag6kS_3G0}$m+(1Mo6Co&Wzl)5|r4=r@oj^eSK{GOLj z)A~LTmxQ&%Ixi)PXp89WEEEy?=*v2`7x(G^n|aYb2DRV(*^p$~g0mYZ zh{HnqSm5P$;lJ_XaSx^l=f2dm`)JDoS=EU`i&$Hu-D?~O5GzwCm@Ma$L;2sJ`an^S z{bOUW47q$}E#u8L%SB#QAbm8M$-H}9^j1OY#H5n||L@;2w1YSYm^zd?IY+{2w8jRL zGdQ^pv-(cEXSNvkN)~Im*Yo1^C5>9C->GcO@Fy3sVIRTD(ku-@^EI8!V-Q-hjOcWt!%)iaFF4)JQ zo$rnd$7!WniZV&GrAxS2&gh?5xkh~b0FUxM^@@2P&NkLGDBe%~R&Jl#%~Fxf6|CR$ z#^#FGsonH(uwx4HZ-#GZD7vTDYQlmj9>1u4tI+|+VKryc;=5kwI2JHWRCHpq2NjQP zajV$fqwcR)1xp{I+w+7alglRl*yXGY(U|1xV!spVzlDT~4`xK3I=y?H?4Ky0W9_8b zzOTyZcL+9^fR4_KB%2(4Y#Y*m86iJ}f*+g1gt}C{O{LB0^8zs#NyrCL?WFc^huLC* zb=JqYPZ&JdgWyDRL179jc2iheeot6{XgtK#^rVvBM#XBMSl!zwh7vyr?cnoy3L}$9 zfHkHFHV1__fr;-pi1k^L7tIY_;&$vv5#mb|E2|yDUkUi4O6>{(-{0RA%Y46HKRkrF zp3MDBk2^~n*!BB2^g9g%C}0F>L4ZSyk4@@{;?T&oRhyeqULO_YOH7^r8B)mMunJc^ z9E;)Sel`cY)@1+n$-y>a0TPqz5XpzJ=@GF&%zOmUa34ftgYk-){{5GVE@!x{zqd-ZF3uT334^RKV zn8#TNVr?yiod$sSz5%7mLo}I-iyU03GuuoPMmrPWA1PVt4SR*ag(M5vIiZjUX@t8f zweQO03O#BGF`FHauThUTTYIV2YwT=}=T2sRYy+U$Q2tG^y09R{@q2Yu-_GMALb%i7 z8;&bsH`*n?KV->LWbE!-li^$>1AG73lmxK`PjVfxCF!ru%gZ*y4`EK9%dX>*#YM=a z8f`FGG|iUuk#RK}!`lTbz~$hLNs)2bt#QG}f9J#*%!*$7t7;0b5-+NhrFGqx+c)4H zVu`{oO-AW)U#)-8vC{4*ki$<-4cU2X#bpdR!t!^HLm8m+$}lT5B-a>}c9Ph9CYJFaRO99(fMv{cr*u zk$@jop;Y{H$fcZw#UD8-?7xFNFmMX(e($SH|KcJ>gXtIowMvPgh*^o@?rNPAD~M~I z0SIlu;jl1W60(S*0g9Oe>6lzpkm^LD$Cpm0X2g81)vY9rCE}rI%06@leH(}h;{x$+ z9sC~75Bv>>i8?Iz!i(ug5%YhB3+^+J1AcLmjG;{eB4jV%)BV$TqF?@YiKoH}8u?E< zk3EQe-rdA5M)Ro>Ov5H{@1hy#q(7a{j~bmbLA80$#0IRo-qHK6(oHS)!}gE z%>RxnaF~_d&yu%TYPN>Fyb%BP19s3hsQX>@U$Y}NFz#)L@c*Pz z{gvu%yS~LC$Of~i&nNSxVN^;0 z%?E3}Zg+xdgEkmY2?_`a2?;8-2F@>x+JoOs_NH+_3i?XC&m6Wxd#c0n>K#0&CnN+s zl~xCLLmVl@auyKwih;vrj{ifyQ@?y${$gEt=2Fjf?)k6vjU5CO1@-hk4;`yBn#a7p zyGxnjFbThB0^P(VlgaCIF_(BE5(q=$^}HkP&(F_6S*E-w6RS9x1F5kvwpn;dkF5WzXl`{*SL=mXAqv;;%=bz}TH#kxVWhLKLOs!6z zw*6KIVo3@p?hzypOJN+Y(JlnU)G)qyCj8{Lf7{M<7J+B}SG@=l1;K~`dE768_}`$T zTr9U+Fz!!Q^*(%s-`YHSh3Z_M2xl+bRU`%ui%?D}`w>9~pI|7+DoNQ!j%!SLv3Ug) zZ(Yw`K_AGX5{#S0AW~lWg~uIj2Z2!UM7kcnFH#A^4WGjsSEzmT`x)cJKe0Gou;OHH zEhZO64*>OQw3x9Rl`_|$o%4SxQ!_X) zPi4L_+d+U0SP}|P=TM+t9xn<^)dWSDt^~6lhE_xqUktTOTor9Ky#jo*MdKXElnx)%W5K~mp+JuUH1`GNf&({ zUPASYR-cfCa|%5!R^hu}kiKkA7O;Ykr-I03%_0+Wnk>OVoM&hk3oo_Ys#F@7a2Pb7 zEQSJmb(7THAXK4nRrXTTmwVBY`rrX zOZ0mXDRbd=9|<652>zE~l(E=DC&G=>L<@+-4X0X0Z;Q9Rh&MbdLn66Miw*vtQL`Hs zs8?P2#KyzWjrEpCn1%>f7DxR=kLr3F8h`!CZQ*6kDhry9_gf$7YvO&>K_-||>VL_1ZANQ~CzY>KF2g)Iq!4_Qi$jQ@BM7EF1&>Y%42>bBc3s zlGlM|s>{y|pyCT(<`B5aA*xlKJdG+mf(=8xX%&iGTJs&Rua!`}{Vw)!%+xc_YqeUz z#A69**Ydwv@v2rUQ_H^WivPFHCHhRsjVw{_`w(Xg=i)N}+g0e!!tSok@HNk`uOdmw zX1fzu2BV4m1m{~lTy1h%x(<7(Cv}!%EK2@&FN=v}KHp-_od1J7go6b$(eIP@w}Ae; zCd|W056R%wmRP!4y-utM1kBp1SBu58uC~h*f2GudG7f~X2?T&?W|IsFyze1=-r zd43~yckK4*Kml(+Pyip7_1LHO4~fOc+4X+8xG0|c_e>ZX^8~Uku|GX;!OKLwLfmY^ z=JLkg=5J@qj1@|qU<`W!L;#5dB+3NBPe+*n2-!w%rPj+1q3~>*sD66wj@&;wcHRFw zR|EyWp-tPRK&_>@FH)o6LdYRL>b-s`yYMfaZ@DcLnEt-$=x!%#iHM}#6e-*#rQK=^ z1^)8*O`TVDz7*pgpMYRz{P(<}0}%^jsv-eC$1rGq0@y#Z2qD+xA&BnJ?(tKm!;>Cqad@Az%254l;6qix@4on&|eI_T!7^m{U23 zpquoc09uf6ys#>Lu z1BXS2lCI~n4$>^w31o(Il9qC|sYG#K^IQ(24~?D^gN*CnuL-f*SCcyPl({`@K`Gzv z>J&Hp|JHa>G)S?tK}IHWllipJCDMTMV!w>tI^cxU2>0TVVN9GfTI{Yi9tpl2M;}fI zfkMp(0JQcg|G<`@zda3z{#_s5-9Xsm#{*B`OabUSTTBqznA6S1%k+0qEQ8R`_vNck z`~jd=ofhapyT`ffKF~q6V;~U-`(n@w{`?0tp?&6mVbWEZ0dNzL_75Ncqc{$DL)y9f z3xec`fiOyQMnvRTkof<<2Md-3`uqDkK5hAp=CMXB_B!9z8gxZEzTfX|6AAc77IAZP z@3m4s@blxK$_I~BM1OJ#qM<9w#wHK;zqmles9FjIApyddx?DyB*%(FKnRS-2{M@g9 zhGd?fPtZ$-6)cA0@F?jzcE80DGx?_C{m|=GI>_g9fF-WtvqC!ombEY@rc%mgK|v!CLdA)b zCD6;~t|YQbxMQ!>B9};K3Ck~UYjyZy`2KlD-5W`Op2}vMn`s#{G1#uHbG%Vz{>D8r zS1PUPmz$1upH{VOw3O?$abfp7(Ru3Uz;JYqPWeh&lp2!qg0 zl$-$unfK@S1Y%USB>k}OAN{Qk+r%ov2z4%1?&e?AL*VT@x3(M#rQ_DFPwp&=Xi?NfZ1%;#67|G7f#t^ z#{~ibKYz5}8NL7fD)>4a+H=ltH|GhmJKO3>h2&esx`KVt)W4%Bwe?9~hibP9ky@Un znR9U1Zv}%mScMiUltk=^i&hmuVN^RiMPz_6XESL~2G1f1>-0}TUQdV-`P|S4JdOd- zoDCwlOvhHDe3kwZa+y_#NDQkU%oR+?ZQRsGxX{+!&DUhLihp}J1#UH87A}#%YxvPG z^4C_43`U*>5o!vhNn-@FBQ;C^y|QcOW1_b8-8R-wB@0nluJa;pDjm{m%1-86ExBDD zpgKA`&rv(xJrb<+m|%V9^2YNUWfD3Q#5@OAfp|NvhgN;7jnCwwbae}BZ!8mP`JsjI zqFrx|_!py>#%OYYhJp;v>VqJV-D%Tq11V(C;a*e-;_l^2Wz^9w-*3Iz>W|Osbek&y zpF>=#)>GkTTgm73gR=O6OyYjNqFBBZAgovCbfJGMPvv||M>@Pnw_ESueB&35N5jcA;TCByl>)A$iJ~M_av;rl zeY`xN*XZ?vWz_12jAPKkU_hSCwC=OFx&DTG2C?8$Bi5G-;&oF_zXlZ z+8owb#OYjc%V1P6cG!DtUiF7WBoLd&VhdmC05p|&6H1hs7cYinGIl{JAJ^BjCQfp2 zSpQ#pUlkQc7p;i~cX#*T?(V_eLkQ5gySuvvcXxLJL6ZQD2lwCvcbUrn&wZFRv*y0t znTOj?=d4v-RlR%HslE64zHc)^0Q#HZ7{#N6+?Z|0b2#xNq72K~ygmY{%ti{Wc4kqb zvwbgcs?s>ptFrRo3b~z<_EO!+$*Or)1*dL4fIEXF@zRADZ@XVbNJOwklG zR=Uh=-e{))tMowU72f9h3!Khs^Hf^tbh1VD7PuqjS}$)buHIhk>$L&)oOmuM8Uo;hamNqN1;3+ZpdlTqIj z>KAD%)$echb$S}oPWl3N>a$$_q#-Bn9$DuLLY>G>*gbo(L@w0D$GysS$Gs?4E_!^j z@0JNDtiF8%mnjaL6Z?O_C2~+>`LyBU-9MCjf{v&9wpa2=hT?Hy)w}t`81ZDsvKim~ zl5OOqXQf&7JB0J8vpQvS|H~qSQF>Pj>tdl`K9nBWs4cwnt|`L9;UHCq6q%TVn8#ra z6#>1Y81&)2UK=HlBBs(z|vFcOrp?_xu8T#$KayqZ+>gGJ5EQZl5x%Twb_vl zDTF)QG^Gk-mgVmtoUamlYO5`DzR{=jIx2BetyM5L$7ob}*X4v&jz3ra^WDwS*GX zYpsg*Zj-2XIW#V|Q`q|sD+R7}z@&=FF5`U;(r}FR9|i{Ij+Hv5ystgb#))6~8C~l# z;bm;EQ?r+sSg~T4ZlPF2o+-;G{tcqi60FK&S4jAr_EVGzNvIV!AtbG7!_sLCDUuOY z>IGhK^(X!4kCwQt7ZlK4f%jQ~M}oaTobc^=V34HDLCG|-6s974)_2VFl(G+_OJazp=TmtpO)n1zW9`l-93?4qF*}lE-7RF@!SfTm{LCZb)R)PyU2Trt@q0uICh@G5JAhQ!{}BGT;+Zcu z@>~{2G}tfzEk&@GKQdtuv(cL>lhP8(!h()6l?^XQPOkd1V*h6jEv=t=XQC~@Yv4h& zbPRtC+xa$R#JaWDEjDd?%u)AATL^Ymj`4RiboY}5=F?2R{_NR6ug)vLQ-C%Bn8Dqw zU04kO;_X`jVYow?LU0)tawOHrt@;#+E>@9^RGPXqD?|MW6P%{!8Fo2qorRp$d&gy29rRI(a~Hj{ta27nE=kowxn9~lHIbl-r+cl_e`y zir_WA{+NDlJyX8S zpGuHu7nzdt*1E;YZ|#QrF3|{xkZ_r4lE>&dyoXfH+Xh51xoc!imT{OC$7EzLD|CB( z8{zeMD*_Sj6=>9J8 zngEwelRlR=C)OrCpb~RV{tgzSN2?9TBghXL-5%GVa5E9rPiG*?xvAUUV z1xtQ5yF(Tz);cQq7FIB>|G^&U1nf?g>=YjhMNJif@~-LZNKq9*ze;7Kp%IG~T5mwU z$?`|^Ibbz9YA8vUKu&LkV)1u!&JaY2=7x+$VM;0V)j{# z=8je4Q*;4fWIdPP-##E)(k=D-WLF{OHg3SqQ%GI{!mL(0p6E$*Nqyj(@+-`D9X5D3 z&0$F8yR}j&lv%{EI`3&fIS=2%EnNK6AXb~CuTY|sEU~?ybNRdw0ks3Vd|Crn75C%k z(fcY5a(p-nnu9eRQ85xO%p$#^&wnuD3(}giCP^+LR_4zmo_=2OrvhZToDLdJkY8v? zc4poIZ(WX#+i4P%)=Zf^%9FcQFZK0`8tG1TVP@~lgk;QfVmG!h#83!=rJISbpZR4= zYC*fLA<|N_g_^sWvk8HxIExciI4Xx;9>;h_ss$hQZo1r=Rawc$py#FpTc8*GN8U-} zLzJz_xF1z#AzX@OOB_+o3*{#nJ({;?tKp>3NmBfZubTB*Xk$c?z8?i!?4YF)@vzaN z<@nMAAp#mJ@LJ9OnvXU5W9gWDa@r4Eaf%^zlZBcUa^Fz~qX!H5(U9=?L}69b(-l|- z4eIjGB!#?+Szpo1;BG-1hN-ZroFE_pnXL-r5R`jL$K>iQoX#ec?_U@GaGMmo&CcdO zkeMhu-FnQs^*kKo2=F#LyidCfHOW}{sqh6UC=N2n`ow=5>ulLpNMx8;!1?YfZA3pYd=%ST*X;;-f`s)f`Dh z)oFZWj&eyrun{K8?#;07Lfe=#y5=_j|~oHI_u zWRb{n7)8WmS7}WR$fFCI&deQh#NU6^Vx}eVJ@f_+*TmmQ-F?h%x7VnxPp@b>Nr8*b zlDmVuariJu#Oj)oI<@$#W86lbu=~)331BCbt*begGL{#ZHcpguS9g#UpR)B7D zU7zW&613m`47@ti_Kmvz%}6q283SLZFTGMSVzYEZ054u+Nr*uXE413YI`^b(S3-kw z*}mAV4DT_WqmBFC1^o5wD|tU)d<}-<><^tB_&12fSCVwTmIKN5{x`TnTb(`>)kLUe zk~Dd6m7VPU^&wU``)H`SBJP-%dq=sUthg05ax`idq12no!J5jGw{lXX)p-$&P zIA0RFT)IcDAKu1(IB*1U^c>NydZmi#f!Ozia>{qqQ+dJ>d)3;|u)c|jL8h-K1fNXa z&|o>iOf(1thGT3pg+JIYdKdz~Jxvf{1SpE#> zz_0ZJO8Q$RDvXJr4;)o8)v)vN>ZD|YIYDCmR*fnG_ci@m#Jia)jPNc+$nXVh_ieS= zJACRAbM$KGU6m%5h{%j4rQxa`s!!OP>izc2YOKaNe4c%Mls)N_S_BFoAkhx!P(5dn zZe;H2ato~YqCq7wQ8teKfj|W^+J+%cuW~za28g30rfuO$Bu(G5L?1=BSj|8%qbNc$ zx7)7;8F-vU%IP3FtA<~tG})v4!0 zF^{G268dF{FM;IS2`lbVTOsxBDVc)v$1Wv zUGY?-0D(DL+I0PMChAx2m5m-hq&^d0lsO`7&sK*w3bj$3KLIn{vQ5ocjFNXgXkhYw znHm!1(=3f8p@FAVs3wq*tEg(IONrc(b!%b;ACHkI8j9s=IfZy@kCUnIH|#`_LM)+6 z)WF(|^=}O*d8#xj#J{}8;hYPc8Ut>q6PLA!pp@NQV?(b?%A{sS*JX;K^kiwqqbX)v zHhXC#=)B)&V%hEXEbWY+g!)6aLz6!Nc89-^yl ztxX8?@4r?xZvGVI-{eb-$x=;ra{hhF7_6@W{2~RWD2t-{(Q_vhn>`Ev8T@N z#HFom1zo@)i+U0cNXJy-q9KTKye-M zFM7ac)N?%?$0KL4GvOkol4XZ*EV;~4i6 zp)Bs{PZD-cb|_YAB+iZ5LUyz@8x8XQ*+ud|o1!Jt@1ahVN*vURrxh4ndtpH0I7`On z*`a$EDik9(#wSCnI9?*>dOra4L&>;X1+1xC< z@pbB>u^RWyA^a%!_3j2V8d4_>P}4{_?SqN)l=o64U<_)lX)b6@&urvBXV$582RZID zX)NEbaJG^GN|=vmCU9bRIHZo}BeDY6+vwbwbKep#_?b1Jk17kl6^*Ln;?sbfJn81 z>c^5t34ABbu0j1tDbjyU>egC9q@$${Hm#UQ?ozoxk0+@Q(B^9x&7Kyi>dh%%P?nno z$tcvv?#QtO0!x4;VKnBkAZm41(nSkt8nU(}7MBgZyLx;CewlNa6hhuuD><6VsD;o`h#*;DWto_;H<&@Pp?t!EE{6jVHnl_O2} zSig>Jk>0K48<|+iY2+J;qnjXuisidFJiQ9OL9>R!dAP$&_EiHe*?M#97^pC9lT}nI zbYplhbZ~GBXk6Rbs3&ef)Y{|;q5i^AbU~b40*i}45)AYf?V63v5|PD8vOrzv++D4% zr4r-(&QQ@LzR1h2sh^%6oB#fe6pBX$+(LfGK1VUjksP!E6{a6_J>HTiq<2GuFiH7G z-DsTyYC$ZJlGowIc<_d(uWOb`@bIfVT!R14Pjb`eNMhKLpQ0AyxhI33kPTpL^9r0U zh(Xh3A!^tMHUxg)xCvdu{^{tP0eD@4AfVs{S!-tZ;Q)ydDEQ)-=&);t&%W9J{gxGv zIEy`XNsP-70jwWSvsVaLW{&tIIo9IuGREt z7KCx?>(wJJ`*9zK48P;`O9lS!aB}dv5!fcN^oFR4=j4E{ZiRYi4(gi?_aan)N zrT-rU&wnsOCjQyeZ$$@oE^#kcS^qiG0+{hYqg(#VykG`4JZr;*?*3CF3Yh@qu_ zPV(QE`)_0ZKXnxV(bjHs8T3QNclZJ2m6buNIpK4y%bx!~@QO%P_)vcFcD-x-bh0bl zf*#{UwC&MY!a|7cfqx&5|GQ^*tN4p@O)4j8J(;-95s5s$1m*w=cb&G4Tf4ne4HwUX z=a1(k$;0gtl!v*6_CcQS+{#b9VEefUlSBaI8GpY=D|N+oBqf=m;6!w1piK=}&CgfF z6-w+%(R%rWN8#BMo!P^^d9ULy_>>K5D=rY|RGz{8L$E9alOPx6QF-NxQRoIWuq$j^ zGQTRS@arbf6o&D4EVO}-Im{EiyK|moip%*`MtZ@X6qX>~==%z5#v zorqzaBD|kS<7Kf;9YT1Y{{eXSpf|(-h0_rPVW!pc-{C;D#O?7vgOu?%`Wga!^XEq; zaQUj}kHas?(joWk$d+KF<+7k_gxpfo{=sKZZ#xH$}TQd%%ptZhdAXg6hRczd(d&Y@2l&c}0UsDo=UJMGreM;k@8 zYxzt4(tDl%qWHH0|92=@hC*;3hX~xRTwQhe*y$GRPxRQU#2>ETV$5&uPfJXdH*WlMC_R9YX@Iu0B5ux<`my2c&5KXeY zRhoBZeAFJVD{NKS>^^jsNr5Y|1O}n!)Q%O)%}E>1!8S?HzV^m)*akWgN(6dOMiD-& z&r)A3T`nb(`NGYmEI=<5I1zid@(?rj4bfCB;QhZ)dU9+GbQy`tUJW^Lm?nG{atQCp zeroi%fg-$sLUFV6LjmRX*>C>?RHgXfn+c`0YZ<>(S2UD>H0|tE5Up46 zj~9jt{so&V#`{PjMl<^C-qTrT>Qiz;VI`ISC;JCmq7dmsT(O z4w!#@zAY>eAcd{aqO>rbR&jQL$pQMrpXG8kyE~@bwlugGC+*YlW}E+c{UA~JF&NK8bGZ|IX=MT=J>i zc5v{4qBz<8NTENH=a@_-#7G4Km|fmpVD5dkeQzJ*sUXwBgC{s2Y& zkrsv?Y>^BKmxrP*5Qf4Ao$kewrT|w!fJAKhLY-xr{Qu4A@e&VqQ#DJ06%ID<{I;$)5KPGw^+BMlW(h*cbU*lEbMf3 zLqKJ4p6G7AK`jDzaG*}gR3*u-XV+#cQul@#b1F}E=7wnO*}b8mB~&9~fnKl!&35&N zxnKkwV9YXkG1j2lLk@z%tvl7~E;{8JG!7-q2dTZ47o!}c-coO@c;>LyG;@*ksdeJ! zJ92xKCm5>>ga=d$gK20jZC^x1pKf2fU*f>+5dt=c-ECBxB7b%|6Q~JgqeBehnZpfu z#vWYHN_85xHH942o-p005K(yaq`Fv@ma1I|q;_&+Zg-Y^9BegFk?b6Fk`IK54TXU1 z3Y2O&5X6d5F%0*s#Psy^G=*H4TJUptRTo;l#u8f3hL5m_YevEKxThZ+RnoGHXMWk_ zH&bZyC;jV3q(MTkkH35AYt}ETS(e9L77uSN;}O88mS?|~be15=_Wng+RXR}$d5Q>h{8AY+ykp@TF9|+mj*<;ru*73dVeE6knaJalX zS;BwZ;5fk|H!$Upjs6RPQ>H)5q}}?DfDrx)YEEc`0fFHL`%_d~_(?1_FX|s=!@{x( zHgn<}!B+NNSK@3Kxv%i>yA0rR*0rx=UrdfySKgjr*ZgDNiFCdEBv$q!uCd0y;>pn5?dI`m$;K0(qBMBG zv6RMq!=>Y}&nc~_|MF6%pO>9(rZt2mcQL91d*_7$*r*VNjsXo78;moSl(a6^9 zh`0|XIpiq@Tc#MCvR-^W4~f(`CQnDl9+f8jaZcQ1?GxG-m38di{7DVFFk4*!+yCz1WVd4UgE09c4mSI9wlqjy%7_(gSFVV%K$tfDAuP%ofqdggXQn6;e^{& z4<{o8OTYb=Lu4BfB2_+Un^2n%r+KQ`PYd2|F2IplM!I~NInUxHq3Nl{Ek(+Sfsre~ zN5KD3kln|QBCBE|-Oe**wwANy6`rX#NSpCqqU>6YM-Nt@!3XI*fEMEkTJLie(&w)G zQZM#HyviddvS9_ox~Fbi#*EBqeyynx%`oRwD_dKn4h27I2q|OUIealV;iExkvbJG) zKCo1Ui2+MhTcw~XZil*m6Emg3SX!rne;68Q5-GSePudkPm zdO2_`rCu6WEn>Z#8L~ZSJY4Y^W=DQK3Sh&UTR3r3K@O&!$L!1c~x z#+2PoaB)}lAC8Y7Nz2bL5KSQ-g~`k8k>^rCVzTi;_QG`Omyf1qDft8|z+(O(HE`IWT+%J!o_{$bSS9VUQ^M%t#UI)4t-oq* zVjcktu7{cwxiWSp-n~eMALDY`QSULmRY3yLbVa0l_%`8P-_KY?7`0TLjG{}>2LZ3VuSX;{fLyfF~Keg;K|2^d0*oPcL1|&l3IU? zZf?up-qPYaW{#@Ild;iu)9eI#lBl&^Q%B!R@hoSFz9ZakPQ$yI-V)>tmCF*U7Tdt( zh3Q@Xyz2PVQepmtdVQnOI z&C-Yk@vNoA5Xe(JB|AJ^>U|^KJ`h`~%h9V~Yv(52*Gn`1~qjDP$X`+}DW`P)<*xSe& z{k?mBaAt>84>^qY8(s<$pXAe;{CFiJ{KHNc&w_RqJiXGh>ba=T^&rqzBDKGcg$1-) zK~WR><|3Mx#uP66bZd6nbrTsMHITFsPbn;Hv=j<6CH~}Y=e*P$1QQ(+sD{+iWBua( zq&B>FlVL1YdqgTd3EJZAX0sk)TwGra`JMeAF=MUAN6)Rh)<1hq?4{vPYV7CdWVI63`cp(t z+SWS($ldOLhQV7@X&YFhaU+{SLEhzi7du>Bmo`C}nYwenlW;_f_47}Lgvo&vfPdW- zFi9VeRjRhw=o7W^EO_S>8ew&&?rifK!h);hm26EojIjoYgJ~mb&<@f9NKE-`yuR6VBVSE(%0(69DwBfzz8MIgG76{-Y NFRd(9C-E`(e*jfL<3j)d literal 0 HcmV?d00001 diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index a91d88311ed..ba666391193 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -276,6 +276,7 @@ import 'vs/workbench/contrib/surveys/browser/languageSurveys.contribution'; // Welcome import 'vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay'; import 'vs/workbench/contrib/welcome/page/browser/welcomePage.contribution'; +import 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution'; import 'vs/workbench/contrib/welcome/walkThrough/browser/walkThrough.contribution'; // Call Hierarchy From 5f569de4cd54e43d0239e339b5f4e60f367cf75f Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 25 Nov 2020 14:26:32 -0800 Subject: [PATCH 0307/1837] more removal of non-null --- .../notebook/browser/contrib/coreActions.ts | 2 +- .../notebook/browser/notebookBrowser.ts | 2 +- .../notebook/browser/notebookEditorWidget.ts | 38 +++++++++++++------ .../view/renderers/backLayerWebView.ts | 6 +-- .../browser/view/renderers/cellRenderer.ts | 20 ++++++++-- .../browser/view/renderers/codeCell.ts | 4 +- .../browser/view/renderers/markdownCell.ts | 33 ++++++++-------- 7 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index aaf6e480c55..ca11f084885 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -103,7 +103,7 @@ const enum CellOverflowToolbarGroups { export interface INotebookActionContext { readonly cellTemplate?: BaseCellRenderTemplate; readonly cell?: ICellViewModel; - readonly notebookEditor: INotebookEditor & IActiveNotebookEditor; + readonly notebookEditor: IActiveNotebookEditor; readonly ui?: boolean; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 7e79b196107..1633a9f7b5d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -207,7 +207,7 @@ export interface INotebookEditorCreationOptions { readonly contributions?: INotebookEditorContributionDescription[]; } -export interface IActiveNotebookEditor { +export interface IActiveNotebookEditor extends INotebookEditor { viewModel: NotebookViewModel; uri: URI; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 29e3ca7840a..a2a8010ae2a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -662,7 +662,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._currentKernelTokenSource = new CancellationTokenSource(); this._localStore.add(this._currentKernelTokenSource); // we don't await for it, otherwise it will slow down the file opening - this._setKernels(textModel, this._currentKernelTokenSource); + this._setKernels(this._currentKernelTokenSource); this._localStore.add(this.notebookService.onDidChangeKernels(async (e) => { if (e && e.toString() !== this.textModel?.uri.toString()) { @@ -671,7 +671,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } this._currentKernelTokenSource?.cancel(); this._currentKernelTokenSource = new CancellationTokenSource(); - await this._setKernels(textModel, this._currentKernelTokenSource); + await this._setKernels(this._currentKernelTokenSource); })); this._localStore.add(this._list.onDidChangeFocus(() => { @@ -746,8 +746,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return result; } - private async _setKernels(textModel: NotebookTextModel, tokenSource: CancellationTokenSource) { - const provider = this.notebookService.getContributedNotebookProvider(textModel.viewType) || this.notebookService.getContributedNotebookProviders(this.viewModel!.uri)[0]; + private async _setKernels(tokenSource: CancellationTokenSource) { + if (!this.viewModel) { + return; + } + + const provider = this.notebookService.getContributedNotebookProvider(this.viewModel.viewType) || this.notebookService.getContributedNotebookProviders(this.viewModel.uri)[0]; const availableKernels = await this.beginComputeContributedKernels(); if (tokenSource.token.isCancellationRequested) { @@ -874,9 +878,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private _updateForMetadata(): void { - const notebookMetadata = this.viewModel!.metadata; + if (!this.viewModel) { + return; + } + + const notebookMetadata = this.viewModel.metadata; this._editorEditable?.set(!!notebookMetadata?.editable); - this._editorRunnable?.set(this.viewModel!.runnable); + this._editorRunnable?.set(this.viewModel.runnable); this._overflowContainer.classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable); this.getDomNode().classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable); @@ -899,8 +907,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } this._webviewResolvePromise = new Promise(async resolve => { - await this._webview!.createWebview(); - this._webview!.webview!.onDidBlur(() => { + if (!this._webview) { + throw new Error('Notebook output webview object is not created successfully.'); + } + + await this._webview.createWebview(); + if (!this._webview.webview) { + throw new Error('Notebook output webview elemented is not created successfully.'); + } + + this._webview.webview.onDidBlur(() => { this._outputFocus?.set(false); this.updateEditorFocus(); @@ -908,7 +924,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webiewFocused = false; } }); - this._webview!.webview!.onDidFocus(() => { + this._webview.webview.onDidFocus(() => { this._outputFocus?.set(true); this.updateEditorFocus(); this._onDidFocusEmitter.fire(); @@ -918,7 +934,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } }); - this._localStore.add(this._webview!.onMessage(({ message, forRenderer }) => { + this._localStore.add(this._webview.onMessage(({ message, forRenderer }) => { if (this.viewModel) { this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.getId(), forRenderer, message); } @@ -926,7 +942,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webviewResolved = true; - resolve(this._webview!); + resolve(this._webview); }); return this._webviewResolvePromise; 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 ce441008431..31fc6590e1f 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -372,7 +372,7 @@ export class BackLayerWebView extends Disposable { }()); `; const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); - this.initialize(htmlContent); + this._initialize(htmlContent); resolveFunc!(); } else { const loaderUri = FileAccess.asBrowserUri('vs/loader.js', require); @@ -396,7 +396,7 @@ var requirejs = (function() { `; const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); - this.initialize(htmlContent); + this._initialize(htmlContent); resolveFunc!(); }); } @@ -404,7 +404,7 @@ var requirejs = (function() { await this._initalized; } - async initialize(content: string) { + private async _initialize(content: string) { if (!document.body.contains(this.element)) { throw new Error('Element is already detached from the DOM tree'); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 9c54b9cbd8c..853f0351a2d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -480,6 +480,10 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } renderElement(element: MarkdownCellViewModel, index: number, templateData: MarkdownCellRenderTemplate, height: number | undefined): void { + if (!this.notebookEditor.hasModel()) { + throw new Error('The notebook editor is not attached with view model yet.'); + } + const removedClassNames: string[] = []; templateData.rootContainer.classList.forEach(className => { if (/^nb\-.*$/.test(className)) { @@ -522,7 +526,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } })); - elementDisposables.add(new CellContextKeyManager(templateData.contextKeyService, this.notebookEditor, this.notebookEditor.viewModel?.notebookDocument!, element)); + elementDisposables.add(new CellContextKeyManager(templateData.contextKeyService, this.notebookEditor, this.notebookEditor.viewModel.notebookDocument!, element)); // render toolbar first this.setupCellToolbarActions(templateData, elementDisposables); @@ -802,7 +806,11 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } private updateForMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void { - const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel!.notebookDocument.metadata); + if (!this.notebookEditor.hasModel()) { + return; + } + + const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel.notebookDocument.metadata); templateData.container.classList.toggle('runnable', !!metadata.runnable); this.updateExecutionOrder(metadata, templateData); templateData.statusBar.cellStatusMessageContainer.textContent = metadata?.statusMessage || ''; @@ -857,6 +865,10 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void { + if (!this.notebookEditor.hasModel()) { + throw new Error('The notebook editor is not attached with view model yet.'); + } + const removedClassNames: string[] = []; templateData.rootContainer.classList.forEach(className => { if (/^nb\-.*$/.test(className)) { @@ -903,7 +915,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende elementDisposables.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData)); this.renderedEditors.set(element, templateData.editor); - elementDisposables.add(new CellContextKeyManager(templateData.contextKeyService, this.notebookEditor, this.notebookEditor.viewModel?.notebookDocument!, element)); + elementDisposables.add(new CellContextKeyManager(templateData.contextKeyService, this.notebookEditor, this.notebookEditor.viewModel.notebookDocument!, element)); this.updateForLayout(element, templateData); elementDisposables.add(element.onDidChangeLayout(() => { @@ -922,7 +934,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.updateForHover(element, templateData); } })); - elementDisposables.add(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + elementDisposables.add(this.notebookEditor.viewModel.notebookDocument.onDidChangeContent(e => { if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { this.updateForMetadata(element, templateData); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index f86890dedba..4c34e365b73 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -12,7 +12,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -28,7 +28,7 @@ export class CodeCell extends Disposable { private _untrustedStatusItem: IDisposable | null = null; constructor( - private notebookEditor: INotebookEditor, + private notebookEditor: IActiveNotebookEditor, private viewCell: CodeCellViewModel, private templateData: CodeCellRenderTemplate, @INotebookService notebookService: INotebookService, diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index cd949babf5b..a22aa498c49 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -12,7 +12,7 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, INotebookEditor, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellFoldingState } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -34,7 +34,7 @@ export class StatefulMarkdownCell extends Disposable { private _activeCellRunPlaceholder: IDisposable | null = null; constructor( - private readonly notebookEditor: INotebookEditor, + private readonly notebookEditor: IActiveNotebookEditor, private readonly viewCell: MarkdownCellViewModel, private readonly templateData: MarkdownCellRenderTemplate, private editorOptions: IEditorOptions, @@ -136,8 +136,7 @@ export class StatefulMarkdownCell extends Disposable { const updatePlaceholder = () => { if ( - this.notebookEditor.viewModel - && this.notebookEditor.getActiveCell() === this.viewCell + this.notebookEditor.getActiveCell() === this.viewCell && !!this.notebookEditor.viewModel.metadata.trusted ) { // active cell and no run status @@ -161,7 +160,7 @@ export class StatefulMarkdownCell extends Disposable { updatePlaceholder(); })); - this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + this._register(this.notebookEditor.viewModel.notebookDocument.onDidChangeContent(e => { if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { updatePlaceholder(); } @@ -198,13 +197,13 @@ export class StatefulMarkdownCell extends Disposable { this.templateData.container.classList.toggle('collapsed', false); if (this.editor) { - editorHeight = this.editor!.getContentHeight(); + editorHeight = this.editor.getContentHeight(); // not first time, we don't need to create editor or bind listeners this.viewCell.attachTextEditor(this.editor); this.focusEditorIfNeeded(); - this.bindEditorListeners(); + this.bindEditorListeners(this.editor); this.editor.layout({ width: this.viewCell.layoutInfo.editorWidth, @@ -260,7 +259,7 @@ export class StatefulMarkdownCell extends Disposable { this.focusEditorIfNeeded(); } - this.bindEditorListeners(); + this.bindEditorListeners(this.editor!); this.viewCell.editorHeight = editorHeight; }); @@ -365,13 +364,13 @@ export class StatefulMarkdownCell extends Disposable { } } - private bindEditorListeners() { - this.localDisposables.add(this.editor!.onDidContentSizeChange(e => { - const viewLayout = this.editor!.getLayoutInfo(); + private bindEditorListeners(editor: CodeEditorWidget) { + this.localDisposables.add(editor.onDidContentSizeChange(e => { + const viewLayout = editor.getLayoutInfo(); if (e.contentHeightChanged) { this.viewCell.editorHeight = e.contentHeight; - this.editor!.layout( + editor.layout( { width: viewLayout.width, height: e.contentHeight @@ -380,25 +379,25 @@ export class StatefulMarkdownCell extends Disposable { } })); - this.localDisposables.add(this.editor!.onDidChangeCursorSelection((e) => { + this.localDisposables.add(editor.onDidChangeCursorSelection((e) => { if (e.source === 'restoreState') { // do not reveal the cell into view if this selection change was caused by restoring editors... return; } - const primarySelection = this.editor!.getSelection(); + const primarySelection = editor.getSelection(); if (primarySelection) { this.notebookEditor.revealLineInViewAsync(this.viewCell, primarySelection!.positionLineNumber); } })); - const updateFocusMode = () => this.viewCell.focusMode = this.editor!.hasWidgetFocus() ? CellFocusMode.Editor : CellFocusMode.Container; - this.localDisposables.add(this.editor!.onDidFocusEditorWidget(() => { + const updateFocusMode = () => this.viewCell.focusMode = editor.hasWidgetFocus() ? CellFocusMode.Editor : CellFocusMode.Container; + this.localDisposables.add(editor.onDidFocusEditorWidget(() => { updateFocusMode(); })); - this.localDisposables.add(this.editor!.onDidBlurEditorWidget(() => { + this.localDisposables.add(editor.onDidBlurEditorWidget(() => { // this is for a special case: // users click the status bar empty space, which we will then focus the editor // so we don't want to update the focus state too eagerly From 764620efaea9c671d2f364f6925fd05ba6403e49 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 25 Nov 2020 21:30:55 -0800 Subject: [PATCH 0308/1837] fix: c++ exception in keytar module Refs https://github.com/microsoft/vscode/issues/111288 --- package.json | 2 +- yarn.lock | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e38f77fcac9..51ec80ae43d 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "https-proxy-agent": "^2.2.3", "iconv-lite-umd": "0.6.8", "jschardet": "2.2.1", - "keytar": "7.2.0", + "keytar": "deepak1556/node-keytar#b36cc753e645ad72a39f8dd6348994e0c4f4905c", "minimist": "^1.2.5", "native-is-elevated": "0.4.1", "native-keymap": "2.2.1", diff --git a/yarn.lock b/yarn.lock index 44086114c87..1f0bd784f15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5567,10 +5567,9 @@ just-debounce@^1.0.0: resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= -keytar@7.2.0: +keytar@deepak1556/node-keytar#b36cc753e645ad72a39f8dd6348994e0c4f4905c: version "7.2.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.2.0.tgz#4db2bec4f9700743ffd9eda22eebb658965c8440" - integrity sha512-ECSaWvoLKI5SI0pGpZQeUV1/lpBYfkaxvoSp3zkiPOz05VavwSfLi8DdEaa9N2ekQZv3Chy+o7aP6n9mairBgw== + resolved "https://codeload.github.com/deepak1556/node-keytar/tar.gz/b36cc753e645ad72a39f8dd6348994e0c4f4905c" dependencies: node-addon-api "^3.0.0" prebuild-install "^6.0.0" From 0a80aacc7be1ab03ec0f94b8ac1a84949a83f35d Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 25 Nov 2020 22:25:28 -0800 Subject: [PATCH 0309/1837] chore: update cache --- build/.cachesalt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/.cachesalt b/build/.cachesalt index 621845b3dd8..cc8a32ae85a 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-24T13:04:41.269Z +2020-11-26T06:24:58.987Z From d547170675ba4ab1fe0d84262428a83135811847 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 07:40:49 +0100 Subject: [PATCH 0310/1837] sandbox - move some changes from PR over to master --- src/vs/code/electron-main/protocol.ts | 15 +++++++++++++++ src/vs/code/electron-main/window.ts | 7 +++---- .../services/decorationRenderOptions.test.ts | 16 ++++++++++++---- .../extensionsWorkbenchService.test.ts | 4 ++-- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/vs/code/electron-main/protocol.ts b/src/vs/code/electron-main/protocol.ts index 41a241ac602..36d0931994e 100644 --- a/src/vs/code/electron-main/protocol.ts +++ b/src/vs/code/electron-main/protocol.ts @@ -37,9 +37,17 @@ export class FileProtocolHandler extends Disposable { // Register vscode-file:// handler defaultSession.protocol.registerFileProtocol(Schemas.vscodeFileResource, (request, callback) => this.handleResourceRequest(request, callback as unknown as ProtocolCallback)); + // Block any file:// access (sandbox only) + if (environmentService.args.__sandbox) { + defaultSession.protocol.interceptFileProtocol(Schemas.file, (request, callback) => this.handleFileRequest(request, callback as unknown as ProtocolCallback)); + } + // Cleanup this._register(toDisposable(() => { defaultSession.protocol.unregisterProtocol(Schemas.vscodeFileResource); + if (environmentService.args.__sandbox) { + defaultSession.protocol.uninterceptProtocol(Schemas.file); + } })); } @@ -74,6 +82,13 @@ export class FileProtocolHandler extends Disposable { return Disposable.None; } + private async handleFileRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback) { + const uri = URI.parse(request.url); + + this.logService.error(`Refused to load resource ${uri.fsPath} from ${Schemas.file}: protocol`); + callback({ error: -3 /* ABORTED */ }); + } + private async handleResourceRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback) { const uri = URI.parse(request.url); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 39f1bc472ca..f6b98e72c98 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -848,11 +848,10 @@ export class CodeWindow extends Disposable implements ICodeWindow { workbench = 'vs/code/electron-browser/workbench/workbench.html'; } - const browserUri = this.environmentService.sandbox ? + return (this.environmentService.sandbox ? FileAccess._asCodeFileUri(workbench, require) : - FileAccess.asBrowserUri(workbench, require); - - return browserUri.with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }).toString(true); + FileAccess.asBrowserUri(workbench, require)) + .with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` }).toString(true); } serializeWindowState(): IWindowState { diff --git a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts index bc522416976..9c8c6c6ed64 100644 --- a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts +++ b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts @@ -149,25 +149,33 @@ suite('Decoration Render Options', () => { assert(readStyleSheet(styleSheet).indexOf(`{background:url('data:image/svg+xml;base64,PHN2ZyB4b+') center center no-repeat;}`) > 0); s.removeDecorationType('example'); + function assertBackground(url1: string, url2: string) { + const actual = readStyleSheet(styleSheet); + assert( + actual.indexOf(`{background:url('${url1}') center center no-repeat;}`) > 0 + || actual.indexOf(`{background:url('${url2}') center center no-repeat;}`) > 0 + ); + } + if (platform.isWindows) { // windows file path (used as string) s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\miles\\more.png') }); - assert(readStyleSheet(styleSheet).indexOf(`{background:url('file:///c:/files/miles/more.png') center center no-repeat;}`) > 0); + assertBackground('file:///c:/files/miles/more.png', 'vscode-file://vscode-app/c:/files/miles/more.png'); s.removeDecorationType('example'); // single quote must always be escaped/encoded s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\foo\\b\'ar.png') }); - assert(readStyleSheet(styleSheet).indexOf(`{background:url('file:///c:/files/foo/b%27ar.png') center center no-repeat;}`) > 0); + assertBackground('file:///c:/files/foo/b%27ar.png', 'vscode-file://vscode-app/c:/files/foo/b%27ar.png'); s.removeDecorationType('example'); } else { // unix file path (used as string) s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/bar.png') }); - assert(readStyleSheet(styleSheet).indexOf(`{background:url('file:///Users/foo/bar.png') center center no-repeat;}`) > 0); + assertBackground('file:///Users/foo/bar.png', 'vscode-file://vscode-app/Users/foo/bar.png'); s.removeDecorationType('example'); // single quote must always be escaped/encoded s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/b\'ar.png') }); - assert(readStyleSheet(styleSheet).indexOf(`{background:url('file:///Users/foo/b%27ar.png') center center no-repeat;}`) > 0); + assertBackground('file:///Users/foo/b%27ar.png', 'vscode-file://vscode-app/Users/foo/b%27ar.png'); s.removeDecorationType('example'); } diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 5096435581b..f4f5d8ee53c 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -222,8 +222,8 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.equal('1.1.0', actual.version); assert.equal('1.1.0', actual.latestVersion); assert.equal('localDescription1', actual.description); - assert.equal('file:///localPath1/localIcon1', actual.iconUrl); - assert.equal('file:///localPath1/localIcon1', actual.iconUrlFallback); + assert.ok(actual.iconUrl === 'file:///localPath1/localIcon1' || actual.iconUrl === 'vscode-file://vscode-app/localPath1/localIcon1'); + assert.ok(actual.iconUrlFallback === 'file:///localPath1/localIcon1' || actual.iconUrlFallback === 'vscode-file://vscode-app/localPath1/localIcon1'); assert.equal(null, actual.licenseUrl); assert.equal(ExtensionState.Installed, actual.state); assert.equal(null, actual.installCount); From 392b6a94e0a23a9687477b795cbe2d8dae6f5ffd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 07:41:52 +0100 Subject: [PATCH 0311/1837] perf - remove redundant performance usages @jrieken fyi --- src/bootstrap-window.js | 1 + src/vs/code/electron-browser/workbench/workbench.js | 2 -- src/vs/code/electron-sandbox/workbench/workbench.js | 2 -- src/vs/workbench/browser/workbench.ts | 3 +-- src/vs/workbench/workbench.web.api.ts | 1 - 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 8edd1780ff6..d7cc72d3bd8 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -275,6 +275,7 @@ */ mark(name) { globalThis.MonacoPerformanceMarks.push(name, Date.now()); + performance.mark(name); } }; } diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index dc0b08b093a..14c69946174 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -28,8 +28,6 @@ // Mark start of workbench perf.mark('didLoadWorkbenchMain'); - performance.mark('workbench-start'); - perf.mark('main/startup'); // @ts-ignore return require('vs/workbench/electron-browser/desktop.main').main(configuration); diff --git a/src/vs/code/electron-sandbox/workbench/workbench.js b/src/vs/code/electron-sandbox/workbench/workbench.js index 162e40bf593..6a46ef2b080 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.js +++ b/src/vs/code/electron-sandbox/workbench/workbench.js @@ -28,8 +28,6 @@ // Mark start of workbench perf.mark('didLoadWorkbenchMain'); - performance.mark('workbench-start'); - perf.mark('main/startup'); // @ts-ignore return require('vs/workbench/electron-sandbox/desktop.main').main(configuration); diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 107e7f7de30..2172c09448d 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -415,8 +415,7 @@ export class Workbench extends Layout { mark('didStartWorkbench'); // Perf reporting (devtools) - performance.mark('workbench-end'); - performance.measure('perf: workbench create & restore', 'workbench-start', 'workbench-end'); + performance.measure('perf: workbench create & restore', 'didLoadWorkbenchMain', 'didStartWorkbench'); } } } diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index d68ec392cca..0ccee7fa3e4 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -462,7 +462,6 @@ function create(domElement: HTMLElement, options: IWorkbenchConstructionOptions) // Mark start of workbench mark('didLoadWorkbenchMain'); - performance.mark('workbench-start'); // Assert that the workbench is not created more than once. We currently // do not support this and require a full context switch to clean-up. From a5e20f89e4499340d75a357bd59df1d50150b73e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 07:42:01 +0100 Subject: [PATCH 0312/1837] :lipstick: imports --- src/vs/code/electron-main/app.ts | 14 +++++++------- .../electron-main/lifecycleMainService.ts | 8 ++++---- .../theme/electron-main/themeMainService.ts | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 87fddedeba9..92ef1a75046 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app, ipcMain as ipc, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session } from 'electron'; +import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session } from 'electron'; import { IProcessEnvironment, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; @@ -270,7 +270,7 @@ export class CodeApplication extends Disposable { //#region Bootstrap IPC Handlers - ipc.on('vscode:fetchShellEnv', async event => { + ipcMain.on('vscode:fetchShellEnv', async event => { const webContents = event.sender; const window = this.windowsMainService?.getWindowByWebContents(event.sender); @@ -320,7 +320,7 @@ export class CodeApplication extends Disposable { acceptShellEnv(shellEnv); }); - ipc.handle('vscode:writeNlsFile', (event, path: unknown, data: unknown) => { + ipcMain.handle('vscode:writeNlsFile', (event, path: unknown, data: unknown) => { const uri = this.validateNlsPath([path]); if (!uri || typeof data !== 'string') { return Promise.reject('Invalid operation (vscode:writeNlsFile)'); @@ -329,7 +329,7 @@ export class CodeApplication extends Disposable { return this.fileService.writeFile(uri, VSBuffer.fromString(data)); }); - ipc.handle('vscode:readNlsFile', async (event, ...paths: unknown[]) => { + ipcMain.handle('vscode:readNlsFile', async (event, ...paths: unknown[]) => { const uri = this.validateNlsPath(paths); if (!uri) { return Promise.reject('Invalid operation (vscode:readNlsFile)'); @@ -338,10 +338,10 @@ export class CodeApplication extends Disposable { return (await this.fileService.readFile(uri)).value.toString(); }); - ipc.on('vscode:toggleDevTools', event => event.sender.toggleDevTools()); - ipc.on('vscode:openDevTools', event => event.sender.openDevTools()); + ipcMain.on('vscode:toggleDevTools', event => event.sender.toggleDevTools()); + ipcMain.on('vscode:openDevTools', event => event.sender.openDevTools()); - ipc.on('vscode:reloadWindow', event => event.sender.reload()); + ipcMain.on('vscode:reloadWindow', event => event.sender.reload()); //#endregion } diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index 955d52f6789..62db3f7510c 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcMain as ipc, app, BrowserWindow } from 'electron'; +import { ipcMain, app, BrowserWindow } from 'electron'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; import { Event, Emitter } from 'vs/base/common/event'; @@ -437,11 +437,11 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe const okChannel = `vscode:ok${oneTimeEventToken}`; const cancelChannel = `vscode:cancel${oneTimeEventToken}`; - ipc.once(okChannel, () => { + ipcMain.once(okChannel, () => { resolve(false); // no veto }); - ipc.once(cancelChannel, () => { + ipcMain.once(cancelChannel, () => { resolve(true); // veto }); @@ -468,7 +468,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe const oneTimeEventToken = this.oneTimeListenerTokenGenerator++; const replyChannel = `vscode:reply${oneTimeEventToken}`; - ipc.once(replyChannel, () => resolve()); + ipcMain.once(replyChannel, () => resolve()); window.send('vscode:onWillUnload', { replyChannel, reason }); }); diff --git a/src/vs/platform/theme/electron-main/themeMainService.ts b/src/vs/platform/theme/electron-main/themeMainService.ts index 7bbacdb3d52..1d07cf7bfc6 100644 --- a/src/vs/platform/theme/electron-main/themeMainService.ts +++ b/src/vs/platform/theme/electron-main/themeMainService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isWindows, isMacintosh } from 'vs/base/common/platform'; -import { ipcMain as ipc, nativeTheme } from 'electron'; +import { ipcMain, nativeTheme } from 'electron'; import { IStateService } from 'vs/platform/state/node/state'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -28,7 +28,7 @@ export class ThemeMainService implements IThemeMainService { declare readonly _serviceBrand: undefined; constructor(@IStateService private stateService: IStateService) { - ipc.on('vscode:changeColorTheme', (e: Event, windowId: number, broadcast: string) => { + ipcMain.on('vscode:changeColorTheme', (e: Event, windowId: number, broadcast: string) => { // Theme changes if (typeof broadcast === 'string') { this.storeBackgroundColor(JSON.parse(broadcast)); From d49955575e50106fa99aade64f70e1011250dbb8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 08:26:12 +0100 Subject: [PATCH 0313/1837] :lipstick: relative pattern --- src/vs/workbench/api/common/extHostTypes.ts | 12 +++++++++--- src/vs/workbench/api/common/extHostWorkspace.ts | 16 ++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 5e103f86870..6c54d1f4f9f 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2189,11 +2189,16 @@ export enum ConfigurationTarget { @es5ClassCompat export class RelativePattern implements IRelativePattern { base: string; - baseFolder?: URI; - pattern: string; - constructor(base: URI | vscode.WorkspaceFolder | string, pattern: string) { + // expose a `baseFolder: URI` property as a workaround for the short-coming + // of `IRelativePattern` only supporting `base: string` which always translates + // to a `file://` URI. With `baseFolder` we can support non-file based folders + // in searches + // (https://github.com/microsoft/vscode/commit/6326543b11cf4998c8fd1564cab5c429a2416db3) + readonly baseFolder?: URI; + + constructor(base: vscode.WorkspaceFolder | URI | string, pattern: string) { if (typeof base !== 'string') { if (!base || !URI.isUri(base) && !URI.isUri(base.uri)) { throw illegalArgument('base'); @@ -2205,6 +2210,7 @@ export class RelativePattern implements IRelativePattern { } if (typeof base === 'string') { + this.baseFolder = URI.file(base); this.base = base; } else if (URI.isUri(base)) { this.baseFolder = base; diff --git a/src/vs/workbench/api/common/extHostWorkspace.ts b/src/vs/workbench/api/common/extHostWorkspace.ts index 1434932e36e..3e0de07e3f4 100644 --- a/src/vs/workbench/api/common/extHostWorkspace.ts +++ b/src/vs/workbench/api/common/extHostWorkspace.ts @@ -467,17 +467,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac } : options.previewOptions; - let includePattern: string | undefined; - let folder: URI | undefined; - if (options.include) { - if (typeof options.include === 'string') { - includePattern = options.include; - } else { - includePattern = options.include.pattern; - folder = (options.include as RelativePattern).baseFolder || URI.file(options.include.base); - } - } - + const { includePattern, folder } = parseSearchInclude(options.include); const excludePattern = (typeof options.exclude === 'string') ? options.exclude : options.exclude ? options.exclude.pattern : undefined; const queryOptions: ITextQueryBuilderOptions = { @@ -572,14 +562,12 @@ function parseSearchInclude(include: RelativePattern | string | undefined): { in includePattern = include; } else { includePattern = include.pattern; - - // include.base must be an absolute path includeFolder = include.baseFolder || URI.file(include.base); } } return { - includePattern: includePattern, + includePattern, folder: includeFolder }; } From 5e6a2779f63c3a1a5d770498c4ead5fd8f34859a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 08:56:12 +0100 Subject: [PATCH 0314/1837] add try/catch for #111177 --- .../workspacesHistoryMainService.ts | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index b6321d7340b..7a5baa225e5 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -330,53 +330,57 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa }); // Recent Workspaces - if (this.getRecentlyOpened().workspaces.length > 0) { + try { + if (this.getRecentlyOpened().workspaces.length > 0) { - // The user might have meanwhile removed items from the jump list and we have to respect that - // so we need to update our list of recent paths with the choice of the user to not add them again - // Also: Windows will not show our custom category at all if there is any entry which was removed - // by the user! See https://github.com/microsoft/vscode/issues/15052 - let toRemove: URI[] = []; - for (let item of app.getJumpListSettings().removedItems) { - const args = item.args; - if (args) { - const match = /^--(folder|file)-uri\s+"([^"]+)"$/.exec(args); - if (match) { - toRemove.push(URI.parse(match[2])); + // The user might have meanwhile removed items from the jump list and we have to respect that + // so we need to update our list of recent paths with the choice of the user to not add them again + // Also: Windows will not show our custom category at all if there is any entry which was removed + // by the user! See https://github.com/microsoft/vscode/issues/15052 + let toRemove: URI[] = []; + for (let item of app.getJumpListSettings().removedItems) { + const args = item.args; + if (args) { + const match = /^--(folder|file)-uri\s+"([^"]+)"$/.exec(args); + if (match) { + toRemove.push(URI.parse(match[2])); + } } } + this.removeRecentlyOpened(toRemove); + + // Add entries + jumpList.push({ + type: 'custom', + name: nls.localize('recentFolders', "Recent Workspaces"), + items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { + const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; + const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); + + let description; + let args; + if (isSingleFolderWorkspaceIdentifier(workspace)) { + description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); + args = `--folder-uri "${workspace.toString()}"`; + } else { + description = nls.localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); + args = `--file-uri "${workspace.configPath.toString()}"`; + } + + return { + type: 'task', + title, + description, + program: process.execPath, + args, + iconPath: 'explorer.exe', // simulate folder icon + iconIndex: 0 + }; + })) + }); } - this.removeRecentlyOpened(toRemove); - - // Add entries - jumpList.push({ - type: 'custom', - name: nls.localize('recentFolders', "Recent Workspaces"), - items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { - const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; - const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); - - let description; - let args; - if (isSingleFolderWorkspaceIdentifier(workspace)) { - description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); - args = `--folder-uri "${workspace.toString()}"`; - } else { - description = nls.localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); - args = `--file-uri "${workspace.configPath.toString()}"`; - } - - return { - type: 'task', - title, - description, - program: process.execPath, - args, - iconPath: 'explorer.exe', // simulate folder icon - iconIndex: 0 - }; - })) - }); + } catch (error) { + this.logService.warn('updateWindowsJumpList#recentWorkspaces', error); // https://github.com/microsoft/vscode/issues/111177 } // Recent @@ -387,7 +391,7 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa try { app.setJumpList(jumpList); } catch (error) { - this.logService.warn('#setJumpList', error); // since setJumpList is relatively new API, make sure to guard for errors + this.logService.warn('updateWindowsJumpList#setJumpList', error); // since setJumpList is relatively new API, make sure to guard for errors } } From 4858682abd5ad10d4c65ca8ecf506d4da0287156 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 09:22:55 +0100 Subject: [PATCH 0315/1837] render file decorations italic when main label is italic --- src/vs/base/browser/ui/iconLabel/iconlabel.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index 06224874c24..da6e0ec421c 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -77,6 +77,10 @@ text-align: center; } +.monaco-icon-label.italic::after { + font-style: italic; +} + /* make sure selection color wins when a label is being selected */ .monaco-list:focus .selected .monaco-icon-label, /* list */ .monaco-list:focus .selected .monaco-icon-label::after From 6da3c138aa48f5468890d0673698801efcc13c30 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 09:26:09 +0100 Subject: [PATCH 0316/1837] apply no tab background style on container, not label --- src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 318a5c130c0..2c2875e4c53 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -297,9 +297,9 @@ export class NoTabsTitleControl extends TitleControl { ); if (isGroupActive) { - editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND) || ''; + titleContainer.style.color = this.getColor(TAB_ACTIVE_FOREGROUND) || ''; } else { - editorLabel.element.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND) || ''; + titleContainer.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND) || ''; } // Update Editor Actions Toolbar From 4031280b29ee6e6d85abac0da91167440c575175 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2020 09:28:15 +0100 Subject: [PATCH 0317/1837] Go to symbol in editor, open to side should reset scroll position in original editor (fix #111346) --- .../editorNavigationQuickAccess.ts | 27 +++++++++++++++---- .../quickAccess/gotoLineQuickAccess.ts | 7 ++--- .../quickAccess/gotoSymbolQuickAccess.ts | 22 ++++++++------- .../quickaccess/gotoLineQuickAccess.ts | 8 +++--- .../quickaccess/gotoSymbolQuickAccess.ts | 12 ++++++--- 5 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts index 039dfbd30df..ef8cf91b8ab 100644 --- a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts @@ -26,6 +26,20 @@ export interface IEditorNavigationQuickAccessOptions { canAcceptInBackground?: boolean; } +export interface IQuickAccessTextEditorContext { + + /** + * The current active editor. + */ + readonly editor: IEditor; + + /** + * If defined, allows to restore the original view state + * the text editor had before quick access opened. + */ + restoreViewState?: () => void; +} + /** * A reusable quick access provider for the editor with support * for adding decorations for navigating in the currently active file @@ -69,6 +83,7 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu // With text control const editor = this.activeTextEditorControl; if (editor && this.canProvideWithTextEditor(editor)) { + const context: IQuickAccessTextEditorContext = { editor }; // Restore any view state if this picker was closed // without actually going to a line @@ -84,18 +99,20 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu lastKnownEditorViewState = withNullAsUndefined(editor.saveViewState()); })); - disposables.add(once(token.onCancellationRequested)(() => { + context.restoreViewState = () => { if (lastKnownEditorViewState && editor === this.activeTextEditorControl) { editor.restoreViewState(lastKnownEditorViewState); } - })); + }; + + disposables.add(once(token.onCancellationRequested)(() => context.restoreViewState?.())); } // Clean up decorations on dispose disposables.add(toDisposable(() => this.clearDecorations(editor))); // Ask subclass for entries - disposables.add(this.provideWithTextEditor(editor, picker, token)); + disposables.add(this.provideWithTextEditor(context, picker, token)); } // Without text control @@ -116,14 +133,14 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu /** * Subclasses to implement to provide picks for the picker when an editor is active. */ - protected abstract provideWithTextEditor(editor: IEditor, picker: IQuickPick, token: CancellationToken): IDisposable; + protected abstract provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick, token: CancellationToken): IDisposable; /** * Subclasses to implement to provide picks for the picker when no editor is active. */ protected abstract provideWithoutTextEditor(picker: IQuickPick, token: CancellationToken): IDisposable; - protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { + protected gotoLocation({ editor }: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { editor.setSelection(options.range); editor.revealRangeInCenter(options.range, ScrollType.Smooth); if (!options.preserveFocus) { diff --git a/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts index 0c17d7c0b41..2885cc4fb0d 100644 --- a/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts @@ -9,7 +9,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { IRange } from 'vs/editor/common/core/range'; -import { AbstractEditorNavigationQuickAccessProvider } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; +import { AbstractEditorNavigationQuickAccessProvider, IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; import { IPosition } from 'vs/editor/common/core/position'; import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorOption, RenderLineNumbersType } from 'vs/editor/common/config/editorOptions'; @@ -33,7 +33,8 @@ export abstract class AbstractGotoLineQuickAccessProvider extends AbstractEditor return Disposable.None; } - protected provideWithTextEditor(editor: IEditor, picker: IQuickPick, token: CancellationToken): IDisposable { + protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick, token: CancellationToken): IDisposable { + const editor = context.editor; const disposables = new DisposableStore(); // Goto line once picked @@ -44,7 +45,7 @@ export abstract class AbstractGotoLineQuickAccessProvider extends AbstractEditor return; } - this.gotoLocation(editor, { range: this.toRange(item.lineNumber, item.column), keyMods: picker.keyMods, preserveFocus: event.inBackground }); + this.gotoLocation(context, { range: this.toRange(item.lineNumber, item.column), keyMods: picker.keyMods, preserveFocus: event.inBackground }); if (!event.inBackground) { picker.hide(); diff --git a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts index ca85c3ce869..9fb3e3d3c65 100644 --- a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts @@ -7,10 +7,10 @@ import { localize } from 'vs/nls'; import { IQuickPick, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IEditor, ScrollType } from 'vs/editor/common/editorCommon'; +import { ScrollType } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { AbstractEditorNavigationQuickAccessProvider, IEditorNavigationQuickAccessOptions } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; +import { AbstractEditorNavigationQuickAccessProvider, IEditorNavigationQuickAccessOptions, IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; import { DocumentSymbol, SymbolKinds, SymbolTag, DocumentSymbolProviderRegistry, SymbolKind } from 'vs/editor/common/modes'; import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { trim, format } from 'vs/base/common/strings'; @@ -48,7 +48,8 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit return Disposable.None; } - protected provideWithTextEditor(editor: IEditor, picker: IQuickPick, token: CancellationToken): IDisposable { + protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick, token: CancellationToken): IDisposable { + const editor = context.editor; const model = this.getModel(editor); if (!model) { return Disposable.None; @@ -56,16 +57,16 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit // Provide symbols from model if available in registry if (DocumentSymbolProviderRegistry.has(model)) { - return this.doProvideWithEditorSymbols(editor, model, picker, token); + return this.doProvideWithEditorSymbols(context, model, picker, token); } // Otherwise show an entry for a model without registry // But give a chance to resolve the symbols at a later // point if possible - return this.doProvideWithoutEditorSymbols(editor, model, picker, token); + return this.doProvideWithoutEditorSymbols(context, model, picker, token); } - private doProvideWithoutEditorSymbols(editor: IEditor, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable { + private doProvideWithoutEditorSymbols(context: IQuickAccessTextEditorContext, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable { const disposables = new DisposableStore(); // Generic pick for not having any symbol information @@ -82,7 +83,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit return; } - disposables.add(this.doProvideWithEditorSymbols(editor, model, picker, token)); + disposables.add(this.doProvideWithEditorSymbols(context, model, picker, token)); })(); return disposables; @@ -116,14 +117,15 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit return symbolProviderRegistryPromise; } - private doProvideWithEditorSymbols(editor: IEditor, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable { + private doProvideWithEditorSymbols(context: IQuickAccessTextEditorContext, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable { + const editor = context.editor; const disposables = new DisposableStore(); // Goto symbol once picked disposables.add(picker.onDidAccept(event => { const [item] = picker.selectedItems; if (item && item.range) { - this.gotoLocation(editor, { range: item.range.selection, keyMods: picker.keyMods, preserveFocus: event.inBackground }); + this.gotoLocation(context, { range: item.range.selection, keyMods: picker.keyMods, preserveFocus: event.inBackground }); if (!event.inBackground) { picker.hide(); @@ -134,7 +136,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit // Goto symbol side by side if enabled disposables.add(picker.onDidTriggerItemButton(({ item }) => { if (item && item.range) { - this.gotoLocation(editor, { range: item.range.selection, keyMods: picker.keyMods, forceSideBySide: true }); + this.gotoLocation(context, { range: item.range.selection, keyMods: picker.keyMods, forceSideBySide: true }); picker.hide(); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index c05ec1cfa36..eb4566740d8 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -5,7 +5,6 @@ import { localize } from 'vs/nls'; import { IKeyMods, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { IEditor } from 'vs/editor/common/editorCommon'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IRange } from 'vs/editor/common/core/range'; import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess'; @@ -17,6 +16,7 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProvider { @@ -41,10 +41,12 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv return this.editorService.activeTextEditorControl; } - protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { + protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) { + context.restoreViewState?.(); // since we open to the side, restore view state in this editor + this.editorService.openEditor(this.editorService.activeEditor, { selection: options.range, pinned: options.keyMods.alt || this.configuration.openEditorPinned, @@ -54,7 +56,7 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv // Otherwise let parent handle it else { - super.gotoLocation(editor, options); + super.gotoLocation(context, options); } } } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 5f73a423de1..bb7642fe74a 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -26,6 +26,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider { @@ -42,11 +43,12 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess //#region DocumentSymbols (text editor required) - protected provideWithTextEditor(editor: IEditor, picker: IQuickPick, token: CancellationToken): IDisposable { + protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick, token: CancellationToken): IDisposable { if (this.canPickFromTableOfContents()) { return this.doGetTableOfContentsPicks(picker); } - return super.provideWithTextEditor(editor, picker, token); + + return super.provideWithTextEditor(context, picker, token); } private get configuration() { @@ -62,10 +64,12 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess return this.editorService.activeTextEditorControl; } - protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { + protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) { + context.restoreViewState?.(); // since we open to the side, restore view state in this editor + this.editorService.openEditor(this.editorService.activeEditor, { selection: options.range, pinned: options.keyMods.alt || this.configuration.openEditorPinned, @@ -75,7 +79,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess // Otherwise let parent handle it else { - super.gotoLocation(editor, options); + super.gotoLocation(context, options); } } From f7a2368ae8ec4e754877c07080b9286d1322d2ec Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 09:29:35 +0100 Subject: [PATCH 0318/1837] tweak padding of file decorations in editor titles --- src/vs/workbench/browser/parts/editor/media/titlecontrol.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css index 59ab0d4afac..e26475babd3 100644 --- a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css @@ -26,6 +26,10 @@ cursor: pointer; } +.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::after { + padding-right: 0; +} + /* Title Actions */ .monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label:not(span), From 2d2a9e7527c6f592abef95b2ea947e3d74ad3631 Mon Sep 17 00:00:00 2001 From: Pikachu920 <28607612+Pikachu920@users.noreply.github.com> Date: Thu, 26 Nov 2020 02:33:03 -0600 Subject: [PATCH 0319/1837] Prevent unwanted concatenation of "null" to feedback URL (#111325) --- .../workbench/contrib/feedback/browser/feedbackStatusbarItem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts index 3bbf80a067f..5f4f0b99150 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts @@ -28,7 +28,7 @@ class TwitterFeedbackService implements IFeedbackDelegate { } submitFeedback(feedback: IFeedback, openerService: IOpenerService): void { - const queryString = `?${feedback.sentiment === 1 ? `hashtags=${this.combineHashTagsAsString()}&` : null}ref_src=twsrc%5Etfw&related=twitterapi%2Ctwitter&text=${encodeURIComponent(feedback.feedback)}&tw_p=tweetbutton&via=${TwitterFeedbackService.VIA_NAME}`; + const queryString = `?${feedback.sentiment === 1 ? `hashtags=${this.combineHashTagsAsString()}&` : ''}ref_src=twsrc%5Etfw&related=twitterapi%2Ctwitter&text=${encodeURIComponent(feedback.feedback)}&tw_p=tweetbutton&via=${TwitterFeedbackService.VIA_NAME}`; const url = TwitterFeedbackService.TWITTER_URL + queryString; openerService.open(URI.parse(url)); From 8298927b3e2162c364addb1df3e983ee35ba48a0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 09:48:10 +0100 Subject: [PATCH 0320/1837] add settings to toggle/tweak editor tab file decorations --- .../browser/parts/editor/noTabsTitleControl.ts | 9 +++++++-- .../workbench/browser/parts/editor/tabsTitleControl.ts | 6 ++++-- src/vs/workbench/browser/workbench.contribution.ts | 10 ++++++++++ src/vs/workbench/common/editor.ts | 4 ++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 2c2875e4c53..6c103357136 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -15,6 +15,7 @@ import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/edito import { Color } from 'vs/base/common/color'; import { withNullAsUndefined, assertIsDefined, assertAllDefined } from 'vs/base/common/types'; import { IEditorGroupTitleDimensions } from 'vs/workbench/browser/parts/editor/editor'; +import { equals } from 'vs/base/common/objects'; interface IRenderedEditorLabel { editor?: IEditorInput; @@ -188,7 +189,7 @@ export class NoTabsTitleControl extends TitleControl { } updateOptions(oldOptions: IEditorPartOptions, newOptions: IEditorPartOptions): void { - if (oldOptions.labelFormat !== newOptions.labelFormat) { + if (oldOptions.labelFormat !== newOptions.labelFormat || !equals(oldOptions.tabDecorations, newOptions.tabDecorations)) { this.redraw(); } } @@ -236,6 +237,7 @@ export class NoTabsTitleControl extends TitleControl { private redraw(): void { const editor = withNullAsUndefined(this.group.activeEditor); + const options = this.accessor.partOptions; const isEditorPinned = editor ? this.group.isPinned(editor) : false; const isGroupActive = this.accessor.activeGroup === this.group; @@ -292,7 +294,10 @@ export class NoTabsTitleControl extends TitleControl { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'], - fileDecorations: { colors: true, badges: true }, + fileDecorations: { + colors: Boolean(options.tabDecorations?.colors), + badges: Boolean(options.tabDecorations?.badges) + }, } ); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index f5318a8878a..fc7f4a3bb3b 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -48,6 +48,7 @@ import { IPath, win32, posix } from 'vs/base/common/path'; import { insert } from 'vs/base/common/arrays'; import { ColorScheme } from 'vs/platform/theme/common/theme'; import { isSafari } from 'vs/base/browser/browser'; +import { equals } from 'vs/base/common/objects'; interface IEditorInputLabel { name?: string; @@ -531,7 +532,8 @@ export class TabsTitleControl extends TitleControl { oldOptions.pinnedTabSizing !== newOptions.pinnedTabSizing || oldOptions.showIcons !== newOptions.showIcons || oldOptions.hasIcons !== newOptions.hasIcons || - oldOptions.highlightModifiedTabs !== newOptions.highlightModifiedTabs + oldOptions.highlightModifiedTabs !== newOptions.highlightModifiedTabs || + !equals(oldOptions.tabDecorations, newOptions.tabDecorations) ) { this.redraw(); } @@ -1116,7 +1118,7 @@ export class TabsTitleControl extends TitleControl { // Label tabLabelWidget.setResource( { name, description, resource: EditorResourceAccessor.getOriginalUri(editor, { supportSideBySide: SideBySideEditor.BOTH }) }, - { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel, fileDecorations: { colors: true, badges: true } } + { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel, fileDecorations: { colors: Boolean(options.tabDecorations?.colors), badges: Boolean(options.tabDecorations?.badges) } } ); // Tests helper diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index fdc99470bb5..9e95f64bf22 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -43,6 +43,16 @@ import { isStandalone } from 'vs/base/browser/browser'; 'markdownDescription': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not. This value is ignored when `#workbench.editor.showTabs#` is `false`."), 'default': false }, + 'workbench.editor.tabDecorations.badges': { + 'type': 'boolean', + 'markdownDescription': nls.localize('tabDecorations.badges', "Controls whether editor file decorations should use badges."), + 'default': true + }, + 'workbench.editor.tabDecorations.colors': { + 'type': 'boolean', + 'markdownDescription': nls.localize('tabDecorations.colors', "Controls whether editor file decorations should use colors."), + 'default': true + }, 'workbench.editor.labelFormat': { 'type': 'string', 'enum': ['default', 'short', 'medium', 'long'], diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 8577e4aeb33..bd066eebe37 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1290,6 +1290,10 @@ interface IEditorPartConfiguration { value?: number; perEditorGroup?: boolean; }; + tabDecorations?: { + badges?: boolean; + colors?: boolean; + } } export interface IEditorPartOptions extends IEditorPartConfiguration { From c6be30405960216069fbb24870d22ecf514d9c00 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 26 Nov 2020 10:01:44 +0100 Subject: [PATCH 0321/1837] Ignore flush errors during dispose since the underlying socket might be already closed --- src/vs/base/parts/ipc/common/ipc.net.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts index 20a2ee63ce3..b27c8734f75 100644 --- a/src/vs/base/parts/ipc/common/ipc.net.ts +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -275,7 +275,11 @@ class ProtocolWriter { } public dispose(): void { - this.flush(); + try { + this.flush(); + } catch (err) { + // ignore error, since the socket could be already closed + } this._isDisposed = true; } From 38a200c746b3953b741a272986bbb6f4018f90ac Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 10:12:06 +0100 Subject: [PATCH 0322/1837] :lipstick: --- .../services/decorations/browser/decorationsService.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index cfcbfd87cc7..7cfea530063 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -107,9 +107,7 @@ class DecorationStyles { private readonly _decorationRules = new Map(); private readonly _dispoables = new DisposableStore(); - constructor( - private _themeService: IThemeService, - ) { + constructor(private readonly _themeService: IThemeService) { this._themeService.onDidColorThemeChange(this._onThemeChange, this, this._dispoables); } @@ -150,7 +148,7 @@ class DecorationStyles { badgeClassName, tooltip, dispose: () => { - if (rule && rule.release()) { + if (rule?.release()) { this._decorationRules.delete(key); rule.removeCSSRules(this._styleElement); rule = undefined; @@ -175,7 +173,7 @@ class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { return this._data.get(uri) ?? this._data.findSuperstr(uri) !== undefined; } - static debouncer(last: FileDecorationChangeEvent | undefined, current: URI | URI[]) { + static debouncer(last: FileDecorationChangeEvent | undefined, current: URI | URI[]): FileDecorationChangeEvent { if (!last) { last = new FileDecorationChangeEvent(); } From b4912314fc04fc8a5da18ccdb2795a5698f480ad Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 10:16:53 +0100 Subject: [PATCH 0323/1837] move file decoration API to stable, https://github.com/microsoft/vscode/issues/54938 --- src/vs/vscode.d.ts | 74 +++++++++++++++++ src/vs/vscode.proposed.d.ts | 82 ------------------- .../workbench/api/common/extHost.api.impl.ts | 1 - 3 files changed, 74 insertions(+), 83 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 7a98e9bc3eb..0995e2129a1 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5546,6 +5546,72 @@ declare module 'vscode' { tooltip?: string; } + /** + * A file decoration represents metadata that can be rendered with a file. + */ + export class FileDecoration { + + /** + * A very short string that represents this decoration. + */ + badge?: string; + + /** + * A human-readable tooltip for this decoration. + */ + tooltip?: string; + + /** + * The color of this decoration. + */ + color?: ThemeColor; + + /** + * A flag expressing that this decoration should be + * propagated to its parents. + */ + propagate?: boolean; + + /** + * Creates a new decoration. + * + * @param badge A letter that represents the decoration. + * @param tooltip The tooltip of the decoration. + * @param color The color of the decoration. + */ + constructor(badge?: string, tooltip?: string, color?: ThemeColor); + } + + /** + * The decoration provider interfaces defines the contract between extensions and + * file decorations. + */ + export interface FileDecorationProvider { + + /** + * An optional event to signal that decorations for one or many files have changed. + * + * *Note* that this event should be used to propagate information about children. + * + * @see [EventEmitter](#EventEmitter) + */ + onDidChangeFileDecorations?: Event; + + /** + * Provide decorations for a given uri. + * + * *Note* that this function is only called when a file gets rendered in the UI. + * This means a decoration from a descendent that propagates upwards must be signaled + * to the editor via the [onDidChangeFileDecorations](#FileDecorationProvider.onDidChangeFileDecorations)-event. + * + * @param uri The uri of the file to provide a decoration for. + * @param token A cancellation token. + * @returns A decoration or a thenable that resolves to such. + */ + provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult; + } + + /** * In a remote window the extension kind describes if an extension * runs where the UI (window) runs or if an extension runs remotely. @@ -8559,6 +8625,14 @@ declare module 'vscode' { */ export function registerTerminalLinkProvider(provider: TerminalLinkProvider): Disposable; + /** + * Register a file decoration provider. + * + * @param provider A [FileDecorationProvider](#FileDecorationProvider). + * @return A [disposable](#Disposable) that unregisters the provider. + */ + export function registerFileDecorationProvider(provider: FileDecorationProvider): Disposable; + /** * The currently active color theme as configured in the settings. The active * theme can be changed via the `workbench.colorTheme` setting. diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 4ee34c795b5..e6109d0ed5d 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -748,88 +748,6 @@ declare module 'vscode' { //#endregion - //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 - - - /** - * A file decoration represents metadata that can be rendered with a file. - */ - export class FileDecoration { - - /** - * A very short string that represents this decoration. - */ - badge?: string; - - /** - * A human-readable tooltip for this decoration. - */ - tooltip?: string; - - /** - * The color of this decoration. - */ - color?: ThemeColor; - - /** - * A flag expressing that this decoration should be - * propagated to its parents. - */ - propagate?: boolean; - - /** - * Creates a new decoration. - * - * @param badge A letter that represents the decoration. - * @param tooltip The tooltip of the decoration. - * @param color The color of the decoration. - */ - constructor(badge?: string, tooltip?: string, color?: ThemeColor); - } - - /** - * The decoration provider interfaces defines the contract between extensions and - * file decorations. - */ - export interface FileDecorationProvider { - - /** - * An optional event to signal that decorations for one or many files have changed. - * - * - * *Note* that this event should be used to propagate information about children. - * - * @see [EventEmitter](#EventEmitter) - */ - onDidChangeFileDecorations?: Event; - - /** - * Provide decorations for a given uri. - * - * *Note* that this function is only called when a file gets rendered in the UI. - * This means a decoration from a descendent that propagates upwards must be signaled - * to the editor via the [onDidChangeFileDecorations](#FileDecorationProvider.onDidChangeFileDecorations)-event. - * - * @param uri The uri of the file to provide a decoration for. - * @param token A cancellation token. - * @returns A decoration or a thenable that resolves to such. - */ - provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult; - } - - export namespace window { - - /** - * Register a file decoration provider. - * - * @param provider A [FileDecorationProvider](#FileDecorationProvider). - * @return A [disposable](#Disposable) that unregisters the provider. - */ - export function registerFileDecorationProvider(provider: FileDecorationProvider): Disposable; - } - - //#endregion - //#region debug /** diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index a8d42e2e243..b2452d35d20 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -639,7 +639,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostCustomEditors.registerCustomEditorProvider(extension, viewType, provider, options); }, registerFileDecorationProvider(provider: vscode.FileDecorationProvider) { - checkProposedApiEnabled(extension); return extHostDecorations.registerFileDecorationProvider(provider, extension.identifier); }, registerUriHandler(handler: vscode.UriHandler) { From 8ba0fd356e3a8d9c64f64b16d2a94b917d18ca34 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 10:46:44 +0100 Subject: [PATCH 0324/1837] IEnvironmentVariableInfo: Use ThemeIcon --- .../terminal/browser/environmentVariableInfo.ts | 10 ++++++---- .../browser/widgets/environmentVariableInfoWidget.ts | 3 ++- .../contrib/terminal/common/environmentVariable.ts | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts b/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts index 09750a14e65..d91501663cc 100644 --- a/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts +++ b/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts @@ -7,6 +7,8 @@ import { IEnvironmentVariableInfo, IMergedEnvironmentVariableCollection, IMerged import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { Codicon } from 'vs/base/common/codicons'; export class EnvironmentVariableInfoStale implements IEnvironmentVariableInfo { readonly requiresAction = true; @@ -53,8 +55,8 @@ export class EnvironmentVariableInfoStale implements IEnvironmentVariableInfo { return info; } - getIcon(): string { - return 'warning'; + getIcon(): ThemeIcon { + return Codicon.warning; } getActions(): { label: string, iconClass?: string, run: () => void, commandId: string }[] { @@ -83,8 +85,8 @@ export class EnvironmentVariableInfoChangesActive implements IEnvironmentVariabl return message + '\n\n```\n' + changes.join('\n') + '\n```'; } - getIcon(): string { - return 'info'; + getIcon(): ThemeIcon { + return Codicon.info; } } diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts b/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts index 3bd49844533..913e4de7947 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts @@ -12,6 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import * as dom from 'vs/base/browser/dom'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IHoverService, IHoverOptions } from 'vs/workbench/services/hover/browser/hover'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class EnvironmentVariableInfoWidget extends Widget implements ITerminalWidget { readonly id = 'env-var-info'; @@ -34,7 +35,7 @@ export class EnvironmentVariableInfoWidget extends Widget implements ITerminalWi attach(container: HTMLElement): void { this._container = container; this._domNode = document.createElement('div'); - this._domNode.classList.add('terminal-env-var-info', 'codicon', `codicon-${this._info.getIcon()}`); + this._domNode.classList.add('terminal-env-var-info', ...ThemeIcon.asClassNameArray(this._info.getIcon())); if (this.requiresAction) { this._domNode.classList.add('requires-action'); } diff --git a/src/vs/workbench/contrib/terminal/common/environmentVariable.ts b/src/vs/workbench/contrib/terminal/common/environmentVariable.ts index bb32eafc81d..196f1849585 100644 --- a/src/vs/workbench/contrib/terminal/common/environmentVariable.ts +++ b/src/vs/workbench/contrib/terminal/common/environmentVariable.ts @@ -6,6 +6,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Event } from 'vs/base/common/event'; import { IProcessEnvironment } from 'vs/base/common/platform'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const IEnvironmentVariableService = createDecorator('environmentVariableService'); @@ -98,6 +99,6 @@ export type ISerializableEnvironmentVariableCollection = [string, IEnvironmentVa export interface IEnvironmentVariableInfo { readonly requiresAction: boolean; getInfo(): string; - getIcon(): string; + getIcon(): ThemeIcon; getActions?(): { label: string, iconClass?: string, run: () => void, commandId: string }[]; } From dcf4cd2a507c5678afa102968fb93a0ba5727d3d Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 10:52:24 +0100 Subject: [PATCH 0325/1837] Improve tunnelFactory doc and remove an escaping undefined --- src/vs/vscode.proposed.d.ts | 3 +++ src/vs/workbench/contrib/remote/browser/tunnelView.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index e6109d0ed5d..7bd8fff04f5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -245,6 +245,9 @@ declare module 'vscode' { * Can be optionally implemented if the extension can forward ports better than the core. * When not implemented, the core will use its default forwarding logic. * When implemented, the core will use this to forward ports. + * + * To enable the "Change Local Port" action on forwarded ports, make sure to set the `localAddress` of + * the returned `Tunnel` to a `{ port: number, host: string; }` and not a string. */ tunnelFactory?: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => Thenable | undefined; diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 7c00838aaa8..80450c79c08 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -969,7 +969,7 @@ namespace ChangeLocalPortAction { const numberValue = Number(value); const newForward = await remoteExplorerService.forward({ host: context.remoteHost, port: context.remotePort }, numberValue, context.name); if (newForward && newForward.tunnelLocalPort !== numberValue) { - notificationService.warn(nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available. Port number {1} has been used instead", value, newForward.tunnelLocalPort)); + notificationService.warn(nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available. Port number {1} has been used instead", value, newForward.tunnelLocalPort ?? newForward.localAddress)); } } }, From ebaf0a2ef035f70f9cc1a52814e19f2c03c4710f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 10:56:53 +0100 Subject: [PATCH 0326/1837] read line preview when having symbol results, https://github.com/microsoft/vscode/issues/109523 --- .../contrib/gotoSymbol/referencesModel.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/contrib/gotoSymbol/referencesModel.ts b/src/vs/editor/contrib/gotoSymbol/referencesModel.ts index 5c4bbe4d021..334928f3cf5 100644 --- a/src/vs/editor/contrib/gotoSymbol/referencesModel.ts +++ b/src/vs/editor/contrib/gotoSymbol/referencesModel.ts @@ -41,10 +41,20 @@ export class OneReference { } get ariaMessage(): string { - return localize( - 'aria.oneReference', "symbol in {0} on line {1} at column {2}", - basename(this.uri), this.range.startLineNumber, this.range.startColumn - ); + + const preview = this.parent.getPreview(this)?.preview(this.range); + + if (!preview) { + return localize( + 'aria.oneReference', "symbol in {0} on line {1} at column {2}", + basename(this.uri), this.range.startLineNumber, this.range.startColumn + ); + } else { + return localize( + 'aria.oneReference.preview', "symbol in {0} on line {1} at column {2}, {3}", + basename(this.uri), this.range.startLineNumber, this.range.startColumn, preview.value + ); + } } } From c13542b7cac87fd6f643bc915c7eb5c4f10ab247 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 11:16:36 +0100 Subject: [PATCH 0327/1837] Remove heading for forwarded ports Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/tunnelView.ts | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 80450c79c08..7b249a140f9 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -62,7 +62,7 @@ export interface ITunnelViewModel { readonly detected: TunnelItem[]; readonly candidates: TunnelItem[]; readonly input: TunnelItem; - groups(): Promise; + groupsAndForwarded(): Promise; } export class TunnelViewModel extends Disposable implements ITunnelViewModel { @@ -89,18 +89,14 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { }; } - async groups(): Promise { - const groups: ITunnelGroup[] = []; + async groupsAndForwarded(): Promise { + const groups: (ITunnelGroup | TunnelItem)[] = []; this._candidates = new Map(); (await this.model.candidates).forEach(candidate => { this._candidates.set(makeAddress(candidate.host, candidate.port), candidate); }); if ((this.model.forwarded.size > 0) || this.remoteExplorerService.getEditableData(undefined)) { - groups.push({ - label: nls.localize('remote.tunnelsView.forwarded', "Forwarded"), - tunnelType: TunnelType.Forwarded, - items: this.forwarded - }); + groups.push(...this.forwarded); } if (this.model.detected.size > 0) { groups.push({ @@ -370,14 +366,7 @@ class TunnelDataSource implements IAsyncDataSource 0) && (items[0].tunnelType === TunnelType.Forwarded)) { - return items; - } - } - return groups; + return element.groupsAndForwarded(); } else if (element instanceof TunnelItem) { return []; } else if ((element).items) { From d9c33ab94146645decc6fbd29e677011c60f91ea Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 11:27:29 +0100 Subject: [PATCH 0328/1837] Fix port nofication cooldown --- src/vs/workbench/contrib/remote/browser/remoteExplorer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 05ff17203f1..4fa9c368ba9 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -194,6 +194,7 @@ class ForwardedPortNotifier extends Disposable { run: () => OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, this.openerService, address) }; this.lastNotification = this.notificationService.prompt(Severity.Info, message, [browserChoice], { neverShowAgain: { id: 'remote.tunnelsView.autoForwardNeverShow', isSecondary: true } }); + this.lastNotifyTime = new Date(); this.lastNotification.onDidClose(() => { this.lastNotification = undefined; }); From 6692bf17e87526f2ae5aff2010b60d8084c8e4de Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 11:34:34 +0100 Subject: [PATCH 0329/1837] find completion item color in detail and at the start/end of documentation, fixes https://github.com/microsoft/vscode/issues/109794 --- .../contrib/suggest/suggestWidgetRenderer.ts | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts index 48fb74da03b..4acc3c1326a 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts @@ -31,23 +31,30 @@ export function getAriaId(index: number): string { export const suggestMoreInfoIcon = registerIcon('suggest-more-info', Codicon.chevronRight, nls.localize('suggestMoreInfoIcon', 'Icon for more information in the suggest widget.')); -const colorRegExp = /^(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))$/i; +const _completionItemColor = new class ColorExtractor { -function extractColor(item: CompletionItem, out: string[]): boolean { - const label = typeof item.completion.label === 'string' - ? item.completion.label - : item.completion.label.name; + private static _regexRelaxed = /(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))/; + private static _regexStrict = new RegExp(`^${ColorExtractor._regexRelaxed.source}$`, 'i'); - if (label.match(colorRegExp)) { - out[0] = label; - return true; + extract(item: CompletionItem, out: string[]): boolean { + if (item.textLabel.match(ColorExtractor._regexStrict)) { + out[0] = item.textLabel; + return true; + } + if (item.completion.detail && item.completion.detail.match(ColorExtractor._regexStrict)) { + out[0] = item.completion.detail; + return true; + } + if (typeof item.completion.documentation === 'string') { + const match = ColorExtractor._regexRelaxed.exec(item.completion.documentation); + if (match && (match.index === 0 || match.index + match[0].length === item.completion.documentation.length)) { + out[0] = match[0]; + return true; + } + } + return false; } - if (typeof item.completion.documentation === 'string' && item.completion.documentation.match(colorRegExp)) { - out[0] = item.completion.documentation; - return true; - } - return false; -} +}; export interface ISuggestionTemplateData { @@ -166,7 +173,7 @@ export class ItemRenderer implements IListRenderer Date: Thu, 26 Nov 2020 11:52:37 +0100 Subject: [PATCH 0330/1837] Fix #107152 --- .../userDataSync/common/userDataSync.ts | 6 +- .../common/userDataSyncService.ts | 26 +++++--- .../common/userDataSyncStoreService.ts | 63 ++++++++++--------- .../common/userDataSyncStoreService.test.ts | 14 ++--- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 35a10cfd197..6d9d58d1bed 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -220,7 +220,9 @@ export enum UserDataSyncErrorCode { TooManyRequestsAndRetryAfter = 'TooManyRequestsAndRetryAfter', /* 429 + Retry-After */ // Local Errors - ConnectionRefused = 'ConnectionRefused', + RequestFailed = 'RequestFailed', + RequestCanceled = 'RequestCanceled', + RequestTimeout = 'RequestTimeout', NoRef = 'NoRef', TurnedOff = 'TurnedOff', SessionExpired = 'SessionExpired', @@ -252,7 +254,7 @@ export class UserDataSyncError extends Error { } export class UserDataSyncStoreError extends UserDataSyncError { - constructor(message: string, code: UserDataSyncErrorCode, readonly operationId: string | undefined) { + constructor(message: string, readonly url: string, code: UserDataSyncErrorCode, readonly operationId: string | undefined) { super(message, code, undefined, operationId); } } diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index c864c456049..2cf4ac375dc 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -5,7 +5,7 @@ import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncErrorCode, - UserDataSyncError, ISyncResourceHandle, IUserDataManifest, ISyncTask, IResourcePreview, IManualSyncTask, ISyncResourcePreview, HEADER_EXECUTION_ID, MergeState, Change, IUserDataSyncStoreManagementService + UserDataSyncError, ISyncResourceHandle, IUserDataManifest, ISyncTask, IResourcePreview, IManualSyncTask, ISyncResourcePreview, HEADER_EXECUTION_ID, MergeState, Change, IUserDataSyncStoreManagementService, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -30,6 +30,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors'; type SyncErrorClassification = { code: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; service: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; + url?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; resource?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; executionId?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; }; @@ -118,9 +119,9 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ } manifest = await this.userDataSyncStoreService.manifest(syncHeaders); } catch (error) { - error = UserDataSyncError.toUserDataSyncError(error); - this.telemetryService.publicLog2<{ code: string, service: string, resource?: string, executionId?: string }, SyncErrorClassification>('sync/error', { code: error.code, resource: error.resource, executionId, service: this.userDataSyncStoreManagementService.userDataSyncStore!.url.toString() }); - throw error; + const userDataSyncError = UserDataSyncError.toUserDataSyncError(error); + this.reportUserDataSyncError(userDataSyncError, executionId); + throw userDataSyncError; } let executed = false; @@ -156,9 +157,9 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ try { manifest = await this.userDataSyncStoreService.manifest(syncHeaders); } catch (error) { - error = UserDataSyncError.toUserDataSyncError(error); - this.telemetryService.publicLog2<{ code: string, service: string, resource?: string, executionId?: string }, SyncErrorClassification>('sync/error', { code: error.code, resource: error.resource, executionId, service: this.userDataSyncStoreManagementService.userDataSyncStore!.url.toString() }); - throw error; + const userDataSyncError = UserDataSyncError.toUserDataSyncError(error); + this.reportUserDataSyncError(userDataSyncError, executionId); + throw userDataSyncError; } return new ManualSyncTask(executionId, manifest, syncHeaders, this.synchronisers, this.logService); @@ -202,9 +203,9 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`); this.updateLastSyncTime(); } catch (error) { - error = UserDataSyncError.toUserDataSyncError(error); - this.telemetryService.publicLog2<{ code: string, service: string, resource?: string, executionId?: string }, SyncErrorClassification>('sync/error', { code: error.code, resource: error.resource, executionId, service: this.userDataSyncStoreManagementService.userDataSyncStore!.url.toString() }); - throw error; + const userDataSyncError = UserDataSyncError.toUserDataSyncError(error); + this.reportUserDataSyncError(userDataSyncError, executionId); + throw userDataSyncError; } finally { this.updateStatus(); this._onSyncErrors.fire(this._syncErrors); @@ -390,6 +391,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ this.logService.error(`${source}: ${toErrorMessage(e)}`); } + private reportUserDataSyncError(userDataSyncError: UserDataSyncError, executionId: string) { + this.telemetryService.publicLog2<{ code: string, service: string, url?: string, resource?: string, executionId?: string }, SyncErrorClassification>('sync/error', + { code: userDataSyncError.code, url: userDataSyncError instanceof UserDataSyncStoreError ? userDataSyncError.url : undefined, resource: userDataSyncError.resource, executionId, service: this.userDataSyncStoreManagementService.userDataSyncStore!.url.toString() }); + } + private computeConflicts(): [SyncResource, IResourcePreview[]][] { return this.synchronisers.filter(s => s.status === SyncStatus.HasConflicts) .map(s => ([s.resource, s.conflicts.map(toStrictResourcePreview)])); diff --git a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts index 545e13e085d..4095868956d 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts @@ -21,6 +21,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { createCancelablePromise, timeout, CancelablePromise } from 'vs/base/common/async'; import { isString, isObject, isArray } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; +import { getErrorMessage, isPromiseCanceledError } from 'vs/base/common/errors'; const SYNC_SERVICE_URL_TYPE = 'sync.store.url.type'; const SYNC_PREVIOUS_STORE = 'sync.previous.store'; @@ -225,7 +226,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync const uri = joinPath(this.userDataSyncStoreUrl, 'resource', resource); const headers: IHeaders = {}; - const context = await this.request({ type: 'GET', url: uri.toString(), headers }, [], CancellationToken.None); + const context = await this.request(uri.toString(), { type: 'GET', headers }, [], CancellationToken.None); const result = await asJson<{ url: string, created: number }[]>(context) || []; return result.map(({ url, created }) => ({ ref: relativePath(uri, uri.with({ path: url }))!, created: created * 1000 /* Server returns in seconds */ })); @@ -240,7 +241,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync const headers: IHeaders = {}; headers['Cache-Control'] = 'no-cache'; - const context = await this.request({ type: 'GET', url, headers }, [], CancellationToken.None); + const context = await this.request(url, { type: 'GET', headers }, [], CancellationToken.None); const content = await asText(context); return content; } @@ -253,7 +254,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync const url = joinPath(this.userDataSyncStoreUrl, 'resource', resource).toString(); const headers: IHeaders = {}; - await this.request({ type: 'DELETE', url, headers }, [], CancellationToken.None); + await this.request(url, { type: 'DELETE', headers }, [], CancellationToken.None); } async read(resource: ServerResource, oldValue: IUserData | null, headers: IHeaders = {}): Promise { @@ -269,7 +270,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync headers['If-None-Match'] = oldValue.ref; } - const context = await this.request({ type: 'GET', url, headers }, [304], CancellationToken.None); + const context = await this.request(url, { type: 'GET', headers }, [304], CancellationToken.None); if (context.res.statusCode === 304) { // There is no new value. Hence return the old value. @@ -278,7 +279,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync const ref = context.res.headers['etag']; if (!ref) { - throw new UserDataSyncStoreError('Server did not return the ref', UserDataSyncErrorCode.NoRef, context.res.headers[HEADER_OPERATION_ID]); + throw new UserDataSyncStoreError('Server did not return the ref', url, UserDataSyncErrorCode.NoRef, context.res.headers[HEADER_OPERATION_ID]); } const content = await asText(context); return { ref, content }; @@ -296,11 +297,11 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync headers['If-Match'] = ref; } - const context = await this.request({ type: 'POST', url, data, headers }, [], CancellationToken.None); + const context = await this.request(url, { type: 'POST', data, headers }, [], CancellationToken.None); const newRef = context.res.headers['etag']; if (!newRef) { - throw new UserDataSyncStoreError('Server did not return the ref', UserDataSyncErrorCode.NoRef, context.res.headers[HEADER_OPERATION_ID]); + throw new UserDataSyncStoreError('Server did not return the ref', url, UserDataSyncErrorCode.NoRef, context.res.headers[HEADER_OPERATION_ID]); } return newRef; } @@ -314,7 +315,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync headers = { ...headers }; headers['Content-Type'] = 'application/json'; - const context = await this.request({ type: 'GET', url, headers }, [], CancellationToken.None); + const context = await this.request(url, { type: 'GET', headers }, [], CancellationToken.None); const manifest = await asJson(context); const currentSessionId = this.storageService.get(USER_SESSION_ID_KEY, StorageScope.GLOBAL); @@ -345,7 +346,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync const url = joinPath(this.userDataSyncStoreUrl, 'resource').toString(); const headers: IHeaders = { 'Content-Type': 'text/plain' }; - await this.request({ type: 'DELETE', url, headers }, [], CancellationToken.None); + await this.request(url, { type: 'DELETE', headers }, [], CancellationToken.None); // clear cached session. this.clearSession(); @@ -356,13 +357,13 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync this.storageService.remove(MACHINE_SESSION_ID_KEY, StorageScope.GLOBAL); } - private async request(options: IRequestOptions, successCodes: number[], token: CancellationToken): Promise { + private async request(url: string, options: IRequestOptions, successCodes: number[], token: CancellationToken): Promise { if (!this.authToken) { - throw new UserDataSyncStoreError('No Auth Token Available', UserDataSyncErrorCode.Unauthorized, undefined); + throw new UserDataSyncStoreError('No Auth Token Available', url, UserDataSyncErrorCode.Unauthorized, undefined); } if (this._donotMakeRequestsUntil && Date.now() < this._donotMakeRequestsUntil.getTime()) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too many requests (429).`, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter, undefined); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too many requests (429).`, url, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter, undefined); } this.setDonotMakeRequestsUntil(undefined); @@ -377,21 +378,23 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync // Add session headers this.addSessionHeaders(options.headers); - this.logService.trace('Sending request to server', { url: options.url, type: options.type, headers: { ...options.headers, ...{ authorization: undefined } } }); + this.logService.trace('Sending request to server', { url, type: options.type, headers: { ...options.headers, ...{ authorization: undefined } } }); let context; try { - context = await this.session.request(options, token); + context = await this.session.request(url, options, token); } catch (e) { if (!(e instanceof UserDataSyncStoreError)) { - e = new UserDataSyncStoreError(`Connection refused for the request '${options.url?.toString()}'.`, UserDataSyncErrorCode.ConnectionRefused, undefined); + const code = isPromiseCanceledError(e) ? UserDataSyncErrorCode.RequestCanceled + : getErrorMessage(e).startsWith('XHR timeout') ? UserDataSyncErrorCode.RequestTimeout : UserDataSyncErrorCode.RequestFailed; + e = new UserDataSyncStoreError(`Connection refused for the request '${url}'.`, url, code, undefined); } - this.logService.info('Request failed', options.url); + this.logService.info('Request failed', url); throw e; } const operationId = context.res.headers[HEADER_OPERATION_ID]; - const requestInfo = { url: options.url, status: context.res.statusCode, 'execution-id': options.headers[HEADER_EXECUTION_ID], 'operation-id': operationId }; + const requestInfo = { url, status: context.res.statusCode, 'execution-id': options.headers[HEADER_EXECUTION_ID], 'operation-id': operationId }; const isSuccess = isSuccessContext(context) || (context.res.statusCode && successCodes.indexOf(context.res.statusCode) !== -1); if (isSuccess) { this.logService.trace('Request succeeded', requestInfo); @@ -402,43 +405,43 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync if (context.res.statusCode === 401) { this.authToken = undefined; this._onTokenFailed.fire(); - throw new UserDataSyncStoreError(`Request '${options.url?.toString()}' failed because of Unauthorized (401).`, UserDataSyncErrorCode.Unauthorized, operationId); + throw new UserDataSyncStoreError(`Request '${url}' failed because of Unauthorized (401).`, url, UserDataSyncErrorCode.Unauthorized, operationId); } this._onTokenSucceed.fire(); if (context.res.statusCode === 409) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Conflict (409). There is new data for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.Conflict, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of Conflict (409). There is new data for this resource. Make the request again with latest data.`, url, UserDataSyncErrorCode.Conflict, operationId); } if (context.res.statusCode === 410) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because the requested resource is not longer available (410).`, UserDataSyncErrorCode.Gone, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because the requested resource is not longer available (410).`, url, UserDataSyncErrorCode.Gone, operationId); } if (context.res.statusCode === 412) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Precondition Failed (412). There is new data for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.PreconditionFailed, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of Precondition Failed (412). There is new data for this resource. Make the request again with latest data.`, url, UserDataSyncErrorCode.PreconditionFailed, operationId); } if (context.res.statusCode === 413) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too large payload (413).`, UserDataSyncErrorCode.TooLarge, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too large payload (413).`, url, UserDataSyncErrorCode.TooLarge, operationId); } if (context.res.statusCode === 426) { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed with status Upgrade Required (426). Please upgrade the client and try again.`, UserDataSyncErrorCode.UpgradeRequired, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed with status Upgrade Required (426). Please upgrade the client and try again.`, url, UserDataSyncErrorCode.UpgradeRequired, operationId); } if (context.res.statusCode === 429) { const retryAfter = context.res.headers['retry-after']; if (retryAfter) { this.setDonotMakeRequestsUntil(new Date(Date.now() + (parseInt(retryAfter) * 1000))); - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too many requests (429).`, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too many requests (429).`, url, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter, operationId); } else { - throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too many requests (429).`, UserDataSyncErrorCode.TooManyRequests, operationId); + throw new UserDataSyncStoreError(`${options.type} request '${url}' failed because of too many requests (429).`, url, UserDataSyncErrorCode.TooManyRequests, operationId); } } if (!isSuccess) { - throw new UserDataSyncStoreError('Server returned ' + context.res.statusCode, UserDataSyncErrorCode.Unknown, operationId); + throw new UserDataSyncStoreError('Server returned ' + context.res.statusCode, url, UserDataSyncErrorCode.Unknown, operationId); } return context; @@ -490,18 +493,20 @@ export class RequestsSession { private readonly logService: IUserDataSyncLogService, ) { } - request(options: IRequestOptions, token: CancellationToken): Promise { + request(url: string, options: IRequestOptions, token: CancellationToken): Promise { if (this.isExpired()) { this.reset(); } + options.url = url; + if (this.requests.length >= this.limit) { this.logService.info('Too many requests', ...this.requests); - throw new UserDataSyncStoreError(`Too many requests. Only ${this.limit} requests allowed in ${this.interval / (1000 * 60)} minutes.`, UserDataSyncErrorCode.LocalTooManyRequests, undefined); + throw new UserDataSyncStoreError(`Too many requests. Only ${this.limit} requests allowed in ${this.interval / (1000 * 60)} minutes.`, url, UserDataSyncErrorCode.LocalTooManyRequests, undefined); } this.startTime = this.startTime || new Date(); - this.requests.push(options.url!); + this.requests.push(url); return this.requestService.request(options, token); } diff --git a/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts b/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts index 3277d22bedf..2c7d1734d71 100644 --- a/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts +++ b/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts @@ -464,10 +464,10 @@ suite('UserDataSyncRequestsSession', () => { test('too many requests are thrown when limit exceeded', async () => { const testObject = new RequestsSession(1, 500, requestService, new NullLogService()); - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); try { - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); } catch (error) { assert.ok(error instanceof UserDataSyncStoreError); assert.equal((error).code, UserDataSyncErrorCode.LocalTooManyRequests); @@ -478,19 +478,19 @@ suite('UserDataSyncRequestsSession', () => { test('requests are handled after session is expired', async () => { const testObject = new RequestsSession(1, 500, requestService, new NullLogService()); - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); await timeout(600); - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); }); test('too many requests are thrown after session is expired', async () => { const testObject = new RequestsSession(1, 500, requestService, new NullLogService()); - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); await timeout(600); - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); try { - await testObject.request({}, CancellationToken.None); + await testObject.request('url', {}, CancellationToken.None); } catch (error) { assert.ok(error instanceof UserDataSyncStoreError); assert.equal((error).code, UserDataSyncErrorCode.LocalTooManyRequests); From 20b649729e0df9db3cf859f51bcf8cfe03863f35 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 10:53:00 +0100 Subject: [PATCH 0331/1837] button: use CSSIcon --- src/vs/base/browser/ui/button/button.ts | 16 ++++++++++------ .../contrib/search/browser/searchWidget.ts | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index 92114b6a0c7..cbf0fc35121 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -15,6 +15,8 @@ import { renderCodicons } from 'vs/base/browser/codicons'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; import { IAction, IActionRunner } from 'vs/base/common/actions'; +import { Codicon, CSSIcon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; @@ -42,7 +44,7 @@ export interface IButton extends IDisposable { readonly element: HTMLElement; readonly onDidClick: BaseEvent; label: string; - icon: string; + icon: CSSIcon; enabled: boolean; style(styles: IButtonStyles): void; focus(): void; @@ -201,8 +203,8 @@ export class Button extends Disposable implements IButton { } } - set icon(iconClassName: string) { - this._element.classList.add(...iconClassName.split(' ')); + set icon(icon: CSSIcon) { + this._element.classList.add(...icon.classNames.split(' ')); } set enabled(value: boolean) { @@ -236,6 +238,8 @@ export interface IButtonWithDropdownOptions extends IButtonOptions { readonly actionRunner?: IActionRunner; } +const dropdownIcon = registerIcon('button-drow-down', Codicon.chevronDown, localize('dropdownIcon', 'Icon for button with dropdowns')); + export class ButtonWithDropdown extends Disposable implements IButton { private readonly button: Button; @@ -256,7 +260,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportCodicons: true })); this.dropdownButton.element.classList.add('monaco-dropdown-button'); - this.dropdownButton.icon = 'codicon codicon-chevron-down'; + this.dropdownButton.icon = dropdownIcon; this._register(this.dropdownButton.onDidClick(() => { options.contextMenuProvider.showContextMenu({ getAnchor: () => this.dropdownButton.element, @@ -272,8 +276,8 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.button.label = value; } - set icon(iconClassName: string) { - this.button.icon = iconClassName; + set icon(icon: CSSIcon) { + this.button.icon = icon; } set enabled(enabled: boolean) { diff --git a/src/vs/workbench/contrib/search/browser/searchWidget.ts b/src/vs/workbench/contrib/search/browser/searchWidget.ts index 4a8c7ebd8f3..a7dbe426c82 100644 --- a/src/vs/workbench/contrib/search/browser/searchWidget.ts +++ b/src/vs/workbench/contrib/search/browser/searchWidget.ts @@ -294,8 +294,8 @@ export class SearchWidget extends Widget { }; this.toggleReplaceButton = this._register(new Button(parent, opts)); this.toggleReplaceButton.element.setAttribute('aria-expanded', 'false'); - this.toggleReplaceButton.element.classList.add(...ThemeIcon.asClassNameArray(searchHideReplaceIcon)); - this.toggleReplaceButton.icon = 'toggle-replace-button'; + this.toggleReplaceButton.element.classList.add('toggle-replace-button'); + this.toggleReplaceButton.icon = ThemeIcon.asCSSIcon(searchHideReplaceIcon); // TODO@joao need to dispose this listener eventually this.toggleReplaceButton.onDidClick(() => this.onToggleReplaceButton()); this.toggleReplaceButton.element.title = nls.localize('search.replace.toggle.button.title', "Toggle Replace"); From 32a18e3f5b2136db6fe6057b2a655a4489387d61 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 11:26:02 +0100 Subject: [PATCH 0332/1837] add Codicon.dropDownButton --- src/vs/base/browser/ui/button/button.ts | 7 ++----- src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts | 3 ++- src/vs/base/common/codicons.ts | 5 +++++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index cbf0fc35121..b3697f9bf25 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -15,8 +15,7 @@ import { renderCodicons } from 'vs/base/browser/codicons'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; import { IAction, IActionRunner } from 'vs/base/common/actions'; -import { Codicon, CSSIcon, registerIcon } from 'vs/base/common/codicons'; -import { localize } from 'vs/nls'; +import { CSSIcon, Codicon } from 'vs/base/common/codicons'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; @@ -238,8 +237,6 @@ export interface IButtonWithDropdownOptions extends IButtonOptions { readonly actionRunner?: IActionRunner; } -const dropdownIcon = registerIcon('button-drow-down', Codicon.chevronDown, localize('dropdownIcon', 'Icon for button with dropdowns')); - export class ButtonWithDropdown extends Disposable implements IButton { private readonly button: Button; @@ -260,7 +257,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportCodicons: true })); this.dropdownButton.element.classList.add('monaco-dropdown-button'); - this.dropdownButton.icon = dropdownIcon; + this.dropdownButton.icon = Codicon.dropDownButton; this._register(this.dropdownButton.onDidClick(() => { options.contextMenuProvider.showContextMenu({ getAnchor: () => this.dropdownButton.element, diff --git a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts index 6540851f701..ea32bdc0721 100644 --- a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts +++ b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts @@ -13,6 +13,7 @@ import { Emitter } from 'vs/base/common/event'; import { ActionViewItem, BaseActionViewItem, IActionViewItemOptions, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; +import { Codicon } from 'vs/base/common/codicons'; export interface IKeybindingProvider { (action: IAction): ResolvedKeybinding | undefined; @@ -169,7 +170,7 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem { super.render(container); if (this.element) { this.element.classList.add('action-dropdown-item'); - this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(new Action('dropdownAction', undefined), (this.options).menuActionsOrProvider, this.contextMenuProvider, { classNames: ['dropdown', 'codicon-chevron-down', ...(this.options).menuActionClassNames || []] }); + this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(new Action('dropdownAction', undefined), (this.options).menuActionsOrProvider, this.contextMenuProvider, { classNames: ['dropdown', ...Codicon.dropDownButton.classNamesArray, ...(this.options).menuActionClassNames || []] }); this.dropdownMenuActionViewItem.render(this.element); } } diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 5448e242fe7..218bf1fc908 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -5,6 +5,7 @@ import { codiconStartMarker } from 'vs/base/common/codicon'; import { Emitter, Event } from 'vs/base/common/event'; +import { localize } from 'vs/nls'; export interface IIconRegistry { readonly all: IterableIterator; @@ -496,8 +497,12 @@ export namespace Codicon { export const passFilled = new Codicon('pass-filled', { character: '\\ebb3' }); export const circleLargeFilled = new Codicon('circle-large-filled', { character: '\\ebb4' }); export const circleLargeOutline = new Codicon('circle-large-outline', { character: '\\ebb5' }); + + export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition); } +// common icons + From a6a53198f6cdea4e3abb1a2aec964b80e402129d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 11:59:52 +0100 Subject: [PATCH 0333/1837] make viewPaneContainer twisties themable --- src/vs/base/browser/ui/splitview/paneview.css | 4 ---- .../browser/parts/views/viewPaneContainer.ts | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/paneview.css b/src/vs/base/browser/ui/splitview/paneview.css index 06743287c1a..f24f308597f 100644 --- a/src/vs/base/browser/ui/splitview/paneview.css +++ b/src/vs/base/browser/ui/splitview/paneview.css @@ -53,10 +53,6 @@ margin-bottom: 2px; } -.monaco-pane-view .pane > .pane-header.expanded > .twisties::before { - transform: rotate(90deg); -} - /* TODO: actions should be part of the pane, but they aren't yet */ .monaco-pane-view .pane > .pane-header > .actions { display: none; diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 339357a5812..0d53a588e34 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -50,6 +50,8 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { URI } from 'vs/base/common/uri'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { Codicon } from 'vs/base/common/codicons'; export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; @@ -70,6 +72,9 @@ type WelcomeActionClassification = { uri: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; }; +const viewPaneContainerExpandedIcon = registerIcon('view-pane-container-expanded', Codicon.chevronDown, nls.localize('viewPaneContainerExpandedIcon', 'Icon for an expanded view pane container.')); +const viewPaneContainerCollapsedIcon = registerIcon('view-pane-container-collapsed', Codicon.chevronRight, nls.localize('viewPaneContainerCollapsedIcon', 'Icon for a collapsed view pane container.')); + const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); interface IItem { @@ -263,7 +268,10 @@ export abstract class ViewPane extends Pane implements IView { if (changed) { this._onDidChangeBodyVisibility.fire(expanded); } - + if (this.twistiesContainer) { + this.twistiesContainer.classList.remove(...ThemeIcon.asClassNameArray(this.getTwistyIcon(!expanded))); + this.twistiesContainer.classList.add(...ThemeIcon.asClassNameArray(this.getTwistyIcon(expanded))); + } return changed; } @@ -288,7 +296,7 @@ export abstract class ViewPane extends Pane implements IView { protected renderHeader(container: HTMLElement): void { this.headerContainer = container; - this.renderTwisties(container); + this.twistiesContainer = append(container, $('.twisties' + ThemeIcon.asCSSSelector(this.getTwistyIcon(this.isExpanded())))); this.renderHeaderTitle(container, this.title); @@ -316,8 +324,8 @@ export abstract class ViewPane extends Pane implements IView { this.updateActionsVisibility(); } - protected renderTwisties(container: HTMLElement): void { - this.twistiesContainer = append(container, $('.twisties.codicon.codicon-chevron-right')); + protected getTwistyIcon(expanded: boolean): ThemeIcon { + return expanded ? viewPaneContainerExpandedIcon : viewPaneContainerCollapsedIcon; } style(styles: IPaneStyles): void { From 8648658c4475740e8ee45bff3bed998998fcf212 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 12:00:48 +0100 Subject: [PATCH 0334/1837] use codicon for openEditorWith picker --- src/vs/workbench/services/editor/common/editorOpenWith.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/editor/common/editorOpenWith.ts b/src/vs/workbench/services/editor/common/editorOpenWith.ts index f0e0503c354..425fa2aba09 100644 --- a/src/vs/workbench/services/editor/common/editorOpenWith.ts +++ b/src/vs/workbench/services/editor/common/editorOpenWith.ts @@ -16,6 +16,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { URI } from 'vs/base/common/uri'; import { extname, basename, isEqual } from 'vs/base/common/resources'; +import { Codicon } from 'vs/base/common/codicons'; /** * Id of the default editor for open with. @@ -71,7 +72,7 @@ export async function openEditorWith( description: entry.active ? nls.localize('promptOpenWith.currentlyActive', 'Currently Active') : undefined, detail: entry.detail, buttons: resourceExt ? [{ - iconClass: 'codicon-settings-gear', + iconClass: Codicon.gear.classNames, tooltip: nls.localize('promptOpenWith.setDefaultTooltip', "Set as default editor for '{0}' files", resourceExt) }] : undefined }; From 1aba2b87c6a55c217579f80df952cc40370f16c8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 12:01:16 +0100 Subject: [PATCH 0335/1837] fix unnecessary import --- src/vs/base/common/codicons.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 218bf1fc908..73eb8d49f73 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -5,7 +5,6 @@ import { codiconStartMarker } from 'vs/base/common/codicon'; import { Emitter, Event } from 'vs/base/common/event'; -import { localize } from 'vs/nls'; export interface IIconRegistry { readonly all: IterableIterator; From 2f8f00d622dab7ad9d9dc7bf9b7abf29db5b87c8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 12:02:43 +0100 Subject: [PATCH 0336/1837] add dropDownButton-icon description --- src/vs/base/common/codicons.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 73eb8d49f73..2483c56287c 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -5,6 +5,7 @@ import { codiconStartMarker } from 'vs/base/common/codicon'; import { Emitter, Event } from 'vs/base/common/event'; +import { localize } from 'vs/nls'; export interface IIconRegistry { readonly all: IterableIterator; @@ -497,7 +498,7 @@ export namespace Codicon { export const circleLargeFilled = new Codicon('circle-large-filled', { character: '\\ebb4' }); export const circleLargeOutline = new Codicon('circle-large-outline', { character: '\\ebb5' }); - export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition); + export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition, localize('dropDownButton', 'Icon for drop down buttons.')); } // common icons From b01183bda2466199047bd59a9dd96f9ba7359f37 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 12:02:58 +0100 Subject: [PATCH 0337/1837] Add extension source to forwarded ports Part of microsoft/vscode-remote-release#4021 --- .../api/browser/mainThreadTunnelService.ts | 4 ++-- .../workbench/api/common/extHost.api.impl.ts | 2 +- .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/common/extHostTunnelService.ts | 5 ++-- .../api/node/extHostTunnelService.ts | 5 ++-- .../contrib/remote/browser/tunnelView.ts | 24 +++++++++++++++---- .../remote/common/remoteExplorerService.ts | 12 ++++++---- 7 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index 25723794d5f..ac9b8356202 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -26,8 +26,8 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun this._register(tunnelService.onTunnelClosed(() => this._proxy.$onDidTunnelsChange())); } - async $openTunnel(tunnelOptions: TunnelOptions): Promise { - const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label); + async $openTunnel(tunnelOptions: TunnelOptions, source: string): Promise { + const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label, source); if (tunnel) { return TunnelDto.fromServiceTunnel(tunnel); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b2452d35d20..ac04adb6547 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -859,7 +859,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I }, openTunnel: (forward: vscode.TunnelOptions) => { checkProposedApiEnabled(extension); - return extHostTunnelService.openTunnel(forward).then(value => { + return extHostTunnelService.openTunnel(extension, forward).then(value => { if (!value) { throw new Error('cannot open tunnel'); } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 69f4f321c84..b71262bcfec 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -955,7 +955,7 @@ export interface MainThreadWindowShape extends IDisposable { } export interface MainThreadTunnelServiceShape extends IDisposable { - $openTunnel(tunnelOptions: TunnelOptions): Promise; + $openTunnel(tunnelOptions: TunnelOptions, source: string | undefined): Promise; $closeTunnel(remote: { host: string, port: number }): Promise; $getTunnels(): Promise; $setTunnelProvider(): Promise; diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index 7444920d47d..29a50ae2700 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -10,6 +10,7 @@ import { RemoteTunnel, TunnelCreationOptions, TunnelOptions } from 'vs/platform/ import { IDisposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; export interface TunnelDto { remoteAddress: { port: number, host: string }; @@ -32,7 +33,7 @@ export interface Tunnel extends vscode.Disposable { export interface IExtHostTunnelService extends ExtHostTunnelServiceShape { readonly _serviceBrand: undefined; - openTunnel(forward: TunnelOptions): Promise; + openTunnel(extension: IExtensionDescription, forward: TunnelOptions): Promise; getTunnels(): Promise; onDidChangeTunnels: vscode.Event; setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise; @@ -51,7 +52,7 @@ export class ExtHostTunnelService implements IExtHostTunnelService { this._proxy = extHostRpc.getProxy(MainContext.MainThreadTunnelService); } - async openTunnel(forward: TunnelOptions): Promise { + async openTunnel(extension: IExtensionDescription, forward: TunnelOptions): Promise { return undefined; } async getTunnels(): Promise { diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index de8123426f7..922451d1079 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -17,6 +17,7 @@ import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHos import { asPromise } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; import { TunnelOptions, TunnelCreationOptions } from 'vs/platform/remote/common/tunnel'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; class ExtensionTunnel implements vscode.Tunnel { private _onDispose: Emitter = new Emitter(); @@ -53,8 +54,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe } } - async openTunnel(forward: TunnelOptions): Promise { - const tunnel = await this._proxy.$openTunnel(forward); + async openTunnel(extension: IExtensionDescription, forward: TunnelOptions): Promise { + const tunnel = await this._proxy.$openTunnel(forward, extension.displayName); if (tunnel) { const disposableTunnel: vscode.Tunnel = new ExtensionTunnel(tunnel.remoteAddress, tunnel.localAddress, () => { return this._proxy.$closeTunnel(tunnel.remoteAddress); diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 7b249a140f9..00b4171a24b 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -384,7 +384,7 @@ interface ITunnelGroup { class TunnelItem implements ITunnelItem { static createFromTunnel(tunnel: Tunnel, type: TunnelType = TunnelType.Forwarded, closeable?: boolean) { - return new TunnelItem(type, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, tunnel.localPort, closeable === undefined ? tunnel.closeable : closeable, tunnel.name, tunnel.description ?? tunnel.runningProcess); + return new TunnelItem(type, tunnel.remoteHost, tunnel.remotePort, tunnel.localAddress, tunnel.localPort, closeable === undefined ? tunnel.closeable : closeable, tunnel.name, tunnel.description ?? tunnel.runningProcess, tunnel.source); } constructor( @@ -396,6 +396,7 @@ class TunnelItem implements ITunnelItem { public closeable?: boolean, public name?: string, private _description?: string, + private source?: string ) { } get label(): string { if (this.name) { @@ -435,11 +436,24 @@ class TunnelItem implements ITunnelItem { } get description(): string | undefined { - if (this._description) { - return this._description; - } else if (this.name && this.localAddress) { - return nls.localize('remote.tunnelsView.forwardedPortDescription0', "{0} \u2192 {1}", this.remotePort, TunnelItem.compactLongAddress(this.localAddress)); + const description: string[] = []; + + if (this.name && this.localAddress) { + description.push(nls.localize('remote.tunnelsView.forwardedPortDescription0', "{0} \u2192 {1}", this.remotePort, TunnelItem.compactLongAddress(this.localAddress))); } + + if (this._description) { + description.push(this._description); + } + + if (this.source) { + description.push(this.source); + } + + if (description.length > 0) { + return description.join(' \u2022 '); + } + return undefined; } } diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 63808d13255..189e1ba5501 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -48,6 +48,7 @@ export interface Tunnel { description?: string; closeable?: boolean; runningProcess: string | undefined; + source?: string; } export function makeAddress(host: string, port: number): string { @@ -177,7 +178,7 @@ export class TunnelModel extends Disposable { } } - async forward(remote: { host: string, port: number }, local?: number, name?: string): Promise { + async forward(remote: { host: string, port: number }, local?: number, name?: string, source?: string): Promise { const existingTunnel = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, remote.host, remote.port); if (!existingTunnel) { const authority = this.environmentService.remoteAuthority; @@ -194,7 +195,8 @@ export class TunnelModel extends Disposable { name: name, closeable: true, localAddress: tunnel.localAddress, - runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, remote.host, remote.port)?.detail + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, remote.host, remote.port)?.detail, + source }; const key = makeAddress(remote.host, remote.port); this.forwarded.set(key, newForward); @@ -313,7 +315,7 @@ export interface IRemoteExplorerService { onDidChangeEditable: Event; setEditable(tunnelItem: ITunnelItem | undefined, data: IEditableData | null): void; getEditableData(tunnelItem: ITunnelItem | undefined): IEditableData | undefined; - forward(remote: { host: string, port: number }, localPort?: number, name?: string): Promise; + forward(remote: { host: string, port: number }, localPort?: number, name?: string, source?: string): Promise; close(remote: { host: string, port: number }): Promise; setTunnelInformation(tunnelInformation: TunnelInformation | undefined): void; setCandidateFilter(filter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined): IDisposable; @@ -360,8 +362,8 @@ class RemoteExplorerService implements IRemoteExplorerService { return this._tunnelModel; } - forward(remote: { host: string, port: number }, local?: number, name?: string): Promise { - return this.tunnelModel.forward(remote, local, name); + forward(remote: { host: string, port: number }, local?: number, name?: string, source?: string): Promise { + return this.tunnelModel.forward(remote, local, name, source); } close(remote: { host: string, port: number }): Promise { From 3c3ed7fb583f27453d92d4a82d1118e7878fc05b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 26 Nov 2020 12:05:39 +0100 Subject: [PATCH 0338/1837] Fix #111351 --- src/vs/base/browser/ui/button/button.css | 4 ---- src/vs/base/browser/ui/dialog/dialog.css | 3 ++- .../browser/parts/notifications/media/notificationsList.css | 4 ++++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.css b/src/vs/base/browser/ui/button/button.css index 3e1e0815554..217c1656e7d 100644 --- a/src/vs/base/browser/ui/button/button.css +++ b/src/vs/base/browser/ui/button/button.css @@ -14,10 +14,6 @@ align-items: center; } -.monaco-button { - outline-offset: 2px !important; -} - .monaco-text-button:hover { text-decoration: none !important; } diff --git a/src/vs/base/browser/ui/dialog/dialog.css b/src/vs/base/browser/ui/dialog/dialog.css index 1f1180b8f3a..7c5ffc1c3fd 100644 --- a/src/vs/base/browser/ui/dialog/dialog.css +++ b/src/vs/base/browser/ui/dialog/dialog.css @@ -148,7 +148,8 @@ width: fit-content; width: -moz-fit-content; padding: 5px 10px; - margin: 4px 5px; /* allows button focus outline to be visible */ overflow: hidden; text-overflow: ellipsis; + margin: 4px 5px; /* allows button focus outline to be visible */ + outline-offset: 2px !important; } diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css index dc1fb11e68c..8bd0a402225 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css @@ -110,6 +110,10 @@ margin: 4px 5px; /* allows button focus outline to be visible */ } +.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-button { + outline-offset: 2px !important; +} + .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-text-button { width: fit-content; width: -moz-fit-content; From 9ee2a1ee1e823db0275d5216b8b0157d29f42dc7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 14:00:39 +0100 Subject: [PATCH 0339/1837] :up: update playwright --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 51ec80ae43d..7998a654b6f 100644 --- a/package.json +++ b/package.json @@ -160,7 +160,7 @@ "opn": "^6.0.0", "optimist": "0.3.5", "p-all": "^1.0.0", - "playwright": "1.3.0", + "playwright": "1.6.2", "pump": "^1.0.1", "queue": "3.0.6", "rcedit": "^1.1.0", From 2d4ec09c1dacf0b7f32c327f88ee0780d7d7ca7e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 14:12:22 +0100 Subject: [PATCH 0340/1837] add yarn lock file --- yarn.lock | 59 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1f0bd784f15..0560b9e37e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3429,10 +3429,10 @@ extract-zip@^1.0.3: mkdirp "0.5.1" yauzl "2.4.1" -extract-zip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.0.tgz#f53b71d44f4ff5a4527a2259ade000fb8b303492" - integrity sha512-i42GQ498yibjdvIhivUsRslx608whtGoFIhF26Z7O4MYncBxp8CwalOs1lnHy21A9sIohWO2+uiE4SRtC9JXDg== +extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== dependencies: debug "^4.1.1" get-stream "^5.1.0" @@ -5373,7 +5373,7 @@ jade@0.26.3: commander "0.6.1" mkdirp "0.3.0" -jpeg-js@^0.4.0: +jpeg-js@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.2.tgz#8b345b1ae4abde64c2da2fe67ea216a114ac279d" integrity sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw== @@ -6093,10 +6093,10 @@ mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" - integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== +mime@^2.4.6: + version "2.4.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" + integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== mimic-fn@^1.0.0: version "1.1.0" @@ -7231,21 +7231,22 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -playwright@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.3.0.tgz#8c33ed29bc0c7d97f82f8322e99be6d7f0d9ff67" - integrity sha512-W3mwXv2XNFugbepSZTZxI314WfI1SAjdZBEeGOu8S5KnPz4RSlunUFgXn6496o8lobPmORLcJ9VTSGyiFfGpaw== +playwright@1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.6.2.tgz#8631aec4d16b081d8ac414637b006099814a69d1" + integrity sha512-KiMmQuANG4O/ozpwxP8EwBBap0/liS3+wwkGo6nBJ4O4951y4ZsRPR1dqwsMOUD9wjsWf3ER+bAmQH5XmEO4Ig== dependencies: debug "^4.1.1" - extract-zip "^2.0.0" + extract-zip "^2.0.1" https-proxy-agent "^5.0.0" - jpeg-js "^0.4.0" - mime "^2.4.4" + jpeg-js "^0.4.2" + mime "^2.4.6" pngjs "^5.0.0" progress "^2.0.3" + proper-lockfile "^4.1.1" proxy-from-env "^1.1.0" rimraf "^3.0.2" - ws "^6.1.0" + ws "^7.3.1" plist@^3.0.1: version "3.0.1" @@ -7667,6 +7668,15 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +proper-lockfile@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.1.tgz#284cf9db9e30a90e647afad69deb7cb06881262c" + integrity sha512-1w6rxXodisVpn7QYvLk706mzprPTAPCYAqxMvctmPN3ekuRk/kuGkGc82pangZiAt4R3lwSuUzheTTn0/Yb7Zg== + dependencies: + graceful-fs "^4.1.11" + retry "^0.12.0" + signal-exit "^3.0.2" + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -8303,6 +8313,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + rimraf@2, rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -10326,12 +10341,10 @@ ws@^3.3.3: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" +ws@^7.3.1: + version "7.4.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" + integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ== xml-name-validator@^1.0.0: version "1.0.0" From b269cd9464e764c88c496453598ffd3fad09a578 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Thu, 26 Nov 2020 15:50:31 +0100 Subject: [PATCH 0341/1837] Add open pull request query --- .vscode/notebooks/endgame.github-issues | 10 ++++++++++ .vscode/notebooks/my-endgame.github-issues | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index fbcd551c806..7e7d8a33ee4 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -17,6 +17,16 @@ "value": "# Preparation", "editable": true }, + { + "kind": 1, + "language": "markdown", + "value": "## Open Pull Requests on the Milestone" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE is:pr is:open" + }, { "kind": 1, "language": "markdown", diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 0e8db03775c..0a049c2d2b9 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -17,6 +17,16 @@ "value": "# Preparation", "editable": true }, + { + "kind": 1, + "language": "markdown", + "value": "## Open Pull Requests on the Milestone" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE $MINE is:pr is:open" + }, { "kind": 1, "language": "markdown", From 6a974d536b3d4848481ceb18be9ec086efb05305 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 15:57:08 +0100 Subject: [PATCH 0342/1837] Change port language to "forwarded" and add icon Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/remoteExplorer.ts | 10 ++++----- .../contrib/remote/browser/tunnelView.ts | 22 +++++++++++++++++-- .../remote/common/remoteExplorerService.ts | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 4fa9c368ba9..6f525dd8565 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -107,17 +107,17 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu let tooltip: string; const count = this.remoteExplorerService.tunnelModel.forwarded.size + this.remoteExplorerService.tunnelModel.detected.size; if (count === 0) { - text = nls.localize('remote.forwardedPorts.statusbarTextNone', "No Ports Available"); + text = nls.localize('remote.forwardedPorts.statusbarTextNone', "No Ports Forwarded"); tooltip = text; } else { if (count === 1) { - text = nls.localize('remote.forwardedPorts.statusbarTextSingle', "1 Port Available"); + text = nls.localize('remote.forwardedPorts.statusbarTextSingle', "1 Port Forwarded"); } else { - text = nls.localize('remote.forwardedPorts.statusbarTextMultiple', "{0} Ports Available", count); + text = nls.localize('remote.forwardedPorts.statusbarTextMultiple', "{0} Ports Forwarded", count); } const allTunnels = Array.from(this.remoteExplorerService.tunnelModel.forwarded.values()); allTunnels.push(...Array.from(this.remoteExplorerService.tunnelModel.detected.values())); - tooltip = nls.localize('remote.forwardedPorts.statusbarTooltip', "Available Ports: {0}", + tooltip = nls.localize('remote.forwardedPorts.statusbarTooltip', "Forwarded Ports: {0}", allTunnels.map(forwarded => forwarded.remotePort).join(', ')); } return { @@ -187,7 +187,7 @@ class ForwardedPortNotifier extends Disposable { tunnels = tunnels.sort((a, b) => a.tunnelRemotePort - b.tunnelRemotePort); const firstTunnel = tunnels.shift()!; const address = makeAddress(firstTunnel.tunnelRemoteHost, firstTunnel.tunnelRemotePort); - const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available. [See all available ports](command:{1}.focus)", + const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available. [See all forwarded ports](command:{1}.focus)", firstTunnel.tunnelRemotePort, TunnelPanel.ID); const browserChoice: IPromptChoice = { label: OpenPortInBrowserAction.LABEL, diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 00b4171a24b..90570a236fc 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -85,7 +85,8 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { tunnelType: TunnelType.Add, remoteHost: 'localhost', remotePort: 0, - description: '' + description: '', + iconClasses: undefined }; } @@ -176,6 +177,7 @@ interface ITunnelTemplateData { elementDisposable: IDisposable; container: HTMLElement; iconLabel: IconLabel; + icon: HTMLElement; actionBar: ActionBar; } @@ -208,6 +210,7 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer('tunnelType', TunnelType.Add); diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 189e1ba5501..20c62f64aff 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -36,6 +36,7 @@ export interface ITunnelItem { name?: string; closeable?: boolean; description?: string; + readonly iconClasses?: string; readonly label: string; } From b2b5647451aae0f93a5db5c0a5fd6a08767d0740 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 16:02:49 +0100 Subject: [PATCH 0343/1837] disable two comparer test that fail in latest safari, https://github.com/microsoft/vscode/issues/111368 fyi @bpasero --- src/vs/base/test/browser/comparers.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/test/browser/comparers.test.ts b/src/vs/base/test/browser/comparers.test.ts index 4c40ea2a065..77ec3adf62d 100644 --- a/src/vs/base/test/browser/comparers.test.ts +++ b/src/vs/base/test/browser/comparers.test.ts @@ -197,7 +197,7 @@ suite('Comparers', () => { // name-only comparisons assert(compareFileNamesDefault('a', 'A') === compareLocale('a', 'A'), 'the same letter sorts by locale'); assert(compareFileNamesDefault('â', 'Â') === compareLocale('â', 'Â'), 'the same accented letter sorts by locale'); - assert.deepEqual(['artichoke', 'Artichoke', 'art', 'Art'].sort(compareFileNamesDefault), ['artichoke', 'Artichoke', 'art', 'Art'].sort(compareLocale), 'words with the same root and different cases sort in locale order'); + // assert.deepEqual(['artichoke', 'Artichoke', 'art', 'Art'].sort(compareFileNamesDefault), ['artichoke', 'Artichoke', 'art', 'Art'].sort(compareLocale), 'words with the same root and different cases sort in locale order'); assert.deepEqual(['email', 'Email', 'émail', 'Émail'].sort(compareFileNamesDefault), ['email', 'Email', 'émail', 'Émail'].sort(compareLocale), 'the same base characters with different case or accents sort in locale order'); // numeric comparisons @@ -259,7 +259,7 @@ suite('Comparers', () => { // name-only comparisons assert(compareFileExtensionsDefault('a', 'A') === compareLocale('a', 'A'), 'the same letter of different case sorts by locale'); assert(compareFileExtensionsDefault('â', 'Â') === compareLocale('â', 'Â'), 'the same accented letter of different case sorts by locale'); - assert.deepEqual(['artichoke', 'Artichoke', 'art', 'Art'].sort(compareFileExtensionsDefault), ['artichoke', 'Artichoke', 'art', 'Art'].sort(compareLocale), 'words with the same root and different cases sort in locale order'); + // assert.deepEqual(['artichoke', 'Artichoke', 'art', 'Art'].sort(compareFileExtensionsDefault), ['artichoke', 'Artichoke', 'art', 'Art'].sort(compareLocale), 'words with the same root and different cases sort in locale order'); assert.deepEqual(['email', 'Email', 'émail', 'Émail'].sort(compareFileExtensionsDefault), ['email', 'Email', 'émail', 'Émail'].sort((a, b) => a.localeCompare(b)), 'the same base characters with different case or accents sort in locale order'); // name plus extension comparisons From 301824029084a596035487fa96c2e8c46a1296f9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 26 Nov 2020 16:07:46 +0100 Subject: [PATCH 0344/1837] add user data init markers --- .../performance/browser/perfviewEditor.ts | 5 +++++ .../services/timer/browser/timerService.ts | 20 +++++++++++++++++++ .../services/userData/browser/userDataInit.ts | 11 +++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index c7bb057a334..6569ec09cff 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -26,6 +26,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { ByteSize, IFileService } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; +import { isWeb } from 'vs/base/common/platform'; export class PerfviewContrib { @@ -174,6 +175,10 @@ class PerfModelContentProvider implements ITextModelContentProvider { table.push(['wait for shell environment', metrics.timers.ellapsedWaitForShellEnv, '[renderer]', undefined]); table.push(['require & init workspace storage', metrics.timers.ellapsedWorkspaceStorageInit, '[renderer]', undefined]); table.push(['init workspace service', metrics.timers.ellapsedWorkspaceServiceInit, '[renderer]', undefined]); + if (isWeb) { + table.push(['init settings and global state from settings sync service', metrics.timers.ellapsedRequiredUserDataInit, '[renderer]', undefined]); + table.push(['init keybindings, snippets & extensions from settings sync service', metrics.timers.ellapsedOtherUserDataInit, '[renderer]', undefined]); + } table.push(['register extensions & spawn extension host', metrics.timers.ellapsedExtensions, '[renderer]', undefined]); table.push(['restore viewlet', metrics.timers.ellapsedViewletRestore, '[renderer]', metrics.viewletId]); table.push(['restore panel', metrics.timers.ellapsedPanelRestore, '[renderer]', metrics.panelId]); diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 2f146375db0..0dab9f40ed0 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -47,6 +47,8 @@ export interface IMemoryInfo { "timers.ellapsedRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedWorkspaceStorageInit" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedWorkspaceServiceInit" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedRequiredUserDataInit" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedOtherUserDataInit" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedViewletRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedPanelRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedEditorRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, @@ -212,6 +214,22 @@ export interface IStartupMetrics { */ readonly ellapsedWorkspaceServiceInit: number; + /** + * The time it took to initialize required user data (settings & global state) using settings sync service. + * + * * Happens in the renderer-process (only in Web) + * * Measured with the `willInitRequiredUserData` and `didInitRequiredUserData` performance marks. + */ + readonly ellapsedRequiredUserDataInit: number; + + /** + * The time it took to initialize other user data (keybindings, snippets & extensions) using settings sync service. + * + * * Happens in the renderer-process (only in Web) + * * Measured with the `willInitOtherUserData` and `didInitOtherUserData` performance marks. + */ + readonly ellapsedOtherUserDataInit: number; + /** * The time it took to load the main-bundle of the workbench, e.g. `workbench.desktop.main.js`. * @@ -400,6 +418,8 @@ export abstract class AbstractTimerService implements ITimerService { ellapsedWaitForShellEnv: perf.getDuration('willWaitForShellEnv', 'didWaitForShellEnv'), ellapsedWorkspaceStorageInit: perf.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage'), ellapsedWorkspaceServiceInit: perf.getDuration('willInitWorkspaceService', 'didInitWorkspaceService'), + ellapsedRequiredUserDataInit: perf.getDuration('willInitRequiredUserData', 'didInitRequiredUserData'), + ellapsedOtherUserDataInit: perf.getDuration('willInitOtherUserData', 'didInitOtherUserData'), ellapsedExtensions: perf.getDuration('willLoadExtensions', 'didLoadExtensions'), ellapsedEditorRestore: perf.getDuration('willRestoreEditors', 'didRestoreEditors'), ellapsedViewletRestore: perf.getDuration('willRestoreViewlet', 'didRestoreViewlet'), diff --git a/src/vs/workbench/services/userData/browser/userDataInit.ts b/src/vs/workbench/services/userData/browser/userDataInit.ts index 7041d437745..23e3b451a92 100644 --- a/src/vs/workbench/services/userData/browser/userDataInit.ts +++ b/src/vs/workbench/services/userData/browser/userDataInit.ts @@ -28,6 +28,7 @@ import { IExtensionGalleryService, IExtensionManagementService, IGlobalExtension import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { mark } from 'vs/base/common/performance'; export const IUserDataInitializationService = createDecorator('IUserDataInitializationService'); export interface IUserDataInitializationService { @@ -228,7 +229,15 @@ class InitializeOtherResourcesContribution implements IWorkbenchContribution { @IUserDataInitializationService userDataInitializeService: IUserDataInitializationService, @IInstantiationService instantiationService: IInstantiationService ) { - userDataInitializeService.initializeOtherResources(instantiationService); + this.initializeOtherResource(userDataInitializeService, instantiationService); + } + + private async initializeOtherResource(userDataInitializeService: IUserDataInitializationService, instantiationService: IInstantiationService): Promise { + if (await userDataInitializeService.requiresInitialization()) { + mark('willInitOtherUserData'); + await userDataInitializeService.initializeOtherResources(instantiationService); + mark('didInitOtherUserData'); + } } } From 58fe1b9dfa5192c8a2dbc38ca525fece75654aad Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 16:13:29 +0100 Subject: [PATCH 0345/1837] Add badge back to ports view Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/remoteExplorer.ts | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 6f525dd8565..2d6ba199868 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { Extensions, IViewContainersRegistry, IViewsRegistry, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; +import { Extensions, IViewContainersRegistry, IViewDescriptorService, IViewsRegistry, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -25,17 +25,21 @@ import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; import { Codicon } from 'vs/base/common/codicons'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; export const VIEWLET_ID = 'workbench.view.remote'; export class ForwardedPortsView extends Disposable implements IWorkbenchContribution { private contextKeyListener?: IDisposable; + private _activityBadge?: IDisposable; private entryAccessor: IStatusbarEntryAccessor | undefined; constructor( @IContextKeyService private readonly contextKeyService: IContextKeyService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, + @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, + @IActivityService private readonly activityService: IActivityService, @IStatusbarService private readonly statusbarService: IStatusbarService ) { super(); @@ -82,18 +86,35 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu const disposable = Registry.as(Extensions.ViewsRegistry).onViewsRegistered(e => { if (e.find(view => view.views.find(viewDescriptor => viewDescriptor.id === TUNNEL_VIEW_ID))) { this._register(this.remoteExplorerService.tunnelModel.onForwardPort(() => { + this.updateActivityBadge(); this.updateStatusBar(); })); this._register(this.remoteExplorerService.tunnelModel.onClosePort(() => { + this.updateActivityBadge(); this.updateStatusBar(); })); + this.updateActivityBadge(); this.updateStatusBar(); disposable.dispose(); } }); } + private updateActivityBadge() { + if (this._activityBadge) { + this._activityBadge.dispose(); + } + if (this.remoteExplorerService.tunnelModel.forwarded.size > 0) { + const viewContainer = this.viewDescriptorService.getViewContainerByViewId(TUNNEL_VIEW_ID); + if (viewContainer) { + this._activityBadge = this.activityService.showViewContainerActivity(viewContainer.id, { + badge: new NumberBadge(this.remoteExplorerService.tunnelModel.forwarded.size, n => n === 1 ? nls.localize('1forwardedPort', "1 forwarded port") : nls.localize('nForwardedPorts', "{0} forwarded ports", n)) + }); + } + } + } + private updateStatusBar() { if (!this.entryAccessor) { this._register(this.entryAccessor = this.statusbarService.addEntry(this.entry, 'status.forwardedPorts', nls.localize('status.forwardedPorts', "Forwarded Ports"), StatusbarAlignment.LEFT, 40)); @@ -106,15 +127,10 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu let text: string; let tooltip: string; const count = this.remoteExplorerService.tunnelModel.forwarded.size + this.remoteExplorerService.tunnelModel.detected.size; + text = `${count}`; if (count === 0) { - text = nls.localize('remote.forwardedPorts.statusbarTextNone', "No Ports Forwarded"); - tooltip = text; + tooltip = nls.localize('remote.forwardedPorts.statusbarTextNone', "No Ports Forwarded"); } else { - if (count === 1) { - text = nls.localize('remote.forwardedPorts.statusbarTextSingle', "1 Port Forwarded"); - } else { - text = nls.localize('remote.forwardedPorts.statusbarTextMultiple', "{0} Ports Forwarded", count); - } const allTunnels = Array.from(this.remoteExplorerService.tunnelModel.forwarded.values()); allTunnels.push(...Array.from(this.remoteExplorerService.tunnelModel.detected.values())); tooltip = nls.localize('remote.forwardedPorts.statusbarTooltip', "Forwarded Ports: {0}", From e5111fc439c6e9202040dd319e866c13a9e068ae Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 16:22:17 +0100 Subject: [PATCH 0346/1837] Only show "Not Forwarded" when auto forward is disabled Part of microsoft/vscode-remote-release#4021 --- .../contrib/remote/browser/remoteExplorer.ts | 16 +++++++-------- .../contrib/remote/browser/tunnelView.ts | 20 +++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 2d6ba199868..5692c447584 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -7,7 +7,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Extensions, IViewContainersRegistry, IViewDescriptorService, IViewsRegistry, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; -import { forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; +import { PORT_AUTO_FORWARD_SETTING, forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -40,7 +40,8 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, @IActivityService private readonly activityService: IActivityService, - @IStatusbarService private readonly statusbarService: IStatusbarService + @IStatusbarService private readonly statusbarService: IStatusbarService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(); this._register(Registry.as(Extensions.ViewsRegistry).registerViewWelcomeContent(TUNNEL_VIEW_ID, { @@ -68,7 +69,7 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu order: 5 }, ViewContainerLocation.Panel); - const tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService); + const tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService, this.configurationService), this.environmentService); const viewsRegistry = Registry.as(Extensions.ViewsRegistry); if (viewContainer) { viewsRegistry.registerViews([tunnelPanelDescriptor!], viewContainer); @@ -147,7 +148,6 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu export class AutomaticPortForwarding extends Disposable implements IWorkbenchContribution { - static AUTO_FORWARD_SETTING = 'remote.autoForwardPorts'; constructor( @ITerminalService readonly terminalService: ITerminalService, @@ -234,7 +234,7 @@ class WindowsAutomaticPortForwarding extends Disposable { super(); this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); this._register(configurationService.onDidChangeConfiguration((e) => { - if (e.affectsConfiguration(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + if (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING)) { this.tryStartStopUrlFinder(); } })); @@ -248,7 +248,7 @@ class WindowsAutomaticPortForwarding extends Disposable { } private tryStartStopUrlFinder() { - if (this.configurationService.getValue(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + if (this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING)) { this.startUrlFinder(); } else { this.stopUrlFinder(); @@ -297,7 +297,7 @@ class LinuxAutomaticPortForwarding extends Disposable { super(); this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); this._register(configurationService.onDidChangeConfiguration((e) => { - if (e.affectsConfiguration(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + if (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING)) { this.startStopCandidateListener(); } })); @@ -306,7 +306,7 @@ class LinuxAutomaticPortForwarding extends Disposable { } private startStopCandidateListener() { - if (this.configurationService.getValue(AutomaticPortForwarding.AUTO_FORWARD_SETTING)) { + if (this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING)) { this.startCandidateListener(); } else { this.stopCandidateListener(); diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 90570a236fc..a99acd36f56 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -45,6 +45,7 @@ import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Codicon } from 'vs/base/common/codicons'; export const forwardedPortsViewEnabled = new RawContextKey('forwardedPortsViewEnabled', false); +export const PORT_AUTO_FORWARD_SETTING = 'remote.autoForwardPorts'; class TunnelTreeVirtualDelegate implements IListVirtualDelegate { getHeight(element: ITunnelItem): number { @@ -73,7 +74,8 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { private _candidates: Map = new Map(); constructor( - @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService) { + @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, + @IConfigurationService private readonly configurationService: IConfigurationService) { super(); this.model = remoteExplorerService.tunnelModel; this._register(this.model.onForwardPort(() => this._onForwardedPortsChanged.fire())); @@ -106,13 +108,15 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { items: this.detected }); } - const candidates = await this.candidates; - if (candidates.length > 0) { - groups.push({ - label: nls.localize('remote.tunnelsView.candidates', "Not Forwarded"), - tunnelType: TunnelType.Candidate, - items: candidates - }); + if (!this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING)) { + const candidates = await this.candidates; + if (candidates.length > 0) { + groups.push({ + label: nls.localize('remote.tunnelsView.candidates', "Not Forwarded"), + tunnelType: TunnelType.Candidate, + items: candidates + }); + } } if (groups.length === 0) { groups.push(this._input); From cb8259c7b75afbbc09980bc59dc32fa62b410e76 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 16:41:52 +0100 Subject: [PATCH 0347/1837] Fix forwarded ports restore race --- .../remote/common/remoteExplorerService.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 20c62f64aff..ef855dfa7ab 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -107,6 +107,7 @@ export class TunnelModel extends Disposable { // onCandidateChanged returns the removed candidates public onCandidatesChanged: Event> = this._onCandidatesChanged.event; private _candidateFilter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined; + private tunnelRestoreValue: string | undefined; constructor( @ITunnelService private readonly tunnelService: ITunnelService, @@ -116,6 +117,7 @@ export class TunnelModel extends Disposable { @IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, ) { super(); + this.tunnelRestoreValue = this.storageService.get(TUNNELS_TO_RESTORE, StorageScope.WORKSPACE); this._candidates = new Map(); this.forwarded = new Map(); this.remoteTunnels = new Map(); @@ -147,8 +149,8 @@ export class TunnelModel extends Disposable { closeable: true, runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort)?.detail }); - this.storeForwarded(); } + this.storeForwarded(); this.remoteTunnels.set(key, tunnel); this._onForwardPort.fire(this.forwarded.get(key)!); })); @@ -164,9 +166,8 @@ export class TunnelModel extends Disposable { async restoreForwarded() { if (this.configurationService.getValue('remote.restoreForwardedPorts')) { - const tunnelsString = this.storageService.get(TUNNELS_TO_RESTORE, StorageScope.WORKSPACE); - if (tunnelsString) { - (JSON.parse(tunnelsString))?.forEach(tunnel => { + if (this.tunnelRestoreValue) { + (JSON.parse(this.tunnelRestoreValue))?.forEach(tunnel => { this.forward({ host: tunnel.remoteHost, port: tunnel.remotePort }, tunnel.localPort, tunnel.name); }); } @@ -213,11 +214,13 @@ export class TunnelModel extends Disposable { } name(host: string, port: number, name: string) { + const existingForwarded = mapHasAddressLocalhostOrAllInterfaces(this.forwarded, host, port); const key = makeAddress(host, port); - if (this.forwarded.has(key)) { - this.forwarded.get(key)!.name = name; + if (existingForwarded) { + existingForwarded.name = name; this.storeForwarded(); this._onPortName.fire({ host, port }); + return; } else if (this.detected.has(key)) { this.detected.get(key)!.name = name; this._onPortName.fire({ host, port }); From a5bda3ee9500bbbffbf2c9c82c9dc9a1e50e476d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 17:10:59 +0100 Subject: [PATCH 0348/1837] support later node for building --- build/npm/preinstall.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index cb88d37adef..b0bbb96341e 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -7,8 +7,8 @@ let err = false; const majorNodeVersion = parseInt(/^(\d+)\./.exec(process.versions.node)[1]); -if (majorNodeVersion < 10 || majorNodeVersion >= 13) { - console.error('\033[1;31m*** Please use node >=10 and <=12.\033[0;0m'); +if (majorNodeVersion < 10 || majorNodeVersion >= 15) { + console.error('\033[1;31m*** Please use node >=10 and <=14.\033[0;0m'); err = true; } From a94217739a68380ff2d2ff4f89a449cdbfe571e6 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Nov 2020 17:18:40 +0100 Subject: [PATCH 0349/1837] Don't auto forward ports in WSL Fixes #111375 --- .../contrib/remote/browser/remoteExplorer.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 5692c447584..85365ed2d41 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -171,7 +171,7 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon this._register(new WindowsAutomaticPortForwarding(terminalService, notificationService, openerService, remoteExplorerService, contextKeyService, configurationService, debugService)); } else if (environment?.os === OperatingSystem.Linux) { - this._register(new LinuxAutomaticPortForwarding(configurationService, remoteExplorerService, notificationService, openerService)); + this._register(new LinuxAutomaticPortForwarding(configurationService, remoteExplorerService, notificationService, openerService, contextKeyService)); } }); } @@ -287,12 +287,14 @@ class LinuxAutomaticPortForwarding extends Disposable { private autoForwarded: Set = new Set(); private notifier: ForwardedPortNotifier; private initialCandidates: Set = new Set(); + private contextServiceListener: IDisposable | undefined; constructor( private readonly configurationService: IConfigurationService, readonly remoteExplorerService: IRemoteExplorerService, readonly notificationService: INotificationService, - readonly openerService: IOpenerService + readonly openerService: IOpenerService, + readonly contextKeyService: IContextKeyService ) { super(); this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); @@ -302,6 +304,12 @@ class LinuxAutomaticPortForwarding extends Disposable { } })); + this.contextServiceListener = this._register(this.contextKeyService.onDidChangeContext(e => { + if (e.affectsSome(new Set(forwardedPortsViewEnabled.keys()))) { + this.startStopCandidateListener(); + } + })); + this.startStopCandidateListener(); } @@ -321,10 +329,12 @@ class LinuxAutomaticPortForwarding extends Disposable { } private startCandidateListener() { - if (this.candidateListener) { - // already started + if (this.candidateListener || !forwardedPortsViewEnabled.getValue(this.contextKeyService)) { return; } + if (this.contextServiceListener) { + this.contextServiceListener.dispose(); + } this.candidateListener = this._register(this.remoteExplorerService.tunnelModel.onCandidatesChanged(this.handleCandidateUpdate, this)); // Capture list of starting candidates so we don't auto forward them later. From 1e6e371d3bd919a4a93b908be68eed8b96282a29 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 17:55:54 +0100 Subject: [PATCH 0350/1837] :liptsick: sort API types and namespaces, enforce proposed API for types --- .../workbench/api/common/extHost.api.impl.ts | 117 ++++++++++++------ 1 file changed, 78 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index ac04adb6547..160f902df9d 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1091,41 +1091,48 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I // namespaces authentication, commands, + comment, + comments, debug, env, extensions, languages, - scm, - test, - comment, - comments, - tasks, notebook, + scm, + tasks, + test, window, workspace, // types Breakpoint: extHostTypes.Breakpoint, + CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall, + CallHierarchyItem: extHostTypes.CallHierarchyItem, + CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall, CancellationTokenSource: CancellationTokenSource, CodeAction: extHostTypes.CodeAction, CodeActionKind: extHostTypes.CodeActionKind, CodeActionTrigger: extHostTypes.CodeActionTrigger, - CodeLens: extHostTypes.CodeLens, CodeInset: extHostTypes.CodeInset, + CodeLens: extHostTypes.CodeLens, Color: extHostTypes.Color, ColorInformation: extHostTypes.ColorInformation, ColorPresentation: extHostTypes.ColorPresentation, - CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState, + ColorThemeKind: extHostTypes.ColorThemeKind, CommentMode: extHostTypes.CommentMode, + CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState, CompletionItem: extHostTypes.CompletionItem, CompletionItemKind: extHostTypes.CompletionItemKind, CompletionItemTag: extHostTypes.CompletionItemTag, CompletionList: extHostTypes.CompletionList, CompletionTriggerKind: extHostTypes.CompletionTriggerKind, ConfigurationTarget: extHostTypes.ConfigurationTarget, + CustomExecution: extHostTypes.CustomExecution, DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable, - DebugAdapterServer: extHostTypes.DebugAdapterServer, - DebugAdapterNamedPipeServer: extHostTypes.DebugAdapterNamedPipeServer, DebugAdapterInlineImplementation: extHostTypes.DebugAdapterInlineImplementation, + DebugAdapterNamedPipeServer: extHostTypes.DebugAdapterNamedPipeServer, + DebugAdapterServer: extHostTypes.DebugAdapterServer, + DebugConfigurationProviderTriggerKind: extHostTypes.DebugConfigurationProviderTriggerKind, + DebugConsoleMode: extHostTypes.DebugConsoleMode, DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior, Diagnostic: extHostTypes.Diagnostic, DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation, @@ -1143,8 +1150,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ExtensionKind: extHostTypes.ExtensionKind, ExtensionMode: extHostTypes.ExtensionMode, ExtensionRuntime: extHostTypes.ExtensionRuntime, - CustomExecution: extHostTypes.CustomExecution, FileChangeType: extHostTypes.FileChangeType, + FileDecoration: extHostTypes.FileDecoration, FileSystemError: extHostTypes.FileSystemError, FileType: files.FileType, FoldingRange: extHostTypes.FoldingRange, @@ -1163,19 +1170,19 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I QuickInputButtons: extHostTypes.QuickInputButtons, Range: extHostTypes.Range, RelativePattern: extHostTypes.RelativePattern, - ResolvedAuthority: extHostTypes.ResolvedAuthority, RemoteAuthorityResolverError: extHostTypes.RemoteAuthorityResolverError, - SemanticTokensLegend: extHostTypes.SemanticTokensLegend, - SemanticTokensBuilder: extHostTypes.SemanticTokensBuilder, - SemanticTokens: extHostTypes.SemanticTokens, - SemanticTokensEdits: extHostTypes.SemanticTokensEdits, - SemanticTokensEdit: extHostTypes.SemanticTokensEdit, + ResolvedAuthority: extHostTypes.ResolvedAuthority, Selection: extHostTypes.Selection, SelectionRange: extHostTypes.SelectionRange, + SemanticTokens: extHostTypes.SemanticTokens, + SemanticTokensBuilder: extHostTypes.SemanticTokensBuilder, + SemanticTokensEdit: extHostTypes.SemanticTokensEdit, + SemanticTokensEdits: extHostTypes.SemanticTokensEdits, + SemanticTokensLegend: extHostTypes.SemanticTokensLegend, ShellExecution: extHostTypes.ShellExecution, ShellQuoting: extHostTypes.ShellQuoting, - SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind, SignatureHelp: extHostTypes.SignatureHelp, + SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind, SignatureInformation: extHostTypes.SignatureInformation, SnippetString: extHostTypes.SnippetString, SourceBreakpoint: extHostTypes.SourceBreakpoint, @@ -1201,31 +1208,63 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I TreeItem: extHostTypes.TreeItem, TreeItem2: extHostTypes.TreeItem, TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState, + UIKind: UIKind, Uri: URI, ViewColumn: extHostTypes.ViewColumn, WorkspaceEdit: extHostTypes.WorkspaceEdit, - // proposed - CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall, - CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall, - CallHierarchyItem: extHostTypes.CallHierarchyItem, - DebugConsoleMode: extHostTypes.DebugConsoleMode, - DebugConfigurationProviderTriggerKind: extHostTypes.DebugConfigurationProviderTriggerKind, - FileDecoration: extHostTypes.FileDecoration, - UIKind: UIKind, - ColorThemeKind: extHostTypes.ColorThemeKind, - TimelineItem: extHostTypes.TimelineItem, - CellKind: extHostTypes.CellKind, - CellOutputKind: extHostTypes.CellOutputKind, - NotebookCellRunState: extHostTypes.NotebookCellRunState, - NotebookRunState: extHostTypes.NotebookRunState, - NotebookCellStatusBarAlignment: extHostTypes.NotebookCellStatusBarAlignment, - NotebookEditorRevealType: extHostTypes.NotebookEditorRevealType, - NotebookCellOutput: extHostTypes.NotebookCellOutput, - NotebookCellOutputItem: extHostTypes.NotebookCellOutputItem, - OnTypeRenameRanges: extHostTypes.OnTypeRenameRanges, - TestRunState: extHostTypes.TestRunState, - TestMessageSeverity: extHostTypes.TestMessageSeverity, - TestState: extHostTypes.TestState, + // proposed api types + get TimelineItem() { + checkProposedApiEnabled(extension); + return extHostTypes.TimelineItem; + }, + get CellKind() { + checkProposedApiEnabled(extension); + return extHostTypes.CellKind; + }, + get CellOutputKind() { + checkProposedApiEnabled(extension); + return extHostTypes.CellOutputKind; + }, + get NotebookCellRunState() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookCellRunState; + }, + get NotebookRunState() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookRunState; + }, + get NotebookCellStatusBarAlignment() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookCellStatusBarAlignment; + }, + get NotebookEditorRevealType() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookEditorRevealType; + }, + get NotebookCellOutput() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookCellOutput; + }, + get NotebookCellOutputItem() { + checkProposedApiEnabled(extension); + return extHostTypes.NotebookCellOutputItem; + }, + get OnTypeRenameRanges() { + checkProposedApiEnabled(extension); + return extHostTypes.OnTypeRenameRanges; + }, + get TestRunState() { + checkProposedApiEnabled(extension); + return extHostTypes.TestRunState; + }, + get TestMessageSeverity() { + checkProposedApiEnabled(extension); + return extHostTypes.TestMessageSeverity; + }, + get TestState() { + checkProposedApiEnabled(extension); + return extHostTypes.TestState; + }, }; }; } From 58a90729c4e8e5e22ef6245450bc8d322ca639aa Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 17:59:17 +0100 Subject: [PATCH 0351/1837] externalize activitybar icons --- .../browser/parts/activitybar/activitybarPart.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index ef4a9b5caa9..39a3ca76efc 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -42,6 +42,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; interface IPlaceholderViewContainer { readonly id: string; @@ -68,6 +69,9 @@ interface ICachedViewContainer { views?: { when?: string }[]; } +const settingsViewBarIcon = registerIcon('settings-view-bar-icon', Codicon.settingsGear, nls.localize('settingsViewBarIcon', 'Settings icon in the view bar.')); +const accountsViewBarIcon = registerIcon('accounts-view-bar-icon', Codicon.account, nls.localize('accountsViewBarIcon', 'Accounts icon in the view bar.')); + export class ActivitybarPart extends Part implements IActivityBarService { declare readonly _serviceBrand: undefined; @@ -602,14 +606,14 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.globalActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.manage', name: nls.localize('manage', "Manage"), - cssClass: Codicon.settingsGear.classNames + cssClass: ThemeIcon.asClassName(settingsViewBarIcon) })); if (this.accountsVisibilityPreference) { this.accountsActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.accounts', name: nls.localize('accounts', "Accounts"), - cssClass: Codicon.account.classNames + cssClass: ThemeIcon.asClassName(accountsViewBarIcon) })); this.globalActivityActionBar.push(this.accountsActivityAction, { index: ActivitybarPart.ACCOUNTS_ACTION_INDEX }); From f0bb23ca02f320816219017234e412caa425851e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 18:02:23 +0100 Subject: [PATCH 0352/1837] more icon work --- .../workbench/contrib/comments/browser/commentNode.ts | 3 ++- .../contrib/comments/browser/commentThreadWidget.ts | 9 +++++++-- .../contrib/customEditor/browser/customEditors.ts | 3 ++- src/vs/workbench/contrib/feedback/browser/feedback.ts | 2 +- .../workbench/contrib/outline/browser/outlinePane.ts | 3 ++- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 6 +++--- .../contrib/tasks/browser/abstractTaskService.ts | 5 +++-- .../workbench/contrib/tasks/browser/taskQuickPick.ts | 11 ++++++++--- 8 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts index 249fd9b1069..a059627b07f 100644 --- a/src/vs/workbench/contrib/comments/browser/commentNode.ts +++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts @@ -34,6 +34,7 @@ import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commen import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; +import { Codicon } from 'vs/base/common/codicons'; export class CommentNode extends Disposable { private _domNode: HTMLElement; @@ -156,7 +157,7 @@ export class CommentNode extends Disposable { { actionViewItemProvider: action => this.actionViewItemProvider(action as Action), actionRunner: this.actionRunner, - classNames: ['toolbar-toggle-pickReactions', 'codicon', 'codicon-reactions'], + classNames: ['toolbar-toggle-pickReactions', ...Codicon.reactions.classNamesArray], anchorAlignmentProvider: () => AnchorAlignment.RIGHT } ); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 914c22eab8f..8f8c4ffcfde 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -31,7 +31,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { contrastBorder, editorForeground, focusBorder, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, transparent } from 'vs/platform/theme/common/colorRegistry'; -import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commentFormActions'; import { CommentGlyphWidget } from 'vs/workbench/contrib/comments/browser/commentGlyphWidget'; import { CommentMenus } from 'vs/workbench/contrib/comments/browser/commentMenus'; @@ -47,9 +47,14 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { Codicon } from 'vs/base/common/codicons'; + + +const collapseIcon = registerIcon('review-comment-collapse', Codicon.chevronUp, nls.localize('collapseIcon', 'Icon to collapse a review comment.')); export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration'; -const COLLAPSE_ACTION_CLASS = 'expand-review-action codicon-chevron-up'; +const COLLAPSE_ACTION_CLASS = 'expand-review-action ' + ThemeIcon.asClassName(collapseIcon); const COMMENT_SCHEME = 'comment'; diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index c67d70f1a95..c57aa6dd36b 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { coalesce, distinct } from 'vs/base/common/arrays'; +import { Codicon } from 'vs/base/common/codicons'; import { Emitter, Event } from 'vs/base/common/event'; import { Lazy } from 'vs/base/common/lazy'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -173,7 +174,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ : undefined, detail: editorDescriptor.providerDisplayName, buttons: resourceExt ? [{ - iconClass: 'codicon-settings-gear', + iconClass: Codicon.settingsGear.classNames, tooltip: nls.localize('promptOpenWith.setDefaultTooltip', "Set as default editor for '{0}' files", resourceExt) }] : undefined })); diff --git a/src/vs/workbench/contrib/feedback/browser/feedback.ts b/src/vs/workbench/contrib/feedback/browser/feedback.ts index fdc7344bb8e..7a6e14dddc5 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedback.ts @@ -277,7 +277,7 @@ export class FeedbackDropdown extends Dropdown { this.sendButton = new Button(buttonsContainer); this.sendButton.enabled = false; this.sendButton.label = nls.localize('tweet', "Tweet"); - dom.prepend(this.sendButton.element, dom.$('span.codicon.codicon-twitter')); + dom.prepend(this.sendButton.element, dom.$('span' + Codicon.twitter.cssSelector)); this.sendButton.element.classList.add('send'); this.sendButton.element.title = nls.localize('tweetFeedback', "Tweet Feedback"); disposables.add(attachButtonStyler(this.sendButton, this.themeService)); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 0fd46248cc5..ab48b16b7ca 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -48,6 +48,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { Codicon } from 'vs/base/common/codicons'; class RequestState { @@ -399,7 +400,7 @@ export class OutlinePane extends ViewPane { getActions(): IAction[] { return [ - new CollapseAction(() => this._tree, true, 'explorer-action codicon-collapse-all') + new CollapseAction(() => this._tree, true, 'explorer-action ' + Codicon.collapseAll.classNames) ]; } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index b23b1174083..3f54b418d40 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -22,7 +22,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { MenuItemAction, IMenuService } from 'vs/platform/actions/common/actions'; import { IAction, IActionViewItem, ActionRunner, Action, RadioGroup, Separator, SubmenuAction, IActionViewItemProvider } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IThemeService, registerThemingParticipant, IFileIconTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IFileIconTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, StatusBarAction, StatusBarActionViewItem, getRepositoryVisibilityActions } from './util'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { WorkbenchCompressibleObjectTree, IOpenEvent } from 'vs/platform/list/browser/listService'; @@ -1229,7 +1229,7 @@ export class ToggleViewModeAction extends Action { } private onDidChangeMode(mode: ViewModelMode): void { - const iconClass = mode === ViewModelMode.List ? 'codicon-list-tree' : 'codicon-list-flat'; + const iconClass = ThemeIcon.asClassName(mode === ViewModelMode.List ? Codicon.listTree : Codicon.listFlat); this.class = `scm-action toggle-view-mode ${iconClass}`; this.checked = this.viewModel.mode === this.mode; } @@ -1658,7 +1658,7 @@ class SCMCollapseAction extends Action { this.enabled = isAnyProviderCollapsible; this.allCollapsed = isAnyProviderCollapsible && this.viewModel.areAllProvidersCollapsed(); this.label = this.allCollapsed ? localize('expand all', "Expand All Repositories") : localize('collapse all', "Collapse All Repositories"); - this.class = this.allCollapsed ? Codicon.expandAll.classNames : Codicon.collapseAll.classNames; + this.class = ThemeIcon.asClassName(this.allCollapsed ? Codicon.expandAll : Codicon.collapseAll); } } diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 35f0c4bde49..64f74982d46 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -76,9 +76,10 @@ import { ITextEditorSelection, TextEditorSelectionRevealType } from 'vs/platform import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; -import { isWorkspaceFolder, TaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQuickPick, QUICKOPEN_SKIP_CONFIG } from 'vs/workbench/contrib/tasks/browser/taskQuickPick'; +import { isWorkspaceFolder, TaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQuickPick, QUICKOPEN_SKIP_CONFIG, configureTaskIcon } from 'vs/workbench/contrib/tasks/browser/taskQuickPick'; import { ILogService } from 'vs/platform/log/common/log'; import { once } from 'vs/base/common/functional'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const QUICKOPEN_HISTORY_LIMIT_CONFIG = 'task.quickOpen.history'; const PROBLEM_MATCHER_NEVER_CONFIG = 'task.problemMatchers.neverPrompt'; @@ -2201,7 +2202,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } for (let task of tasks) { let entry: TaskQuickPickEntry = TaskQuickPickEntry(task); - entry.buttons = [{ iconClass: 'codicon-gear', tooltip: nls.localize('configureTask', "Configure Task") }]; + entry.buttons = [{ iconClass: ThemeIcon.asClassName(configureTaskIcon), tooltip: nls.localize('configureTask', "Configure Task") }]; if (selectedEntry && (task === selectedEntry.task)) { entries.unshift(selectedEntry); } else { diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index 5a91e831891..f1539810aa0 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -15,6 +15,8 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { Disposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const QUICKOPEN_DETAIL_CONFIG = 'task.quickOpen.detail'; export const QUICKOPEN_SKIP_CONFIG = 'task.quickOpen.skip'; @@ -32,6 +34,9 @@ export interface TaskTwoLevelQuickPickEntry extends IQuickPickItem { const SHOW_ALL: string = nls.localize('taskQuickPick.showAll', "Show All Tasks..."); +export const configureTaskIcon = registerIcon('tasks-list-configure', Codicon.gear, nls.localize('configureTaskIcon', 'Configration icon in the tasks selection list.')); +const removeTaskIcon = registerIcon('tasks-remove', Codicon.close, nls.localize('removeTaskIcon', 'Icon for remove in the tasks selection list.')); + export class TaskQuickPick extends Disposable { private sorter: TaskSorter; private topLevelEntries: QuickPickInput[] | undefined; @@ -65,7 +70,7 @@ export class TaskQuickPick extends Disposable { private createTaskEntry(task: Task | ConfiguringTask, extraButtons: IQuickInputButton[] = []): TaskTwoLevelQuickPickEntry { const entry: TaskTwoLevelQuickPickEntry = { label: this.guessTaskLabel(task), description: this.taskService.getTaskDescription(task), task, detail: this.showDetail() ? task.configurationProperties.detail : undefined }; - entry.buttons = [{ iconClass: 'codicon-gear', tooltip: nls.localize('configureTask', "Configure Task") }, ...extraButtons]; + entry.buttons = [{ iconClass: ThemeIcon.asClassName(configureTaskIcon), tooltip: nls.localize('configureTask', "Configure Task") }, ...extraButtons]; return entry; } @@ -145,7 +150,7 @@ export class TaskQuickPick extends Disposable { recentTasks = dedupeAndPrune.recentTasks; if (recentTasks.length > 0) { const removeRecentButton: IQuickInputButton = { - iconClass: 'codicon-close', + iconClass: ThemeIcon.asClassName(removeTaskIcon), tooltip: nls.localize('removeRecent', 'Remove Recently Used Task') }; this.createEntriesForGroup(this.topLevelEntries, recentTasks, nls.localize('recentlyUsed', 'recently used'), [removeRecentButton]); @@ -176,7 +181,7 @@ export class TaskQuickPick extends Disposable { picker.onDidTriggerItemButton(async (context) => { let task = context.item.task; - if (task && !Types.isString(task) && context.button.iconClass === 'codicon-close') { + if (task && !Types.isString(task) && context.button.iconClass === ThemeIcon.asClassName(removeTaskIcon)) { const key = task.getRecentlyUsedKey(); if (key) { this.taskService.removeRecentlyUsedTask(key); From 44af5d2af2ba46235c63feaa52772aa094113d23 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 18:02:58 +0100 Subject: [PATCH 0353/1837] marker view icons --- .../contrib/markers/browser/markersTreeViewer.ts | 13 ++++++++----- .../contrib/markers/browser/markersViewActions.ts | 8 ++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index 67f945f0b0d..6a344c8a012 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -14,7 +14,7 @@ import { ResourceMarkers, Marker, RelatedInformation } from 'vs/workbench/contri import Messages from 'vs/workbench/contrib/markers/browser/messages'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; -import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { QuickFixAction, QuickFixActionViewItem } from 'vs/workbench/contrib/markers/browser/markersViewActions'; @@ -53,6 +53,8 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Progress } from 'vs/platform/progress/common/progress'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export type TreeElement = ResourceMarkers | Marker | RelatedInformation; @@ -255,9 +257,10 @@ export class MarkerRenderer implements ITreeRenderer 1; action.tooltip = multiline ? localize('single line', "Show message in single line") : localize('multi line', "Show message in multiple lines"); - action.class = multiline ? expandedClass : collapsedClass; + action.class = ThemeIcon.asClassName(multiline ? expandedIcon : collapsedIcon); action.run = () => { if (viewModel) { viewModel.multiline = !viewModel.multiline; } return Promise.resolve(); }; this.multilineActionbar.push([action], { icon: true, label: false }); } diff --git a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts index 55fbbbb1402..973e9e69720 100644 --- a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts +++ b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts @@ -12,7 +12,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import Messages from 'vs/workbench/contrib/markers/browser/messages'; import Constants from 'vs/workbench/contrib/markers/browser/constants'; -import { IThemeService, registerThemingParticipant, ICssStyleCollector, IColorTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, ICssStyleCollector, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { toDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -28,6 +28,7 @@ import { IViewsService } from 'vs/workbench/common/views'; import { Codicon } from 'vs/base/common/codicons'; import { BaseActionViewItem, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export class ShowProblemsPanelAction extends Action { @@ -256,6 +257,9 @@ class FiltersDropdownMenuActionViewItem extends DropdownMenuActionViewItem { } + +const filterIcon = registerIcon('markers-view-filter', Codicon.filter, localize('filterIcon', 'Icon for the filter configuration in the markers view.')); + export class MarkersFilterActionViewItem extends BaseActionViewItem { private delayedFilterUpdate: Delayer; @@ -279,7 +283,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { this._register(toDisposable(() => this.delayedFilterUpdate.cancel())); this._register(filterController.onDidFocusFilter(() => this.focus())); this._register(filterController.onDidClearFilterText(() => this.clearFilterText())); - this.filtersAction = new Action('markersFiltersAction', Messages.MARKERS_PANEL_ACTION_TOOLTIP_MORE_FILTERS, 'markers-filters codicon-filter'); + this.filtersAction = new Action('markersFiltersAction', Messages.MARKERS_PANEL_ACTION_TOOLTIP_MORE_FILTERS, 'markers-filters ' + ThemeIcon.asClassName(filterIcon)); this.filtersAction.checked = this.hasFiltersChanged(); this._register(filterController.filters.onDidChange(e => this.onDidFiltersChange(e))); } From c219b0673cc86b22f7782c5371002d71a2ff9986 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2020 18:04:27 +0100 Subject: [PATCH 0354/1837] :lipstick: discover and mark more proposed types --- .../workbench/api/common/extHost.api.impl.ts | 31 ++++++++++++++----- src/vs/workbench/api/common/extHostTypes.ts | 13 -------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 160f902df9d..67b147b4cad 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1112,7 +1112,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I CodeAction: extHostTypes.CodeAction, CodeActionKind: extHostTypes.CodeActionKind, CodeActionTrigger: extHostTypes.CodeActionTrigger, - CodeInset: extHostTypes.CodeInset, CodeLens: extHostTypes.CodeLens, Color: extHostTypes.Color, ColorInformation: extHostTypes.ColorInformation, @@ -1149,7 +1148,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I EventEmitter: Emitter, ExtensionKind: extHostTypes.ExtensionKind, ExtensionMode: extHostTypes.ExtensionMode, - ExtensionRuntime: extHostTypes.ExtensionRuntime, FileChangeType: extHostTypes.FileChangeType, FileDecoration: extHostTypes.FileDecoration, FileSystemError: extHostTypes.FileSystemError, @@ -1160,7 +1158,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I Hover: extHostTypes.Hover, IndentAction: languageConfiguration.IndentAction, Location: extHostTypes.Location, - LogLevel: extHostTypes.LogLevel, MarkdownString: extHostTypes.MarkdownString, OverviewRulerLane: OverviewRulerLane, ParameterInformation: extHostTypes.ParameterInformation, @@ -1170,8 +1167,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I QuickInputButtons: extHostTypes.QuickInputButtons, Range: extHostTypes.Range, RelativePattern: extHostTypes.RelativePattern, - RemoteAuthorityResolverError: extHostTypes.RemoteAuthorityResolverError, - ResolvedAuthority: extHostTypes.ResolvedAuthority, Selection: extHostTypes.Selection, SelectionRange: extHostTypes.SelectionRange, SemanticTokens: extHostTypes.SemanticTokens, @@ -1186,7 +1181,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I SignatureInformation: extHostTypes.SignatureInformation, SnippetString: extHostTypes.SnippetString, SourceBreakpoint: extHostTypes.SourceBreakpoint, - SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType, StandardTokenType: extHostTypes.StandardTokenType, StatusBarAlignment: extHostTypes.StatusBarAlignment, SymbolInformation: extHostTypes.SymbolInformation, @@ -1206,13 +1200,36 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ThemeColor: extHostTypes.ThemeColor, ThemeIcon: extHostTypes.ThemeIcon, TreeItem: extHostTypes.TreeItem, - TreeItem2: extHostTypes.TreeItem, TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState, UIKind: UIKind, Uri: URI, ViewColumn: extHostTypes.ViewColumn, WorkspaceEdit: extHostTypes.WorkspaceEdit, // proposed api types + get LogLevel() { + checkProposedApiEnabled(extension); + return extHostTypes.LogLevel; + }, + get TreeItem2() { + checkProposedApiEnabled(extension); + return extHostTypes.TreeItem; + }, + get RemoteAuthorityResolverError() { + checkProposedApiEnabled(extension); + return extHostTypes.RemoteAuthorityResolverError; + }, + get ResolvedAuthority() { + checkProposedApiEnabled(extension); + return extHostTypes.ResolvedAuthority; + }, + get SourceControlInputBoxValidationType() { + checkProposedApiEnabled(extension); + return extHostTypes.SourceControlInputBoxValidationType; + }, + get ExtensionRuntime() { + checkProposedApiEnabled(extension); + return extHostTypes.ExtensionRuntime; + }, get TimelineItem() { checkProposedApiEnabled(extension); return extHostTypes.TimelineItem; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 6c54d1f4f9f..9fdbf188f9e 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1275,19 +1275,6 @@ export class CodeLens { } } - -export class CodeInset { - - range: Range; - height?: number; - - constructor(range: Range, height?: number) { - this.range = range; - this.height = height; - } -} - - @es5ClassCompat export class MarkdownString extends BaseMarkdownString implements vscode.MarkdownString { From c84fa206d4e4ec10d3bdcb6b94bf133a429303c2 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 18:05:10 +0100 Subject: [PATCH 0355/1837] add preferences icons --- src/vs/base/browser/ui/toolbar/toolbar.ts | 5 ++-- .../preferences/browser/keybindingsEditor.ts | 12 ++++---- .../preferences/browser/media/preferences.css | 16 ----------- .../browser/preferences.contribution.ts | 14 +++++----- .../preferences/browser/preferencesIcons.ts | 28 +++++++++++++++++++ .../browser/preferencesRenderers.ts | 5 ++-- .../preferences/browser/preferencesWidgets.ts | 23 ++++++++++----- .../preferences/browser/settingsEditor2.ts | 5 ++-- .../preferences/browser/settingsTree.ts | 18 +++--------- .../preferences/browser/settingsWidgets.ts | 12 ++++---- 10 files changed, 76 insertions(+), 62 deletions(-) create mode 100644 src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index d2b361446a7..ba5ce3d08c6 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -11,7 +11,7 @@ import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, CSSIcon, registerIcon } from 'vs/base/common/codicons'; import { EventMultiplexer } from 'vs/base/common/event'; import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; @@ -27,6 +27,7 @@ export interface IToolBarOptions { toggleMenuTitle?: string; anchorAlignmentProvider?: () => AnchorAlignment; renderDropdownAsChildElement?: boolean; + moreIcon?: CSSIcon; } /** @@ -72,7 +73,7 @@ export class ToolBar extends Disposable { actionViewItemProvider: this.options.actionViewItemProvider, actionRunner: this.actionRunner, keybindingProvider: this.options.getKeyBinding, - classNames: toolBarMoreIcon.classNamesArray, + classNames: (options.moreIcon ?? toolBarMoreIcon).classNames, anchorAlignmentProvider: this.options.anchorAlignmentProvider, menuAsChild: !!this.options.renderDropdownAsChildElement } diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index af69f6a7450..ba060683bdb 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -43,11 +43,11 @@ import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { Emitter, Event } from 'vs/base/common/event'; import { MenuRegistry, MenuId, isIMenuItem } from 'vs/platform/actions/common/actions'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { preferencesEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; import { Color, RGBA } from 'vs/base/common/color'; import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IKeybindingsEditorPane } from 'vs/workbench/services/preferences/common/preferences'; +import { keybindingsRecordKeysIcon, keybindingsSortIcon, keybindingsAddIcon, preferencesClearInputIcon, keybindingsEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; const $ = DOM.$; @@ -135,12 +135,12 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP const recordKeysActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS); const recordKeysActionLabel = localize('recordKeysLabel', "Record Keys"); - this.recordKeysAction = new Action(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, recordKeysActionKeybinding ? localize('recordKeysLabelWithKeybinding', "{0} ({1})", recordKeysActionLabel, recordKeysActionKeybinding.getLabel()) : recordKeysActionLabel, 'codicon-record-keys'); + this.recordKeysAction = new Action(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, recordKeysActionKeybinding ? localize('recordKeysLabelWithKeybinding', "{0} ({1})", recordKeysActionLabel, recordKeysActionKeybinding.getLabel()) : recordKeysActionLabel, ThemeIcon.asClassName(keybindingsRecordKeysIcon)); this.recordKeysAction.checked = false; const sortByPrecedenceActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE); const sortByPrecedenceActionLabel = localize('sortByPrecedeneLabel', "Sort by Precedence"); - this.sortByPrecedenceAction = new Action('keybindings.editor.sortByPrecedence', sortByPrecedenceActionKeybinding ? localize('sortByPrecedeneLabelWithKeybinding', "{0} ({1})", sortByPrecedenceActionLabel, sortByPrecedenceActionKeybinding.getLabel()) : sortByPrecedenceActionLabel, 'codicon-sort-precedence'); + this.sortByPrecedenceAction = new Action('keybindings.editor.sortByPrecedence', sortByPrecedenceActionKeybinding ? localize('sortByPrecedeneLabelWithKeybinding', "{0} ({1})", sortByPrecedenceActionLabel, sortByPrecedenceActionKeybinding.getLabel()) : sortByPrecedenceActionLabel, ThemeIcon.asClassName(keybindingsSortIcon)); this.sortByPrecedenceAction.checked = false; } @@ -345,7 +345,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP const fullTextSearchPlaceholder = localize('SearchKeybindings.FullTextSearchPlaceholder', "Type to search in keybindings"); const keybindingsSearchPlaceholder = localize('SearchKeybindings.KeybindingsSearchPlaceholder', "Recording Keys. Press Escape to exit"); - const clearInputAction = new Action(KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Keybindings Search Input"), 'codicon-clear-all', false, () => { this.clearSearchResults(); return Promise.resolve(null); }); + const clearInputAction = new Action(KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Keybindings Search Input"), ThemeIcon.asClassName(preferencesClearInputIcon), false, () => { this.clearSearchResults(); return Promise.resolve(null); }); const searchContainer = DOM.append(this.headerContainer, $('.search-container')); this.searchWidget = this._register(this.instantiationService.createInstance(KeybindingsSearchWidget, searchContainer, { @@ -926,7 +926,7 @@ class ActionsColumn extends Column { private createEditAction(keybindingItemEntry: IKeybindingItemEntry): IAction { const keybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_DEFINE); return { - class: ThemeIcon.asClassName(preferencesEditIcon), + class: ThemeIcon.asClassName(keybindingsEditIcon), enabled: true, id: 'editKeybinding', tooltip: keybinding ? localize('editKeybindingLabelWithKey', "Change Keybinding {0}", `(${keybinding.getLabel()})`) : localize('editKeybindingLabel', "Change Keybinding"), @@ -937,7 +937,7 @@ class ActionsColumn extends Column { private createAddAction(keybindingItemEntry: IKeybindingItemEntry): IAction { const keybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_DEFINE); return { - class: 'codicon-add', + class: ThemeIcon.asClassName(keybindingsAddIcon), enabled: true, id: 'addKeybinding', tooltip: keybinding ? localize('addKeybindingLabelWithKey', "Add Keybinding {0}", `(${keybinding.getLabel()})`) : localize('addKeybindingLabel', "Add Keybinding"), diff --git a/src/vs/workbench/contrib/preferences/browser/media/preferences.css b/src/vs/workbench/contrib/preferences/browser/media/preferences.css index 41382bd2349..89e322320c5 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/preferences.css +++ b/src/vs/workbench/contrib/preferences/browser/media/preferences.css @@ -194,22 +194,6 @@ justify-content: center; } -.monaco-editor .settings-group-title-widget .title-container.collapsed .codicon::before { - transform: rotate(-90deg); -} - -.monaco-editor .codicon-edit { - transform: rotate(-90deg); - width:16px; - height: 16px; - cursor: pointer; -} - -.monaco-editor .codicon-edit.hidden { - display: none; - visibility: hidden; -} - .monaco-editor .dim-configuration { color: #b1b1b1; } diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index 9c28d342232..153e92a3717 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -40,7 +40,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { DefaultPreferencesEditorInput, KeybindingsEditorInput, PreferencesEditorInput, SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; -import { Codicon } from 'vs/base/common/codicons'; +import { preferencesOpenSettingsIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search'; @@ -278,7 +278,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon super({ id: '_workbench.openUserSettingsEditor', title: OPEN_SETTINGS2_ACTION_TITLE, - icon: Codicon.goToFile, + icon: preferencesOpenSettingsIcon, menu: [{ id: MenuId.EditorTitle, when: ResourceContextKey.Resource.isEqualTo(that.environmentService.settingsResource.toString()), @@ -296,7 +296,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon super({ id: SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, title: { value: nls.localize('openSettingsJson', "Open Settings (JSON)"), original: 'Open Settings (JSON)' }, - icon: Codicon.goToFile, + icon: preferencesOpenSettingsIcon, menu: [{ id: MenuId.EditorTitle, when: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR.toNegated()), @@ -816,7 +816,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon id: 'workbench.action.openGlobalKeybindings', title: { value: nls.localize('openGlobalKeybindings', "Open Keyboard Shortcuts"), original: 'Open Keyboard Shortcuts' }, category, - icon: Codicon.goToFile, + icon: preferencesOpenSettingsIcon, keybinding: { when: null, weight: KeybindingWeight.WorkbenchContrib, @@ -873,7 +873,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon id: 'workbench.action.openGlobalKeybindingsFile', title: { value: nls.localize('openGlobalKeybindingsFile', "Open Keyboard Shortcuts (JSON)"), original: 'Open Keyboard Shortcuts (JSON)' }, category, - icon: Codicon.goToFile, + icon: preferencesOpenSettingsIcon, menu: [ { id: MenuId.CommandPalette }, { @@ -1124,7 +1124,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon command: { id: commandId, title: OPEN_SETTINGS2_ACTION_TITLE, - icon: Codicon.goToFile + icon: preferencesOpenSettingsIcon }, when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.workspaceSettingsResource!.toString()), WorkbenchStateContext.isEqualTo('workspace')), group: 'navigation', @@ -1149,7 +1149,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon command: { id: commandId, title: OPEN_SETTINGS2_ACTION_TITLE, - icon: Codicon.goToFile + icon: preferencesOpenSettingsIcon }, when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.getFolderSettingsResource(folder.uri)!.toString())), group: 'navigation', diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts b/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts new file mode 100644 index 00000000000..ec9d0a95823 --- /dev/null +++ b/src/vs/workbench/contrib/preferences/browser/preferencesIcons.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + +export const settingsGroupExpandedIcon = registerIcon('settings-group-expanded', Codicon.chevronDown, localize('settingsGroupExpandedIcon', 'Icon for an expanded section in the split JSON settings editor.')); +export const settingsGroupCollapsedIcon = registerIcon('settings-group-collapsed', Codicon.chevronRight, localize('settingsGroupCollapsedIcon', 'Icon for an collapsed section in the split JSON settings editor.')); +export const settingsScopeDropDownIcon = registerIcon('settings-folder-dropdown', Codicon.triangleDown, localize('settingsScopeDropDownIcon', 'Icon for the folder dropdown button in the split JSON settings editor.')); +export const settingsMoreActionIcon = registerIcon('settings-more-action', Codicon.gear, localize('settingsMoreActionIcon', 'Icon for the \'more actions\' action in the settings UI.')); + +export const keybindingsRecordKeysIcon = registerIcon('keybindings-record-keys', Codicon.recordKeys, localize('keybindingsRecordKeysIcon', 'Icon for the \'record keys\' action in the keybinding UI.')); +export const keybindingsSortIcon = registerIcon('keybindings-sort', Codicon.sortPrecedence, localize('keybindingsSortIcon', 'Icon for the \'sort by precedence\' toggle in the keybinding UI.')); + +export const keybindingsEditIcon = registerIcon('keybindings-edit', Codicon.edit, localize('keybindingsEditIcon', 'Icon for the edit action in the keybinding UI.')); +export const keybindingsAddIcon = registerIcon('keybindings-add', Codicon.add, localize('keybindingsAddIcon', 'Icon for the add action in the keybinding UI.')); + +export const settingsEditIcon = registerIcon('settings-edit', Codicon.edit, localize('settingsEditIcon', 'Icon for the edit action in the settings UI.')); +export const settingsAddIcon = registerIcon('settings-add', Codicon.add, localize('settingsAddIcon', 'Icon for the add action in the settings UI.')); + +export const settingsRemoveIcon = registerIcon('settings-remove', Codicon.close, localize('settingsRemoveIcon', 'Icon for the remove action in the settings UI.')); +export const settingsDiscardIcon = registerIcon('settings-discard', Codicon.discard, localize('preferencesDiscardIcon', 'Icon for the discard action in the settings UI.')); + +export const preferencesClearInputIcon = registerIcon('preferences-clear-input', Codicon.clearAll, localize('preferencesClearInput', 'Icon for clear input in the settings and keybinding UI.')); +export const preferencesOpenSettingsIcon = registerIcon('preferences-open-settings', Codicon.goToFile, localize('preferencesOpenSettings', 'Icon for open settings commands.')); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts index 7c2bee4dc42..49511397cfd 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts @@ -25,7 +25,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; -import { DefaultSettingsHeaderWidget, EditPreferenceWidget, SettingsGroupTitleWidget, SettingsHeaderWidget, preferencesEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; +import { DefaultSettingsHeaderWidget, EditPreferenceWidget, SettingsGroupTitleWidget, SettingsHeaderWidget } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; import { IFilterResult, IPreferencesEditorModel, IPreferencesService, ISetting, ISettingsEditorModel, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; import { DefaultSettingsEditorModel, SettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IMarkerService, IMarkerData, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers'; @@ -33,6 +33,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { FindDecorations } from 'vs/editor/contrib/find/findDecorations'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { settingsEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; export interface IPreferencesRenderer extends IDisposable { readonly preferencesModel: IPreferencesEditorModel; @@ -738,7 +739,7 @@ class EditSettingRenderer extends Disposable { const decorations = this.editor.getLineDecorations(line); if (decorations) { for (const { options } of decorations) { - if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf(ThemeIcon.asClassName(preferencesEditIcon)) === -1) { + if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf(ThemeIcon.asClassName(settingsEditIcon)) === -1) { return false; } } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index d24ee483241..573e5f07d46 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -35,9 +35,8 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { ISettingsGroup, IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { isEqual } from 'vs/base/common/resources'; -import { Codicon } from 'vs/base/common/codicons'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { settingsEditIcon, settingsGroupCollapsedIcon, settingsGroupExpandedIcon, settingsScopeDropDownIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; export class SettingsHeaderWidget extends Widget implements IViewZone { @@ -172,13 +171,23 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { this._register(focusTracker.onDidFocus(() => this.toggleFocus(true))); this._register(focusTracker.onDidBlur(() => this.toggleFocus(false))); - this.icon = DOM.append(this.titleContainer, DOM.$('.codicon.codicon-chevron-down')); + this.icon = DOM.append(this.titleContainer, DOM.$('')); this.title = DOM.append(this.titleContainer, DOM.$('.title')); this.title.textContent = this.settingsGroup.title + ` (${this.settingsGroup.sections.reduce((count, section) => count + section.settings.length, 0)})`; + this.updateTwisty(false); this.layout(); } + private getTwistyIcon(isCollapsed: boolean): ThemeIcon { + return isCollapsed ? settingsGroupCollapsedIcon : settingsGroupExpandedIcon; + } + + private updateTwisty(collapse: boolean) { + this.icon.classList.remove(...ThemeIcon.asClassNameArray(this.getTwistyIcon(!collapse))); + this.icon.classList.add(...ThemeIcon.asClassNameArray(this.getTwistyIcon(collapse))); + } + render() { if (!this.settingsGroup.range) { // #61352 @@ -194,6 +203,7 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { toggleCollapse(collapse: boolean) { this.titleContainer.classList.toggle('collapsed', collapse); + this.updateTwisty(collapse); } toggleFocus(focus: boolean): void { @@ -258,6 +268,7 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { private collapse(collapse: boolean) { if (collapse !== this.isCollapsed()) { this.titleContainer.classList.toggle('collapsed', collapse); + this.updateTwisty(collapse); this._onToggled.fire(collapse); } } @@ -346,7 +357,7 @@ export class FolderSettingsActionViewItem extends BaseActionViewItem { this.container = container; this.labelElement = DOM.$('.action-title'); this.detailsElement = DOM.$('.action-details'); - this.dropDownElement = DOM.$('.dropdown-icon.codicon.codicon-triangle-down.hide'); + this.dropDownElement = DOM.$('.dropdown-icon.hide' + ThemeIcon.asCSSSelector(settingsScopeDropDownIcon)); this.anchorElement = DOM.$('a.action-label.folder-settings', { role: 'button', 'aria-haspopup': 'true', @@ -747,8 +758,6 @@ export class SearchWidget extends Widget { } } -export const preferencesEditIcon = registerIcon('preferences-edit', Codicon.edit, localize('preferencesEditIcon', 'Icon for the edit action in preferences.')); - export class EditPreferenceWidget extends Disposable { private _line: number = -1; @@ -786,7 +795,7 @@ export class EditPreferenceWidget extends Disposable { this._line = line; newDecoration.push({ options: { - glyphMarginClassName: ThemeIcon.asClassName(preferencesEditIcon), + glyphMarginClassName: ThemeIcon.asClassName(settingsEditIcon), glyphMarginHoverMessage: new MarkdownString().appendText(hoverMessage), stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, }, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 64d3da690d3..3a77d68ebed 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -35,7 +35,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { badgeBackground, badgeForeground, contrastBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IUserDataAutoSyncEnablementService, IUserDataSyncService, SyncStatus } from 'vs/platform/userDataSync/common/userDataSync'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorMemento, IEditorOpenContext, IEditorPane } from 'vs/workbench/common/editor'; @@ -52,6 +52,7 @@ import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEdit import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IUserDataSyncWorkbenchService } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { preferencesClearInputIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; export const enum SettingsFocusContext { Search, @@ -435,7 +436,7 @@ export class SettingsEditor2 extends EditorPane { const searchContainer = DOM.append(this.headerContainer, $('.search-container')); - const clearInputAction = new Action(SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Settings Search Input"), 'codicon-clear-all', false, () => { this.clearSearchResults(); return Promise.resolve(null); }); + const clearInputAction = new Action(SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Settings Search Input"), ThemeIcon.asClassName(preferencesClearInputIcon), false, () => { this.clearSearchResults(); return Promise.resolve(null); }); this.searchWidget = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${SettingsEditor2.ID}.searchbox`, searchContainer, { triggerCharacters: ['@'], diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 6e09eb02531..3b26e64a130 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -38,7 +38,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { editorBackground, errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler'; -import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { getIgnoredSettings } from 'vs/platform/userDataSync/common/settingsMerge'; import { ITOCEntry } from 'vs/workbench/contrib/preferences/browser/settingsLayout'; import { ISettingsEditorViewState, settingKeyToDisplayFormat, SettingsTreeElement, SettingsTreeGroupChild, SettingsTreeGroupElement, SettingsTreeNewExtensionsElement, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels'; @@ -56,6 +56,7 @@ import { IListService, WorkbenchObjectTree } from 'vs/platform/list/browser/list import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { ILogService } from 'vs/platform/log/common/log'; +import { settingsMoreActionIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; const $ = DOM.$; @@ -635,22 +636,12 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre const toolbar = new ToolBar(container, this._contextMenuService, { toggleMenuTitle, - renderDropdownAsChildElement: true + renderDropdownAsChildElement: true, + moreIcon: ThemeIcon.asCSSIcon(settingsMoreActionIcon) // change icon from ellipsis to gear }); return toolbar; } - private fixToolbarIcon(toolbar: ToolBar): void { - const button = toolbar.getElement().querySelector('.codicon-toolbar-more'); - if (button) { - (button).tabIndex = 0; - - // change icon from ellipsis to gear - (button).classList.add('codicon-gear'); - (button).classList.remove('codicon-toolbar-more'); - } - } - protected renderSettingElement(node: ITreeNode, index: number, template: ISettingItemTemplate | ISettingBoolItemTemplate): void { const element = node.element; template.context = element; @@ -658,7 +649,6 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre const actions = this.disposableActionFactory(element.setting); actions.forEach(a => template.elementDisposables?.add(a)); template.toolbar.setActions([], [...this.settingActions, ...actions]); - this.fixToolbarIcon(template.toolbar); const setting = element.setting; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts index 023052f548c..9994ccc1b5e 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts @@ -24,7 +24,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView import { editorWidgetBorder, focusBorder, foreground, inputBackground, inputBorder, inputForeground, listActiveSelectionBackground, listActiveSelectionForeground, listFocusBackground, listHoverBackground, listHoverForeground, listInactiveSelectionBackground, listInactiveSelectionForeground, registerColor, selectBackground, selectBorder, selectForeground, simpleCheckboxBackground, simpleCheckboxBorder, simpleCheckboxForeground, textLinkActiveForeground, textLinkForeground, textPreformatForeground, transparent } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { preferencesEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; +import { settingsDiscardIcon, settingsEditIcon, settingsRemoveIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; const $ = DOM.$; export const settingsHeaderForeground = registerColor('settings.headerForeground', { light: '#444444', dark: '#e7e7e7', hc: '#ffffff' }, localize('headerForeground', "The foreground color for a section header or active title.")); @@ -496,14 +496,14 @@ export class ListSettingWidget extends AbstractListSettingWidget protected getActionsForItem(item: IListDataItem, idx: number): IAction[] { return [ { - class: ThemeIcon.asClassName(preferencesEditIcon), + class: ThemeIcon.asClassName(settingsEditIcon), enabled: true, id: 'workbench.action.editListItem', tooltip: this.getLocalizedStrings().editActionTooltip, run: () => this.editSetting(idx) }, { - class: 'codicon-close', + class: ThemeIcon.asClassName(settingsRemoveIcon), enabled: true, id: 'workbench.action.removeListItem', tooltip: this.getLocalizedStrings().deleteActionTooltip, @@ -740,7 +740,7 @@ export class ObjectSettingWidget extends AbstractListSettingWidget Date: Thu, 26 Nov 2020 18:13:51 +0100 Subject: [PATCH 0356/1837] some more cleanup, enfore proposed API checks, fyi @RMacfarlane --- .../workbench/api/common/extHost.api.impl.ts | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 67b147b4cad..fa598def051 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -51,7 +51,7 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; -import * as vscode from 'vscode'; +import type * as vscode from 'vscode'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { originalFSPath } from 'vs/base/common/resources'; import { values } from 'vs/base/common/collections'; @@ -203,40 +203,50 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I })(); const authentication: typeof vscode.authentication = { - registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable { - return extHostAuthentication.registerAuthenticationProvider(provider); - }, - get onDidChangeAuthenticationProviders(): Event { - return extHostAuthentication.onDidChangeAuthenticationProviders; - }, - getProviderIds(): Thenable> { - return extHostAuthentication.getProviderIds(); - }, - get providerIds(): string[] { - return extHostAuthentication.providerIds; - }, - get providers(): ReadonlyArray { - return extHostAuthentication.providers; - }, getSession(providerId: string, scopes: string[], options?: vscode.AuthenticationGetSessionOptions) { return extHostAuthentication.getSession(extension, providerId, scopes, options as any); }, - logout(providerId: string, sessionId: string): Thenable { - return extHostAuthentication.logout(providerId, sessionId); - }, get onDidChangeSessions(): Event { return extHostAuthentication.onDidChangeSessions; }, + registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable { + checkProposedApiEnabled(extension); + return extHostAuthentication.registerAuthenticationProvider(provider); + }, + get onDidChangeAuthenticationProviders(): Event { + checkProposedApiEnabled(extension); + return extHostAuthentication.onDidChangeAuthenticationProviders; + }, + getProviderIds(): Thenable> { + checkProposedApiEnabled(extension); + return extHostAuthentication.getProviderIds(); + }, + get providerIds(): string[] { + checkProposedApiEnabled(extension); + return extHostAuthentication.providerIds; + }, + get providers(): ReadonlyArray { + checkProposedApiEnabled(extension); + return extHostAuthentication.providers; + }, + logout(providerId: string, sessionId: string): Thenable { + checkProposedApiEnabled(extension); + return extHostAuthentication.logout(providerId, sessionId); + }, getPassword(key: string): Thenable { + checkProposedApiEnabled(extension); return extHostAuthentication.getPassword(extension, key); }, setPassword(key: string, value: string): Thenable { + checkProposedApiEnabled(extension); return extHostAuthentication.setPassword(extension, key, value); }, deletePassword(key: string): Thenable { + checkProposedApiEnabled(extension); return extHostAuthentication.deletePassword(extension, key); }, get onDidChangePassword(): Event { + checkProposedApiEnabled(extension); return extHostAuthentication.onDidChangePassword; } }; @@ -894,14 +904,13 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I } }; - const comment: typeof vscode.comments = { + // namespace: comments + const comments: typeof vscode.comments = { createCommentController(id: string, label: string) { return extHostComment.createCommentController(extension, id, label); } }; - const comments = comment; - // namespace: debug const debug: typeof vscode.debug = { get activeDebugSession() { @@ -1038,6 +1047,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostNotebook.registerNotebookKernelProvider(extension, selector, provider); }, createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType { + checkProposedApiEnabled(extension); return extHostNotebook.createNotebookEditorDecorationType(options); }, get activeNotebookEditor(): vscode.NotebookEditor | undefined { @@ -1091,7 +1101,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I // namespaces authentication, commands, - comment, comments, debug, env, From 818174d4e868db11cac25d71e0b1d29d852b4a90 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2020 18:17:35 +0100 Subject: [PATCH 0357/1837] bulk edit service: Show infinte progress when there is only 1 item since we do not know how long it takes --- src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index 558b4a0f90a..ca55a105790 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -63,7 +63,9 @@ class BulkEdit { } } - this._progress.report({ increment: 0, total: 100 }); + // Show infinte progress when there is only 1 item since we do not know how long it takes + const increment = this._edits.length > 1 ? 0 : undefined; + this._progress.report({ increment, total: 100 }); // Increment by percentage points since progress API expects that const progress: IProgress = { report: _ => this._progress.report({ increment: 100 / this._edits.length }) }; From 26a0c24c6c77af4e163d71beb6b3ef89e86cd7b8 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2020 18:18:58 +0100 Subject: [PATCH 0358/1837] fixes #111218 --- src/vs/workbench/contrib/files/browser/fileActions.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index ced14610695..85ae6b84699 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -878,7 +878,12 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole const notificationService = accessor.get(INotificationService); const commandService = accessor.get(ICommandService); + const wasHidden = !viewsService.isViewVisible(VIEW_ID); const view = await viewsService.openView(VIEW_ID, true); + if (wasHidden) { + // Give explorer some time to resolve itself #111218 + await timeout(500); + } if (!view) { // Can happen in empty workspace case (https://github.com/microsoft/vscode/issues/100604) From f70430eae481259050615d11f6374ac8800bc7c0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 26 Nov 2020 18:53:51 +0100 Subject: [PATCH 0359/1837] download to temp location first and rename --- .../node/extensionDownloader.ts | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/extensionManagement/node/extensionDownloader.ts b/src/vs/platform/extensionManagement/node/extensionDownloader.ts index f11e0174b7d..822dd47b117 100644 --- a/src/vs/platform/extensionManagement/node/extensionDownloader.ts +++ b/src/vs/platform/extensionManagement/node/extensionDownloader.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; +import { rename } from 'vs/base/node/pfs'; import { IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { IExtensionGalleryService, IGalleryExtension, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -13,6 +14,7 @@ import { ExtensionIdentifierWithVersion, groupByExtension } from 'vs/platform/ex import { ILogService } from 'vs/platform/log/common/log'; import { generateUuid } from 'vs/base/common/uuid'; import * as semver from 'vs/base/common/semver/semver'; +import { isWindows } from 'vs/base/common/platform'; const ExtensionIdVersionRegex = /^([^.]+\..+)-(\d+\.\d+\.\d+)$/; @@ -36,8 +38,21 @@ export class ExtensionsDownloader extends Disposable { async downloadExtension(extension: IGalleryExtension, operation: InstallOperation): Promise { await this.cleanUpPromise; - const location = joinPath(this.extensionsDownloadDir, this.getName(extension)); - await this.download(extension, location, operation); + const vsixName = this.getName(extension); + const location = joinPath(this.extensionsDownloadDir, vsixName); + + // Download only if vsix does not exist + if (!await this.fileService.exists(location)) { + // Download to temporary location first only if vsix does not exist + const tempLocation = joinPath(this.extensionsDownloadDir, `.${vsixName}`); + if (!await this.fileService.exists(tempLocation)) { + await this.extensionGalleryService.download(extension, tempLocation, operation); + } + + // Rename temp location to original + await this.rename(tempLocation, location, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */); + } + return location; } @@ -45,9 +60,15 @@ export class ExtensionsDownloader extends Disposable { // noop as caching is enabled always } - private async download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise { - if (!await this.fileService.exists(location)) { - await this.extensionGalleryService.download(extension, location, operation); + private async rename(from: URI, to: URI, retryUntil: number): Promise { + try { + await rename(from.fsPath, to.fsPath); + } catch (error) { + if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) { + this.logService.info(`Failed renaming ${from} to ${to} with 'EPERM' error. Trying again...`); + return this.rename(from, to, retryUntil); + } + throw error; } } From 5c2127ec74b79c578a551822aee679058648ef21 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 26 Nov 2020 19:49:39 +0100 Subject: [PATCH 0360/1837] Fix #110964 --- src/vs/code/node/cliProcessMain.ts | 2 +- .../common/extensionManagement.ts | 5 ++- .../common/extensionManagementIpc.ts | 6 +-- .../node/extensionManagementService.ts | 37 ++++++++++--------- .../userDataSync/common/extensionsSync.ts | 6 +-- .../browser/extensions.contribution.ts | 2 +- .../extensions/browser/extensionsViewlet.ts | 2 +- .../common/extensionManagementService.ts | 10 ++--- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 817f3f1ecd6..84fa06d76d5 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -331,7 +331,7 @@ export class Main { return; } console.log(localize('uninstalling', "Uninstalling {0}...", id)); - await this.extensionManagementService.uninstall(extensionToUninstall, true); + await this.extensionManagementService.uninstall(extensionToUninstall); uninstalledExtensions.push(extensionToUninstall); console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id)); } diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 0c20952bb6b..0e46a92d69f 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -201,7 +201,8 @@ export class ExtensionManagementError extends Error { } } -export type InstallOptions = { isBuiltin?: boolean, isMachineScoped?: boolean }; +export type InstallOptions = { isBuiltin?: boolean, isMachineScoped?: boolean, donotIncludePackAndDependencies?: boolean }; +export type UninstallOptions = { donotIncludePack?: boolean, donotCheckDependents?: boolean }; export const IExtensionManagementService = createDecorator('extensionManagementService'); export interface IExtensionManagementService { @@ -218,7 +219,7 @@ export interface IExtensionManagementService { install(vsix: URI, options?: InstallOptions): Promise; canInstall(extension: IGalleryExtension): Promise; installFromGallery(extension: IGalleryExtension, options?: InstallOptions): Promise; - uninstall(extension: ILocalExtension, force?: boolean): Promise; + uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise; reinstallFromGallery(extension: ILocalExtension): Promise; getInstalled(type?: ExtensionType): Promise; getExtensionsReport(): Promise; diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index caa8e8364cf..75422f963b2 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension, IExtensionTipsService, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension, IExtensionTipsService, InstallOptions, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { Emitter, Event } from 'vs/base/common/event'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IURITransformer, DefaultURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; @@ -128,8 +128,8 @@ export class ExtensionManagementChannelClient extends Disposable implements IExt return Promise.resolve(this.channel.call('installFromGallery', [extension, installOptions])).then(local => transformIncomingExtension(local, null)); } - uninstall(extension: ILocalExtension, force = false): Promise { - return Promise.resolve(this.channel.call('uninstall', [extension!, force])); + uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise { + return Promise.resolve(this.channel.call('uninstall', [extension!, options])); } reinstallFromGallery(extension: ILocalExtension): Promise { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 11135f9eb7b..af1092c14fd 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -20,7 +20,8 @@ import { INSTALL_ERROR_MALICIOUS, INSTALL_ERROR_INCOMPATIBLE, ExtensionManagementError, - InstallOptions + InstallOptions, + UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, getGalleryExtensionId, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -297,11 +298,13 @@ export class ExtensionManagementService extends Disposable implements IExtension try { await this.extensionsDownloader.delete(URI.file(installableExtension.zipPath)); } catch (error) { /* Ignore */ } - try { - await this.installDependenciesAndPackExtensions(local, existingExtension, options); - } catch (error) { - try { await this.uninstall(local); } catch (error) { /* Ignore */ } - throw error; + if (!options.donotIncludePackAndDependencies) { + try { + await this.installDependenciesAndPackExtensions(local, existingExtension, options); + } catch (error) { + try { await this.uninstall(local); } catch (error) { /* Ignore */ } + throw error; + } } if (existingExtension && semver.neq(existingExtension.manifest.version, extension.version)) { @@ -471,7 +474,7 @@ export class ExtensionManagementService extends Disposable implements IExtension await Promise.all(extensionsToUninstall.map(local => this.uninstall(local))); } - async uninstall(extension: ILocalExtension): Promise { + async uninstall(extension: ILocalExtension, options: UninstallOptions = {}): Promise { this.logService.trace('ExtensionManagementService#uninstall', extension.identifier.id); const installed = await this.getInstalled(ExtensionType.User); const extensionToUninstall = installed.find(e => areSameExtensions(e.identifier, extension.identifier)); @@ -480,7 +483,7 @@ export class ExtensionManagementService extends Disposable implements IExtension } try { - await this.checkForDependenciesAndUninstall(extensionToUninstall, installed); + await this.checkForDependenciesAndUninstall(extensionToUninstall, installed, options); } catch (error) { throw this.joinErrors(error); } @@ -533,15 +536,11 @@ export class ExtensionManagementService extends Disposable implements IExtension }, new Error('')); } - private async checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[]): Promise { + private async checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[], options: UninstallOptions): Promise { try { await this.preUninstallExtension(extension); - const packedExtensions = this.getAllPackExtensionsToUninstall(extension, installed); - if (packedExtensions.length) { - await this.uninstallExtensions(extension, packedExtensions, installed); - } else { - await this.uninstallExtensions(extension, [], installed); - } + const packedExtensions = options.donotIncludePack ? [] : this.getAllPackExtensionsToUninstall(extension, installed); + await this.uninstallExtensions(extension, packedExtensions, installed, options); } catch (error) { await this.postUninstallExtension(extension, new ExtensionManagementError(error instanceof Error ? error.message : error, INSTALL_ERROR_LOCAL)); throw error; @@ -549,10 +548,12 @@ export class ExtensionManagementService extends Disposable implements IExtension await this.postUninstallExtension(extension); } - private async uninstallExtensions(extension: ILocalExtension, otherExtensionsToUninstall: ILocalExtension[], installed: ILocalExtension[]): Promise { + private async uninstallExtensions(extension: ILocalExtension, otherExtensionsToUninstall: ILocalExtension[], installed: ILocalExtension[], options: UninstallOptions): Promise { const extensionsToUninstall = [extension, ...otherExtensionsToUninstall]; - for (const e of extensionsToUninstall) { - this.checkForDependents(e, extensionsToUninstall, installed, extension); + if (!options.donotCheckDependents) { + for (const e of extensionsToUninstall) { + this.checkForDependents(e, extensionsToUninstall, installed, extension); + } } await Promise.all([this.uninstallExtension(extension), ...otherExtensionsToUninstall.map(d => this.doUninstall(d))]); } diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index cb447e33233..e716e1355f4 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -350,7 +350,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse const extensionsToRemove = installedExtensions.filter(({ identifier, isBuiltin }) => !isBuiltin && removed.some(r => areSameExtensions(identifier, r))); await Promise.all(extensionsToRemove.map(async extensionToRemove => { this.logService.trace(`${this.syncResourceLogLabel}: Uninstalling local extension...`, extensionToRemove.identifier.id); - await this.extensionManagementService.uninstall(extensionToRemove); + await this.extensionManagementService.uninstall(extensionToRemove, { donotIncludePack: true, donotCheckDependents: true }); this.logService.info(`${this.syncResourceLogLabel}: Uninstalled local extension.`, extensionToRemove.identifier.id); removeFromSkipped.push(extensionToRemove.identifier); })); @@ -407,7 +407,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse // Install only if the extension does not exist if (!installedExtension) { this.logService.trace(`${this.syncResourceLogLabel}: Installing extension...`, e.identifier.id, extension.version); - await this.extensionManagementService.installFromGallery(extension, { isMachineScoped: false } /* pass options to prevent install and sync dialog in web */); + await this.extensionManagementService.installFromGallery(extension, { isMachineScoped: false, donotIncludePackAndDependencies: true } /* pass options to prevent install and sync dialog in web */); this.logService.info(`${this.syncResourceLogLabel}: Installed extension.`, e.identifier.id, extension.version); removeFromSkipped.push(extension.identifier); } @@ -572,5 +572,3 @@ export class ExtensionsInitializer extends AbstractInitializer { } } - - diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index dba30cc4e53..0131794a247 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -286,7 +286,7 @@ CommandsRegistry.registerCommand({ } try { - await extensionManagementService.uninstall(extensionToUninstall, true); + await extensionManagementService.uninstall(extensionToUninstall); } catch (e) { onUnexpectedError(e); throw e; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 58756f6ba69..d84feeb497d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -820,7 +820,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution { .filter(e => maliciousSet.has(e.identifier.id)); if (maliciousExtensions.length) { - return Promise.all(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e, true).then(() => { + return Promise.all(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e).then(() => { this.notificationService.prompt( Severity.Warning, localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", e.identifier.id), diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index f8f2a470fb8..b1781e08b4c 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -5,7 +5,7 @@ import { Event, EventMultiplexer } from 'vs/base/common/event'; import { - ILocalExtension, IGalleryExtension, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata, IExtensionGalleryService, INSTALL_ERROR_NOT_SUPPORTED, InstallOptions + ILocalExtension, IGalleryExtension, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata, IExtensionGalleryService, INSTALL_ERROR_NOT_SUPPORTED, InstallOptions, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionManagementServer, IExtensionManagementServerService, IWorkbenchExtensioManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionType, isLanguagePackExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; @@ -68,7 +68,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return flatten(result); } - async uninstall(extension: ILocalExtension): Promise { + async uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise { const server = this.getServer(extension); if (!server) { return Promise.reject(`Invalid location ${extension.location.toString()}`); @@ -77,7 +77,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench if (isLanguagePackExtension(extension.manifest)) { return this.uninstallEverywhere(extension); } - return this.uninstallInServer(extension, server); + return this.uninstallInServer(extension, server, options); } return server.extensionManagementService.uninstall(extension); } @@ -101,7 +101,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return promise; } - private async uninstallInServer(extension: ILocalExtension, server: IExtensionManagementServer, force?: boolean): Promise { + private async uninstallInServer(extension: ILocalExtension, server: IExtensionManagementServer, options?: UninstallOptions): Promise { if (server === this.extensionManagementServerService.localExtensionManagementServer) { const installedExtensions = await this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.getInstalled(ExtensionType.User); const dependentNonUIExtensions = installedExtensions.filter(i => !prefersExecuteOnUI(i.manifest, this.productService, this.configurationService) @@ -110,7 +110,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return Promise.reject(new Error(this.getDependentsErrorMessage(extension, dependentNonUIExtensions))); } } - return server.extensionManagementService.uninstall(extension, force); + return server.extensionManagementService.uninstall(extension, options); } private getDependentsErrorMessage(extension: ILocalExtension, dependents: ILocalExtension[]): string { From 2f0552737c39d47b5920aea6f5988bd1b3960f82 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 20:26:54 +0100 Subject: [PATCH 0361/1837] terminal icons --- .../terminal/browser/terminal.contribution.ts | 5 +---- .../contrib/terminal/browser/terminalActions.ts | 12 +++++++----- .../contrib/terminal/browser/terminalIcons.ts | 14 ++++++++++++++ .../terminal/browser/terminalQuickAccess.ts | 6 ++++-- 4 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/browser/terminalIcons.ts diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index d0f5208055b..61d5525a798 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -36,8 +36,7 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { terminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; -import { Codicon } from 'vs/base/common/codicons'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { terminalViewIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; // Register services registerSingleton(ITerminalService, TerminalService, true); @@ -61,8 +60,6 @@ CommandsRegistry.registerCommand({ id: quickAccessNavigatePreviousInTerminalPick const configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration(terminalConfiguration); -const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nls.localize('terminalViewIcon', 'View icon of the terminal view.')); - // Register views const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: TERMINAL_VIEW_ID, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 166378ba3b6..63264f9ab96 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -9,7 +9,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService import { TERMINAL_VIEW_ID, ITerminalConfigHelper, TitleEventSource, TERMINAL_COMMAND_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, IRemoteTerminalAttachTarget } from 'vs/workbench/contrib/terminal/common/terminal'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IQuickInputService, IPickOptions, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; @@ -42,6 +42,8 @@ import { FindInFilesCommand, IFindInFilesArgs } from 'vs/workbench/contrib/searc import { ILabelService } from 'vs/platform/label/common/label'; import { RemoteNameContext } from 'vs/workbench/browser/contextkeys'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { killTerminalIcon, newTerminalIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; +import { Codicon } from 'vs/base/common/codicons'; async function getCwdForSplit(configHelper: ITerminalConfigHelper, instance: ITerminalInstance, folders?: IWorkspaceFolder[], commandService?: ICommandService): Promise { switch (configHelper.config.splitCwd) { @@ -96,7 +98,7 @@ export class KillTerminalAction extends Action { id: string, label: string, @ITerminalService private readonly _terminalService: ITerminalService ) { - super(id, label, 'terminal-action codicon-trash'); + super(id, label, 'terminal-action ' + ThemeIcon.asClassName(killTerminalIcon)); } async run() { @@ -176,7 +178,7 @@ export class CreateNewTerminalAction extends Action { @ICommandService private readonly _commandService: ICommandService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService ) { - super(id, label, 'terminal-action codicon-add'); + super(id, label, 'terminal-action ' + ThemeIcon.asClassName(newTerminalIcon)); } async run(event?: any) { @@ -217,8 +219,8 @@ export class SplitTerminalAction extends Action { public static readonly ID = TERMINAL_COMMAND_ID.SPLIT; public static readonly LABEL = localize('workbench.action.terminal.split', "Split Terminal"); public static readonly SHORT_LABEL = localize('workbench.action.terminal.split.short', "Split"); - public static readonly HORIZONTAL_CLASS = 'terminal-action codicon-split-horizontal'; - public static readonly VERTICAL_CLASS = 'terminal-action codicon-split-vertical'; + public static readonly HORIZONTAL_CLASS = 'terminal-action ' + Codicon.splitHorizontal.classNames; + public static readonly VERTICAL_CLASS = 'terminal-action ' + Codicon.splitVertical.classNames; constructor( id: string, label: string, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts b/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts new file mode 100644 index 00000000000..ba49a6c8cd0 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + +export const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nls.localize('terminalViewIcon', 'View icon of the terminal view.')); + +export const renameTerminalIcon = registerIcon('terminal-rename', Codicon.gear, localize('renameTerminalIcon', 'Icon for rename in the terminal quick menu.')); +export const killTerminalIcon = registerIcon('terminal-kill', Codicon.trash, localize('killTerminalIcon', 'Icon for killing a terminal instance.')); +export const newTerminalIcon = registerIcon('terminal-new', Codicon.add, localize('newTerminalIcon', 'Icon for creating a new terminal instance.')); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts index 6c4af635014..7a283761ab4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts @@ -10,6 +10,8 @@ import { matchesFuzzy } from 'vs/base/common/filters'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { killTerminalIcon, renameTerminalIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; export class TerminalQuickAccessProvider extends PickerQuickAccessProvider { @@ -39,11 +41,11 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider Date: Thu, 26 Nov 2020 20:37:06 +0100 Subject: [PATCH 0362/1837] dirty dff icons --- src/vs/platform/theme/common/iconRegistry.ts | 3 +++ src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/theme/common/iconRegistry.ts b/src/vs/platform/theme/common/iconRegistry.ts index a7474fc4a54..0f9d1cfbf9d 100644 --- a/src/vs/platform/theme/common/iconRegistry.ts +++ b/src/vs/platform/theme/common/iconRegistry.ts @@ -259,3 +259,6 @@ iconRegistry.onDidChange(() => { // common icons export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.')); + +export const gotoPreviousLocation = registerIcon('goto-previous-location', Codicons.Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.')); +export const gotoNextLocation = registerIcon('goto-next-location', Codicons.Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.')); diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 6055740bf11..ffd41e575a8 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -19,7 +19,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur 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 } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IColorTheme, ICssStyleCollector, themeColorFromId, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; import { Color, RGBA } from 'vs/base/common/color'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; @@ -48,6 +48,7 @@ import { ISplice } from 'vs/base/common/sequence'; import { createStyleSheet } from 'vs/base/browser/dom'; import { ITextFileEditorModel, IResolvedTextFileEditorModel, ITextFileService, isTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; +import { gotoNextLocation, gotoPreviousLocation } from 'vs/platform/theme/common/iconRegistry'; class DiffActionRunner extends ActionRunner { @@ -246,8 +247,8 @@ class DirtyDiffWidget extends PeekViewWidget { protected _fillHead(container: HTMLElement): void { super._fillHead(container); - const previous = this.instantiationService.createInstance(UIEditorAction, this.editor, new ShowPreviousChangeAction(), 'codicon-arrow-up'); - const next = this.instantiationService.createInstance(UIEditorAction, this.editor, new ShowNextChangeAction(), 'codicon-arrow-down'); + const previous = this.instantiationService.createInstance(UIEditorAction, this.editor, new ShowPreviousChangeAction(), ThemeIcon.asClassName(gotoPreviousLocation)); + const next = this.instantiationService.createInstance(UIEditorAction, this.editor, new ShowNextChangeAction(), ThemeIcon.asClassName(gotoNextLocation)); this._disposables.add(previous); this._disposables.add(next); From 43f5beb3073acae03002994600ca5834e277c403 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 20:37:39 +0100 Subject: [PATCH 0363/1837] fix terminal icons --- src/vs/workbench/contrib/terminal/browser/terminalIcons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts b/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts index ba49a6c8cd0..88d2b313117 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalIcons.ts @@ -7,7 +7,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -export const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nls.localize('terminalViewIcon', 'View icon of the terminal view.')); +export const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, localize('terminalViewIcon', 'View icon of the terminal view.')); export const renameTerminalIcon = registerIcon('terminal-rename', Codicon.gear, localize('renameTerminalIcon', 'Icon for rename in the terminal quick menu.')); export const killTerminalIcon = registerIcon('terminal-kill', Codicon.trash, localize('killTerminalIcon', 'Icon for killing a terminal instance.')); From 83f8b96a9495f8f5d020022470de27cf6625baf8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 21:58:21 +0100 Subject: [PATCH 0364/1837] add extension icons --- .../browser/extensions.contribution.ts | 4 +-- .../extensions/browser/extensionsActions.ts | 20 +++++------ .../extensions/browser/extensionsIcons.ts | 33 +++++++++++++++++++ .../extensions/browser/extensionsViewlet.ts | 5 +-- .../extensions/browser/extensionsViews.ts | 13 ++++---- .../extensions/browser/extensionsWidgets.ts | 22 ++++++------- .../browser/media/extensionsWidgets.css | 10 +++--- 7 files changed, 70 insertions(+), 37 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 0131794a247..839c3ffbe15 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -64,9 +64,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; -import { Codicon } from 'vs/base/common/codicons'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { ShowRuntimeExtensionsAction } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; +import { extensionsViewIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -105,7 +104,6 @@ Registry.as(EditorExtensions.Editors).registerEditor( new SyncDescriptor(ExtensionsInput) ]); -const extensionsViewIcon = registerIcon('extensions-view-icon', Codicon.extensions, localize('extensionsViewIcon', 'View icon of the extensions view.')); Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 17b2a03b755..f04205af75a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -30,7 +30,7 @@ import { IExtensionService, toExtension, toExtensionDescription } from 'vs/workb import { URI } from 'vs/base/common/uri'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, registerColor, foreground } from 'vs/platform/theme/common/colorRegistry'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; @@ -55,7 +55,6 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { IProductService } from 'vs/platform/product/common/productService'; import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; -import { Codicon } from 'vs/base/common/codicons'; import { IViewsService } from 'vs/workbench/common/views'; import { IActionViewItemOptions, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { EXTENSIONS_CONFIG, IExtensionsConfigContent } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; @@ -65,6 +64,7 @@ import { ActionWithDropdownActionViewItem, IActionWithDropdownActionViewItemOpti import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; import { ILogService } from 'vs/platform/log/common/log'; import * as Constants from 'vs/workbench/contrib/logs/common/logConstants'; +import { clearSearchResultsIcon, infoIcon, manageExtensionIcon, refreshIcon, syncEnabledIcon, syncIgnoredIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; function getRelativeDateLabel(date: Date): string { const delta = new Date().getTime() - date.getTime(); @@ -864,7 +864,7 @@ export class ManageExtensionAction extends ExtensionDropDownAction { static readonly ID = 'extensions.manage'; - private static readonly Class = `${ExtensionAction.ICON_ACTION_CLASS} manage codicon-gear`; + private static readonly Class = `${ExtensionAction.ICON_ACTION_CLASS} manage ` + ThemeIcon.asClassName(manageExtensionIcon); private static readonly HideManageExtensionClass = `${ManageExtensionAction.Class} hide`; constructor( @@ -945,7 +945,7 @@ export class ExtensionEditorManageExtensionAction extends ExtensionDropDownActio constructor( @IInstantiationService instantiationService: IInstantiationService ) { - super('extensionEditor.manageExtension', '', `${ExtensionAction.ICON_ACTION_CLASS} manage codicon-gear`, true, true, instantiationService); + super('extensionEditor.manageExtension', '', `${ExtensionAction.ICON_ACTION_CLASS} manage ${ThemeIcon.asClassName(manageExtensionIcon)}`, true, true, instantiationService); this.tooltip = localize('manage', "Manage"); } @@ -1778,7 +1778,7 @@ export class ClearExtensionsSearchResultsAction extends Action { label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'codicon-clear-all', true); + super(id, label, ThemeIcon.asClassName(clearSearchResultsIcon), true); } async run(): Promise { @@ -1820,7 +1820,7 @@ export class RefreshExtensionsAction extends Action { label: string, @IViewsService private readonly viewsService: IViewsService ) { - super(id, label, 'codicon-refresh', true); + super(id, label, ThemeIcon.asClassName(refreshIcon), true); } async run(): Promise { @@ -2488,8 +2488,8 @@ export class MaliciousStatusLabelAction extends ExtensionAction { export class ToggleSyncExtensionAction extends ExtensionDropDownAction { - private static readonly IGNORED_SYNC_CLASS = `${ExtensionAction.ICON_ACTION_CLASS} extension-sync codicon-sync-ignored`; - private static readonly SYNC_CLASS = `${ToggleSyncExtensionAction.ICON_ACTION_CLASS} extension-sync codicon-sync`; + private static readonly IGNORED_SYNC_CLASS = `${ExtensionAction.ICON_ACTION_CLASS} extension-sync ${ThemeIcon.asClassName(syncIgnoredIcon)}`; + private static readonly SYNC_CLASS = `${ToggleSyncExtensionAction.ICON_ACTION_CLASS} extension-sync ${ThemeIcon.asClassName(syncEnabledIcon)}`; constructor( @IConfigurationService private readonly configurationService: IConfigurationService, @@ -2606,8 +2606,8 @@ export class ExtensionToolTipAction extends ExtensionAction { export class SystemDisabledWarningAction extends ExtensionAction { private static readonly CLASS = `${ExtensionAction.ICON_ACTION_CLASS} system-disable`; - private static readonly WARNING_CLASS = `${SystemDisabledWarningAction.CLASS} ${Codicon.warning.classNames}`; - private static readonly INFO_CLASS = `${SystemDisabledWarningAction.CLASS} ${Codicon.info.classNames}`; + private static readonly WARNING_CLASS = `${SystemDisabledWarningAction.CLASS} ${ThemeIcon.asClassName(warningIcon)}`; + private static readonly INFO_CLASS = `${SystemDisabledWarningAction.CLASS} ${ThemeIcon.asClassName(infoIcon)}`; updateWhenCounterExtensionChanges: boolean = true; private _runningExtensions: IExtensionDescription[] | null = null; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts b/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts new file mode 100644 index 00000000000..55fea5ddf9f --- /dev/null +++ b/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts @@ -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. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + +export const extensionsViewIcon = registerIcon('extensions-view-icon', Codicon.extensions, localize('extensionsViewIcon', 'View icon of the extensions view.')); + +export const manageExtensionIcon = registerIcon('extensions-manage', Codicon.gear, localize('manageExtensionIcon', 'Icon for the \'Manage\' action in the extensions view.')); + +export const clearSearchResultsIcon = registerIcon('extensions-clear-search-results', Codicon.clearAll, localize('clearSearchResultsIcon', 'Icon for the \'Clear Search Result\' action in the extensions view.')); +export const refreshIcon = registerIcon('extensions-refresh', Codicon.refresh, localize('refreshIcon', 'Icon for the \'Refresh\' action in the extensions view.')); +export const filterIcon = registerIcon('extensions-filter', Codicon.filter, localize('filterIcon', 'Icon for the \'Filter\' action in the extensions view.')); + +export const installLocalInRemoteIcon = registerIcon('extensions-install-local-in-remote', Codicon.cloudDownload, localize('installLocalInRemoteIcon', 'Icon for the \'Install Local Extension in Remote\' action in the extensions view.')); +export const installWorkspaceRecommendedIcon = registerIcon('extensions-install-workspace-recommended', Codicon.cloudDownload, localize('installWorkspaceRecommendedIcon', 'Icon for the \'Install Workspace Recommended Extensions\' action in the extensions view.')); +export const configureRecommendedIcon = registerIcon('extensions-configure-recommended', Codicon.pencil, localize('configureRecommendedIcon', 'Icon for the \'Configure Recommended Extensions\' action in the extensions view.')); + +export const syncEnabledIcon = registerIcon('extensions-sync-enabled', Codicon.sync, localize('syncEnabledIcon', 'Icon to indicate that an extension is synced.')); +export const syncIgnoredIcon = registerIcon('extensions-sync-ignored', Codicon.syncIgnored, localize('syncIgnoredIcon', 'Icon to indicate that an extension is ignored when syncing.')); +export const remoteIcon = registerIcon('extensions-remote', Codicon.remote, localize('remoteIcon', 'Icon to indicate that an extension is remote in the extensions view and editor.')); +export const installCountIcon = registerIcon('extensions-install-count', Codicon.cloudDownload, localize('installCountIcon', 'Icon shown along with the install count in the extensions view and editor.')); +export const ratingIcon = registerIcon('extensions-rating', Codicon.star, localize('ratingIcon', 'Icon shown along with the rating in the extensions view and editor.')); + +export const starFullIcon = registerIcon('extensions-star-full', Codicon.starFull, localize('starFullIcon', 'Full star icon used for the rating in the extensions editor.')); +export const starHalfIcon = registerIcon('extensions-star-half', Codicon.starHalf, localize('starHalfIcon', 'Half star icon used for the rating in the extensions editor.')); +export const starEmptyIcon = registerIcon('extensions-star-empty', Codicon.starEmpty, localize('starEmptyIcon', 'Empty star icon used for the rating in the extensions editor.')); + +export const warningIcon = registerIcon('extensions-warning-message', Codicon.warning, localize('warningIcon', 'Icon shown with a warning message in the extensions editor.')); +export const infoIcon = registerIcon('extensions-info-message', Codicon.info, localize('infoIcon', 'Icon shown with an info message in the extensions editor.')); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index d84feeb497d..afe9ebc8a72 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -32,7 +32,7 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import Severity from 'vs/base/common/severity'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; @@ -63,6 +63,7 @@ import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { isWeb } from 'vs/base/common/platform'; import { memoize } from 'vs/base/common/decorators'; +import { filterIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; const DefaultViewsContext = new RawContextKey('defaultExtensionViews', true); const SearchMarketplaceExtensionsContext = new RawContextKey('searchMarketplaceExtensions', false); @@ -582,7 +583,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE } return [ - this._register(new SubmenuAction('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), filterActions, 'codicon-filter')), + this._register(new SubmenuAction('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), filterActions, ThemeIcon.asClassName(filterIcon))), this._register(this.instantiationService.createInstance(RefreshExtensionsAction, RefreshExtensionsAction.ID, RefreshExtensionsAction.LABEL)), this._register(this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, () => this.searchBox!.getValue() || '')), ]; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index f31da0e23af..1466661faa5 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -20,7 +20,7 @@ import { Delegate, Renderer, IExtensionsViewState, EXTENSION_LIST_ELEMENT_HEIGHT import { ExtensionState, IExtension, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery'; import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -49,6 +49,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { configureRecommendedIcon, installLocalInRemoteIcon, installWorkspaceRecommendedIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; // Extensions that are automatically classified as Programming Language extensions, but should be Feature extensions const FORCE_FEATURE_EXTENSIONS = ['vscode.git', 'vscode.search-result']; @@ -823,10 +824,10 @@ export class ExtensionsListView extends ViewPane { if (count === 0 && this.isBodyVisible()) { if (error) { if (error instanceof ExtensionListViewWarning) { - this.bodyTemplate.messageSeverityIcon.className = `codicon ${SeverityIcon.className(Severity.Warning)}`; + this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Warning); this.bodyTemplate.messageBox.textContent = getErrorMessage(error); } else { - this.bodyTemplate.messageSeverityIcon.className = `codicon ${SeverityIcon.className(Severity.Error)}`; + this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Error); this.bodyTemplate.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error)); } } else { @@ -991,7 +992,7 @@ export class ServerInstalledExtensionsView extends ExtensionsListView { getActions(): IAction[] { if (this.extensionManagementServerService.remoteExtensionManagementServer && this.extensionManagementServerService.localExtensionManagementServer === this.options.server) { const installLocalExtensionsInRemoteAction = this._register(this.instantiationService.createInstance(InstallLocalExtensionsInRemoteAction)); - installLocalExtensionsInRemoteAction.class = 'codicon codicon-cloud-download'; + installLocalExtensionsInRemoteAction.class = ThemeIcon.asClassName(installLocalInRemoteIcon); return [installLocalExtensionsInRemoteAction]; } return []; @@ -1086,11 +1087,11 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView { getActions(): IAction[] { if (!this.installAllAction) { - this.installAllAction = this._register(new Action('workbench.extensions.action.installWorkspaceRecommendedExtensions', localize('installWorkspaceRecommendedExtensions', "Install Workspace Recommended Extensions"), 'codicon codicon-cloud-download', false, () => this.installWorkspaceRecommendations())); + this.installAllAction = this._register(new Action('workbench.extensions.action.installWorkspaceRecommendedExtensions', localize('installWorkspaceRecommendedExtensions', "Install Workspace Recommended Extensions"), ThemeIcon.asClassName(installWorkspaceRecommendedIcon), false, () => this.installWorkspaceRecommendations())); } const configureWorkspaceFolderAction = this._register(this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL)); - configureWorkspaceFolderAction.class = 'codicon codicon-pencil'; + configureWorkspaceFolderAction.class = ThemeIcon.asClassName(configureRecommendedIcon); return [this.installAllAction, configureWorkspaceFolderAction]; } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts index 13ab99ba2d8..55607b038fe 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts @@ -13,13 +13,14 @@ import { IExtensionManagementServerService } from 'vs/workbench/services/extensi import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; import { ILabelService } from 'vs/platform/label/common/label'; import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionToolTipAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; -import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme'; import { Emitter, Event } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; +import { installCountIcon, ratingIcon, remoteIcon, starEmptyIcon, starFullIcon, starHalfIcon, syncIgnoredIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; export abstract class ExtensionWidget extends Disposable implements IExtensionContainer { private _extension: IExtension | null = null; @@ -85,7 +86,7 @@ export class InstallCountWidget extends ExtensionWidget { installLabel = installCount.toLocaleString(platform.locale); } - append(this.container, $('span.codicon.codicon-cloud-download')); + append(this.container, $('span' + ThemeIcon.asCSSSelector(installCountIcon))); const count = append(this.container, $('span.count')); count.textContent = installLabel; } @@ -125,18 +126,18 @@ export class RatingsWidget extends ExtensionWidget { const rating = Math.round(this.extension.rating * 2) / 2; if (this.small) { - append(this.container, $('span.codicon.codicon-star-full')); + append(this.container, $('span' + ThemeIcon.asCSSSelector(starFullIcon))); const count = append(this.container, $('span.count')); count.textContent = String(rating); } else { for (let i = 1; i <= 5; i++) { if (rating >= i) { - append(this.container, $('span.codicon.codicon-star-full')); + append(this.container, $('span' + ThemeIcon.asCSSSelector(starFullIcon))); } else if (rating >= i - 0.5) { - append(this.container, $('span.codicon.codicon-star-half')); + append(this.container, $('span' + ThemeIcon.asCSSSelector(starHalfIcon))); } else { - append(this.container, $('span.codicon.codicon-star-empty')); + append(this.container, $('span' + ThemeIcon.asCSSSelector(starEmptyIcon))); } } } @@ -222,7 +223,7 @@ export class RecommendationWidget extends ExtensionWidget { if (extRecommendations[this.extension.identifier.id.toLowerCase()]) { this.element = append(this.parent, $('div.extension-bookmark')); const recommendation = append(this.element, $('.recommendation')); - append(recommendation, $('span.codicon.codicon-star')); + append(recommendation, $('span' + ThemeIcon.asCSSSelector(ratingIcon))); const applyBookmarkStyle = (theme: IColorTheme) => { const bgColor = theme.getColor(extensionButtonProminentBackground); const fgColor = theme.getColor(extensionButtonProminentForeground); @@ -288,7 +289,7 @@ class RemoteBadge extends Disposable { } private render(): void { - append(this.element, $('span.codicon.codicon-remote')); + append(this.element, $('span' + ThemeIcon.asCSSSelector(remoteIcon))); const applyBadgeStyle = () => { if (!this.element) { @@ -354,10 +355,9 @@ export class SyncIgnoredWidget extends ExtensionWidget { @IUserDataAutoSyncEnablementService private readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService, ) { super(); - this.element = append(container, $('span.extension-sync-ignored.codicon.codicon-sync-ignored')); + this.element = append(container, $('span.extension-sync-ignored' + ThemeIcon.asCSSSelector(syncIgnoredIcon))); this.element.title = localize('syncingore.label', "This extension is ignored during sync."); - this.element.classList.add('codicon'); - this.element.classList.add('codicon-sync-ignored'); + this.element.classList.add(...ThemeIcon.asClassNameArray(syncIgnoredIcon)); this.element.classList.add('hide'); this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectedKeys.includes('settingsSync.ignoredExtensions'))(() => this.render())); this._register(userDataAutoSyncEnablementService.onDidChangeEnablement(() => this.update())); diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css index 01e247b05a4..737320d942c 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css @@ -15,7 +15,7 @@ font-size: 80%; } -.extension-ratings > .codicon[class*='codicon-star']:not(:first-child) { +.extension-ratings > .codicon[class*='codicon-extensions-rating']:not(:first-child) { margin-left: 3px; } @@ -28,17 +28,17 @@ } /* TODO @misolori make this a color token */ -.extension-ratings .codicon-star-full, -.extension-ratings .codicon-star-half { +.extension-ratings .codicon-extensions-star-full, +.extension-ratings .codicon-extensions-star-half { color: #FF8E00 !important; } .extension-install-count .codicon, -.extension-action.codicon-gear { +.extension-action.codicon-extensions-manage { color: inherit; } -.extension-ratings .codicon-star-empty { +.extension-ratings .codicon-extensions-star-empty { opacity: .4; } From 8234453386c0037f68ec11d3a431b7c3742c8f13 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 22:12:23 +0100 Subject: [PATCH 0365/1837] update tests --- .../test/electron-browser/extensionsActions.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts index 750878b2d0b..40cf65cc233 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts @@ -419,7 +419,7 @@ suite('ExtensionsActions', () => { .then(extensions => { testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('extension-action icon manage codicon-gear', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage', testObject.class); assert.equal('', testObject.tooltip); }); }); @@ -434,7 +434,7 @@ suite('ExtensionsActions', () => { .then(page => { testObject.extension = page.firstPage[0]; assert.ok(!testObject.enabled); - assert.equal('extension-action icon manage codicon-gear hide', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage hide', testObject.class); assert.equal('', testObject.tooltip); }); }); @@ -451,7 +451,7 @@ suite('ExtensionsActions', () => { installEvent.fire({ identifier: gallery.identifier, gallery }); assert.ok(!testObject.enabled); - assert.equal('extension-action icon manage codicon-gear hide', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage hide', testObject.class); assert.equal('', testObject.tooltip); }); }); @@ -469,7 +469,7 @@ suite('ExtensionsActions', () => { didInstallEvent.fire({ identifier: gallery.identifier, gallery, operation: InstallOperation.Install, local: aLocalExtension('a', gallery, gallery) }); assert.ok(testObject.enabled); - assert.equal('extension-action icon manage codicon-gear', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage', testObject.class); assert.equal('', testObject.tooltip); }); }); @@ -484,7 +484,7 @@ suite('ExtensionsActions', () => { .then(extensions => { testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('extension-action icon manage codicon-gear', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage', testObject.class); assert.equal('', testObject.tooltip); }); }); @@ -501,7 +501,7 @@ suite('ExtensionsActions', () => { uninstallEvent.fire(local.identifier); assert.ok(!testObject.enabled); - assert.equal('extension-action icon manage codicon-gear', testObject.class); + assert.equal('extension-action icon manage codicon codicon-extensions-manage', testObject.class); assert.equal('Uninstalling', testObject.tooltip); }); }); From 1e77bd81d83c798ae93f8a77526ebfa78edad824 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 26 Nov 2020 22:30:05 +0100 Subject: [PATCH 0366/1837] registerCodicon --- .../base/browser/ui/breadcrumbs/breadcrumbsWidget.ts | 4 ++-- src/vs/base/browser/ui/dialog/dialog.ts | 10 +++++----- src/vs/base/browser/ui/menu/menu.ts | 6 +++--- src/vs/base/browser/ui/menu/menubar.ts | 4 ++-- .../base/browser/ui/scrollbar/horizontalScrollbar.ts | 6 +++--- .../base/browser/ui/scrollbar/verticalScrollbar.ts | 6 +++--- src/vs/base/browser/ui/toolbar/toolbar.ts | 4 ++-- src/vs/base/browser/ui/tree/treeIcons.ts | 12 ++++++------ src/vs/base/common/codicons.ts | 2 +- src/vs/base/parts/quickinput/browser/quickInput.ts | 4 ++-- .../workbench/contrib/tasks/browser/taskQuickPick.ts | 3 ++- 11 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts index 27981af2787..37b6b03fe31 100644 --- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts +++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts @@ -11,7 +11,7 @@ import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; import 'vs/css!./breadcrumbsWidget'; export abstract class BreadcrumbsItem { @@ -56,7 +56,7 @@ export interface IBreadcrumbsItemEvent { payload: any; } -const breadcrumbSeparatorIcon = registerIcon('breadcrumb-separator', Codicon.chevronRight); +const breadcrumbSeparatorIcon = registerCodicon('breadcrumb-separator', Codicon.chevronRight); export class BreadcrumbsWidget { diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index 21d3092acd1..4d8a075dfca 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -17,7 +17,7 @@ import { Action } from 'vs/base/common/actions'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { isMacintosh, isLinux } from 'vs/base/common/platform'; import { SimpleCheckbox, ISimpleCheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; export interface IDialogInputOptions { @@ -60,10 +60,10 @@ interface ButtonMapEntry { readonly index: number; } -const dialogErrorIcon = registerIcon('dialog-error', Codicon.error); -const dialogWarningIcon = registerIcon('dialog-warning', Codicon.warning); -const dialogInfoIcon = registerIcon('dialog-info', Codicon.info); -const dialogCloseIcon = registerIcon('dialog-close', Codicon.close); +const dialogErrorIcon = registerCodicon('dialog-error', Codicon.error); +const dialogWarningIcon = registerCodicon('dialog-warning', Codicon.warning); +const dialogInfoIcon = registerCodicon('dialog-info', Codicon.info); +const dialogCloseIcon = registerCodicon('dialog-close', Codicon.close); export class Dialog extends Disposable { private readonly element: HTMLElement; diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 300a8b8cec3..fc129fef580 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -18,7 +18,7 @@ import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; import { Event } from 'vs/base/common/event'; import { AnchorAlignment, layout, LayoutAnchorPosition } from 'vs/base/browser/ui/contextview/contextview'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; -import { Codicon, registerIcon, stripCodicons } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon, stripCodicons } from 'vs/base/common/codicons'; import { BaseActionViewItem, ActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles'; import { isFirefox } from 'vs/base/browser/browser'; @@ -27,8 +27,8 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/; export const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\s&])/g; -const menuSelectionIcon = registerIcon('menu-selection', Codicon.check); -const menuSubmenuIcon = registerIcon('menu-submenu', Codicon.chevronRight); +const menuSelectionIcon = registerCodicon('menu-selection', Codicon.check); +const menuSubmenuIcon = registerCodicon('menu-submenu', Codicon.chevronRight); export enum Direction { Right, diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index c8e8c9d2c23..55858a5890b 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -21,11 +21,11 @@ import { asArray } from 'vs/base/common/arrays'; import { ScanCodeUtils, ScanCode } from 'vs/base/common/scanCode'; import { isMacintosh } from 'vs/base/common/platform'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; const $ = DOM.$; -const menuBarMoreIcon = registerIcon('menubar-more', Codicon.more); +const menuBarMoreIcon = registerCodicon('menubar-more', Codicon.more); export interface IMenuBarOptions { enableMnemonics?: boolean; diff --git a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts index 636751f72c6..9d9a2268394 100644 --- a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts @@ -9,11 +9,11 @@ import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/s import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow'; import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState'; import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; -const scrollbarButtonLeftIcon = registerIcon('scrollbar-button-left', Codicon.triangleLeft); -const scrollbarButtonRightIcon = registerIcon('scrollbar-button-right', Codicon.triangleRight); +const scrollbarButtonLeftIcon = registerCodicon('scrollbar-button-left', Codicon.triangleLeft); +const scrollbarButtonRightIcon = registerCodicon('scrollbar-button-right', Codicon.triangleRight); export class HorizontalScrollbar extends AbstractScrollbar { diff --git a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts index 4f8e8f30a19..12d2887b6d1 100644 --- a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts @@ -9,10 +9,10 @@ import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/s import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow'; import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState'; import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; -const scrollbarButtonUpIcon = registerIcon('scrollbar-button-up', Codicon.triangleUp); -const scrollbarButtonDownIcon = registerIcon('scrollbar-button-down', Codicon.triangleDown); +const scrollbarButtonUpIcon = registerCodicon('scrollbar-button-up', Codicon.triangleUp); +const scrollbarButtonDownIcon = registerCodicon('scrollbar-button-down', Codicon.triangleDown); export class VerticalScrollbar extends AbstractScrollbar { diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index d2b361446a7..1ee792b8e21 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -11,12 +11,12 @@ import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; import { EventMultiplexer } from 'vs/base/common/event'; import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; -const toolBarMoreIcon = registerIcon('toolbar-more', Codicon.more); +const toolBarMoreIcon = registerCodicon('toolbar-more', Codicon.more); export interface IToolBarOptions { orientation?: ActionsOrientation; diff --git a/src/vs/base/browser/ui/tree/treeIcons.ts b/src/vs/base/browser/ui/tree/treeIcons.ts index bccd5188923..9755ae59e04 100644 --- a/src/vs/base/browser/ui/tree/treeIcons.ts +++ b/src/vs/base/browser/ui/tree/treeIcons.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; -export const treeItemExpandedIcon = registerIcon('tree-item-expanded', Codicon.chevronDown); // collapsed is done with rotation +export const treeItemExpandedIcon = registerCodicon('tree-item-expanded', Codicon.chevronDown); // collapsed is done with rotation -export const treeFilterOnTypeOnIcon = registerIcon('tree-filter-on-type-on', Codicon.listFilter); -export const treeFilterOnTypeOffIcon = registerIcon('tree-filter-on-type-off', Codicon.listSelection); -export const treeFilterClearIcon = registerIcon('tree-filter-clear', Codicon.close); +export const treeFilterOnTypeOnIcon = registerCodicon('tree-filter-on-type-on', Codicon.listFilter); +export const treeFilterOnTypeOffIcon = registerCodicon('tree-filter-on-type-off', Codicon.listSelection); +export const treeFilterClearIcon = registerCodicon('tree-filter-clear', Codicon.close); -export const treeItemLoadingIcon = registerIcon('tree-item-loading', Codicon.loading); +export const treeItemLoadingIcon = registerCodicon('tree-item-loading', Codicon.loading); diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 2483c56287c..8681df3231f 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -47,7 +47,7 @@ const _registry = new Registry(); export const iconRegistry: IIconRegistry = _registry; -export function registerIcon(id: string, def: Codicon, description?: string) { +export function registerCodicon(id: string, def: Codicon, description?: string): Codicon { return new Codicon(id, def, description); } diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 67542f72259..bddbd8a6eb9 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -27,7 +27,7 @@ import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/lis import { List, IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { IInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox'; import { Color } from 'vs/base/common/color'; -import { registerIcon, Codicon } from 'vs/base/common/codicons'; +import { registerCodicon, Codicon } from 'vs/base/common/codicons'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { escape } from 'vs/base/common/strings'; import { renderCodicons } from 'vs/base/browser/codicons'; @@ -72,7 +72,7 @@ const $ = dom.$; type Writeable = { -readonly [P in keyof T]: T[P] }; -const backButtonIcon = registerIcon('quick-input-back', Codicon.arrowLeft, localize('backButtonIcon', 'Icon for the back button in the quick input dialog.')); +const backButtonIcon = registerCodicon('quick-input-back', Codicon.arrowLeft, localize('backButtonIcon', 'Icon for the back button in the quick input dialog.')); const backButton = { iconClass: backButtonIcon.classNames, diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index f1539810aa0..a423d76657c 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -15,8 +15,9 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { Disposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; export const QUICKOPEN_DETAIL_CONFIG = 'task.quickOpen.detail'; export const QUICKOPEN_SKIP_CONFIG = 'task.quickOpen.skip'; From 8784b77bfd050187a91946489684fa52fdc2e021 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 27 Nov 2020 07:28:31 +0100 Subject: [PATCH 0367/1837] fix #110699 --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 17b2a03b755..dea1ca1971f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -376,7 +376,7 @@ export class InstallAndSyncAction extends AbstractInstallAction { ) { super(`extensions.installAndSync`, localize('install', "Install"), InstallAndSyncAction.Class, extensionsWorkbenchService, instantiationService, runtimeExtensionService, workbenchThemeService, labelService); - this.tooltip = localize('install everywhere tooltip', "Install this extension in all your synced {0} instances", productService.nameLong); + this.tooltip = localize({ key: 'install everywhere tooltip', comment: ['Placeholder is the name of the product. Eg: Visual Studio Code or Visual Studio Code - Insiders'] }, "Install this extension in all your synced {0} instances", productService.nameLong); this._register(Event.any(userDataAutoSyncEnablementService.onDidChangeEnablement, Event.filter(userDataSyncResourceEnablementService.onDidChangeResourceEnablement, e => e[0] === SyncResource.Extensions))(() => this.update())); } From 98f80c4047d6698bc02a8424e98ef03d9670a7d4 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 27 Nov 2020 07:37:37 +0100 Subject: [PATCH 0368/1837] Fix #110698 --- .../contrib/extensions/browser/extensionsActions.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index dea1ca1971f..03afc022339 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -347,7 +347,9 @@ export class InstallAction extends AbstractInstallAction { if (server === this.extensionManagementServerService.remoteExtensionManagementServer) { const host = this.extensionManagementServerService.remoteExtensionManagementServer.label; - this.label = isMachineScoped ? localize('install on remote and do not sync', "Install on {0} (Do not sync)", host) : localize('install on remote', "Install on {0}", host); + this.label = isMachineScoped + ? localize({ key: 'install in remote and do not sync', comment: ['This is the name of the action to install an extension in remote server and do not sync it. Placeholder is for the name of remote server.'] }, "Install in {0} (Do not sync)", host) + : localize({ key: 'install in remote', comment: ['This is the name of the action to install an extension in remote server. Placeholder is for the name of remote server.'] }, "Install in {0}", host); return; } @@ -547,7 +549,9 @@ export class RemoteInstallAction extends InstallInOtherServerAction { } protected getInstallLabel(): string { - return this.extensionManagementServerService.remoteExtensionManagementServer ? localize('Install on Server', "Install in {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label) : InstallInOtherServerAction.INSTALL_LABEL; + return this.extensionManagementServerService.remoteExtensionManagementServer + ? localize({ key: 'install in remote', comment: ['This is the name of the action to install an extension in remote server. Placeholder is for the name of remote server.'] }, "Install in {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label) + : InstallInOtherServerAction.INSTALL_LABEL; } } From cfe2e99ad894212e577cb1f9f32da6373f1f7a09 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2020 09:42:05 +0100 Subject: [PATCH 0369/1837] debug: load all stack frames text shuold have initial color when selected so it is readable fixes #111218 --- src/vs/workbench/contrib/debug/browser/media/debugViewlet.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css index e0b6acb323a..853b3adae48 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css @@ -84,6 +84,7 @@ /* Make icons and text the same color as the list foreground on focus selection */ .debug-pane .monaco-list:focus .monaco-list-row.selected .state.label, +.debug-pane .monaco-list:focus .monaco-list-row.selected .load-all, .debug-pane .monaco-list:focus .monaco-list-row.selected.focused .state.label, .debug-pane .monaco-list:focus .monaco-list-row.selected .codicon, .debug-pane .monaco-list:focus .monaco-list-row.selected.focused .codicon { From ac9e250cce9f2e883c1f11526e2ed1e237187159 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2020 09:55:08 +0100 Subject: [PATCH 0370/1837] support node 15 --- build/npm/preinstall.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index b0bbb96341e..94dbb3b9e0d 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -7,8 +7,8 @@ let err = false; const majorNodeVersion = parseInt(/^(\d+)\./.exec(process.versions.node)[1]); -if (majorNodeVersion < 10 || majorNodeVersion >= 15) { - console.error('\033[1;31m*** Please use node >=10 and <=14.\033[0;0m'); +if (majorNodeVersion < 10 || majorNodeVersion >= 16) { + console.error('\033[1;31m*** Please use node >=10 and <=16.\033[0;0m'); err = true; } From 2cd7a70d629fd5cac500341174291b0bfd120a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 26 Nov 2020 22:07:17 +0100 Subject: [PATCH 0371/1837] original urls get passed along with openUrl --- src/vs/code/electron-main/app.ts | 27 ++++++++++--------- .../launch/electron-main/launchMainService.ts | 8 +++--- src/vs/platform/url/common/url.ts | 2 ++ src/vs/platform/url/common/urlIpc.ts | 4 +-- .../url/electron-main/electronUrlListener.ts | 23 ++++++++++------ .../contrib/url/browser/url.contribution.ts | 2 +- 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 92ef1a75046..42c242bb579 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -24,7 +24,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IURLService } from 'vs/platform/url/common/url'; +import { IOpenURLOptions, IURLService } from 'vs/platform/url/common/url'; import { URLHandlerChannelClient, URLHandlerRouter } from 'vs/platform/url/common/urlIpc'; import { ITelemetryService, machineIdKey } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; @@ -73,7 +73,6 @@ import { INativeHostMainService, NativeHostMainService } from 'vs/platform/nativ import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService'; import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { coalesce } from 'vs/base/common/arrays'; import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels'; import { WebviewMainService } from 'vs/platform/webview/electron-main/webviewMainService'; import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService'; @@ -663,30 +662,32 @@ export class CodeApplication extends Disposable { // Check for initial URLs to handle from protocol link invocations const pendingWindowOpenablesFromProtocolLinks: IWindowOpenable[] = []; - const pendingProtocolLinksToHandle = coalesce([ - + const pendingProtocolLinksToHandle = [ // Windows/Linux: protocol handler invokes CLI with --open-url ...this.environmentService.args['open-url'] ? this.environmentService.args._urls || [] : [], // macOS: open-url events ...((global).getOpenUrls() || []) as string[] - ].map(pendingUrlToHandle => { + ].map(url => { try { - return URI.parse(pendingUrlToHandle); - } catch (error) { - return undefined; + return { uri: URI.parse(url), url }; + } catch { + return null; + } + }).filter((obj): obj is { uri: URI, url: string } => { + if (!obj) { + return false; } - })).filter(pendingUriToHandle => { // If URI should be blocked, filter it out - if (this.shouldBlockURI(pendingUriToHandle)) { + if (this.shouldBlockURI(obj.uri)) { return false; } // Filter out any protocol link that wants to open as window so that // we open the right set of windows on startup and not restore the // previous workspace too. - const windowOpenable = this.getWindowOpenableFromProtocolLink(pendingUriToHandle); + const windowOpenable = this.getWindowOpenableFromProtocolLink(obj.uri); if (windowOpenable) { pendingWindowOpenablesFromProtocolLinks.push(windowOpenable); @@ -700,7 +701,7 @@ export class CodeApplication extends Disposable { const app = this; const environmentService = this.environmentService; urlService.registerHandler({ - async handleURL(uri: URI): Promise { + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { // If URI should be blocked, behave as if it's handled if (app.shouldBlockURI(uri)) { @@ -732,7 +733,7 @@ export class CodeApplication extends Disposable { await window.ready(); - return urlService.open(uri); + return urlService.open(uri, options); } return false; diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 2e48223e568..9b3d6566394 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -35,14 +35,14 @@ export interface IRemoteDiagnosticOptions { includeWorkspaceMetadata?: boolean; } -function parseOpenUrl(args: NativeParsedArgs): URI[] { +function parseOpenUrl(args: NativeParsedArgs): { uri: URI, url: string }[] { if (args['open-url'] && args._urls && args._urls.length > 0) { // --open-url must contain -- followed by the url(s) // process.argv is used over args._ as args._ are resolved to file paths at this point return coalesce(args._urls .map(url => { try { - return URI.parse(url); + return { uri: URI.parse(url), url }; } catch (err) { return null; } @@ -101,8 +101,8 @@ export class LaunchMainService implements ILaunchMainService { // Make sure a window is open, ready to receive the url event whenWindowReady.then(() => { - for (const url of urlsToOpen) { - this.urlService.open(url); + for (const { uri, url } of urlsToOpen) { + this.urlService.open(uri, { originalUrl: url }); } }); } diff --git a/src/vs/platform/url/common/url.ts b/src/vs/platform/url/common/url.ts index 2069fc48e51..5202226dd22 100644 --- a/src/vs/platform/url/common/url.ts +++ b/src/vs/platform/url/common/url.ts @@ -18,6 +18,8 @@ export interface IOpenURLOptions { * might be shown to the user. */ trusted?: boolean; + + originalUrl?: string; } export interface IURLHandler { diff --git a/src/vs/platform/url/common/urlIpc.ts b/src/vs/platform/url/common/urlIpc.ts index 08d19ffd5be..52fad0e241d 100644 --- a/src/vs/platform/url/common/urlIpc.ts +++ b/src/vs/platform/url/common/urlIpc.ts @@ -19,7 +19,7 @@ export class URLHandlerChannel implements IServerChannel { call(_: unknown, command: string, arg?: any): Promise { switch (command) { - case 'handleURL': return this.handler.handleURL(URI.revive(arg)); + case 'handleURL': return this.handler.handleURL(URI.revive(arg[0]), arg[1]); } throw new Error(`Call not found: ${command}`); @@ -31,7 +31,7 @@ export class URLHandlerChannelClient implements IURLHandler { constructor(private channel: IChannel) { } handleURL(uri: URI, options?: IOpenURLOptions): Promise { - return this.channel.call('handleURL', uri.toJSON()); + return this.channel.call('handleURL', [uri.toJSON(), options]); } } diff --git a/src/vs/platform/url/electron-main/electronUrlListener.ts b/src/vs/platform/url/electron-main/electronUrlListener.ts index efc15e02965..50ca2ea249c 100644 --- a/src/vs/platform/url/electron-main/electronUrlListener.ts +++ b/src/vs/platform/url/electron-main/electronUrlListener.ts @@ -34,13 +34,13 @@ function uriFromRawUrl(url: string): URI | null { */ export class ElectronURLListener { - private uris: URI[] = []; + private uris: { uri: URI, url: string }[] = []; private retryCount = 0; private flushDisposable: IDisposable = Disposable.None; private disposables = new DisposableStore(); constructor( - initialUrisToHandle: URI[], + initialUrisToHandle: { uri: URI, url: string }[], private readonly urlService: IURLService, windowsMainService: IWindowsMainService, environmentService: IEnvironmentMainService @@ -64,8 +64,15 @@ export class ElectronURLListener { return url; }); - const onOpenUrl = Event.filter(Event.map(onOpenElectronUrl, uriFromRawUrl), (uri): uri is URI => !!uri); - onOpenUrl(this.urlService.open, this.urlService, this.disposables); + this.disposables.add(onOpenElectronUrl(url => { + const uri = uriFromRawUrl(url); + + if (!uri) { + return; + } + + this.urlService.open(uri, { originalUrl: url }); + })); // Send initial links to the window once it has loaded const isWindowReady = windowsMainService.getWindows() @@ -84,13 +91,13 @@ export class ElectronURLListener { return; } - const uris: URI[] = []; + const uris: { uri: URI, url: string }[] = []; - for (const uri of this.uris) { - const handled = await this.urlService.open(uri); + for (const obj of this.uris) { + const handled = await this.urlService.open(obj.uri, { originalUrl: obj.url }); if (!handled) { - uris.push(uri); + uris.push(obj); } } diff --git a/src/vs/workbench/contrib/url/browser/url.contribution.ts b/src/vs/workbench/contrib/url/browser/url.contribution.ts index 949c9980357..5d3a01480bd 100644 --- a/src/vs/workbench/contrib/url/browser/url.contribution.ts +++ b/src/vs/workbench/contrib/url/browser/url.contribution.ts @@ -37,7 +37,7 @@ class OpenUrlAction extends Action2 { return quickInputService.input({ prompt: localize('urlToOpen', "URL to open") }).then(input => { if (input) { const uri = URI.parse(input); - urlService.open(uri, { trusted: true }); + urlService.open(uri, { originalUrl: input }); } }); } From 14415847e16ac8cdbc0bdbc7178c1a722164fc67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 26 Nov 2020 17:14:15 +0100 Subject: [PATCH 0372/1837] trusted extension urls --- src/vs/code/electron-main/app.ts | 8 ++ .../common/extensionUrlTrust.ts | 13 +++ .../common/extensionUrlTrustIpc.ts | 36 +++++++ .../node/extensionUrlTrustService.ts | 97 +++++++++++++++++++ .../platform/product/common/productService.ts | 1 + .../browser/extensionUrlTrustService.ts | 18 ++++ .../extensionUrlTrustService.ts | 20 ++++ .../extensions/browser/extensionUrlHandler.ts | 12 +-- src/vs/workbench/workbench.sandbox.main.ts | 1 + src/vs/workbench/workbench.web.main.ts | 1 + 10 files changed, 201 insertions(+), 6 deletions(-) create mode 100644 src/vs/platform/extensionManagement/common/extensionUrlTrust.ts create mode 100644 src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts create mode 100644 src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts create mode 100644 src/vs/workbench/services/extensionManagement/browser/extensionUrlTrustService.ts create mode 100644 src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 42c242bb579..8dd876940a9 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -88,6 +88,9 @@ import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/ele import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { isEqualOrParent } from 'vs/base/common/extpath'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; +import { ExtensionUrlTrustChannel } from 'vs/platform/extensionManagement/common/extensionUrlTrustIpc'; +import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -520,6 +523,7 @@ export class CodeApplication extends Disposable { services.set(IWebviewManagerService, new SyncDescriptor(WebviewMainService)); services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService)); services.set(IMenubarMainService, new SyncDescriptor(MenubarMainService)); + services.set(IExtensionUrlTrustService, new SyncDescriptor(ExtensionUrlTrustService)); const storageMainService = new StorageMainService(this.logService, this.environmentService); services.set(IStorageMainService, storageMainService); @@ -635,6 +639,10 @@ export class CodeApplication extends Disposable { const urlChannel = createChannelReceiver(urlService); electronIpcServer.registerChannel('url', urlChannel); + const extensionUrlTrustService = accessor.get(IExtensionUrlTrustService); + const extensionUrlTrustChannel = new ExtensionUrlTrustChannel(extensionUrlTrustService); + electronIpcServer.registerChannel('extensionUrlTrust', extensionUrlTrustChannel); + const webviewManagerService = accessor.get(IWebviewManagerService); const webviewChannel = createChannelReceiver(webviewManagerService); electronIpcServer.registerChannel('webview', webviewChannel); diff --git a/src/vs/platform/extensionManagement/common/extensionUrlTrust.ts b/src/vs/platform/extensionManagement/common/extensionUrlTrust.ts new file mode 100644 index 00000000000..b26395646b7 --- /dev/null +++ b/src/vs/platform/extensionManagement/common/extensionUrlTrust.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const IExtensionUrlTrustService = createDecorator('extensionUrlTrustService'); + +export interface IExtensionUrlTrustService { + readonly _serviceBrand: undefined; + isExtensionUrlTrusted(extensionId: string, url: string): Promise; +} diff --git a/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts b/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts new file mode 100644 index 00000000000..347b931c181 --- /dev/null +++ b/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; +import { Event } from 'vs/base/common/event'; +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; + +export class ExtensionUrlTrustChannel implements IServerChannel { + + constructor(private service: IExtensionUrlTrustService) { } + + listen(): Event { + throw new Error('No events supported'); + } + + call(_: any, command: string, arg?: any): Promise { + switch (command) { + case 'isExtensionUrlTrusted': return this.service.isExtensionUrlTrusted(arg[0], arg[1]); + } + + throw new Error('Invalid call'); + } +} + +export class ExtensionUrlTrustChannelClient implements IExtensionUrlTrustService { + + declare readonly _serviceBrand: undefined; + + constructor(private readonly channel: IChannel) { } + + isExtensionUrlTrusted(extensionId: string, url: string): Promise { + return this.channel.call('isExtensionUrlTrusted', [extensionId, url]); + } +} diff --git a/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts b/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts new file mode 100644 index 00000000000..b75f1740d3a --- /dev/null +++ b/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts @@ -0,0 +1,97 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as crypto from 'crypto'; +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IProductService } from 'vs/platform/product/common/productService'; + +export class ExtensionUrlTrustService implements IExtensionUrlTrustService { + + declare readonly _serviceBrand: undefined; + + private trustedExtensionUrlPublicKeys = new Map(); + + constructor( + @IProductService private readonly productService: IProductService, + @ILogService private readonly logService: ILogService + ) { } + + async isExtensionUrlTrusted(extensionId: string, url: string): Promise { + if (!this.productService.trustedExtensionUrlPublicKeys) { + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'There are no configured trusted keys'); + return false; + } + + const match = /^(.*)#([^#]+)$/.exec(url); + + if (!match) { + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Uri has no fragment', url); + return false; + } + + const [, originalUrl, fragment] = match; + + let keys = this.trustedExtensionUrlPublicKeys.get(extensionId); + + if (!keys) { + keys = this.productService.trustedExtensionUrlPublicKeys[extensionId]; + + if (!keys || keys.length === 0) { + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Extension doesn\'t have any trusted keys', extensionId); + return false; + } + + this.trustedExtensionUrlPublicKeys.set(extensionId, [...keys]); + } + + const fragmentBuffer = Buffer.from(decodeURIComponent(fragment), 'base64'); + + if (fragmentBuffer.length <= 6) { + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Uri fragment is not a signature', url); + return false; + } + + const timestampBuffer = fragmentBuffer.slice(0, 6); + const timestamp = fragmentBuffer.readUIntBE(0, 6); + const diff = Date.now() - timestamp; + + if (diff < 0 || diff > 600_000) { // 10 minutes + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Signed uri has expired', url); + return false; + } + + const signatureBuffer = fragmentBuffer.slice(6); + const verify = crypto.createVerify('SHA256'); + verify.write(timestampBuffer); + verify.write(Buffer.from(originalUrl)); + verify.end(); + + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + + if (key === null) { // failed to be parsed before + continue; + } else if (typeof key === 'string') { // needs to be parsed + try { + key = crypto.createPublicKey({ key: Buffer.from(key, 'base64'), format: 'der', type: 'spki' }); + keys[i] = key; + } catch (err) { + this.logService.warn('ExtensionUrlTrustService#isExtensionUrlTrusted', `Failed to parse trusted extension uri public key #${i + 1} for ${extensionId}:`, err); + keys[i] = null; + continue; + } + } + + if (verify.verify(key, signatureBuffer)) { + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Signed uri is valid', url); + return true; + } + } + + this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Signed uri could not be verified', url); + return false; + } +} diff --git a/src/vs/platform/product/common/productService.ts b/src/vs/platform/product/common/productService.ts index 333e5b24b05..74a8c744a11 100644 --- a/src/vs/platform/product/common/productService.ts +++ b/src/vs/platform/product/common/productService.ts @@ -80,6 +80,7 @@ export interface IProductConfiguration { readonly remoteExtensionTips?: { [remoteName: string]: IRemoteExtensionTip; }; readonly extensionKeywords?: { [extension: string]: readonly string[]; }; readonly keymapExtensionTips?: readonly string[]; + readonly trustedExtensionUrlPublicKeys?: { [id: string]: string[]; }; readonly crashReporter?: { readonly companyName: string; diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionUrlTrustService.ts b/src/vs/workbench/services/extensionManagement/browser/extensionUrlTrustService.ts new file mode 100644 index 00000000000..7ade5f59ab0 --- /dev/null +++ b/src/vs/workbench/services/extensionManagement/browser/extensionUrlTrustService.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; + +class ExtensionUrlTrustService implements IExtensionUrlTrustService { + + declare readonly _serviceBrand: undefined; + + async isExtensionUrlTrusted(): Promise { + return false; + } +} + +registerSingleton(IExtensionUrlTrustService, ExtensionUrlTrustService); diff --git a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts new file mode 100644 index 00000000000..d3f1fc741c0 --- /dev/null +++ b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; +import { ExtensionUrlTrustChannelClient } from 'vs/platform/extensionManagement/common/extensionUrlTrustIpc'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; + +class ExtensionUrlTrustService extends ExtensionUrlTrustChannelClient { + + declare readonly _serviceBrand: undefined; + + constructor(@IMainProcessService mainProcessService: IMainProcessService) { + super(mainProcessService.getChannel('extensionUrlTrust')); + } +} + +registerSingleton(IExtensionUrlTrustService, ExtensionUrlTrustService); diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 57dc911b054..129ab322e21 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -26,6 +26,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; +import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; const FIVE_MINUTES = 5 * 60 * 1000; const THIRTY_SECONDS = 30 * 1000; @@ -101,7 +102,8 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { @IExtensionGalleryService private readonly galleryService: IExtensionGalleryService, @IStorageService private readonly storageService: IStorageService, @IConfigurationService private readonly configurationService: IConfigurationService, - @IProgressService private readonly progressService: IProgressService + @IProgressService private readonly progressService: IProgressService, + @IExtensionUrlTrustService private readonly extensionUrlTrustService: IExtensionUrlTrustService ) { this.userTrustedExtensionsStorage = new UserTrustedExtensionIdStorage(storageService); @@ -135,11 +137,9 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { return true; } - let trusted = options?.trusted; - - if (!trusted) { - trusted = this.didUserTrustExtension(ExtensionIdentifier.toKey(extensionId)); - } + const trusted = options?.trusted + || (options?.originalUrl ? await this.extensionUrlTrustService.isExtensionUrlTrusted(extensionId, options.originalUrl) : false) + || this.didUserTrustExtension(ExtensionIdentifier.toKey(extensionId)); if (!trusted) { let uriString = uri.toString(false); diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts index af1be3fb94e..e653630cf55 100644 --- a/src/vs/workbench/workbench.sandbox.main.ts +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -46,6 +46,7 @@ import 'vs/workbench/services/accessibility/electron-sandbox/accessibilityServic import 'vs/workbench/services/path/electron-sandbox/pathService'; import 'vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService'; import 'vs/workbench/services/extensionManagement/electron-sandbox/extensionManagementService'; +import 'vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService'; import 'vs/workbench/services/credentials/electron-sandbox/credentialsService'; import 'vs/workbench/services/encryption/electron-sandbox/encryptionService'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 1746e7929ef..bc640014d69 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -41,6 +41,7 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService'; import 'vs/workbench/services/keybinding/browser/keyboardLayoutService'; import 'vs/workbench/services/extensions/browser/extensionService'; import 'vs/workbench/services/extensionManagement/common/extensionManagementServerService'; +import 'vs/workbench/services/extensionManagement/browser/extensionUrlTrustService'; import 'vs/workbench/services/telemetry/browser/telemetryService'; import 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; import 'vs/workbench/services/credentials/browser/credentialsService'; From 14d59bef9272a309da6c99aa28eee1a26a8bd530 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2020 10:34:22 +0100 Subject: [PATCH 0373/1837] Allow status items with error background color (fix #110214) (#111353) * Allow status items with error background color (fix #110214) * rename to statusBarItem.errorBackground * address feedback and add error colors * address feedback --- src/vs/vscode.proposed.d.ts | 23 ++++++++++++ .../api/browser/mainThreadStatusBar.ts | 4 +-- .../workbench/api/common/extHost.api.impl.ts | 2 +- .../workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostStatusBar.ts | 35 ++++++++++++++++--- src/vs/workbench/common/theme.ts | 12 +++++++ 6 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 7bd8fff04f5..e2c0f8e90bd 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2403,4 +2403,27 @@ declare module 'vscode' { location?: Location; } //#endregion + + //#region Statusbar Item Background Color (https://github.com/microsoft/vscode/issues/110214) + + /** + * A status bar item is a status bar contribution that can + * show text and icons and run a command on click. + */ + export interface StatusBarItem { + + /** + * The background color for this entry. + * + * Note: the supported colors for background are currently limited to + * `ThemeColors` with id `statusBarItem.errorBackground`. Other `ThemeColors` + * will be ignored. + * + * When setting the background color to `statusBarItem.errorBackground`, it is + * recommended to also set `color` to `statusBarItem.errorForeground`. + */ + backgroundColor: ThemeColor | undefined; + } + + //#endregion } diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index d50bc8f08eb..a847df3bd0d 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -27,7 +27,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this.entries.clear(); } - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void { + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void { // if there are icons in the text use the tooltip for the aria label let ariaLabel: string; let role: string | undefined = undefined; @@ -37,7 +37,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { } else { ariaLabel = text ? text.replace(MainThreadStatusBar.CODICON_REGEXP, (_match, codiconName) => codiconName) : ''; } - const entry: IStatusbarEntry = { text, tooltip, command, color, ariaLabel, role }; + const entry: IStatusbarEntry = { text, tooltip, command, color, backgroundColor, ariaLabel, role }; if (typeof priority === 'undefined') { priority = 0; diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index fa598def051..4a9d5fe9b95 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -600,7 +600,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I priority = priority; } - return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation); + return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation, extension); }, setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): vscode.Disposable { return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b71262bcfec..b40e9d0f9f2 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -565,7 +565,7 @@ export interface MainThreadQuickOpenShape extends IDisposable { } export interface MainThreadStatusBarShape extends IDisposable { - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void; + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void; $dispose(id: number): void; } diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index edbaec0f60a..317c788e332 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -10,9 +10,12 @@ import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto } from import { localize } from 'vs/nls'; import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private static ID_GEN = 0; + private static ALLOWED_BACKGROUND_COLORS = new Set(['statusBarItem.errorBackground']); private _id: number; private _alignment: number; @@ -26,6 +29,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private _text: string = ''; private _tooltip?: string; private _color?: string | ThemeColor; + private _backgroundColor?: ThemeColor; private readonly _internalCommandRegistration = new DisposableStore(); private _command?: { readonly fromApi: string | vscode.Command, @@ -36,8 +40,9 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private _proxy: MainThreadStatusBarShape; private _commands: CommandsConverter; private _accessibilityInformation?: vscode.AccessibilityInformation; + private _extension?: IExtensionDescription; - constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation) { + constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation, extension?: IExtensionDescription) { this._id = ExtHostStatusBarEntry.ID_GEN++; this._proxy = proxy; this._commands = commands; @@ -46,6 +51,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { this._alignment = alignment; this._priority = priority; this._accessibilityInformation = accessibilityInformation; + this._extension = extension; } public get id(): number { @@ -72,6 +78,14 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { return this._color; } + public get backgroundColor(): ThemeColor | undefined { + if (this._extension) { + checkProposedApiEnabled(this._extension); + } + + return this._backgroundColor; + } + public get command(): string | vscode.Command | undefined { return this._command?.fromApi; } @@ -95,6 +109,19 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { this.update(); } + public set backgroundColor(color: ThemeColor | undefined) { + if (this._extension) { + checkProposedApiEnabled(this._extension); + } + + if (color && !ExtHostStatusBarEntry.ALLOWED_BACKGROUND_COLORS.has(color.id)) { + color = undefined; + } + + this._backgroundColor = color; + this.update(); + } + public set command(command: string | vscode.Command | undefined) { if (this._command?.fromApi === command) { return; @@ -146,7 +173,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { // Set to status bar this._proxy.$setEntry(this.id, this._statusId, this._statusName, this.text, this.tooltip, this._command?.internal, this.color, - this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT, + this.backgroundColor, this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT, this._priority, this._accessibilityInformation); }, 0); } @@ -207,8 +234,8 @@ export class ExtHostStatusBar { this._statusMessage = new StatusBarMessage(this); } - createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation): vscode.StatusBarItem { - return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation); + createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation, extension?: IExtensionDescription): vscode.StatusBarItem { + return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation, extension); } setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): Disposable { diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index f7451eda51d..bf2d99cefc6 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -395,6 +395,18 @@ export const STATUS_BAR_PROMINENT_ITEM_BACKGROUND = registerColor('statusBarItem hc: Color.black.transparent(0.5), }, nls.localize('statusBarProminentItemBackground', "Status bar prominent items background color. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); +export const STATUS_BAR_ERROR_ITEM_BACKGROUND = registerColor('statusBarItem.errorBackground', { + dark: Color.red, + light: Color.red, + hc: null, +}, nls.localize('statusBarErrorItemBackground', "Status bar error items background color. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); + +export const STATUS_BAR_ERROR_ITEM_FOREGROUND = registerColor('statusBarItem.errorForeground', { + dark: STATUS_BAR_FOREGROUND, + light: STATUS_BAR_FOREGROUND, + hc: STATUS_BAR_FOREGROUND, +}, nls.localize('statusBarErrorItemForeground', "Status bar error items foreground color. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); + export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.prominentHoverBackground', { dark: Color.black.transparent(0.3), light: Color.black.transparent(0.3), From 44ddde116f440916f5b913f04ab927cfdefb96d5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2020 10:42:38 +0100 Subject: [PATCH 0374/1837] adopt checkProposedApiEnabled //cc @joaomoreno --- src/vs/workbench/api/common/extHostSCM.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 2d39371d18f..058061633e8 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -17,6 +17,7 @@ import { ISplice } from 'vs/base/common/sequence'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; type ProviderHandle = number; type GroupHandle = number; @@ -221,17 +222,13 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { private _validateInput: IValidateInput | undefined; get validateInput(): IValidateInput | undefined { - if (!this._extension.enableProposedApi) { - throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`); - } + checkProposedApiEnabled(this._extension); return this._validateInput; } set validateInput(fn: IValidateInput | undefined) { - if (!this._extension.enableProposedApi) { - throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`); - } + checkProposedApiEnabled(this._extension); if (fn && typeof fn !== 'function') { throw new Error(`[${this._extension.identifier.value}]: Invalid SCM input box validation function`); From 1e0af437748e4cc699827ffc87e109ef15bc869f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 10:51:21 +0100 Subject: [PATCH 0375/1837] trusted ext urls: use 1 hour instead of 10 mins --- .../extensionManagement/node/extensionUrlTrustService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts b/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts index b75f1740d3a..8b638a63fe7 100644 --- a/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts +++ b/src/vs/platform/extensionManagement/node/extensionUrlTrustService.ts @@ -58,7 +58,7 @@ export class ExtensionUrlTrustService implements IExtensionUrlTrustService { const timestamp = fragmentBuffer.readUIntBE(0, 6); const diff = Date.now() - timestamp; - if (diff < 0 || diff > 600_000) { // 10 minutes + if (diff < 0 || diff > 3_600_000) { // 1 hour this.logService.trace('ExtensionUrlTrustService#isExtensionUrlTrusted', 'Signed uri has expired', url); return false; } From 42bb62a06f55ac858c9c4cd29adef98259e9b4f8 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Fri, 27 Nov 2020 10:57:03 +0100 Subject: [PATCH 0376/1837] Exclude endgame-plan label --- .vscode/notebooks/endgame.github-issues | 8 +++++--- .vscode/notebooks/my-endgame.github-issues | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 7e7d8a33ee4..d01f9ef76e0 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -20,12 +20,14 @@ { "kind": 1, "language": "markdown", - "value": "## Open Pull Requests on the Milestone" + "value": "## Open Pull Requests on the Milestone", + "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:pr is:open" + "value": "$REPOS $MILESTONE is:pr is:open", + "editable": true }, { "kind": 1, @@ -36,7 +38,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan", + "value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan -label:endgame-plan", "editable": true }, { diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 0a049c2d2b9..a8d1bbbc07d 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -20,12 +20,14 @@ { "kind": 1, "language": "markdown", - "value": "## Open Pull Requests on the Milestone" + "value": "## Open Pull Requests on the Milestone", + "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:pr is:open" + "value": "$REPOS $MILESTONE $MINE is:pr is:open", + "editable": true }, { "kind": 1, @@ -36,7 +38,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan", + "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan -label:endgame-plan", "editable": true }, { From 6253e47773060ecf7c001e7ddbc4a8d144619c93 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 27 Nov 2020 11:03:11 +0100 Subject: [PATCH 0377/1837] #44542 ability to reveal setting --- .../browser/parts/editor/editorStatus.ts | 2 +- .../preferences/browser/preferencesActions.ts | 2 +- .../preferences/browser/settingsEditor2.ts | 2 +- .../preferences/browser/preferencesService.ts | 40 +++++++++++-------- .../preferences/common/preferences.ts | 12 ++++-- 5 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 30ef71397b8..1d85f0ad554 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -1150,7 +1150,7 @@ export class ChangeModeAction extends Action { // User decided to configure settings for current language if (pick === configureModeSettings) { - this.preferencesService.openGlobalSettings(true, { editSetting: `[${withUndefinedAsNull(currentModeId)}]` }); + this.preferencesService.openGlobalSettings(true, { revealSetting: { key: `[${withUndefinedAsNull(currentModeId)}]`, edit: true } }); return; } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts index 8b095ecb557..e6955647cc7 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts @@ -55,7 +55,7 @@ export class ConfigureLanguageBasedSettingsAction extends Action { if (pick) { const modeId = this.modeService.getModeIdForLanguageName(pick.label.toLowerCase()); if (typeof modeId === 'string') { - return this.preferencesService.openGlobalSettings(true, { editSetting: `[${modeId}]` }); + return this.preferencesService.openGlobalSettings(true, { revealSetting: { key: `[${modeId}]`, edit: true } }); } } return undefined; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 64d3da690d3..9537e203f38 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -660,7 +660,7 @@ export class SettingsEditor2 extends EditorPane { this.settingRenderers = this.instantiationService.createInstance(SettingTreeRenderers); this._register(this.settingRenderers.onDidChangeSetting(e => this.onDidChangeSetting(e.key, e.value, e.type))); this._register(this.settingRenderers.onDidOpenSettings(settingKey => { - this.openSettingsFile({ editSetting: settingKey }); + this.openSettingsFile({ revealSetting: { key: settingKey, edit: true } }); })); this._register(this.settingRenderers.onDidClickSettingLink(settingName => this.onDidClickSetting(settingName))); this._register(this.settingRenderers.onDidFocusSetting(element => { diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index 5e3a6b49137..7cf56fbc39d 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -329,8 +329,8 @@ export class PreferencesService extends Disposable implements IPreferencesServic } } const editor = await this.doOpenSettings(configurationTarget, resource, options, group); - if (editor && options?.editSetting) { - await this.editSetting(options?.editSetting, editor, resource); + if (editor && options?.revealSetting) { + await this.revealSetting(options.revealSetting.key, !!options.revealSetting.edit, editor, resource); } return editor; } @@ -589,7 +589,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic ]; } - private async editSetting(settingKey: string, editor: IEditorPane, settingsResource: URI): Promise { + private async revealSetting(settingKey: string, edit: boolean, editor: IEditorPane, settingsResource: URI): Promise { const codeEditor = editor ? getCodeEditor(editor.getControl()) : null; if (!codeEditor) { return; @@ -598,16 +598,18 @@ export class PreferencesService extends Disposable implements IPreferencesServic if (!settingsModel) { return; } - const position = await this.getPositionToEdit(settingKey, settingsModel, codeEditor); + const position = await this.getPositionToReveal(settingKey, edit, settingsModel, codeEditor); if (position) { codeEditor.setPosition(position); codeEditor.revealPositionNearTop(position); codeEditor.focus(); - await this.commandService.executeCommand('editor.action.triggerSuggest'); + if (edit) { + await this.commandService.executeCommand('editor.action.triggerSuggest'); + } } } - private async getPositionToEdit(settingKey: string, settingsModel: IPreferencesEditorModel, codeEditor: ICodeEditor): Promise { + private async getPositionToReveal(settingKey: string, edit: boolean, settingsModel: IPreferencesEditorModel, codeEditor: ICodeEditor): Promise { const model = codeEditor.getModel(); if (!model) { return null; @@ -620,7 +622,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic let position = null; const type = schema ? schema.type : 'object' /* Override Identifier */; let setting = settingsModel.getPreference(settingKey); - if (!setting) { + if (!setting && edit) { const defaultValue = (type === 'object' || type === 'array') ? this.configurationService.inspect(settingKey).defaultValue : getDefaultValue(type); if (defaultValue !== undefined) { const key = settingsModel instanceof WorkspaceConfigurationEditorModel ? ['settings', settingKey] : [settingKey]; @@ -630,18 +632,22 @@ export class PreferencesService extends Disposable implements IPreferencesServic } if (setting) { - position = { lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 }; - if (type === 'object' || type === 'array') { - codeEditor.setPosition(position); - await CoreEditingCommands.LineBreakInsert.runEditorCommand(null, codeEditor, null); - position = { lineNumber: position.lineNumber + 1, column: model.getLineMaxColumn(position.lineNumber + 1) }; - const firstNonWhiteSpaceColumn = model.getLineFirstNonWhitespaceColumn(position.lineNumber); - if (firstNonWhiteSpaceColumn) { - // Line has some text. Insert another new line. - codeEditor.setPosition({ lineNumber: position.lineNumber, column: firstNonWhiteSpaceColumn }); + if (edit) { + position = { lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 }; + if (type === 'object' || type === 'array') { + codeEditor.setPosition(position); await CoreEditingCommands.LineBreakInsert.runEditorCommand(null, codeEditor, null); - position = { lineNumber: position.lineNumber, column: model.getLineMaxColumn(position.lineNumber) }; + position = { lineNumber: position.lineNumber + 1, column: model.getLineMaxColumn(position.lineNumber + 1) }; + const firstNonWhiteSpaceColumn = model.getLineFirstNonWhitespaceColumn(position.lineNumber); + if (firstNonWhiteSpaceColumn) { + // Line has some text. Insert another new line. + codeEditor.setPosition({ lineNumber: position.lineNumber, column: firstNonWhiteSpaceColumn }); + await CoreEditingCommands.LineBreakInsert.runEditorCommand(null, codeEditor, null); + position = { lineNumber: position.lineNumber, column: model.getLineMaxColumn(position.lineNumber) }; + } } + } else { + position = { lineNumber: setting.keyRange.startLineNumber, column: setting.keyRange.startColumn }; } } diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index d31b2ddf52a..736eeef7f27 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -163,7 +163,10 @@ export interface ISettingsEditorOptions extends IEditorOptions { target?: ConfigurationTarget; folderUri?: URI; query?: string; - editSetting?: string; + revealSetting?: { + key: string; + edit?: boolean; + }; } /** @@ -174,7 +177,10 @@ export class SettingsEditorOptions extends EditorOptions implements ISettingsEdi target?: ConfigurationTarget; folderUri?: URI; query?: string; - editSetting?: string; + revealSetting?: { + key: string; + edit?: boolean; + }; static create(settings: ISettingsEditorOptions): SettingsEditorOptions { const options = new SettingsEditorOptions(); @@ -183,7 +189,7 @@ export class SettingsEditorOptions extends EditorOptions implements ISettingsEdi options.target = settings.target; options.folderUri = settings.folderUri; options.query = settings.query; - options.editSetting = settings.editSetting; + options.revealSetting = settings.revealSetting; return options; } From 71836f95ddca411b79f36e2e995886ddeff7cd34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 11:19:45 +0100 Subject: [PATCH 0378/1837] fixes #111366 --- build/.cachesalt | 2 +- build/azure-pipelines/darwin/product-build-darwin.yml | 3 +-- build/azure-pipelines/linux/product-build-alpine.yml | 3 +-- build/azure-pipelines/linux/product-build-linux.yml | 5 ++--- build/azure-pipelines/web/product-build-web.yml | 3 +-- build/azure-pipelines/win32/product-build-win32.yml | 5 ++--- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/build/.cachesalt b/build/.cachesalt index cc8a32ae85a..b89f52bd923 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-26T06:24:58.987Z +2020-11-27T10:19:32.507Z diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 3da70b5e6ae..a9faf84116f 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -85,13 +85,12 @@ steps: export npm_config_arch=$(VSCODE_ARCH) export npm_config_node_gyp=$(which node-gyp) export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk + export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break echo "Yarn failed, trying again..." done - env: - CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index e24b479c648..c2901a85a02 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -78,12 +78,11 @@ steps: - script: | set -e + export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break echo "Yarn failed, trying again..." done - env: - CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index ed048f0693d..516a0f026ae 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -68,13 +68,12 @@ steps: - script: | set -e + export npm_config_arch=$(VSCODE_ARCH) + export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break echo "Yarn failed, trying again..." done - env: - CHILD_CONCURRENCY: 1 - npm_config_arch: $(NPM_ARCH) displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 7afbb85952b..f979d35f45b 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -68,12 +68,11 @@ steps: - script: | set -e + export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break echo "Yarn failed, trying again..." done - env: - CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 11881b353b2..804c6970ef4 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -73,10 +73,9 @@ steps: . build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/retry.ps1 $ErrorActionPreference = "Stop" + $env:npm_config_arch="$(VSCODE_ARCH)" + $env:CHILD_CONCURRENCY="1" retry { exec { yarn --frozen-lockfile } } - env: - npm_config_arch: $(VSCODE_ARCH) - CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) From bafc05ff0a672c14d739d372f88ac24f4441d6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 11:30:34 +0100 Subject: [PATCH 0379/1837] fix retry --- build/azure-pipelines/win32/retry.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/azure-pipelines/win32/retry.ps1 b/build/azure-pipelines/win32/retry.ps1 index 6f46bb3f450..002a5e274b7 100644 --- a/build/azure-pipelines/win32/retry.ps1 +++ b/build/azure-pipelines/win32/retry.ps1 @@ -11,7 +11,7 @@ function Retry & $cmd return } catch { - Write-Error -ErrorRecord $_ + # noop } } From f6249641f2fd276e7687fea618a86729e0d57f1f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 11:36:43 +0100 Subject: [PATCH 0380/1837] externalize notebook items --- src/vs/platform/theme/common/themeService.ts | 3 ++ .../notebook/browser/contrib/coreActions.ts | 32 +++++++++---------- .../notebook/browser/contrib/fold/folding.ts | 2 +- .../browser/contrib/status/editorStatus.ts | 7 ++-- .../notebook/browser/diff/cellComponents.ts | 10 +++--- .../browser/diff/notebookDiffActions.ts | 10 +++--- .../notebook/browser/notebookEditorWidget.ts | 5 +-- .../contrib/notebook/browser/notebookIcons.ts | 30 +++++++++++++++++ .../browser/view/renderers/cellOutput.ts | 4 ++- .../browser/view/renderers/cellRenderer.ts | 6 ++-- .../browser/view/renderers/markdownCell.ts | 8 +++-- 11 files changed, 80 insertions(+), 37 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/notebookIcons.ts diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 7650acb28d2..f82c45767e5 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -100,6 +100,9 @@ export namespace ThemeIcon { }; } + export function asCodiconLabel(icon: ThemeIcon): string { + return '$(' + icon.id + ')'; + } export function revive(icon: any): ThemeIcon | undefined { if (ThemeIcon.isThemeIcon(icon)) { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index ca11f084885..acf32d1a96a 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Codicon } from 'vs/base/common/codicons'; import * as glob from 'vs/base/common/glob'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; @@ -28,6 +27,7 @@ import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExclu import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons'; // Notebook Commands const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute'; @@ -237,7 +237,7 @@ registerAction2(class extends NotebookCellAction { } ] }, - icon: Codicon.play + icon: icons.executeIcon }); } @@ -271,7 +271,7 @@ registerAction2(class extends NotebookCellAction { super({ id: CANCEL_CELL_COMMAND_ID, title: localize('notebookActions.cancel', "Stop Cell Execution"), - icon: Codicon.primitiveSquare, + icon: icons.stopIcon, description: { description: localize('notebookActions.execute', "Execute Cell"), args: [ @@ -330,7 +330,7 @@ export class ExecuteCellAction extends MenuItemAction { { id: EXECUTE_CELL_COMMAND_ID, title: localize('notebookActions.executeCell', "Execute Cell"), - icon: Codicon.play + icon: icons.executeIcon }, undefined, { shouldForwardArgs: true }, @@ -348,7 +348,7 @@ export class CancelCellAction extends MenuItemAction { { id: CANCEL_CELL_COMMAND_ID, title: localize('notebookActions.CancelCell', "Cancel Execution"), - icon: Codicon.primitiveSquare + icon: icons.stopIcon }, undefined, { shouldForwardArgs: true }, @@ -366,7 +366,7 @@ export class DeleteCellAction extends MenuItemAction { { id: DELETE_CELL_COMMAND_ID, title: localize('notebookActions.deleteCell', "Delete Cell"), - icon: Codicon.trash, + icon: icons.deleteCellIcon, }, undefined, { shouldForwardArgs: true }, @@ -512,7 +512,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: EXECUTE_NOTEBOOK_COMMAND_ID, title: localize('notebookActions.menu.executeNotebook', "Execute Notebook (Run all cells)"), - icon: Codicon.runAll, + icon: icons.executeAllIcon, }, order: -1, group: 'navigation', @@ -523,7 +523,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CANCEL_NOTEBOOK_COMMAND_ID, title: localize('notebookActions.menu.cancelNotebook', "Stop Notebook Execution"), - icon: Codicon.primitiveSquare, + icon: icons.stopIcon, }, order: -1, group: 'navigation', @@ -840,7 +840,7 @@ registerAction2(class extends NotebookCellAction { order: CellToolbarOrder.EditCell, group: CELL_TITLE_CELL_GROUP_ID }, - icon: Codicon.pencil, + icon: icons.editIcon, }); } @@ -864,7 +864,7 @@ registerAction2(class extends NotebookCellAction { order: CellToolbarOrder.SaveCell, group: CELL_TITLE_CELL_GROUP_ID }, - icon: Codicon.check, + icon: icons.stopEditIcon, keybinding: { when: ContextKeyExpr.and( NOTEBOOK_EDITOR_FOCUSED, @@ -906,7 +906,7 @@ registerAction2(class extends NotebookCellAction { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.not(InputFocusedContextKey)), weight: KeybindingWeight.WorkbenchContrib }, - icon: Codicon.trash + icon: icons.deleteCellIcon }); } @@ -950,7 +950,7 @@ registerAction2(class extends NotebookCellAction { { id: MOVE_CELL_UP_COMMAND_ID, title: localize('notebookActions.moveCellUp', "Move Cell Up"), - icon: Codicon.arrowUp, + icon: icons.moveUpIcon, keybinding: { primary: KeyMod.Alt | KeyCode.UpArrow, when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, InputFocusedContext.toNegated()), @@ -970,7 +970,7 @@ registerAction2(class extends NotebookCellAction { { id: MOVE_CELL_DOWN_COMMAND_ID, title: localize('notebookActions.moveCellDown', "Move Cell Down"), - icon: Codicon.arrowDown, + icon: icons.moveDownIcon, keybinding: { primary: KeyMod.Alt | KeyCode.DownArrow, when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, InputFocusedContext.toNegated()), @@ -1413,7 +1413,7 @@ registerAction2(class extends NotebookCellAction { primary: KeyMod.Alt | KeyCode.Delete, weight: KeybindingWeight.WorkbenchContrib }, - icon: Codicon.clearAll + icon: icons.clearIcon }); } @@ -1563,7 +1563,7 @@ registerAction2(class extends NotebookAction { group: 'navigation', order: 0 }, - icon: Codicon.clearAll + icon: icons.clearIcon }); } @@ -1623,7 +1623,7 @@ registerAction2(class extends NotebookCellAction { // title: localize('notebookActions.joinCellBelow', "Join with Next Cell") // } }, - icon: Codicon.splitVertical, + icon: icons.splitCellIcon, keybinding: { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_EDITOR_CURSOR_BEGIN_END.toNegated()), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKSLASH), diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts b/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts index 0e4f30a001d..0235b4431fb 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts @@ -116,7 +116,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont const target = e.event.target as HTMLElement; - if (target.classList.contains('codicon-chevron-down') || target.classList.contains('codicon-chevron-right')) { + if (target.classList.contains('codicon-notebook-collapsed') || target.classList.contains('codicon-notebook-expanded')) { const parent = target.parentElement as HTMLElement; if (!parent.classList.contains('notebook-folding-indicator')) { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index 9d8041863b7..2f32225cbb7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -21,7 +21,8 @@ import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/l import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { Codicon } from 'vs/base/common/codicons'; +import { configureKernelIcon, selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerAction2(class extends Action2 { @@ -31,7 +32,7 @@ registerAction2(class extends Action2 { category: NOTEBOOK_ACTIONS_CATEGORY, title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' }, precondition: NOTEBOOK_IS_ACTIVE_EDITOR, - icon: Codicon.serverEnvironment, + icon: selectKernelIcon, f1: true }); } @@ -74,7 +75,7 @@ registerAction2(class extends Action2 { a.resolve(editor.uri!, editor.getId(), tokenSource.token); }, buttons: [{ - iconClass: 'codicon-settings-gear', + iconClass: ThemeIcon.asClassName(configureKernelIcon), tooltip: nls.localize('notebook.promptKernel.setDefaultTooltip', "Set as default kernel provider for '{0}'", editor.viewModel!.viewType) }] }; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index f18929bbd0e..f526080b2e1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -12,7 +12,6 @@ import { CellDiffRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_M import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; -import { renderCodicons } from 'vs/base/browser/codicons'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { format } from 'vs/base/common/jsonFormatter'; @@ -29,6 +28,9 @@ import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/men import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { renderCodicons } from 'vs/base/browser/codicons'; const fixedEditorOptions: IEditorOptions = { padding: { @@ -146,7 +148,7 @@ class PropertyHeader extends Disposable { const target = e.event.target as HTMLElement; - if (target.classList.contains('codicon-chevron-down') || target.classList.contains('codicon-chevron-right')) { + if (target.classList.contains('codicon-notebook-collapsed') || target.classList.contains('codicon-notebook-expanded')) { const parent = target.parentElement as HTMLElement; if (!parent) { @@ -198,9 +200,9 @@ class PropertyHeader extends Disposable { private _updateFoldingIcon() { if (this.accessor.getFoldingState(this.cell) === PropertyFoldingState.Collapsed) { - DOM.reset(this._foldingIndicator, ...renderCodicons('$(chevron-right)')); + DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(collapsedIcon))); } else { - DOM.reset(this._foldingIndicator, ...renderCodicons('$(chevron-down)')); + DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(expandedIcon))); } } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index bf5df7503ae..cb8709d167d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Codicon } from 'vs/base/common/codicons'; import { IBulkEditService, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; @@ -12,6 +11,7 @@ import { ActiveEditorContext, viewColumnToEditorGroup } from 'vs/workbench/commo import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; +import { openAsTextIcon, revertIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -21,7 +21,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'notebook.diff.switchToText', - icon: Codicon.fileCode, + icon: openAsTextIcon, title: { value: localize('notebook.diff.switchToText', "Open Text Diff Editor"), original: 'Open Text Diff Editor' }, precondition: ActiveEditorContext.isEqualTo(NotebookTextDiffEditor.ID), menu: [{ @@ -57,7 +57,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertMetadata', title: localize('notebook.diff.cell.revertMetadata', "Revert Metadata"), - icon: Codicon.discard, + icon: revertIcon, f1: false, menu: { id: MenuId.NotebookDiffCellMetadataTitle @@ -87,7 +87,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertOutputs', title: localize('notebook.diff.cell.revertOutputs', "Revert Outputs"), - icon: Codicon.discard, + icon: revertIcon, f1: false, menu: { id: MenuId.NotebookDiffCellOutputsTitle @@ -117,7 +117,7 @@ registerAction2(class extends Action2 { { id: 'notebook.diff.cell.revertInput', title: localize('notebook.diff.cell.revertInput', "Revert Input"), - icon: Codicon.discard, + icon: revertIcon, f1: false, menu: { id: MenuId.NotebookDiffCellInputTitle diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index a2a8010ae2a..c8a7a459f66 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -35,7 +35,7 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { contrastBorder, diffInserted, diffRemoved, editorBackground, errorForeground, focusBorder, foreground, listInactiveSelectionBackground, registerColor, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground, transparent } from 'vs/platform/theme/common/colorRegistry'; -import { IColorTheme, IThemeService, registerThemingParticipant, ThemeColor } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, registerThemingParticipant, ThemeColor, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorMemento } from 'vs/workbench/common/editor'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; @@ -61,6 +61,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { configureKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; const $ = DOM.$; @@ -1659,7 +1660,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._activeKernelResolvePromise = this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token); }, buttons: [{ - iconClass: 'codicon-settings-gear', + iconClass: ThemeIcon.asClassName(configureKernelIcon), tooltip: nls.localize('notebook.promptKernel.setDefaultTooltip', "Set as default kernel provider for '{0}'", this.viewModel!.viewType) }] }; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts new file mode 100644 index 00000000000..f40d89b4e1d --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + + +export const configureKernelIcon = registerIcon('notebook-kernel-configure', Codicon.settingsGear, localize('configureKernel', 'Configure icon in kernel configuation widget in notebook editors.')); +export const selectKernelIcon = registerIcon('notebook-kernel-select', Codicon.serverEnvironment, localize('selectKernelIcon', 'Configure icon to select a kernel in notebook editors.')); + +export const executeIcon = registerIcon('notebook-execute', Codicon.play, localize('executeIcon', 'Icon to execute in notebook editors.')); +export const stopIcon = registerIcon('notebook-execute', Codicon.primitiveSquare, localize('stopIcon', 'Icon to stop an execution in notebook editors.')); +export const deleteCellIcon = registerIcon('notebook-delete-cell', Codicon.trash, localize('deleteCellIcon', 'Icon to delete a cell in notebook editors.')); +export const executeAllIcon = registerIcon('notebook-execute-all', Codicon.runAll, localize('executeAllIcon', 'Icon to execute all cells in notebook editors.')); +export const editIcon = registerIcon('notebook-edit', Codicon.pencil, localize('editIcon', 'Icon to edit a cell in notebook editors.')); +export const stopEditIcon = registerIcon('notebook-stop-edit', Codicon.check, localize('stopEditIcon', 'Icon to stop editing a cell in notebook editors.')); +export const moveUpIcon = registerIcon('notebook-move-up', Codicon.arrowUp, localize('moveUpIcon', 'Icon to move a cell up in notebook editors.')); +export const moveDownIcon = registerIcon('notebook-move-down', Codicon.arrowDown, localize('moveDownIcon', 'Icon to move a cell down in notebook editors.')); +export const clearIcon = registerIcon('notebook-clear', Codicon.clearAll, localize('clearIcon', 'Icon to clear cell outputs in notebook editors.')); +export const splitCellIcon = registerIcon('notebook-split-cell', Codicon.splitVertical, localize('splitCellIcon', 'Icon to split a cell in notebook editors.')); +export const unfoldIcon = registerIcon('notebook-unfold', Codicon.unfold, localize('unfoldIcon', 'Icon to unfold a cell in notebook editors.')); + +export const collapsedIcon = registerIcon('notebook-collapsed', Codicon.chevronRight, localize('collapsedIcon', 'Icon to annotated a collapsed section in notebook editors.')); +export const expandedIcon = registerIcon('notebook-expanded', Codicon.chevronDown, localize('expandedIcon', 'Icon to annotated a expanded section in notebook editors.')); +export const openAsTextIcon = registerIcon('notebook-open-as-text', Codicon.fileCode, localize('openAsTextIcon', 'Icon to open the notebook in a text editor.')); +export const revertIcon = registerIcon('notebook-revert', Codicon.discard, localize('revertIcon', 'Icon to revert in notebook editors.')); +export const mimetypeIcon = registerIcon('notebook-mimetype', Codicon.code, localize('mimetypeIcon', 'Icon for a mime type notebook editors.')); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index f2dbc30f49e..b0f47bb4817 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -21,6 +21,8 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; const OUTPUT_COUNT_LIMIT = 500; @@ -69,7 +71,7 @@ export class OutputElement extends Disposable { if (mimeTypes.length > 1) { outputItemDiv.style.position = 'relative'; const mimeTypePicker = DOM.$('.multi-mimetype-output'); - mimeTypePicker.classList.add('codicon', 'codicon-code'); + mimeTypePicker.classList.add(...ThemeIcon.asClassNameArray(mimetypeIcon)); mimeTypePicker.tabIndex = 0; mimeTypePicker.title = nls.localize('mimeTypePicker', "Choose a different output mimetype, available mimetypes: {0}", mimeTypes.map(mimeType => mimeType.mimeType).join(', ')); outputItemDiv.appendChild(mimeTypePicker); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 853f0351a2d..7ffaeaadece 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -49,6 +49,8 @@ import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/vie import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, NotebookCellsChangeType, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CodiconActionViewItem, createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { unfoldIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; const $ = DOM.$; @@ -357,8 +359,8 @@ abstract class AbstractCellRenderer { } protected setupCollapsedPart(container: HTMLElement): { collapsedPart: HTMLElement, expandButton: HTMLElement } { - const collapsedPart = DOM.append(container, $('.cell.cell-collapsed-part', undefined, ...renderCodicons('$(unfold)'))); - const expandButton = collapsedPart.querySelector('.codicon') as HTMLElement; + const collapsedPart = DOM.append(container, $('.cell.cell-collapsed-part', undefined, $('span.expandButton' + ThemeIcon.asCSSSelector(unfoldIcon)))); + const expandButton = collapsedPart.querySelector('.expandButton') as HTMLElement; const keybinding = this.keybindingService.lookupKeybinding(EXPAND_CELL_CONTENT_COMMAND_ID); let title = localize('cellExpandButtonLabel', "Expand"); if (keybinding) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index a22aa498c49..8670a3c4a62 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -6,7 +6,6 @@ import * as DOM from 'vs/base/browser/dom'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { renderCodicons } from 'vs/base/browser/codicons'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; @@ -22,6 +21,9 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { getExecuteCellPlaceholder, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { renderCodicons } from 'vs/base/browser/codicons'; export class StatefulMarkdownCell extends Disposable { @@ -353,10 +355,10 @@ export class StatefulMarkdownCell extends Disposable { this.templateData.foldingIndicator.innerText = ''; break; case CellFoldingState.Collapsed: - DOM.reset(this.templateData.foldingIndicator, ...renderCodicons('$(chevron-right)')); + DOM.reset(this.templateData.foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(collapsedIcon))); break; case CellFoldingState.Expanded: - DOM.reset(this.templateData.foldingIndicator, ...renderCodicons('$(chevron-down)')); + DOM.reset(this.templateData.foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(expandedIcon))); break; default: From fddc9bb221d60bbb76abae4b1378141325a1bbe4 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 11:46:02 +0100 Subject: [PATCH 0381/1837] success/error icons --- src/vs/workbench/contrib/notebook/browser/notebookIcons.ts | 4 +++- .../contrib/notebook/browser/view/renderers/cellRenderer.ts | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts index f40d89b4e1d..f0005149142 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts @@ -7,7 +7,6 @@ import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; - export const configureKernelIcon = registerIcon('notebook-kernel-configure', Codicon.settingsGear, localize('configureKernel', 'Configure icon in kernel configuation widget in notebook editors.')); export const selectKernelIcon = registerIcon('notebook-kernel-select', Codicon.serverEnvironment, localize('selectKernelIcon', 'Configure icon to select a kernel in notebook editors.')); @@ -23,6 +22,9 @@ export const clearIcon = registerIcon('notebook-clear', Codicon.clearAll, locali export const splitCellIcon = registerIcon('notebook-split-cell', Codicon.splitVertical, localize('splitCellIcon', 'Icon to split a cell in notebook editors.')); export const unfoldIcon = registerIcon('notebook-unfold', Codicon.unfold, localize('unfoldIcon', 'Icon to unfold a cell in notebook editors.')); +export const successStateIcon = registerIcon('notebook-state-success', Codicon.check, localize('successStateIcon', 'Icon to indicate a success state in notebook editors.')); +export const errorStateIcon = registerIcon('notebook-state-error', Codicon.error, localize('errorStateIcon', 'Icon to indicate a error state in notebook editors.')); + export const collapsedIcon = registerIcon('notebook-collapsed', Codicon.chevronRight, localize('collapsedIcon', 'Icon to annotated a collapsed section in notebook editors.')); export const expandedIcon = registerIcon('notebook-expanded', Codicon.chevronDown, localize('expandedIcon', 'Icon to annotated a expanded section in notebook editors.')); export const openAsTextIcon = registerIcon('notebook-open-as-text', Codicon.fileCode, localize('openAsTextIcon', 'Icon to open the notebook in a text editor.')); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 7ffaeaadece..6bb372a25f0 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -50,7 +50,7 @@ import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/n import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, NotebookCellsChangeType, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CodiconActionViewItem, createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { unfoldIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { errorStateIcon, successStateIcon, unfoldIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; const $ = DOM.$; @@ -1050,9 +1050,9 @@ export class RunStateRenderer { } if (runState === NotebookCellRunState.Success) { - DOM.reset(this.element, ...renderCodicons('$(check)')); + DOM.reset(this.element, ...renderCodicons(ThemeIcon.asCodiconLabel(successStateIcon))); } else if (runState === NotebookCellRunState.Error) { - DOM.reset(this.element, ...renderCodicons('$(error)')); + DOM.reset(this.element, ...renderCodicons(ThemeIcon.asCodiconLabel(errorStateIcon))); } else if (runState === NotebookCellRunState.Running) { DOM.reset(this.element, ...renderCodicons('$(sync~spin)')); From 4e45d27a72f55ef49213800d73badeb124d6ff7e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 12:12:54 +0100 Subject: [PATCH 0382/1837] fix stopIcon name --- src/vs/workbench/contrib/notebook/browser/notebookIcons.ts | 2 +- test/smoke/src/areas/notebook/notebook.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts index f0005149142..c0d6564bdad 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts @@ -11,7 +11,7 @@ export const configureKernelIcon = registerIcon('notebook-kernel-configure', Cod export const selectKernelIcon = registerIcon('notebook-kernel-select', Codicon.serverEnvironment, localize('selectKernelIcon', 'Configure icon to select a kernel in notebook editors.')); export const executeIcon = registerIcon('notebook-execute', Codicon.play, localize('executeIcon', 'Icon to execute in notebook editors.')); -export const stopIcon = registerIcon('notebook-execute', Codicon.primitiveSquare, localize('stopIcon', 'Icon to stop an execution in notebook editors.')); +export const stopIcon = registerIcon('notebook-stop', Codicon.primitiveSquare, localize('stopIcon', 'Icon to stop an execution in notebook editors.')); export const deleteCellIcon = registerIcon('notebook-delete-cell', Codicon.trash, localize('deleteCellIcon', 'Icon to delete a cell in notebook editors.')); export const executeAllIcon = registerIcon('notebook-execute-all', Codicon.runAll, localize('executeAllIcon', 'Icon to execute all cells in notebook editors.')); export const editIcon = registerIcon('notebook-edit', Codicon.pencil, localize('editIcon', 'Icon to edit a cell in notebook editors.')); diff --git a/test/smoke/src/areas/notebook/notebook.test.ts b/test/smoke/src/areas/notebook/notebook.test.ts index bf037e68594..dd739a8ae8e 100644 --- a/test/smoke/src/areas/notebook/notebook.test.ts +++ b/test/smoke/src/areas/notebook/notebook.test.ts @@ -67,7 +67,7 @@ export function setup() { const app = this.app as Application; await app.workbench.notebook.openNotebook(); await app.workbench.notebook.insertNotebookCell('code'); - await app.workbench.notebook.executeCellAction('.notebook-editor .monaco-list-row.focused div.monaco-toolbar .codicon-debug'); + await app.workbench.notebook.executeCellAction('.notebook-editor .monaco-list-row.focused div.monaco-toolbar .codicon-notebook-execute'); await app.workbench.notebook.waitForActiveCellEditorContents('test'); }); }); From 8012c255e560e610eadb30364d993b6f0674a439 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 12:19:03 +0100 Subject: [PATCH 0383/1837] fix keybinding smoke test after icon name changes --- test/automation/src/keybindings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/automation/src/keybindings.ts b/test/automation/src/keybindings.ts index abd0ccf9055..1de40d42bc9 100644 --- a/test/automation/src/keybindings.ts +++ b/test/automation/src/keybindings.ts @@ -24,7 +24,7 @@ export class KeybindingsEditor { await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item'); await this.code.waitForElement('.keybindings-list-container .monaco-list-row.keybinding-item.focused.selected'); - await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .codicon.codicon-add'); + await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .codicon-keybindings-add'); await this.code.waitForActiveElement('.defineKeybindingWidget .monaco-inputbox input'); await this.code.dispatchKeybinding(keybinding); From 0321ca5d96714f50116453b3272dcecb9920f23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 12:22:04 +0100 Subject: [PATCH 0384/1837] fixes #106664 --- extensions/git/src/api/api1.ts | 2 +- extensions/git/src/api/git.d.ts | 1 + extensions/git/src/remoteSource.ts | 46 ++++++++++++++++--- extensions/github/src/remoteSourceProvider.ts | 28 +++++++++-- extensions/github/src/typings/git.d.ts | 2 + 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/extensions/git/src/api/api1.ts b/extensions/git/src/api/api1.ts index 8bcdba44112..0a309c6f96b 100644 --- a/extensions/git/src/api/api1.ts +++ b/extensions/git/src/api/api1.ts @@ -357,7 +357,7 @@ export function registerAPICommands(extension: GitExtensionImpl): Disposable { return; } - return pickRemoteSource(extension.model, opts); + return pickRemoteSource(extension.model, opts as any); })); return Disposable.from(...disposables); diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index f63b0b12c3c..b9a09632b66 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -212,6 +212,7 @@ export interface RemoteSourceProvider { readonly icon?: string; // codicon name readonly supportsQuery?: boolean; getRemoteSources(query?: string): ProviderResult; + getBranches?(url: string): ProviderResult; publishRepository?(repository: Repository): Promise; } diff --git a/extensions/git/src/remoteSource.ts b/extensions/git/src/remoteSource.ts index 3676832c5c4..cbe437d6af0 100644 --- a/extensions/git/src/remoteSource.ts +++ b/extensions/git/src/remoteSource.ts @@ -82,9 +82,17 @@ export interface PickRemoteSourceOptions { readonly providerLabel?: (provider: RemoteSourceProvider) => string; readonly urlLabel?: string; readonly providerName?: string; + readonly branch?: boolean; // then result is PickRemoteSourceResult } -export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions = {}): Promise { +export interface PickRemoteSourceResult { + readonly url: string; + readonly branch?: string; +} + +export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch?: false | undefined }): Promise; +export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch: true }): Promise; +export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions = {}): Promise { const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>(); quickpick.ignoreFocusOut = true; @@ -93,7 +101,7 @@ export async function pickRemoteSource(model: Model, options: PickRemoteSourceOp .filter(provider => provider.name === options.providerName)[0]; if (provider) { - return await pickProviderSource(provider); + return await pickProviderSource(provider, options); } } @@ -127,24 +135,48 @@ export async function pickRemoteSource(model: Model, options: PickRemoteSourceOp if (result.url) { return result.url; } else if (result.provider) { - return await pickProviderSource(result.provider); + return await pickProviderSource(result.provider, options); } } return undefined; } -async function pickProviderSource(provider: RemoteSourceProvider): Promise { +async function pickProviderSource(provider: RemoteSourceProvider, options: PickRemoteSourceOptions = {}): Promise { const quickpick = new RemoteSourceProviderQuickPick(provider); const remote = await quickpick.pick(); + let url: string | undefined; + if (remote) { if (typeof remote.url === 'string') { - return remote.url; + url = remote.url; } else if (remote.url.length > 0) { - return await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") }); + url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") }); } } - return undefined; + if (!url || !options.branch) { + return url; + } + + if (!provider.getBranches) { + return { url }; + } + + const branches = await provider.getBranches(url); + + if (!branches) { + return { url }; + } + + const branch = await window.showQuickPick(branches, { + placeHolder: localize('branch name', "Branch name") + }); + + if (!branch) { + return { url }; + } + + return { url, branch }; } diff --git a/extensions/github/src/remoteSourceProvider.ts b/extensions/github/src/remoteSourceProvider.ts index f16bf07cf7a..c2803fe2678 100644 --- a/extensions/github/src/remoteSourceProvider.ts +++ b/extensions/github/src/remoteSourceProvider.ts @@ -8,6 +8,12 @@ import { getOctokit } from './auth'; import { Octokit } from '@octokit/rest'; import { publishRepository } from './publish'; +function parse(url: string): { owner: string, repo: string } | undefined { + const match = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\.git/i.exec(url) + || /^git@github\.com:([^/]+)\/([^/]+)\.git/i.exec(url); + return (match && { owner: match[1], repo: match[2] }) ?? undefined; +} + function asRemoteSource(raw: any): RemoteSource { return { name: `$(github) ${raw.full_name}`, @@ -30,11 +36,10 @@ export class GithubRemoteSourceProvider implements RemoteSourceProvider { const octokit = await getOctokit(); if (query) { - const match = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\.git/i.exec(query) - || /^git@github\.com:([^/]+)\/([^/]+)\.git/i.exec(query); + const repository = parse(query); - if (match) { - const raw = await octokit.repos.get({ owner: match[1], repo: match[2] }); + if (repository) { + const raw = await octokit.repos.get(repository); return [asRemoteSource(raw.data)]; } } @@ -75,6 +80,21 @@ export class GithubRemoteSourceProvider implements RemoteSourceProvider { return raw.data.items.map(asRemoteSource); } + async getBranches(url: string): Promise { + const repository = parse(url); + + if (!repository) { + return []; + } + + const octokit = await getOctokit(); + const branches = await octokit.repos.listBranches(repository); + const repo = await octokit.repos.get(repository); + const defaultBranch = repo.data.default_branch; + + return branches.data.map(b => b.name).sort((a, b) => a === defaultBranch ? -1 : b === defaultBranch ? 1 : 0); + } + publishRepository(repository: Repository): Promise { return publishRepository(this.gitAPI, repository); } diff --git a/extensions/github/src/typings/git.d.ts b/extensions/github/src/typings/git.d.ts index 54f21b96dbb..b9a09632b66 100644 --- a/extensions/github/src/typings/git.d.ts +++ b/extensions/github/src/typings/git.d.ts @@ -130,6 +130,7 @@ export interface CommitOptions { signoff?: boolean; signCommit?: boolean; empty?: boolean; + noVerify?: boolean; } export interface BranchQuery { @@ -211,6 +212,7 @@ export interface RemoteSourceProvider { readonly icon?: string; // codicon name readonly supportsQuery?: boolean; getRemoteSources(query?: string): ProviderResult; + getBranches?(url: string): ProviderResult; publishRepository?(repository: Repository): Promise; } From 2fb5b5b696d96e9a439f9db80dd57ad529447ecc Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2020 12:36:15 +0100 Subject: [PATCH 0385/1837] fixes #44542 --- .../contrib/debug/browser/debugConfigurationManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index d7caaef4389..1357826cd28 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -689,7 +689,7 @@ class UserLaunch extends AbstractLaunch implements ILaunch { } async openConfigFile(preserveFocus: boolean): Promise<{ editor: IEditorPane | null, created: boolean }> { - const editor = await this.preferencesService.openGlobalSettings(true, { preserveFocus }); + const editor = await this.preferencesService.openGlobalSettings(true, { preserveFocus, revealSetting: { key: 'launch' } }); return ({ editor: withUndefinedAsNull(editor), created: false From cae277a203cc78403f2577fc23b5502d32d0ef43 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 13:10:59 +0100 Subject: [PATCH 0386/1837] Add a command for open port in browser Part of https://github.com/microsoft/vscode/issues/111402 --- .../contrib/remote/browser/tunnelView.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index a99acd36f56..efa84164465 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -927,6 +927,43 @@ export namespace OpenPortInBrowserAction { } } +namespace OpenPortInBrowserCommandPaletteAction { + export const ID = 'remote.tunnel.openCommandPalette'; + export const LABEL = nls.localize('remote.tunnel.openCommandPalette', "Open Port in Browser"); + + interface QuickPickTunnel extends IQuickPickItem { + tunnel?: TunnelItem; + } + + export function handler(): ICommandHandler { + return async (accessor, arg) => { + const model = accessor.get(IRemoteExplorerService).tunnelModel; + const quickPickService = accessor.get(IQuickInputService); + const openerService = accessor.get(IOpenerService); + const commandService = accessor.get(ICommandService); + const options: QuickPickTunnel[] = [...model.forwarded, ...model.detected].map(value => { + const tunnelItem = TunnelItem.createFromTunnel(value[1]); + return { + label: tunnelItem.label, + description: tunnelItem.description, + tunnel: tunnelItem + }; + }); + if (options.length === 0) { + options.push({ + label: nls.localize('remote.tunnel.openCommandPaletteNone', "No ports currently forwarded. Open the ports view to get started.") + }); + } + const picked = await quickPickService.pick(options, { placeHolder: nls.localize('remote.tunnel.openCommandPalettePick', "Choose the port to open") }); + if (picked && picked.tunnel) { + return OpenPortInBrowserAction.run(model, openerService, makeAddress(picked.tunnel.remoteHost, picked.tunnel.remotePort)); + } else if (picked) { + return commandService.executeCommand(`${TUNNEL_VIEW_ID}.focus`); + } + }; + } +} + namespace CopyAddressAction { export const INLINE_ID = 'remote.tunnel.copyAddressInline'; export const COMMANDPALETTE_ID = 'remote.tunnel.copyAddressCommandPalette'; @@ -1033,6 +1070,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ CommandsRegistry.registerCommand(ClosePortAction.COMMANDPALETTE_ID, ClosePortAction.commandPaletteHandler()); CommandsRegistry.registerCommand(OpenPortInBrowserAction.ID, OpenPortInBrowserAction.handler()); +CommandsRegistry.registerCommand(OpenPortInBrowserCommandPaletteAction.ID, OpenPortInBrowserCommandPaletteAction.handler()); KeybindingsRegistry.registerCommandAndKeybindingRule({ id: CopyAddressAction.INLINE_ID, weight: KeybindingWeight.WorkbenchContrib + tunnelViewCommandsWeightBonus, @@ -1064,6 +1102,13 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ }, when: forwardedPortsViewEnabled })); +MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ + command: { + id: OpenPortInBrowserCommandPaletteAction.ID, + title: OpenPortInBrowserCommandPaletteAction.LABEL + }, + when: forwardedPortsViewEnabled +})); MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({ group: 'navigation', order: 0, From c3414f3cf3a100891209aaed12c26ca9b10d43c3 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 13:18:32 +0100 Subject: [PATCH 0387/1837] Always show the open view option in the open in browser command --- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index efa84164465..bb5bf09d445 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -951,7 +951,11 @@ namespace OpenPortInBrowserCommandPaletteAction { }); if (options.length === 0) { options.push({ - label: nls.localize('remote.tunnel.openCommandPaletteNone', "No ports currently forwarded. Open the ports view to get started.") + label: nls.localize('remote.tunnel.openCommandPaletteNone', "No ports currently forwarded. Open the Ports view to get started.") + }); + } else { + options.push({ + label: nls.localize('remote.tunnel.openCommandPaletteView', "Open the Ports view...") }); } const picked = await quickPickService.pick(options, { placeHolder: nls.localize('remote.tunnel.openCommandPalettePick', "Choose the port to open") }); From 995983da548faf7e2fb94267a193eb846c1a3acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 14:02:13 +0100 Subject: [PATCH 0388/1837] github: get all branches --- extensions/github/src/remoteSourceProvider.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/extensions/github/src/remoteSourceProvider.ts b/extensions/github/src/remoteSourceProvider.ts index c2803fe2678..17b153006dc 100644 --- a/extensions/github/src/remoteSourceProvider.ts +++ b/extensions/github/src/remoteSourceProvider.ts @@ -88,11 +88,25 @@ export class GithubRemoteSourceProvider implements RemoteSourceProvider { } const octokit = await getOctokit(); - const branches = await octokit.repos.listBranches(repository); + + const branches: string[] = []; + let page = 1; + + while (true) { + let res = await octokit.repos.listBranches({ ...repository, per_page: 100, page }); + + if (res.data.length === 0) { + break; + } + + branches.push(...res.data.map(b => b.name)); + page++; + } + const repo = await octokit.repos.get(repository); const defaultBranch = repo.data.default_branch; - return branches.data.map(b => b.name).sort((a, b) => a === defaultBranch ? -1 : b === defaultBranch ? 1 : 0); + return branches.sort((a, b) => a === defaultBranch ? -1 : b === defaultBranch ? 1 : 0); } publishRepository(repository: Repository): Promise { From f8d1c07e164f6972b11eded1dad94b5860ceea45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 14:36:54 +0100 Subject: [PATCH 0389/1837] use createChannelReceiver, createChannelSender --- src/vs/code/electron-main/app.ts | 3 +- .../common/extensionUrlTrustIpc.ts | 36 ------------------- .../extensionUrlTrustService.ts | 11 ++++-- 3 files changed, 9 insertions(+), 41 deletions(-) delete mode 100644 src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 8dd876940a9..4454bf477f5 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -89,7 +89,6 @@ import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { isEqualOrParent } from 'vs/base/common/extpath'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; -import { ExtensionUrlTrustChannel } from 'vs/platform/extensionManagement/common/extensionUrlTrustIpc'; import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService'; export class CodeApplication extends Disposable { @@ -640,7 +639,7 @@ export class CodeApplication extends Disposable { electronIpcServer.registerChannel('url', urlChannel); const extensionUrlTrustService = accessor.get(IExtensionUrlTrustService); - const extensionUrlTrustChannel = new ExtensionUrlTrustChannel(extensionUrlTrustService); + const extensionUrlTrustChannel = createChannelReceiver(extensionUrlTrustService); electronIpcServer.registerChannel('extensionUrlTrust', extensionUrlTrustChannel); const webviewManagerService = accessor.get(IWebviewManagerService); diff --git a/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts b/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts deleted file mode 100644 index 347b931c181..00000000000 --- a/src/vs/platform/extensionManagement/common/extensionUrlTrustIpc.ts +++ /dev/null @@ -1,36 +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 { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { Event } from 'vs/base/common/event'; -import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; - -export class ExtensionUrlTrustChannel implements IServerChannel { - - constructor(private service: IExtensionUrlTrustService) { } - - listen(): Event { - throw new Error('No events supported'); - } - - call(_: any, command: string, arg?: any): Promise { - switch (command) { - case 'isExtensionUrlTrusted': return this.service.isExtensionUrlTrusted(arg[0], arg[1]); - } - - throw new Error('Invalid call'); - } -} - -export class ExtensionUrlTrustChannelClient implements IExtensionUrlTrustService { - - declare readonly _serviceBrand: undefined; - - constructor(private readonly channel: IChannel) { } - - isExtensionUrlTrusted(extensionId: string, url: string): Promise { - return this.channel.call('isExtensionUrlTrusted', [extensionId, url]); - } -} diff --git a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts index d3f1fc741c0..e89aa76d7c2 100644 --- a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts +++ b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts @@ -3,17 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; -import { ExtensionUrlTrustChannelClient } from 'vs/platform/extensionManagement/common/extensionUrlTrustIpc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -class ExtensionUrlTrustService extends ExtensionUrlTrustChannelClient { +class ExtensionUrlTrustService implements IExtensionUrlTrustService { declare readonly _serviceBrand: undefined; + private service: IExtensionUrlTrustService; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - super(mainProcessService.getChannel('extensionUrlTrust')); + this.service = createChannelSender(mainProcessService.getChannel('extensionUrlTrust')); + } + + isExtensionUrlTrusted(extensionId: string, url: string): Promise { + return this.service.isExtensionUrlTrusted(extensionId, url); } } From 483e81f3b81e7c76a0a448cfd5dd9906710593bf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 14:42:55 +0100 Subject: [PATCH 0390/1837] Fix duplicate port forwards for ipv4 vs ipv6 Fixes https://github.com/microsoft/vscode/issues/111400 --- src/vs/platform/remote/common/tunnel.ts | 8 ++++- .../remote/common/remoteExplorerService.ts | 33 ++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index a15e58462a6..980c3203a08 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -60,8 +60,14 @@ export function extractLocalHostUriMetaDataForPortMapping(uri: URI): { address: }; } +export const LOCALHOST_ADDRESSES = ['localhost', '127.0.0.1', '0:0:0:0:0:0:0:1', '::1']; export function isLocalhost(host: string): boolean { - return host === 'localhost' || host === '127.0.0.1'; + return LOCALHOST_ADDRESSES.indexOf(host) >= 0; +} + +export const ALL_INTERFACES_ADDRESSES = ['0.0.0.0', '0:0:0:0:0:0:0:0', '::']; +export function isAllInterfaces(host: string): boolean { + return ALL_INTERFACES_ADDRESSES.indexOf(host) >= 0; } function getOtherLocalhost(host: string): string | undefined { diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index ef855dfa7ab..be29f38f980 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -7,7 +7,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { isLocalhost, ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; +import { ALL_INTERFACES_ADDRESSES, isAllInterfaces, isLocalhost, ITunnelService, LOCALHOST_ADDRESSES, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IEditableData } from 'vs/workbench/common/views'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -65,18 +65,29 @@ export function parseAddress(address: string): { host: string, port: number } | } export function mapHasAddress(map: Map, host: string, port: number): T | undefined { - if (!isLocalhost(host)) { - return map.get(makeAddress(host, port)); + const initialAddress = map.get(makeAddress(host, port)); + if (initialAddress) { + return initialAddress; } - const stringAddress = makeAddress('localhost', port); - if (map.has(stringAddress)) { - return map.get(stringAddress); - } - const numberAddress = makeAddress('127.0.0.1', port); - if (map.has(numberAddress)) { - return map.get(numberAddress); + if (isLocalhost(host)) { + // Do localhost checks + for (const testHost of LOCALHOST_ADDRESSES) { + const testAddress = makeAddress(testHost, port); + if (map.has(testAddress)) { + return map.get(testAddress); + } + } + } else if (isAllInterfaces(host)) { + // Do all interfaces checks + for (const testHost of ALL_INTERFACES_ADDRESSES) { + const testAddress = makeAddress(testHost, port); + if (map.has(testAddress)) { + return map.get(testAddress); + } + } } + return undefined; } @@ -85,7 +96,7 @@ export function mapHasAddressLocalhostOrAllInterfaces(map: Map, ho if (originalAddress) { return originalAddress; } - const otherHost = host === '0.0.0.0' ? 'localhost' : (host === 'localhost' ? '0.0.0.0' : undefined); + const otherHost = isAllInterfaces(host) ? 'localhost' : (host === 'localhost' ? '0.0.0.0' : undefined); if (otherHost) { return mapHasAddress(map, otherHost, port); } From 6391d710cf14eeadd9031bc8d20c86e9f734858d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2020 14:43:43 +0100 Subject: [PATCH 0391/1837] adopt latest loader, pass trusted types policy to loader, adopt in loader-usages --- src/vs/base/common/worker/simpleWorker.ts | 4 ++ src/vs/base/worker/workerMain.ts | 10 +++- .../code/browser/workbench/workbench-dev.html | 9 +++- src/vs/code/browser/workbench/workbench.html | 9 +++- src/vs/loader.js | 52 ++++--------------- .../worker/extensionHostWorkerMain.ts | 10 +++- 6 files changed, 45 insertions(+), 49 deletions(-) diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index 19f154a7943..1b81394ae64 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -358,6 +358,10 @@ export class SimpleWorkerServer { delete loaderConfig.paths['vs']; } } + if (typeof loaderConfig.trustedTypesPolicy !== undefined) { + // don't use, it has been destroyed during serialize + delete loaderConfig['trustedTypesPolicy']; + } // Since this is in a web worker, enable catching errors loaderConfig.catchError = true; diff --git a/src/vs/base/worker/workerMain.ts b/src/vs/base/worker/workerMain.ts index 71c6724e984..c39dba9a350 100644 --- a/src/vs/base/worker/workerMain.ts +++ b/src/vs/base/worker/workerMain.ts @@ -8,14 +8,20 @@ let MonacoEnvironment = (self).MonacoEnvironment; let monacoBaseUrl = MonacoEnvironment && MonacoEnvironment.baseUrl ? MonacoEnvironment.baseUrl : '../../../'; + const trustedTypesPolicy = self.trustedTypes?.createPolicy('amdLoader', { createScriptURL: value => value }); + if (typeof (self).define !== 'function' || !(self).define.amd) { - importScripts(monacoBaseUrl + 'vs/loader.js'); + let loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js'; + if (trustedTypesPolicy) { + loaderSrc = trustedTypesPolicy.createScriptURL(loaderSrc); + } + importScripts(loaderSrc as string); } require.config({ baseUrl: monacoBaseUrl, catchError: true, - createTrustedScriptURL: (value: string) => value, + trustedTypesPolicy, }); let loadCode = function (moduleId: string) { diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index c3c259cfa83..8b1869294e6 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -33,7 +33,14 @@ self.require = { baseUrl: `${window.location.origin}/static/out`, recordStats: true, - createTrustedScriptURL: value => value, + trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', { + createScriptURL(value) { + if(value.startsWith(window.location.origin)) { + return value; + } + throw new Error(`Invalid script url: ${value}`) + } + }), paths: { 'vscode-textmate': `${window.location.origin}/static/remote/web/node_modules/vscode-textmate/release/main`, 'vscode-oniguruma': `${window.location.origin}/static/remote/web/node_modules/vscode-oniguruma/release/main`, diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index 300ceb2fbb8..1dbdce5d6e0 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -32,7 +32,14 @@ self.require = { baseUrl: `${window.location.origin}/static/out`, recordStats: true, - createTrustedScriptURL: value => value, + trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', { + createScriptURL(value) { + if(value.startsWith(window.location.origin)) { + return value; + } + throw new Error(`Invalid script url: ${value}`) + } + }), paths: { 'vscode-textmate': `${window.location.origin}/static/node_modules/vscode-textmate/release/main`, 'vscode-oniguruma': `${window.location.origin}/static/node_modules/vscode-oniguruma/release/main`, diff --git a/src/vs/loader.js b/src/vs/loader.js index 571bb67f650..76db9773690 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -198,6 +198,9 @@ var AMDLoader; if (!obj || typeof obj !== 'object' || obj instanceof RegExp) { return obj; } + if (!Array.isArray(obj) && Object.getPrototypeOf(obj) !== Object.prototype) { + return obj; + } var result = Array.isArray(obj) ? [] : {}; Utilities.forEachProperty(obj, function (key, value) { if (value && typeof value === 'object') { @@ -618,37 +621,8 @@ var AMDLoader; }; return OnlyOnceScriptLoader; }()); - var trustedTypesPolyfill = new /** @class */ (function () { - function class_1() { - } - class_1.prototype.installIfNeeded = function () { - if (typeof globalThis.trustedTypes !== 'undefined') { - return; // already defined - } - var _defaultRules = { - createHTML: function () { throw new Error('Policy\'s TrustedTypePolicyOptions did not specify a \'createHTML\' member'); }, - createScript: function () { throw new Error('Policy\'s TrustedTypePolicyOptions did not specify a \'createScript\' member'); }, - createScriptURL: function () { throw new Error('Policy\'s TrustedTypePolicyOptions did not specify a \'createScriptURL\' member'); }, - }; - globalThis.trustedTypes = { - createPolicy: function (name, rules) { - var _a, _b, _c; - return { - name: name, - createHTML: (_a = rules.createHTML) !== null && _a !== void 0 ? _a : _defaultRules.createHTML, - createScript: (_b = rules.createScript) !== null && _b !== void 0 ? _b : _defaultRules.createScript, - createScriptURL: (_c = rules.createScriptURL) !== null && _c !== void 0 ? _c : _defaultRules.createScriptURL, - }; - } - }; - }; - return class_1; - }()); - //#endregion var BrowserScriptLoader = /** @class */ (function () { function BrowserScriptLoader() { - // polyfill trustedTypes-support if missing - trustedTypesPolyfill.installIfNeeded(); } /** * Attach load / error listeners to a script element and remove them when either one has fired. @@ -691,12 +665,9 @@ var AMDLoader; script.setAttribute('async', 'async'); script.setAttribute('type', 'text/javascript'); this.attachListeners(script, callback, errorback); - var createTrustedScriptURL = moduleManager.getConfig().getOptionsLiteral().createTrustedScriptURL; - if (createTrustedScriptURL) { - if (!this.scriptSourceURLPolicy) { - this.scriptSourceURLPolicy = trustedTypes.createPolicy('amdLoader', { createScriptURL: createTrustedScriptURL }); - } - scriptSrc = this.scriptSourceURLPolicy.createScriptURL(scriptSrc); + var trustedTypesPolicy = moduleManager.getConfig().getOptionsLiteral().trustedTypesPolicy; + if (trustedTypesPolicy) { + scriptSrc = trustedTypesPolicy.createScriptURL(scriptSrc); } script.setAttribute('src', scriptSrc); // Propagate CSP nonce to dynamically created script tag. @@ -711,16 +682,11 @@ var AMDLoader; }()); var WorkerScriptLoader = /** @class */ (function () { function WorkerScriptLoader() { - // polyfill trustedTypes-support if missing - trustedTypesPolyfill.installIfNeeded(); } WorkerScriptLoader.prototype.load = function (moduleManager, scriptSrc, callback, errorback) { - var createTrustedScriptURL = moduleManager.getConfig().getOptionsLiteral().createTrustedScriptURL; - if (createTrustedScriptURL) { - if (!this.scriptSourceURLPolicy) { - this.scriptSourceURLPolicy = trustedTypes.createPolicy('amdLoader', { createScriptURL: createTrustedScriptURL }); - } - scriptSrc = this.scriptSourceURLPolicy.createScriptURL(scriptSrc); + var trustedTypesPolicy = moduleManager.getConfig().getOptionsLiteral().trustedTypesPolicy; + if (trustedTypesPolicy) { + scriptSrc = trustedTypesPolicy.createScriptURL(scriptSrc); } try { importScripts(scriptSrc); diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts index b39a5cbb9ea..f5c55522504 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts @@ -8,14 +8,20 @@ let MonacoEnvironment = (self).MonacoEnvironment; let monacoBaseUrl = MonacoEnvironment && MonacoEnvironment.baseUrl ? MonacoEnvironment.baseUrl : '../../../../../'; + const trustedTypesPolicy = self.trustedTypes?.createPolicy('amdLoader', { createScriptURL: value => value }); + if (typeof (self).define !== 'function' || !(self).define.amd) { - importScripts(monacoBaseUrl + 'vs/loader.js'); + let loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js'; + if (trustedTypesPolicy) { + loaderSrc = trustedTypesPolicy.createScriptURL(loaderSrc); + } + importScripts(loaderSrc as string); } require.config({ baseUrl: monacoBaseUrl, catchError: true, - createTrustedScriptURL: (value: string) => value + trustedTypesPolicy }); require(['vs/workbench/services/extensions/worker/extensionHostWorker'], () => { }, err => console.error(err)); From 3495d2fd76c2698d9a9090904bdfb629aca1405e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 14:55:55 +0100 Subject: [PATCH 0392/1837] :lipstick: --- .../electron-sandbox/extensionUrlTrustService.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts index e89aa76d7c2..3cabb495102 100644 --- a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts +++ b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts @@ -8,17 +8,12 @@ import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/commo import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -class ExtensionUrlTrustService implements IExtensionUrlTrustService { +class ExtensionUrlTrustService { declare readonly _serviceBrand: undefined; - private service: IExtensionUrlTrustService; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - this.service = createChannelSender(mainProcessService.getChannel('extensionUrlTrust')); - } - - isExtensionUrlTrusted(extensionId: string, url: string): Promise { - return this.service.isExtensionUrlTrusted(extensionId, url); + return createChannelSender(mainProcessService.getChannel('extensionUrlTrust')); } } From 8891878a3b7fe4dbf4bc5397967792c9bac31bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 14:58:26 +0100 Subject: [PATCH 0393/1837] bump cache --- build/.cachesalt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/.cachesalt b/build/.cachesalt index b89f52bd923..0313c1fb6ef 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-27T10:19:32.507Z +2020-11-27T13:58:21.232Z From 016655c546779fd1420ea3f688465d39b6f43b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 15:13:51 +0100 Subject: [PATCH 0394/1837] fixes #104629 --- .../contrib/scm/browser/scmViewService.ts | 103 +++++++++++++++++- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewService.ts b/src/vs/workbench/contrib/scm/browser/scmViewService.ts index 2704f6a7bbe..78ac23a1588 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewService.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewService.ts @@ -5,10 +5,21 @@ import { DisposableStore } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; -import { ISCMViewService, ISCMRepository, ISCMService, ISCMViewVisibleRepositoryChangeEvent, ISCMMenus } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMViewService, ISCMRepository, ISCMService, ISCMViewVisibleRepositoryChangeEvent, ISCMMenus, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; import { Iterable } from 'vs/base/common/iterator'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SCMMenus } from 'vs/workbench/contrib/scm/browser/menus'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { debounce } from 'vs/base/common/decorators'; + +function getProviderStorageKey(provider: ISCMProvider): string { + return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`; +} + +export interface ISCMViewServiceState { + readonly all: string[]; + readonly visible: number[]; +} export class SCMViewService implements ISCMViewService { @@ -16,6 +27,9 @@ export class SCMViewService implements ISCMViewService { readonly menus: ISCMMenus; + private didFinishLoading: boolean = false; + private provisionalVisibleRepository: ISCMRepository | undefined; + private previousState: ISCMViewServiceState | undefined; private disposables = new DisposableStore(); private _visibleRepositoriesSet = new Set(); @@ -84,7 +98,8 @@ export class SCMViewService implements ISCMViewService { constructor( @ISCMService private readonly scmService: ISCMService, - @IInstantiationService instantiationService: IInstantiationService + @IInstantiationService instantiationService: IInstantiationService, + @IStorageService private readonly storageService: IStorageService ) { this.menus = instantiationService.createInstance(SCMMenus); @@ -94,13 +109,63 @@ export class SCMViewService implements ISCMViewService { for (const repository of scmService.repositories) { this.onDidAddRepository(repository); } + + try { + this.previousState = JSON.parse(storageService.get('scm:view:visibleRepositories', StorageScope.WORKSPACE, '')); + this.eventuallyFinishLoading(); + } catch { + // noop + } + + storageService.onWillSaveState(this.onWillSaveState, this, this.disposables); } private onDidAddRepository(repository: ISCMRepository): void { + if (!this.didFinishLoading) { + this.eventuallyFinishLoading(); + } + + let removed: Iterable = Iterable.empty(); + + if (this.previousState) { + const index = this.previousState.all.indexOf(getProviderStorageKey(repository.provider)); + + if (index === -1) { // saw a repo we did not expect + const added: ISCMRepository[] = []; + for (const repo of this.scmService.repositories) { // all should be visible + if (!this._visibleRepositoriesSet.has(repo)) { + added.push(repository); + } + } + + this._visibleRepositories = [...this.scmService.repositories]; + this._visibleRepositoriesSet = new Set(this.scmService.repositories); + this._onDidChangeRepositories.fire({ added, removed: Iterable.empty() }); + this.finishLoading(); + return; + } + + const visible = this.previousState.visible.indexOf(index) > -1; + + if (!visible) { + if (this._visibleRepositories.length === 0) { // should make it visible, until other repos come along + this.provisionalVisibleRepository = repository; + } else { + return; + } + } else { + if (this.provisionalVisibleRepository) { + this._visibleRepositories = []; + this._visibleRepositoriesSet = new Set(); + removed = [this.provisionalVisibleRepository]; + this.provisionalVisibleRepository = undefined; + } + } + } + this._visibleRepositories.push(repository); this._visibleRepositoriesSet.add(repository); - - this._onDidChangeRepositories.fire({ added: [repository], removed: Iterable.empty() }); + this._onDidChangeRepositories.fire({ added: [repository], removed }); if (!this._focusedRepository) { this.focus(repository); @@ -108,6 +173,10 @@ export class SCMViewService implements ISCMViewService { } private onDidRemoveRepository(repository: ISCMRepository): void { + if (!this.didFinishLoading) { + this.eventuallyFinishLoading(); + } + const index = this._visibleRepositories.indexOf(repository); if (index > -1) { @@ -166,6 +235,32 @@ export class SCMViewService implements ISCMViewService { this._onDidFocusRepository.fire(repository); } + private onWillSaveState(): void { + if (!this.didFinishLoading) { // don't remember state, if the workbench didn't really finish loading + return; + } + + const all = this.scmService.repositories.map(r => getProviderStorageKey(r.provider)); + const visible = this.visibleRepositories.map(r => all.indexOf(getProviderStorageKey(r.provider))); + const raw = JSON.stringify({ all, visible }); + + this.storageService.store('scm:view:visibleRepositories', raw, StorageScope.WORKSPACE, StorageTarget.MACHINE); + } + + @debounce(2000) + private eventuallyFinishLoading(): void { + this.finishLoading(); + } + + private finishLoading(): void { + if (this.didFinishLoading) { + return; + } + + this.didFinishLoading = true; + this.previousState = undefined; + } + dispose(): void { this.disposables.dispose(); this._onDidChangeRepositories.dispose(); From 01bbb81052086edf3398e599f218e189c44b0658 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 15:38:57 +0100 Subject: [PATCH 0395/1837] Finalize markdown tree tooltip and resolveTreeItem Fixes #100741 --- src/vs/vscode.d.ts | 21 ++++++++++++++++- src/vs/vscode.proposed.d.ts | 23 ------------------- .../workbench/api/common/extHostTreeViews.ts | 8 +++---- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0995e2129a1..4bdfe60574f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -8809,6 +8809,25 @@ declare module 'vscode' { * @return Parent of `element`. */ getParent?(element: T): ProviderResult; + + /** + * Called only on hover to resolve the [TreeItem](#TreeItem.tooltip) property if it is undefined. + * Only properties that were undefined can be resolved in `resolveTreeItem`. + * Functionality may be expanded later to include being called to resolve other missing + * properties on selection and/or on open. + * + * Will only ever be called once per TreeItem. + * + * *Note* that this function is called when tree items are already showing in the UI. + * Because of that, no property that changes the presentation (label, description, command, etc.) + * can be changed. + * + * @param element The object associated with the TreeItem + * @param item Undefined properties of `item` should be set then `item` should be returned. + * @return The resolved tree item or a thenable that resolves to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveTreeItem?(item: TreeItem, element: T): ProviderResult; } export class TreeItem { @@ -8848,7 +8867,7 @@ declare module 'vscode' { /** * The tooltip text when you hover over this item. */ - tooltip?: string | undefined; + tooltip?: string | MarkdownString | undefined; /** * The [command](#Command) that should be executed when the tree item is selected. diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index e2c0f8e90bd..89fd9e466e0 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -943,29 +943,6 @@ declare module 'vscode' { //#endregion //#region Tree View: https://github.com/microsoft/vscode/issues/61313 - - // https://github.com/microsoft/vscode/issues/100741 - export interface TreeDataProvider { - /** - * Called only on hover to resolve the TreeItem2#tooltip property if it is undefined. - * Only properties that were undefined can be resolved in `resolveTreeItem`. - * Will only ever be called once per TreeItem. - * Functionality may be expanded later to include being called to resolve other missing - * properties on selection and/or on open. - * - * @param element - * @param item Undefined properties of `item` should be set then `item` should be returned. - */ - resolveTreeItem?(item: TreeItem2, element: T): ProviderResult; - } - - export class TreeItem2 extends TreeItem { - /** - * Content to be shown when you hover over the tree item. - */ - tooltip?: string | MarkdownString | /* for compilation */ any; - } - export interface TreeView extends Disposable { reveal(element: T | undefined, options?: { select?: boolean, focus?: boolean, expand?: boolean | number }): Thenable; } diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index af3a31890f2..63d307018bc 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -17,7 +17,6 @@ import { TreeItemCollapsibleState, ThemeIcon, MarkdownString as MarkdownStringTy import { isUndefinedOrNull, isString } from 'vs/base/common/types'; import { equals, coalesce } from 'vs/base/common/arrays'; import { ILogService } from 'vs/platform/log/common/log'; -import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters'; import { IMarkdownString } from 'vs/base/common/htmlContent'; @@ -182,7 +181,7 @@ type TreeData = { message: boolean, element: T | Root | false }; interface TreeNode extends IDisposable { item: ITreeItem; - extensionItem: vscode.TreeItem2; + extensionItem: vscode.TreeItem; parent: TreeNode | Root; children?: TreeNode[]; } @@ -569,13 +568,12 @@ class ExtHostTreeView extends Disposable { private getTooltip(tooltip?: string | vscode.MarkdownString): string | IMarkdownString | undefined { if (MarkdownStringType.isMarkdownString(tooltip)) { - checkProposedApiEnabled(this.extension); return MarkdownString.from(tooltip); } return tooltip; } - private createTreeNode(element: T, extensionTreeItem: vscode.TreeItem2, parent: TreeNode | Root): TreeNode { + private createTreeNode(element: T, extensionTreeItem: vscode.TreeItem, parent: TreeNode | Root): TreeNode { const disposable = new DisposableStore(); const handle = this.createHandle(element, extensionTreeItem, parent); const icon = this.getLightIconPath(extensionTreeItem); @@ -604,7 +602,7 @@ class ExtHostTreeView extends Disposable { }; } - private getThemeIcon(extensionTreeItem: vscode.TreeItem2): ThemeIcon | undefined { + private getThemeIcon(extensionTreeItem: vscode.TreeItem): ThemeIcon | undefined { return extensionTreeItem.iconPath instanceof ThemeIcon ? extensionTreeItem.iconPath : undefined; } From 79b6d35bd6414c912f848799c916b3df7ab1c59e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2020 15:46:54 +0100 Subject: [PATCH 0396/1837] remove TreeItem2 --- src/vs/workbench/api/common/extHost.api.impl.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 4a9d5fe9b95..1482f98d8c1 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1219,10 +1219,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension); return extHostTypes.LogLevel; }, - get TreeItem2() { - checkProposedApiEnabled(extension); - return extHostTypes.TreeItem; - }, get RemoteAuthorityResolverError() { checkProposedApiEnabled(extension); return extHostTypes.RemoteAuthorityResolverError; From 6795d766a0a77aef8c72305948a4e63e41d996a9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2020 15:51:19 +0100 Subject: [PATCH 0397/1837] remove old logging API proposal, fixes https://github.com/microsoft/vscode/issues/85992 --- src/vs/vscode.proposed.d.ts | 27 ------------ .../workbench/api/common/extHost.api.impl.ts | 12 ----- .../api/common/extHostTypeConverters.ts | 44 ------------------- src/vs/workbench/api/common/extHostTypes.ts | 10 ----- .../browser/api/extHostTypeConverter.test.ts | 13 +----- 5 files changed, 1 insertion(+), 105 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 89fd9e466e0..ef21f863b6d 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -771,34 +771,7 @@ declare module 'vscode' { //#endregion - //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 - /** - * @deprecated DO NOT USE, will be removed - */ - export enum LogLevel { - Trace = 1, - Debug = 2, - Info = 3, - Warning = 4, - Error = 5, - Critical = 6, - Off = 7 - } - - export namespace env { - /** - * @deprecated DO NOT USE, will be removed - */ - export const logLevel: LogLevel; - - /** - * @deprecated DO NOT USE, will be removed - */ - export const onDidChangeLogLevel: Event; - } - - //#endregion //#region @joaomoreno: SCM validation diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1482f98d8c1..1fbbd8118b4 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -305,14 +305,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I get appName() { return initData.environment.appName; }, get appRoot() { return initData.environment.appRoot?.fsPath ?? ''; }, get uriScheme() { return initData.environment.appUriScheme; }, - get logLevel() { - checkProposedApiEnabled(extension); - return typeConverters.LogLevel.to(extHostLogService.getLevel()); - }, - get onDidChangeLogLevel() { - checkProposedApiEnabled(extension); - return Event.map(extHostLogService.onDidChangeLogLevel, l => typeConverters.LogLevel.to(l)); - }, get clipboard(): vscode.Clipboard { return extHostClipboard; }, @@ -1215,10 +1207,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ViewColumn: extHostTypes.ViewColumn, WorkspaceEdit: extHostTypes.WorkspaceEdit, // proposed api types - get LogLevel() { - checkProposedApiEnabled(extension); - return extHostTypes.LogLevel; - }, get RemoteAuthorityResolverError() { checkProposedApiEnabled(extension); return extHostTypes.RemoteAuthorityResolverError; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index e82a7c10759..468afd933bb 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1255,50 +1255,6 @@ export namespace LanguageSelector { } } -export namespace LogLevel { - export function from(extLevel: types.LogLevel): _MainLogLevel { - switch (extLevel) { - case types.LogLevel.Trace: - return _MainLogLevel.Trace; - case types.LogLevel.Debug: - return _MainLogLevel.Debug; - case types.LogLevel.Info: - return _MainLogLevel.Info; - case types.LogLevel.Warning: - return _MainLogLevel.Warning; - case types.LogLevel.Error: - return _MainLogLevel.Error; - case types.LogLevel.Critical: - return _MainLogLevel.Critical; - case types.LogLevel.Off: - return _MainLogLevel.Off; - default: - return _MainLogLevel.Info; - } - } - - export function to(mainLevel: _MainLogLevel): types.LogLevel { - switch (mainLevel) { - case _MainLogLevel.Trace: - return types.LogLevel.Trace; - case _MainLogLevel.Debug: - return types.LogLevel.Debug; - case _MainLogLevel.Info: - return types.LogLevel.Info; - case _MainLogLevel.Warning: - return types.LogLevel.Warning; - case _MainLogLevel.Error: - return types.LogLevel.Error; - case _MainLogLevel.Critical: - return types.LogLevel.Critical; - case _MainLogLevel.Off: - return types.LogLevel.Off; - default: - return types.LogLevel.Info; - } - } -} - export namespace NotebookCellOutput { export function from(output: types.NotebookCellOutput): IDisplayOutput { return output.toJSON(); diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 9fdbf188f9e..d30a2e5f5d3 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2336,16 +2336,6 @@ export class EvaluatableExpression implements vscode.EvaluatableExpression { } } -export enum LogLevel { - Trace = 1, - Debug = 2, - Info = 3, - Warning = 4, - Error = 5, - Critical = 6, - Off = 7 -} - //#region file api export enum FileChangeType { diff --git a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts index feb4e1dd1ed..c64d371478d 100644 --- a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts @@ -5,10 +5,9 @@ import * as assert from 'assert'; -import { MarkdownString, LogLevel } from 'vs/workbench/api/common/extHostTypeConverters'; +import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters'; import { isEmptyObject } from 'vs/base/common/types'; import { forEach } from 'vs/base/common/collections'; -import * as types from 'vs/workbench/api/common/extHostTypes'; import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; import { URI } from 'vs/base/common/uri'; @@ -82,14 +81,4 @@ suite('ExtHostTypeConverter', function () { } }); }); - - test('LogLevel', () => { - assert.equal(LogLevel.from(types.LogLevel.Error), _MainLogLevel.Error); - assert.equal(LogLevel.from(types.LogLevel.Info), _MainLogLevel.Info); - assert.equal(LogLevel.from(types.LogLevel.Off), _MainLogLevel.Off); - - assert.equal(LogLevel.to(_MainLogLevel.Error), types.LogLevel.Error); - assert.equal(LogLevel.to(_MainLogLevel.Info), types.LogLevel.Info); - assert.equal(LogLevel.to(_MainLogLevel.Off), types.LogLevel.Off); - }); }); From cd9be282b7671aa3b4967fe61e76b0e5a42bfde6 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2020 15:49:49 +0100 Subject: [PATCH 0398/1837] Add condition editing UI to breakpoint filters fixes #111227 --- .../contrib/debug/browser/breakpointsView.ts | 143 +++++++++++++++--- .../contrib/debug/browser/debugActions.ts | 2 +- .../contrib/debug/browser/debugService.ts | 10 +- .../contrib/debug/browser/debugSession.ts | 13 +- .../debug/browser/media/debugViewlet.css | 6 +- .../workbench/contrib/debug/common/debug.ts | 7 +- .../contrib/debug/common/debugModel.ts | 13 +- .../contrib/debug/common/debugStorage.ts | 2 +- .../contrib/debug/common/debugViewModel.ts | 14 +- .../debug/test/browser/breakpoints.test.ts | 4 +- .../contrib/debug/test/browser/mockDebug.ts | 4 + 11 files changed, 179 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 22dcf505982..c57458f49a5 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -94,6 +94,7 @@ export class BreakpointsView extends ViewPane { this.list = >this.instantiationService.createInstance(WorkbenchList, 'Breakpoints', container, delegate, [ this.instantiationService.createInstance(BreakpointsRenderer), new ExceptionBreakpointsRenderer(this.debugService), + new ExceptionBreakpointInputRenderer(this.debugService, this.contextViewService, this.themeService), this.instantiationService.createInstance(FunctionBreakpointsRenderer), this.instantiationService.createInstance(DataBreakpointsRenderer), new FunctionBreakpointInputRenderer(this.debugService, this.contextViewService, this.themeService, this.labelService) @@ -136,9 +137,9 @@ export class BreakpointsView extends ViewPane { if (element instanceof Breakpoint) { openBreakpointSource(element, e.sideBySide, e.editorOptions.preserveFocus || false, e.editorOptions.pinned || !e.editorOptions.preserveFocus, this.debugService, this.editorService); } - if (e.browserEvent instanceof MouseEvent && e.browserEvent.detail === 2 && element instanceof FunctionBreakpoint && element !== this.debugService.getViewModel().getSelectedFunctionBreakpoint()) { + if (e.browserEvent instanceof MouseEvent && e.browserEvent.detail === 2 && element instanceof FunctionBreakpoint && element !== this.debugService.getViewModel().getSelectedBreakpoint()) { // double click - this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); + this.debugService.getViewModel().setSelectedBreakpoint(element); this.onBreakpointsChange(); } })); @@ -201,12 +202,19 @@ export class BreakpointsView extends ViewPane { } } } else { - this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); + this.debugService.getViewModel().setSelectedBreakpoint(element); this.onBreakpointsChange(); } })); actions.push(new Separator()); } + if (element instanceof ExceptionBreakpoint && element.supportsCondition) { + actions.push(new Action('workbench.action.debug.editExceptionBreakpointCondition', nls.localize('editCondition', "Edit Condition..."), '', true, async () => { + this.debugService.getViewModel().setSelectedBreakpoint(element); + this.onBreakpointsChange(); + })); + actions.push(new Separator()); + } actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService)); @@ -286,7 +294,7 @@ class BreakpointsDelegate implements IListVirtualDelegate { return BreakpointsRenderer.ID; } if (element instanceof FunctionBreakpoint) { - const selected = this.debugService.getViewModel().getSelectedFunctionBreakpoint(); + const selected = this.debugService.getViewModel().getSelectedBreakpoint(); if (!element.name || (selected && selected.getId() === element.getId())) { return FunctionBreakpointInputRenderer.ID; } @@ -294,6 +302,10 @@ class BreakpointsDelegate implements IListVirtualDelegate { return FunctionBreakpointsRenderer.ID; } if (element instanceof ExceptionBreakpoint) { + const selected = this.debugService.getViewModel().getSelectedBreakpoint(); + if (selected && selected.getId() === element.getId()) { + return ExceptionBreakpointInputRenderer.ID; + } return ExceptionBreakpointsRenderer.ID; } if (element instanceof DataBreakpoint) { @@ -321,7 +333,11 @@ interface IBreakpointTemplateData extends IBaseBreakpointWithIconTemplateData { filePath: HTMLElement; } -interface IInputTemplateData { +interface IExceptionBreakpointTemplateData extends IBaseBreakpointTemplateData { + condition: HTMLElement; +} + +interface IFunctionBreakpointInputTemplateData { inputBox: InputBox; checkbox: HTMLInputElement; icon: HTMLElement; @@ -330,6 +346,14 @@ interface IInputTemplateData { toDispose: IDisposable[]; } +interface IExceptionBreakpointInputTemplateData { + inputBox: InputBox; + checkbox: HTMLInputElement; + breakpoint: IExceptionBreakpoint; + reactedOnEvent: boolean; + toDispose: IDisposable[]; +} + class BreakpointsRenderer implements IListRenderer { constructor( @@ -395,7 +419,7 @@ class BreakpointsRenderer implements IListRenderer { +class ExceptionBreakpointsRenderer implements IListRenderer { constructor( private debugService: IDebugService @@ -409,8 +433,8 @@ class ExceptionBreakpointsRenderer implements IListRenderer { +class FunctionBreakpointInputRenderer implements IListRenderer { constructor( private debugService: IDebugService, @@ -568,8 +595,8 @@ class FunctionBreakpointInputRenderer implements IListRenderer { if (!template.reactedOnEvent) { template.reactedOnEvent = true; - this.debugService.getViewModel().setSelectedFunctionBreakpoint(undefined); + this.debugService.getViewModel().setSelectedBreakpoint(undefined); if (inputBox.value && (renamed || template.breakpoint.name)) { this.debugService.renameFunctionBreakpoint(template.breakpoint.getId(), renamed ? inputBox.value : template.breakpoint.name); } else { @@ -620,7 +647,7 @@ class FunctionBreakpointInputRenderer implements IListRenderer { + + constructor( + private debugService: IDebugService, + private contextViewService: IContextViewService, + private themeService: IThemeService + ) { + // noop + } + + static readonly ID = 'exceptionbreakpointinput'; + + get templateId() { + return ExceptionBreakpointInputRenderer.ID; + } + + renderTemplate(container: HTMLElement): IExceptionBreakpointInputTemplateData { + const template: IExceptionBreakpointInputTemplateData = Object.create(null); + + const breakpoint = dom.append(container, $('.breakpoint')); + breakpoint.classList.add('exception'); + template.checkbox = createCheckbox(); + + dom.append(breakpoint, template.checkbox); + const inputBoxContainer = dom.append(breakpoint, $('.inputBoxContainer')); + const inputBox = new InputBox(inputBoxContainer, this.contextViewService, { + placeholder: nls.localize('exceptionBreakpointPlaceholder', "Break when expression evaluates to true"), + ariaLabel: nls.localize('exceptionBreakpointAriaLabel', "Type exception breakpoint condition") + }); + const styler = attachInputBoxStyler(inputBox, this.themeService); + const toDispose: IDisposable[] = [inputBox, styler]; + + const wrapUp = (success: boolean) => { + if (!template.reactedOnEvent) { + template.reactedOnEvent = true; + this.debugService.getViewModel().setSelectedBreakpoint(undefined); + let newCondition = template.breakpoint.condition; + if (success) { + newCondition = inputBox.value !== '' ? inputBox.value : undefined; + } + this.debugService.setExceptionBreakpointCondition(template.breakpoint, newCondition); + } + }; + + toDispose.push(dom.addStandardDisposableListener(inputBox.inputElement, 'keydown', (e: IKeyboardEvent) => { + const isEscape = e.equals(KeyCode.Escape); + const isEnter = e.equals(KeyCode.Enter); + if (isEscape || isEnter) { + e.preventDefault(); + e.stopPropagation(); + wrapUp(isEnter); + } + })); + toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => { + // Need to react with a timeout on the blur event due to possible concurent splices #56443 + setTimeout(() => { + wrapUp(true); + }); + })); + + template.inputBox = inputBox; + template.toDispose = toDispose; + return template; + } + + renderElement(exceptionBreakpoint: ExceptionBreakpoint, _index: number, data: IExceptionBreakpointInputTemplateData): void { + data.breakpoint = exceptionBreakpoint; + data.reactedOnEvent = false; + data.checkbox.checked = exceptionBreakpoint.enabled; + data.checkbox.disabled = true; + data.inputBox.value = exceptionBreakpoint.condition || ''; + setTimeout(() => { + data.inputBox.focus(); + data.inputBox.select(); + }, 0); + } + + disposeTemplate(templateData: IExceptionBreakpointInputTemplateData): void { dispose(templateData.toDispose); } } @@ -763,7 +872,7 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: messages.push(nls.localize('logMessage', "Log Message: {0}", breakpoint.logMessage)); } if (breakpoint.condition) { - messages.push(nls.localize('expression', "Expression: {0}", breakpoint.condition)); + messages.push(nls.localize('expression', "Expression condition: {0}", breakpoint.condition)); } if (breakpoint.hitCondition) { messages.push(nls.localize('hitCount', "Hit Count: {0}", breakpoint.hitCondition)); diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 9fae429ed01..3c94721040d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -322,7 +322,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { } protected isEnabled(_: State): boolean { - return !this.debugService.getViewModel().getSelectedFunctionBreakpoint() + return !this.debugService.getViewModel().getSelectedBreakpoint() && this.debugService.getModel().getFunctionBreakpoints().every(fbp => !!fbp.name); } } diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 4e99febee24..e05a471f57b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -32,7 +32,7 @@ import { IAction, Action } from 'vs/base/common/actions'; import { deepClone, equals } from 'vs/base/common/objects'; import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IStackFrame, getStateLabel, IDebugSessionOptions, CONTEXT_DEBUG_UX, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, IGlobalConfig, CALLSTACK_VIEW_ID, IAdapterManager } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IStackFrame, getStateLabel, IDebugSessionOptions, CONTEXT_DEBUG_UX, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, IGlobalConfig, CALLSTACK_VIEW_ID, IAdapterManager, IExceptionBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { getExtensionHostDebugSession } from 'vs/workbench/contrib/debug/common/debugUtils'; import { isErrorWithActions } from 'vs/base/common/errorsWithActions'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -918,7 +918,7 @@ export class DebugService implements IDebugService { addFunctionBreakpoint(name?: string, id?: string): void { const newFunctionBreakpoint = this.model.addFunctionBreakpoint(name || '', id); - this.viewModel.setSelectedFunctionBreakpoint(newFunctionBreakpoint); + this.viewModel.setSelectedBreakpoint(newFunctionBreakpoint); } async renameFunctionBreakpoint(id: string, newFunctionName: string): Promise { @@ -946,6 +946,12 @@ export class DebugService implements IDebugService { await this.sendDataBreakpoints(); } + async setExceptionBreakpointCondition(exceptionBreakpoint: IExceptionBreakpoint, condition: string | undefined): Promise { + this.model.setExceptionBreakpointCondition(exceptionBreakpoint, condition); + this.debugStorage.storeBreakpoints(this.model); + await this.sendExceptionBreakpoints(); + } + async sendAllBreakpoints(session?: IDebugSession): Promise { await Promise.all(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session))); await this.sendFunctionBreakpoints(session); diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 663ff7109de..9b8c75afab8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -394,7 +394,18 @@ export class DebugSession implements IDebugSession { } if (this.raw.readyForBreakpoints) { - await this.raw.setExceptionBreakpoints({ filters: exbpts.map(exb => exb.filter) }); + const args: DebugProtocol.SetExceptionBreakpointsArguments = this.capabilities.supportsExceptionFilterOptions ? { + filters: [], + filterOptions: exbpts.map(exb => { + if (exb.condition) { + return { filterId: exb.filter, condition: exb.condition }; + } + + return { filterId: exb.filter }; + }) + } : { filters: exbpts.map(exb => exb.filter) }; + + await this.raw.setExceptionBreakpoints(args); } } diff --git a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css index 853b3adae48..47cafc6aec9 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css @@ -318,10 +318,10 @@ justify-content: center; } -.debug-pane .debug-breakpoints .breakpoint > .file-path { +.debug-pane .debug-breakpoints .breakpoint > .file-path, +.debug-pane .debug-breakpoints .breakpoint.exception > .condition { opacity: 0.7; - font-size: 0.9em; - margin-left: 0.8em; + margin-left: 0.9em; flex: 1; text-overflow: ellipsis; overflow: hidden; diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 14a4b09ce7b..253547f14a5 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -402,6 +402,7 @@ export interface IFunctionBreakpoint extends IBaseBreakpoint { export interface IExceptionBreakpoint extends IEnablement { readonly filter: string; readonly label: string; + readonly condition: string | undefined; } export interface IDataBreakpoint extends IBaseBreakpoint { @@ -436,9 +437,9 @@ export interface IViewModel extends ITreeElement { readonly focusedStackFrame: IStackFrame | undefined; getSelectedExpression(): IExpression | undefined; - getSelectedFunctionBreakpoint(): IFunctionBreakpoint | undefined; + getSelectedBreakpoint(): IFunctionBreakpoint | IExceptionBreakpoint | undefined; setSelectedExpression(expression: IExpression | undefined): void; - setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint | undefined): void; + setSelectedBreakpoint(functionBreakpoint: IFunctionBreakpoint | IExceptionBreakpoint | undefined): void; updateViews(): void; isMultiSessionView(): boolean; @@ -865,6 +866,8 @@ export interface IDebugService { */ removeDataBreakpoints(id?: string): Promise; + setExceptionBreakpointCondition(breakpoint: IExceptionBreakpoint, condition: string | undefined): Promise; + /** * Sends all breakpoints to the passed session. * If session is not passed, sends all breakpoints to each session. diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 499029c2a66..fe52108c95c 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -858,7 +858,7 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint { export class ExceptionBreakpoint extends Enablement implements IExceptionBreakpoint { - constructor(public filter: string, public label: string, enabled: boolean) { + constructor(public filter: string, public label: string, enabled: boolean, public supportsCondition: boolean, public condition: string | undefined) { super(enabled, generateUuid()); } @@ -867,6 +867,8 @@ export class ExceptionBreakpoint extends Enablement implements IExceptionBreakpo result.filter = this.filter; result.label = this.label; result.enabled = this.enabled; + result.supportsCondition = this.supportsCondition; + result.condition = this.condition; return result; } @@ -1060,19 +1062,24 @@ export class DebugModel implements IDebugModel { setExceptionBreakpoints(data: DebugProtocol.ExceptionBreakpointsFilter[]): void { if (data) { - if (this.exceptionBreakpoints.length === data.length && this.exceptionBreakpoints.every((exbp, i) => exbp.filter === data[i].filter && exbp.label === data[i].label)) { + if (this.exceptionBreakpoints.length === data.length && this.exceptionBreakpoints.every((exbp, i) => exbp.filter === data[i].filter && exbp.label === data[i].label && exbp.supportsCondition === data[i].supportsCondition)) { // No change return; } this.exceptionBreakpoints = data.map(d => { const ebp = this.exceptionBreakpoints.filter(ebp => ebp.filter === d.filter).pop(); - return new ExceptionBreakpoint(d.filter, d.label, ebp ? ebp.enabled : !!d.default); + return new ExceptionBreakpoint(d.filter, d.label, ebp ? ebp.enabled : !!d.default, !!d.supportsCondition, ebp?.condition); }); this._onDidChangeBreakpoints.fire(undefined); } } + setExceptionBreakpointCondition(exceptionBreakpoint: IExceptionBreakpoint, condition: string | undefined): void { + (exceptionBreakpoint as ExceptionBreakpoint).condition = condition; + this._onDidChangeBreakpoints.fire(undefined); + } + areBreakpointsActivated(): boolean { return this.breakpointsActivated; } diff --git a/src/vs/workbench/contrib/debug/common/debugStorage.ts b/src/vs/workbench/contrib/debug/common/debugStorage.ts index 0789f259385..42583a6169c 100644 --- a/src/vs/workbench/contrib/debug/common/debugStorage.ts +++ b/src/vs/workbench/contrib/debug/common/debugStorage.ts @@ -49,7 +49,7 @@ export class DebugStorage { let result: ExceptionBreakpoint[] | undefined; try { result = JSON.parse(this.storageService.get(DEBUG_EXCEPTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((exBreakpoint: any) => { - return new ExceptionBreakpoint(exBreakpoint.filter, exBreakpoint.label, exBreakpoint.enabled); + return new ExceptionBreakpoint(exBreakpoint.filter, exBreakpoint.label, exBreakpoint.enabled, exBreakpoint.supportsCondition, exBreakpoint.condition); }); } catch (e) { } diff --git a/src/vs/workbench/contrib/debug/common/debugViewModel.ts b/src/vs/workbench/contrib/debug/common/debugViewModel.ts index 7a4b1fbaca3..e7541cd89e7 100644 --- a/src/vs/workbench/contrib/debug/common/debugViewModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugViewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug'; +import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, IExceptionBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; @@ -16,7 +16,7 @@ export class ViewModel implements IViewModel { private _focusedSession: IDebugSession | undefined; private _focusedThread: IThread | undefined; private selectedExpression: IExpression | undefined; - private selectedFunctionBreakpoint: IFunctionBreakpoint | undefined; + private selectedBreakpoint: IFunctionBreakpoint | IExceptionBreakpoint | undefined; private readonly _onDidFocusSession = new Emitter(); private readonly _onDidFocusStackFrame = new Emitter<{ stackFrame: IStackFrame | undefined, explicit: boolean }>(); private readonly _onDidSelectExpression = new Emitter(); @@ -112,8 +112,8 @@ export class ViewModel implements IViewModel { return this._onDidSelectExpression.event; } - getSelectedFunctionBreakpoint(): IFunctionBreakpoint | undefined { - return this.selectedFunctionBreakpoint; + getSelectedBreakpoint(): IFunctionBreakpoint | IExceptionBreakpoint | undefined { + return this.selectedBreakpoint; } updateViews(): void { @@ -124,9 +124,9 @@ export class ViewModel implements IViewModel { return this._onWillUpdateViews.event; } - setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint | undefined): void { - this.selectedFunctionBreakpoint = functionBreakpoint; - this.breakpointSelectedContextKey.set(!!functionBreakpoint); + setSelectedBreakpoint(breakpoint: IFunctionBreakpoint | IExceptionBreakpoint | undefined): void { + this.selectedBreakpoint = breakpoint; + this.breakpointSelectedContextKey.set(!!breakpoint); } isMultiSessionView(): boolean { diff --git a/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts b/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts index 675fc6aa136..1a2bed97418 100644 --- a/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts @@ -259,7 +259,7 @@ suite('Debug - Breakpoints', () => { const breakpoints = model.getBreakpoints(); let result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[0]); - assert.equal(result.message, 'Expression: x > 5'); + assert.equal(result.message, 'Expression condition: x > 5'); assert.equal(result.icon.id, 'debug-breakpoint-conditional'); result = getBreakpointMessageAndIcon(State.Stopped, true, breakpoints[1]); @@ -337,7 +337,7 @@ suite('Debug - Breakpoints', () => { assert.equal(decorations[0].options.beforeContentClassName, undefined); assert.equal(decorations[1].options.beforeContentClassName, `debug-breakpoint-placeholder`); assert.equal(decorations[0].options.overviewRuler?.position, OverviewRulerLane.Left); - const expected = new MarkdownString().appendCodeblock(languageIdentifier.language, 'Expression: x > 5'); + const expected = new MarkdownString().appendCodeblock(languageIdentifier.language, 'Expression condition: x > 5'); assert.deepEqual(decorations[0].options.glyphMarginHoverMessage, expected); decorations = createBreakpointDecorations(textModel, breakpoints, State.Running, true, false); diff --git a/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts b/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts index cc78ff0038f..96a346ab9c8 100644 --- a/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/browser/mockDebug.ts @@ -86,6 +86,10 @@ export class MockDebugService implements IDebugService { throw new Error('not implemented'); } + setExceptionBreakpointCondition(breakpoint: IExceptionBreakpoint, condition: string): Promise { + throw new Error('Method not implemented.'); + } + public addFunctionBreakpoint(): void { } public moveWatchExpression(id: string, position: number): void { } From f13720627f4720528d7642775c0f6e272ef637f1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 16:20:18 +0100 Subject: [PATCH 0399/1837] Improve task dependency cycle check Fixes #111369 --- .../tasks/browser/terminalTaskSystem.ts | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 15f0a23d5a1..b011e99c726 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -174,7 +174,6 @@ export class TerminalTaskSystem implements ITaskSystem { }; private activeTasks: IStringDictionary; - private dependencyCycleCheck: Set; private instances: IStringDictionary; private busyTasks: IStringDictionary; private terminals: IStringDictionary; @@ -211,7 +210,6 @@ export class TerminalTaskSystem implements ITaskSystem { ) { this.activeTasks = Object.create(null); - this.dependencyCycleCheck = new Set(); this.instances = Object.create(null); this.busyTasks = Object.create(null); this.terminals = Object.create(null); @@ -251,7 +249,7 @@ export class TerminalTaskSystem implements ITaskSystem { } try { - const executeResult = { kind: TaskExecuteKind.Started, task, started: {}, promise: this.executeTask(task, resolver, trigger) }; + const executeResult = { kind: TaskExecuteKind.Started, task, started: {}, promise: this.executeTask(task, resolver, trigger, new Set()) }; executeResult.promise.then(summary => { this.lastTask = this.currentTask; }); @@ -439,28 +437,18 @@ export class TerminalTaskSystem implements ITaskSystem { return Promise.all(promises); } - private hasDependencyCycle(task: Task): boolean { - const key = task.getCommonTaskId(); - if (this.dependencyCycleCheck.has(key)) { - this.showDependencyCycleMessage(task); - return true; - } else { - this.dependencyCycleCheck.add(key); - return false; - } - } private showDependencyCycleMessage(task: Task) { this.log(nls.localize('dependencyCycle', - 'There is a dependency cycle. See task {0}.', + 'There is a dependency cycle. See task "{0}".', task._label )); this.showOutput(); } - private async executeTask(task: Task, resolver: ITaskResolver, trigger: string, alreadyResolved?: Map): Promise { - if (this.hasDependencyCycle(task)) { - this.dependencyCycleCheck.delete(task.getCommonTaskId()); + private async executeTask(task: Task, resolver: ITaskResolver, trigger: string, encounteredDependencies: Set, alreadyResolved?: Map): Promise { + if (encounteredDependencies.has(task.getCommonTaskId())) { + this.showDependencyCycleMessage(task); return {}; } @@ -474,7 +462,8 @@ export class TerminalTaskSystem implements ITaskSystem { let promise = this.activeTasks[key] ? this.activeTasks[key].promise : undefined; if (!promise) { this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.DependsOnStarted, task)); - promise = this.executeDependencyTask(dependencyTask, resolver, trigger, alreadyResolved); + encounteredDependencies.add(task.getCommonTaskId()); + promise = this.executeDependencyTask(dependencyTask, resolver, trigger, encounteredDependencies, alreadyResolved); } promises.push(promise); if (task.configurationProperties.dependsOrder === DependsOrder.sequence) { @@ -500,13 +489,13 @@ export class TerminalTaskSystem implements ITaskSystem { if ((ContributedTask.is(task) || CustomTask.is(task)) && (task.command)) { return Promise.all(promises).then((summaries): Promise | ITaskSummary => { + encounteredDependencies.delete(task.getCommonTaskId()); for (let summary of summaries) { if (summary.exitCode !== 0) { this.removeInstances(task); return { exitCode: summary.exitCode }; } } - this.dependencyCycleCheck.delete(task.getCommonTaskId()); if (this.isRerun) { return this.reexecuteCommand(task, trigger, alreadyResolved!); } else { @@ -514,8 +503,8 @@ export class TerminalTaskSystem implements ITaskSystem { } }); } else { - this.dependencyCycleCheck.delete(task.getCommonTaskId()); return Promise.all(promises).then((summaries): ITaskSummary => { + encounteredDependencies.delete(task.getCommonTaskId()); for (let summary of summaries) { if (summary.exitCode !== 0) { return { exitCode: summary.exitCode }; @@ -526,11 +515,11 @@ export class TerminalTaskSystem implements ITaskSystem { } } - private async executeDependencyTask(task: Task, resolver: ITaskResolver, trigger: string, alreadyResolved?: Map): Promise { + private async executeDependencyTask(task: Task, resolver: ITaskResolver, trigger: string, encounteredDependencies: Set, alreadyResolved?: Map): Promise { // If the task is a background task with a watching problem matcher, we don't wait for the whole task to finish, // just for the problem matcher to go inactive. if (!task.configurationProperties.isBackground) { - return this.executeTask(task, resolver, trigger, alreadyResolved); + return this.executeTask(task, resolver, trigger, encounteredDependencies, alreadyResolved); } const inactivePromise = new Promise(resolve => { @@ -541,7 +530,7 @@ export class TerminalTaskSystem implements ITaskSystem { } }); }); - return Promise.race([inactivePromise, this.executeTask(task, resolver, trigger, alreadyResolved)]); + return Promise.race([inactivePromise, this.executeTask(task, resolver, trigger, encounteredDependencies, alreadyResolved)]); } private async resolveAndFindExecutable(systemInfo: TaskSystemInfo | undefined, workspaceFolder: IWorkspaceFolder | undefined, task: CustomTask | ContributedTask, cwd: string | undefined, envPath: string | undefined): Promise { From 627ad0b4ee553d233b80336ebb241f911e4bff07 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 16:31:44 +0100 Subject: [PATCH 0400/1837] rename OnTypeRename -> LinkedEditing (for #109923) --- .../client/src/htmlClient.ts | 18 +- .../html-language-features/package.nls.json | 2 +- .../server/src/htmlServer.ts | 10 +- .../server/src/modes/htmlMode.ts | 2 +- .../server/src/modes/languageModes.ts | 2 +- src/vs/editor/common/config/editorOptions.ts | 13 +- src/vs/editor/common/modes.ts | 20 +-- .../common/standalone/standaloneEnums.ts | 133 +++++++------- .../linkedEditing.ts} | 70 ++++---- .../test/linkedEditing.test..ts} | 32 ++-- src/vs/editor/editor.all.ts | 2 +- .../standalone/browser/standaloneLanguages.ts | 8 +- src/vs/monaco.d.ts | 162 +++++++++--------- src/vs/vscode.proposed.d.ts | 31 ++-- .../api/browser/mainThreadLanguageFeatures.ts | 10 +- .../workbench/api/common/extHost.api.impl.ts | 8 +- .../workbench/api/common/extHost.protocol.ts | 6 +- .../api/common/extHostLanguageFeatures.ts | 24 +-- src/vs/workbench/api/common/extHostTypes.ts | 2 +- 19 files changed, 286 insertions(+), 269 deletions(-) rename src/vs/editor/contrib/{rename/onTypeRename.ts => linkedEditing/linkedEditing.ts} (82%) rename src/vs/editor/contrib/{rename/test/onTypeRename.test.ts => linkedEditing/test/linkedEditing.test..ts} (93%) diff --git a/extensions/html-language-features/client/src/htmlClient.ts b/extensions/html-language-features/client/src/htmlClient.ts index b537efd4ecc..494b935a7ca 100644 --- a/extensions/html-language-features/client/src/htmlClient.ts +++ b/extensions/html-language-features/client/src/htmlClient.ts @@ -27,8 +27,8 @@ namespace CustomDataChangedNotification { namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); } -namespace OnTypeRenameRequest { - export const type: RequestType = new RequestType('html/onTypeRename'); +namespace LinkedEditingRequest { + export const type: RequestType = new RequestType('html/linkedEditing'); } // experimental: semantic tokens @@ -44,7 +44,7 @@ namespace SemanticTokenLegendRequest { } namespace SettingIds { - export const renameOnType = 'editor.renameOnType'; + export const linkedRename = 'editor.linkedRename'; export const formatEnable = 'html.format.enable'; } @@ -169,10 +169,10 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua } }); - disposable = languages.registerOnTypeRenameRangeProvider(documentSelector, { - async provideOnTypeRenameRanges(document, position) { + disposable = languages.registerLinkedEditingRangeProvider(documentSelector, { + async provideLinkedEditingRanges(document, position) { const param = client.code2ProtocolConverter.asTextDocumentPositionParams(document, position); - return client.sendRequest(OnTypeRenameRequest.type, param).then(response => { + return client.sendRequest(LinkedEditingRequest.type, param).then(response => { if (response) { return { ranges: response.map(r => client.protocol2CodeConverter.asRange(r)) @@ -301,7 +301,7 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua const promptForTypeOnRenameKey = 'html.promptForTypeOnRename'; const promptForTypeOnRename = extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForTypeOnRenameKey) !== false) && - !workspace.getConfiguration('editor', { languageId: 'html' }).get('renameOnType'); + !workspace.getConfiguration('editor', { languageId: 'html' }).get('linkedRename'); if (promptForTypeOnRename) { const activeEditorListener = window.onDidChangeActiveTextEditor(async e => { @@ -309,9 +309,9 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua context.globalState.update(promptForTypeOnRenameKey, false); activeEditorListener.dispose(); const configure = localize('configureButton', 'Configure'); - const res = await window.showInformationMessage(localize('renameOnTypeQuestion', 'VS Code now has built-in support for auto-renaming tags. Do you want to enable it?'), configure); + const res = await window.showInformationMessage(localize('linkedRenameQuestion', 'VS Code now has built-in support for auto-renaming tags. Do you want to enable it?'), configure); if (res === configure) { - commands.executeCommand('workbench.action.openSettings', SettingIds.renameOnType); + commands.executeCommand('workbench.action.openSettings', SettingIds.linkedRename); } } }); diff --git a/extensions/html-language-features/package.nls.json b/extensions/html-language-features/package.nls.json index 986a379166c..ddcb5f75048 100644 --- a/extensions/html-language-features/package.nls.json +++ b/extensions/html-language-features/package.nls.json @@ -29,5 +29,5 @@ "html.validate.styles": "Controls whether the built-in HTML language support validates embedded styles.", "html.autoClosingTags": "Enable/disable autoclosing of HTML tags.", "html.mirrorCursorOnMatchingTag": "Enable/disable mirroring cursor on matching HTML tag.", - "html.mirrorCursorOnMatchingTagDeprecationMessage": "Deprecated in favor of `editor.renameOnType`" + "html.mirrorCursorOnMatchingTagDeprecationMessage": "Deprecated in favor of `editor.linkedEditing`" } diff --git a/extensions/html-language-features/server/src/htmlServer.ts b/extensions/html-language-features/server/src/htmlServer.ts index 1ddfef6ce34..7a900fff4f2 100644 --- a/extensions/html-language-features/server/src/htmlServer.ts +++ b/extensions/html-language-features/server/src/htmlServer.ts @@ -33,8 +33,8 @@ namespace CustomDataChangedNotification { namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); } -namespace OnTypeRenameRequest { - export const type: RequestType = new RequestType('html/onTypeRename'); +namespace LinkedEditingRequest { + export const type: RequestType = new RequestType('html/linkedEditing'); } // experimental: semantic tokens @@ -508,15 +508,15 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) }, null, `Error while computing rename for ${params.textDocument.uri}`, token); }); - connection.onRequest(OnTypeRenameRequest.type, (params, token) => { + connection.onRequest(LinkedEditingRequest.type, (params, token) => { return runSafe(async () => { const document = documents.get(params.textDocument.uri); if (document) { const pos = params.position; if (pos.character > 0) { const mode = languageModes.getModeAtPosition(document, Position.create(pos.line, pos.character - 1)); - if (mode && mode.doOnTypeRename) { - return mode.doOnTypeRename(document, pos); + if (mode && mode.doLinkedEditing) { + return mode.doLinkedEditing(document, pos); } } } diff --git a/extensions/html-language-features/server/src/modes/htmlMode.ts b/extensions/html-language-features/server/src/modes/htmlMode.ts index 96462f8e011..7723717f763 100644 --- a/extensions/html-language-features/server/src/modes/htmlMode.ts +++ b/extensions/html-language-features/server/src/modes/htmlMode.ts @@ -80,7 +80,7 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace: const htmlDocument = htmlDocuments.get(document); return htmlLanguageService.findMatchingTagPosition(document, position, htmlDocument); }, - async doOnTypeRename(document: TextDocument, position: Position) { + async doLinkedEditing(document: TextDocument, position: Position) { const htmlDocument = htmlDocuments.get(document); return htmlLanguageService.findOnTypeRenameRanges(document, position, htmlDocument); }, diff --git a/extensions/html-language-features/server/src/modes/languageModes.ts b/extensions/html-language-features/server/src/modes/languageModes.ts index e47df5a797b..3a926197eaa 100644 --- a/extensions/html-language-features/server/src/modes/languageModes.ts +++ b/extensions/html-language-features/server/src/modes/languageModes.ts @@ -48,7 +48,7 @@ export interface LanguageMode { doHover?: (document: TextDocument, position: Position) => Promise; doSignatureHelp?: (document: TextDocument, position: Position) => Promise; doRename?: (document: TextDocument, position: Position, newName: string) => Promise; - doOnTypeRename?: (document: TextDocument, position: Position) => Promise; + doLinkedEditing?: (document: TextDocument, position: Position) => Promise; findDocumentHighlight?: (document: TextDocument, position: Position) => Promise; findDocumentSymbols?: (document: TextDocument) => Promise; findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext) => Promise; diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index d314ae046a3..04eb4d3bc40 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -144,9 +144,13 @@ export interface IEditorOptions { */ readOnly?: boolean; /** - * Rename matching regions on type. + * Enable linked editing. * Defaults to false. */ + linkedEditing?: boolean; + /** + * deprecated, use linkedEditing instead + */ renameOnType?: boolean; /** * Should the editor render validation decorations. @@ -3682,6 +3686,7 @@ export const enum EditorOption { lineHeight, lineNumbers, lineNumbersMinChars, + linkedEditing, links, matchBrackets, minimap, @@ -4033,6 +4038,10 @@ export const EditorOptions = { EditorOption.lineNumbersMinChars, 'lineNumbersMinChars', 5, 1, 300 )), + linkedEditing: register(new EditorBooleanOption( + EditorOption.linkedEditing, 'linkedEditing', false, + { description: nls.localize('linkedEditing', "Controls whether the editor has linked editing enabled. Depending on the language, related symbols, e.g. HTML tags, are updated while editing.") } + )), links: register(new EditorBooleanOption( EditorOption.links, 'links', true, { description: nls.localize('links', "Controls whether the editor should detect links and make them clickable.") } @@ -4134,7 +4143,7 @@ export const EditorOptions = { )), renameOnType: register(new EditorBooleanOption( EditorOption.renameOnType, 'renameOnType', false, - { description: nls.localize('renameOnType', "Controls whether the editor auto renames on type.") } + { description: nls.localize('renameOnType', "Controls whether the editor auto renames on type."), markdownDeprecationMessage: nls.localize('renameOnTypeDeprecate', "Deprecated, use `editor.linkedEditing` instead.") } )), renderControlCharacters: register(new EditorBooleanOption( EditorOption.renderControlCharacters, 'renderControlCharacters', false, diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index d5e6aa10124..fe0d7335d09 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -819,24 +819,24 @@ export interface DocumentHighlightProvider { } /** - * The rename range provider interface defines the contract between extensions and - * the live-rename feature. + * The linked editing range provider interface defines the contract between extensions and + * the linked editing feature. */ -export interface OnTypeRenameRangeProvider { +export interface LinkedEditingRangeProvider { /** - * Provide a list of ranges that can be live-renamed together. + * Provide a list of ranges that can be edited together. */ - provideOnTypeRenameRanges(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult; + provideLinkedEditingRanges(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult; } /** - * Represents a list of ranges that can be renamed together along with a word pattern to describe valid range contents. + * Represents a list of ranges that can be edited together along with a word pattern to describe valid contents. */ -export interface OnTypeRenameRanges { +export interface LinkedEditingRanges { /** - * A list of ranges that can be renamed together. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap + * A list of ranges that can be edited together. The ranges must have + * identical length and text content. The ranges cannot overlap */ ranges: IRange[]; @@ -1737,7 +1737,7 @@ export const DocumentHighlightProviderRegistry = new LanguageFeatureRegistry(); +export const LinkedEditingRangeProviderRegistry = new LanguageFeatureRegistry(); /** * @internal diff --git a/src/vs/editor/common/standalone/standaloneEnums.ts b/src/vs/editor/common/standalone/standaloneEnums.ts index 7558e45806a..258074c44f2 100644 --- a/src/vs/editor/common/standalone/standaloneEnums.ts +++ b/src/vs/editor/common/standalone/standaloneEnums.ts @@ -224,72 +224,73 @@ export enum EditorOption { lineHeight = 54, lineNumbers = 55, lineNumbersMinChars = 56, - links = 57, - matchBrackets = 58, - minimap = 59, - mouseStyle = 60, - mouseWheelScrollSensitivity = 61, - mouseWheelZoom = 62, - multiCursorMergeOverlapping = 63, - multiCursorModifier = 64, - multiCursorPaste = 65, - occurrencesHighlight = 66, - overviewRulerBorder = 67, - overviewRulerLanes = 68, - padding = 69, - parameterHints = 70, - peekWidgetDefaultFocus = 71, - definitionLinkOpensInPeek = 72, - quickSuggestions = 73, - quickSuggestionsDelay = 74, - readOnly = 75, - renameOnType = 76, - renderControlCharacters = 77, - renderIndentGuides = 78, - renderFinalNewline = 79, - renderLineHighlight = 80, - renderLineHighlightOnlyWhenFocus = 81, - renderValidationDecorations = 82, - renderWhitespace = 83, - revealHorizontalRightPadding = 84, - roundedSelection = 85, - rulers = 86, - scrollbar = 87, - scrollBeyondLastColumn = 88, - scrollBeyondLastLine = 89, - scrollPredominantAxis = 90, - selectionClipboard = 91, - selectionHighlight = 92, - selectOnLineNumbers = 93, - showFoldingControls = 94, - showUnused = 95, - snippetSuggestions = 96, - smartSelect = 97, - smoothScrolling = 98, - stopRenderingLineAfter = 99, - suggest = 100, - suggestFontSize = 101, - suggestLineHeight = 102, - suggestOnTriggerCharacters = 103, - suggestSelection = 104, - tabCompletion = 105, - tabIndex = 106, - unusualLineTerminators = 107, - useTabStops = 108, - wordSeparators = 109, - wordWrap = 110, - wordWrapBreakAfterCharacters = 111, - wordWrapBreakBeforeCharacters = 112, - wordWrapColumn = 113, - wordWrapMinified = 114, - wrappingIndent = 115, - wrappingStrategy = 116, - showDeprecated = 117, - editorClassName = 118, - pixelRatio = 119, - tabFocusMode = 120, - layoutInfo = 121, - wrappingInfo = 122 + linkedEditing = 57, + links = 58, + matchBrackets = 59, + minimap = 60, + mouseStyle = 61, + mouseWheelScrollSensitivity = 62, + mouseWheelZoom = 63, + multiCursorMergeOverlapping = 64, + multiCursorModifier = 65, + multiCursorPaste = 66, + occurrencesHighlight = 67, + overviewRulerBorder = 68, + overviewRulerLanes = 69, + padding = 70, + parameterHints = 71, + peekWidgetDefaultFocus = 72, + definitionLinkOpensInPeek = 73, + quickSuggestions = 74, + quickSuggestionsDelay = 75, + readOnly = 76, + renameOnType = 77, + renderControlCharacters = 78, + renderIndentGuides = 79, + renderFinalNewline = 80, + renderLineHighlight = 81, + renderLineHighlightOnlyWhenFocus = 82, + renderValidationDecorations = 83, + renderWhitespace = 84, + revealHorizontalRightPadding = 85, + roundedSelection = 86, + rulers = 87, + scrollbar = 88, + scrollBeyondLastColumn = 89, + scrollBeyondLastLine = 90, + scrollPredominantAxis = 91, + selectionClipboard = 92, + selectionHighlight = 93, + selectOnLineNumbers = 94, + showFoldingControls = 95, + showUnused = 96, + snippetSuggestions = 97, + smartSelect = 98, + smoothScrolling = 99, + stopRenderingLineAfter = 100, + suggest = 101, + suggestFontSize = 102, + suggestLineHeight = 103, + suggestOnTriggerCharacters = 104, + suggestSelection = 105, + tabCompletion = 106, + tabIndex = 107, + unusualLineTerminators = 108, + useTabStops = 109, + wordSeparators = 110, + wordWrap = 111, + wordWrapBreakAfterCharacters = 112, + wordWrapBreakBeforeCharacters = 113, + wordWrapColumn = 114, + wordWrapMinified = 115, + wrappingIndent = 116, + wrappingStrategy = 117, + showDeprecated = 118, + editorClassName = 119, + pixelRatio = 120, + tabFocusMode = 121, + layoutInfo = 122, + wrappingInfo = 123 } /** diff --git a/src/vs/editor/contrib/rename/onTypeRename.ts b/src/vs/editor/contrib/linkedEditing/linkedEditing.ts similarity index 82% rename from src/vs/editor/contrib/rename/onTypeRename.ts rename to src/vs/editor/contrib/linkedEditing/linkedEditing.ts index b0bfc7c585d..9c984b987b7 100644 --- a/src/vs/editor/contrib/rename/onTypeRename.ts +++ b/src/vs/editor/contrib/linkedEditing/linkedEditing.ts @@ -14,7 +14,7 @@ import { Position, IPosition } from 'vs/editor/common/core/position'; import { ITextModel, IModelDeltaDecoration, TrackedRangeStickiness, IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { OnTypeRenameRangeProviderRegistry, OnTypeRenameRanges } from 'vs/editor/common/modes'; +import { LinkedEditingRangeProviderRegistry, LinkedEditingRanges } from 'vs/editor/common/modes'; import { first, createCancelablePromise, CancelablePromise, Delayer } from 'vs/base/common/async'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { ContextKeyExpr, RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -30,19 +30,21 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic import { Color } from 'vs/base/common/color'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; -export const CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE = new RawContextKey('onTypeRenameInputVisible', false); +export const CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE = new RawContextKey('LinkedEditingInputVisible', false); -export class OnTypeRenameContribution extends Disposable implements IEditorContribution { +const DECORATION_CLASS_NAME = 'linked-editing-decoration'; - public static readonly ID = 'editor.contrib.onTypeRename'; +export class LinkedEditingContribution extends Disposable implements IEditorContribution { + + public static readonly ID = 'editor.contrib.linkedEditing'; private static readonly DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges, - className: 'on-type-rename-decoration' + className: DECORATION_CLASS_NAME }); - static get(editor: ICodeEditor): OnTypeRenameContribution { - return editor.getContribution(OnTypeRenameContribution.ID); + static get(editor: ICodeEditor): LinkedEditingContribution { + return editor.getContribution(LinkedEditingContribution.ID); } private _debounceDuration = 200; @@ -91,11 +93,11 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr this._register(this._editor.onDidChangeModel(() => this.reinitialize())); this._register(this._editor.onDidChangeConfiguration(e => { - if (e.hasChanged(EditorOption.renameOnType)) { + if (e.hasChanged(EditorOption.linkedEditing) || e.hasChanged(EditorOption.renameOnType)) { this.reinitialize(); } })); - this._register(OnTypeRenameRangeProviderRegistry.onDidChange(() => this.reinitialize())); + this._register(LinkedEditingRangeProviderRegistry.onDidChange(() => this.reinitialize())); this._register(this._editor.onDidChangeModelLanguage(() => this.reinitialize())); this.reinitialize(); @@ -103,7 +105,7 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr private reinitialize() { const model = this._editor.getModel(); - const isEnabled = model !== null && this._editor.getOption(EditorOption.renameOnType) && OnTypeRenameRangeProviderRegistry.has(model); + const isEnabled = model !== null && (this._editor.getOption(EditorOption.linkedEditing) || this._editor.getOption(EditorOption.renameOnType)) && LinkedEditingRangeProviderRegistry.has(model); if (isEnabled === this._enabled) { return; } @@ -220,7 +222,7 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr try { this._ignoreChangeEvent = true; const prevEditOperationType = this._editor._getViewModel().getPrevEditOperationType(); - this._editor.executeEdits('onTypeRename', edits); + this._editor.executeEdits('linkedEditing', edits); this._editor._getViewModel().setPrevEditOperationType(prevEditOperationType); } finally { this._ignoreChangeEvent = false; @@ -281,7 +283,7 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr this._currentRequestModelVersion = modelVersionId; const request = createCancelablePromise(async token => { try { - const response = await getOnTypeRenameRanges(model, position, token); + const response = await getLinkedEditingRanges(model, position, token); if (request !== this._currentRequest) { return; } @@ -311,12 +313,12 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr } if (!foundReferenceRange) { - // Cannot do on type rename if the ranges are not where the cursor is... + // Cannot do linked editing if the ranges are not where the cursor is... this.clearRanges(); return; } - const decorations: IModelDeltaDecoration[] = ranges.map(range => ({ range: range, options: OnTypeRenameContribution.DECORATION })); + const decorations: IModelDeltaDecoration[] = ranges.map(range => ({ range: range, options: LinkedEditingContribution.DECORATION })); this._visibleContextKey.set(true); this._currentDecorations = this._editor.deltaDecorations(this._currentDecorations, decorations); } catch (err) { @@ -360,12 +362,12 @@ export class OnTypeRenameContribution extends Disposable implements IEditorContr // } } -export class OnTypeRenameAction extends EditorAction { +export class LinkedEditingAction extends EditorAction { constructor() { super({ - id: 'editor.action.onTypeRename', - label: nls.localize('onTypeRename.label', "On Type Rename Symbol"), - alias: 'On Type Rename Symbol', + id: 'editor.action.linkedEditing', + label: nls.localize('linkedEditing.label', "Start Linked Editing"), + alias: 'Start Linked Editing', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasRenameProvider), kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, @@ -396,7 +398,7 @@ export class OnTypeRenameAction extends EditorAction { } run(_accessor: ServicesAccessor, editor: ICodeEditor): Promise { - const controller = OnTypeRenameContribution.get(editor); + const controller = LinkedEditingContribution.get(editor); if (controller) { return Promise.resolve(controller.updateRanges(true)); } @@ -404,9 +406,9 @@ export class OnTypeRenameAction extends EditorAction { } } -const OnTypeRenameCommand = EditorCommand.bindToContribution(OnTypeRenameContribution.get); -registerEditorCommand(new OnTypeRenameCommand({ - id: 'cancelOnTypeRenameInput', +const LinkedEditingCommand = EditorCommand.bindToContribution(LinkedEditingContribution.get); +registerEditorCommand(new LinkedEditingCommand({ + id: 'cancelLinkedEditingInput', precondition: CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE, handler: x => x.clearRanges(), kbOpts: { @@ -418,15 +420,15 @@ registerEditorCommand(new OnTypeRenameCommand({ })); -function getOnTypeRenameRanges(model: ITextModel, position: Position, token: CancellationToken): Promise { - const orderedByScore = OnTypeRenameRangeProviderRegistry.ordered(model); +function getLinkedEditingRanges(model: ITextModel, position: Position, token: CancellationToken): Promise { + const orderedByScore = LinkedEditingRangeProviderRegistry.ordered(model); - // in order of score ask the on type rename provider + // in order of score ask the linked editing range provider // until someone response with a good result // (good = not null) - return first(orderedByScore.map(provider => async () => { + return first(orderedByScore.map(provider => async () => { try { - return await provider.provideOnTypeRenameRanges(model, position, token); + return await provider.provideLinkedEditingRanges(model, position, token); } catch (e) { onUnexpectedExternalError(e); return undefined; @@ -434,15 +436,15 @@ function getOnTypeRenameRanges(model: ITextModel, position: Position, token: Can }), result => !!result && arrays.isNonEmptyArray(result?.ranges)); } -export const editorOnTypeRenameBackground = registerColor('editor.onTypeRenameBackground', { dark: Color.fromHex('#f00').transparent(0.3), light: Color.fromHex('#f00').transparent(0.3), hc: Color.fromHex('#f00').transparent(0.3) }, nls.localize('editorOnTypeRenameBackground', 'Background color when the editor auto renames on type.')); +export const editorLinkedEditingBackground = registerColor('editor.linkedEditingBackground', { dark: Color.fromHex('#f00').transparent(0.3), light: Color.fromHex('#f00').transparent(0.3), hc: Color.fromHex('#f00').transparent(0.3) }, nls.localize('editorLinkedEditingBackground', 'Background color when the editor auto renames on type.')); registerThemingParticipant((theme, collector) => { - const editorOnTypeRenameBackgroundColor = theme.getColor(editorOnTypeRenameBackground); - if (editorOnTypeRenameBackgroundColor) { - collector.addRule(`.monaco-editor .on-type-rename-decoration { background: ${editorOnTypeRenameBackgroundColor}; border-left-color: ${editorOnTypeRenameBackgroundColor}; }`); + const editorLinkedEditingBackgroundColor = theme.getColor(editorLinkedEditingBackground); + if (editorLinkedEditingBackgroundColor) { + collector.addRule(`.monaco-editor .${DECORATION_CLASS_NAME} { background: ${editorLinkedEditingBackgroundColor}; border-left-color: ${editorLinkedEditingBackgroundColor}; }`); } }); -registerModelAndPositionCommand('_executeRenameOnTypeProvider', (model, position) => getOnTypeRenameRanges(model, position, CancellationToken.None)); +registerModelAndPositionCommand('_executeLinkedEditingProvider', (model, position) => getLinkedEditingRanges(model, position, CancellationToken.None)); -registerEditorContribution(OnTypeRenameContribution.ID, OnTypeRenameContribution); -registerEditorAction(OnTypeRenameAction); +registerEditorContribution(LinkedEditingContribution.ID, LinkedEditingContribution); +registerEditorAction(LinkedEditingAction); diff --git a/src/vs/editor/contrib/rename/test/onTypeRename.test.ts b/src/vs/editor/contrib/linkedEditing/test/linkedEditing.test..ts similarity index 93% rename from src/vs/editor/contrib/rename/test/onTypeRename.test.ts rename to src/vs/editor/contrib/linkedEditing/test/linkedEditing.test..ts index 34d30e861b9..9b00cb4b8d2 100644 --- a/src/vs/editor/contrib/rename/test/onTypeRename.test.ts +++ b/src/vs/editor/contrib/linkedEditing/test/linkedEditing.test..ts @@ -10,7 +10,7 @@ import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { Handler } from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; -import { OnTypeRenameContribution } from 'vs/editor/contrib/rename/onTypeRename'; +import { LinkedEditingContribution } from 'vs/editor/contrib/linkedEditing/linkedEditing'; import { createTestCodeEditor, ITestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; @@ -30,12 +30,12 @@ interface TestEditor { redo(): void; } -const languageIdentifier = new modes.LanguageIdentifier('onTypeRenameTestLangage', 74); +const languageIdentifier = new modes.LanguageIdentifier('linkedEditingTestLangage', 74); LanguageConfigurationRegistry.register(languageIdentifier, { wordPattern: /[a-zA-Z]+/ }); -suite('On type rename', () => { +suite('linked editing', () => { const disposables = new DisposableStore(); setup(() => { @@ -66,8 +66,8 @@ suite('On type rename', () => { expectedEndText: string | string[] ) { test(name, async () => { - disposables.add(modes.OnTypeRenameRangeProviderRegistry.register(mockFileSelector, { - provideOnTypeRenameRanges(model: ITextModel, pos: IPosition) { + disposables.add(modes.LinkedEditingRangeProviderRegistry.register(mockFileSelector, { + provideLinkedEditingRanges(model: ITextModel, pos: IPosition) { const wordAtPos = model.getWordAtPosition(pos); if (wordAtPos) { const matches = model.findMatches(wordAtPos.word, false, false, true, USUAL_WORD_SEPARATORS, false); @@ -78,25 +78,25 @@ suite('On type rename', () => { })); const editor = createMockEditor(initialState.text); - editor.updateOptions({ renameOnType: true }); - const ontypeRenameContribution = editor.registerAndInstantiateContribution( - OnTypeRenameContribution.ID, - OnTypeRenameContribution + editor.updateOptions({ linkedEditing: true }); + const linkedEditingContribution = editor.registerAndInstantiateContribution( + LinkedEditingContribution.ID, + LinkedEditingContribution ); - ontypeRenameContribution.setDebounceDuration(0); + linkedEditingContribution.setDebounceDuration(0); const testEditor: TestEditor = { setPosition(pos: Position) { editor.setPosition(pos); - return ontypeRenameContribution.currentUpdateTriggerPromise; + return linkedEditingContribution.currentUpdateTriggerPromise; }, setSelection(sel: IRange) { editor.setSelection(sel); - return ontypeRenameContribution.currentUpdateTriggerPromise; + return linkedEditingContribution.currentUpdateTriggerPromise; }, trigger(source: string | null | undefined, handlerId: string, payload: any) { editor.trigger(source, handlerId, payload); - return ontypeRenameContribution.currentSyncTriggerPromise; + return linkedEditingContribution.currentSyncTriggerPromise; }, undo() { CoreEditingCommands.Undo.runEditorCommand(null, editor, null); @@ -251,7 +251,7 @@ suite('On type rename', () => { // testCase('Selection insert - across two boundary', state, async (editor) => { // const pos = new Position(1, 2); // await editor.setPosition(pos); - // await ontypeRenameContribution.updateLinkedUI(pos); + // await linkedEditingContribution.updateLinkedUI(pos); // await editor.setSelection(new Range(1, 4, 1, 9)); // await editor.trigger('keyboard', Handler.Type, { text: 'i' }); // }, ''); @@ -383,7 +383,7 @@ suite('On type rename', () => { // testCase('Delete - left all', state, async (editor) => { // const pos = new Position(1, 3); // await editor.setPosition(pos); - // await ontypeRenameContribution.updateLinkedUI(pos); + // await linkedEditingContribution.updateLinkedUI(pos); // await editor.trigger('keyboard', 'deleteAllLeft', {}); // }, '>'); @@ -393,7 +393,7 @@ suite('On type rename', () => { // testCase('Delete - left all then undo', state, async (editor) => { // const pos = new Position(1, 5); // await editor.setPosition(pos); - // await ontypeRenameContribution.updateLinkedUI(pos); + // await linkedEditingContribution.updateLinkedUI(pos); // await editor.trigger('keyboard', 'deleteAllLeft', {}); // editor.undo(); // }, '>'); diff --git a/src/vs/editor/editor.all.ts b/src/vs/editor/editor.all.ts index 28d1c9b6af0..904283213ac 100644 --- a/src/vs/editor/editor.all.ts +++ b/src/vs/editor/editor.all.ts @@ -31,10 +31,10 @@ import 'vs/editor/contrib/hover/hover'; import 'vs/editor/contrib/indentation/indentation'; import 'vs/editor/contrib/inPlaceReplace/inPlaceReplace'; import 'vs/editor/contrib/linesOperations/linesOperations'; +import 'vs/editor/contrib/linkedEditing/linkedEditing'; import 'vs/editor/contrib/links/links'; import 'vs/editor/contrib/multicursor/multicursor'; import 'vs/editor/contrib/parameterHints/parameterHints'; -import 'vs/editor/contrib/rename/onTypeRename'; import 'vs/editor/contrib/rename/rename'; import 'vs/editor/contrib/smartSelect/smartSelect'; import 'vs/editor/contrib/snippet/snippetController2'; diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index e9ce3faf2b3..9bb40fa3750 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -392,10 +392,10 @@ export function registerDocumentHighlightProvider(languageId: string, provider: } /** - * Register an on type rename range provider. + * Register an linked editing range provider. */ -export function registerOnTypeRenameRangeProvider(languageId: string, provider: modes.OnTypeRenameRangeProvider): IDisposable { - return modes.OnTypeRenameRangeProviderRegistry.register(languageId, provider); +export function registerLinkedEditingRangeProvider(languageId: string, provider: modes.LinkedEditingRangeProvider): IDisposable { + return modes.LinkedEditingRangeProviderRegistry.register(languageId, provider); } /** @@ -566,7 +566,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { registerHoverProvider: registerHoverProvider, registerDocumentSymbolProvider: registerDocumentSymbolProvider, registerDocumentHighlightProvider: registerDocumentHighlightProvider, - registerOnTypeRenameRangeProvider: registerOnTypeRenameRangeProvider, + registerLinkedEditingRangeProvider: registerLinkedEditingRangeProvider, registerDefinitionProvider: registerDefinitionProvider, registerImplementationProvider: registerImplementationProvider, registerTypeDefinitionProvider: registerTypeDefinitionProvider, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 6d61191086b..46a8b655b07 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2691,9 +2691,13 @@ declare namespace monaco.editor { */ readOnly?: boolean; /** - * Rename matching regions on type. + * Enable linked editing. * Defaults to false. */ + linkedEditing?: boolean; + /** + * deprecated, use linkedEditing instead + */ renameOnType?: boolean; /** * Should the editor render validation decorations. @@ -3949,72 +3953,73 @@ declare namespace monaco.editor { lineHeight = 54, lineNumbers = 55, lineNumbersMinChars = 56, - links = 57, - matchBrackets = 58, - minimap = 59, - mouseStyle = 60, - mouseWheelScrollSensitivity = 61, - mouseWheelZoom = 62, - multiCursorMergeOverlapping = 63, - multiCursorModifier = 64, - multiCursorPaste = 65, - occurrencesHighlight = 66, - overviewRulerBorder = 67, - overviewRulerLanes = 68, - padding = 69, - parameterHints = 70, - peekWidgetDefaultFocus = 71, - definitionLinkOpensInPeek = 72, - quickSuggestions = 73, - quickSuggestionsDelay = 74, - readOnly = 75, - renameOnType = 76, - renderControlCharacters = 77, - renderIndentGuides = 78, - renderFinalNewline = 79, - renderLineHighlight = 80, - renderLineHighlightOnlyWhenFocus = 81, - renderValidationDecorations = 82, - renderWhitespace = 83, - revealHorizontalRightPadding = 84, - roundedSelection = 85, - rulers = 86, - scrollbar = 87, - scrollBeyondLastColumn = 88, - scrollBeyondLastLine = 89, - scrollPredominantAxis = 90, - selectionClipboard = 91, - selectionHighlight = 92, - selectOnLineNumbers = 93, - showFoldingControls = 94, - showUnused = 95, - snippetSuggestions = 96, - smartSelect = 97, - smoothScrolling = 98, - stopRenderingLineAfter = 99, - suggest = 100, - suggestFontSize = 101, - suggestLineHeight = 102, - suggestOnTriggerCharacters = 103, - suggestSelection = 104, - tabCompletion = 105, - tabIndex = 106, - unusualLineTerminators = 107, - useTabStops = 108, - wordSeparators = 109, - wordWrap = 110, - wordWrapBreakAfterCharacters = 111, - wordWrapBreakBeforeCharacters = 112, - wordWrapColumn = 113, - wordWrapMinified = 114, - wrappingIndent = 115, - wrappingStrategy = 116, - showDeprecated = 117, - editorClassName = 118, - pixelRatio = 119, - tabFocusMode = 120, - layoutInfo = 121, - wrappingInfo = 122 + linkedEditing = 57, + links = 58, + matchBrackets = 59, + minimap = 60, + mouseStyle = 61, + mouseWheelScrollSensitivity = 62, + mouseWheelZoom = 63, + multiCursorMergeOverlapping = 64, + multiCursorModifier = 65, + multiCursorPaste = 66, + occurrencesHighlight = 67, + overviewRulerBorder = 68, + overviewRulerLanes = 69, + padding = 70, + parameterHints = 71, + peekWidgetDefaultFocus = 72, + definitionLinkOpensInPeek = 73, + quickSuggestions = 74, + quickSuggestionsDelay = 75, + readOnly = 76, + renameOnType = 77, + renderControlCharacters = 78, + renderIndentGuides = 79, + renderFinalNewline = 80, + renderLineHighlight = 81, + renderLineHighlightOnlyWhenFocus = 82, + renderValidationDecorations = 83, + renderWhitespace = 84, + revealHorizontalRightPadding = 85, + roundedSelection = 86, + rulers = 87, + scrollbar = 88, + scrollBeyondLastColumn = 89, + scrollBeyondLastLine = 90, + scrollPredominantAxis = 91, + selectionClipboard = 92, + selectionHighlight = 93, + selectOnLineNumbers = 94, + showFoldingControls = 95, + showUnused = 96, + snippetSuggestions = 97, + smartSelect = 98, + smoothScrolling = 99, + stopRenderingLineAfter = 100, + suggest = 101, + suggestFontSize = 102, + suggestLineHeight = 103, + suggestOnTriggerCharacters = 104, + suggestSelection = 105, + tabCompletion = 106, + tabIndex = 107, + unusualLineTerminators = 108, + useTabStops = 109, + wordSeparators = 110, + wordWrap = 111, + wordWrapBreakAfterCharacters = 112, + wordWrapBreakBeforeCharacters = 113, + wordWrapColumn = 114, + wordWrapMinified = 115, + wrappingIndent = 116, + wrappingStrategy = 117, + showDeprecated = 118, + editorClassName = 119, + pixelRatio = 120, + tabFocusMode = 121, + layoutInfo = 122, + wrappingInfo = 123 } export const EditorOptions: { acceptSuggestionOnCommitCharacter: IEditorOption; @@ -4074,6 +4079,7 @@ declare namespace monaco.editor { lineHeight: IEditorOption; lineNumbers: IEditorOption; lineNumbersMinChars: IEditorOption; + linkedEditing: IEditorOption; links: IEditorOption; matchBrackets: IEditorOption; minimap: IEditorOption; @@ -5093,9 +5099,9 @@ declare namespace monaco.languages { export function registerDocumentHighlightProvider(languageId: string, provider: DocumentHighlightProvider): IDisposable; /** - * Register an on type rename range provider. + * Register an linked editing range provider. */ - export function registerOnTypeRenameRangeProvider(languageId: string, provider: OnTypeRenameRangeProvider): IDisposable; + export function registerLinkedEditingRangeProvider(languageId: string, provider: LinkedEditingRangeProvider): IDisposable; /** * Register a definition provider (used by e.g. go to definition). @@ -5839,23 +5845,23 @@ declare namespace monaco.languages { } /** - * The rename range provider interface defines the contract between extensions and - * the live-rename feature. + * The linked editing range provider interface defines the contract between extensions and + * the linked editing feature. */ - export interface OnTypeRenameRangeProvider { + export interface LinkedEditingRangeProvider { /** - * Provide a list of ranges that can be live-renamed together. + * Provide a list of ranges that can be edited together. */ - provideOnTypeRenameRanges(model: editor.ITextModel, position: Position, token: CancellationToken): ProviderResult; + provideLinkedEditingRanges(model: editor.ITextModel, position: Position, token: CancellationToken): ProviderResult; } /** - * Represents a list of ranges that can be renamed together along with a word pattern to describe valid range contents. + * Represents a list of ranges that can be edited together along with a word pattern to describe valid contents. */ - export interface OnTypeRenameRanges { + export interface LinkedEditingRanges { /** - * A list of ranges that can be renamed together. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap + * A list of ranges that can be edited together. The ranges must have + * identical length and text content. The ranges cannot overlap */ ranges: IRange[]; /** diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index ef21f863b6d..c63df0d73d4 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -983,52 +983,51 @@ declare module 'vscode' { //#endregion - //#region OnTypeRename: https://github.com/microsoft/vscode/issues/109923 @aeschli + //#region LinkedEditing: https://github.com/microsoft/vscode/issues/109923 @aeschli /** - * The 'on type' rename range provider interface defines the contract between extensions and - * the 'on type' rename feature. + * The linked editing range provider interface defines the contract between extensions and + * the linked editing feature. */ - export interface OnTypeRenameRangeProvider { + export interface LinkedEditingRangeProvider { /** * For a given position in a document, returns the range of the symbol at the position and all ranges - * that have the same content and can be renamed together. Optionally a word pattern can be returned - * to describe valid contents. A rename to one of the ranges can be applied to all other ranges if the new content - * is valid. + * that have the same content. A change to one of the ranges can be applied to all other ranges if the new content + * is valid. An optional word pattern can be returned with the result to describe valid contents. * If no result-specific word pattern is provided, the word pattern from the language configuration is used. * * @param document The document in which the provider was invoked. * @param position The position at which the provider was invoked. * @param token A cancellation token. - * @return A list of ranges that can be renamed together + * @return A list of ranges that can be edited together */ - provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; + provideLinkedEditingRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; } namespace languages { /** - * Register a 'on type' rename range provider. + * Register a linked editing range provider. * * Multiple providers can be registered for a language. In that case providers are sorted * by their [score](#languages.match) and the best-matching provider that has a result is used. Failure * of the selected provider will cause a failure of the whole operation. * * @param selector A selector that defines the documents this provider is applicable to. - * @param provider An 'on type' rename range provider. + * @param provider A linked editing range provider. * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ - export function registerOnTypeRenameRangeProvider(selector: DocumentSelector, provider: OnTypeRenameRangeProvider): Disposable; + export function registerLinkedEditingRangeProvider(selector: DocumentSelector, provider: LinkedEditingRangeProvider): Disposable; } /** - * Represents a list of ranges that can be renamed together along with a word pattern to describe valid range contents. + * Represents a list of ranges that can be edited together along with a word pattern to describe valid range contents. */ - export class OnTypeRenameRanges { + export class LinkedEditingRanges { constructor(ranges: Range[], wordPattern?: RegExp); /** - * A list of ranges that can be renamed together. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap. + * A list of ranges that can be edited together. The ranges must have + * identical length and text content. The ranges cannot overlap. */ readonly ranges: Range[]; diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index f06c51cdc75..ddea8e0e9d1 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -260,12 +260,12 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha })); } - // --- on type rename + // --- linked editing - $registerOnTypeRenameRangeProvider(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, modes.OnTypeRenameRangeProviderRegistry.register(selector, { - provideOnTypeRenameRanges: async (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise => { - const res = await this._proxy.$provideOnTypeRenameRanges(handle, model.uri, position, token); + $registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void { + this._registrations.set(handle, modes.LinkedEditingRangeProviderRegistry.register(selector, { + provideLinkedEditingRanges: async (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise => { + const res = await this._proxy.$provideLinkedEditingRanges(handle, model.uri, position, token); if (res) { return { ranges: res.ranges, diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1fbbd8118b4..b1a130753e1 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -420,9 +420,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { return extHostLanguageFeatures.registerDocumentHighlightProvider(extension, checkSelector(selector), provider); }, - registerOnTypeRenameRangeProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeRenameRangeProvider): vscode.Disposable { + registerLinkedEditingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.LinkedEditingRangeProvider): vscode.Disposable { checkProposedApiEnabled(extension); - return extHostLanguageFeatures.registerOnTypeRenameRangeProvider(extension, checkSelector(selector), provider); + return extHostLanguageFeatures.registerLinkedEditingRangeProvider(extension, checkSelector(selector), provider); }, registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { return extHostLanguageFeatures.registerReferenceProvider(extension, checkSelector(selector), provider); @@ -1259,9 +1259,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension); return extHostTypes.NotebookCellOutputItem; }, - get OnTypeRenameRanges() { + get LinkedEditingRanges() { checkProposedApiEnabled(extension); - return extHostTypes.OnTypeRenameRanges; + return extHostTypes.LinkedEditingRanges; }, get TestRunState() { checkProposedApiEnabled(extension); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b40e9d0f9f2..b97a962f6ed 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -384,7 +384,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable { $registerHoverProvider(handle: number, selector: IDocumentFilterDto[]): void; $registerEvaluatableExpressionProvider(handle: number, selector: IDocumentFilterDto[]): void; $registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void; - $registerOnTypeRenameRangeProvider(handle: number, selector: IDocumentFilterDto[]): void; + $registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void; $registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void; $registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void; $registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void; @@ -1403,7 +1403,7 @@ export interface ILanguageWordDefinitionDto { regexFlags: string } -export interface IOnTypeRenameRangesDto { +export interface ILinkedEditingRangesDto { ranges: IRange[]; wordPattern?: IRegExpDto; } @@ -1420,7 +1420,7 @@ export interface ExtHostLanguageFeaturesShape { $provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; $provideEvaluatableExpression(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; $provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; - $provideOnTypeRenameRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; + $provideLinkedEditingRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; $provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise; $provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise; $resolveCodeAction(handle: number, id: ChainedCacheId, token: CancellationToken): Promise; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 6868dd77e07..49cde88e19c 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -311,18 +311,18 @@ class DocumentHighlightAdapter { } } -class OnTypeRenameRangeAdapter { +class LinkedEditingRangeAdapter { constructor( private readonly _documents: ExtHostDocuments, - private readonly _provider: vscode.OnTypeRenameRangeProvider + private readonly _provider: vscode.LinkedEditingRangeProvider ) { } - provideOnTypeRenameRanges(resource: URI, position: IPosition, token: CancellationToken): Promise { + provideLinkedEditingRanges(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); const pos = typeConvert.Position.to(position); - return asPromise(() => this._provider.provideOnTypeRenameRanges(doc, pos, token)).then(value => { + return asPromise(() => this._provider.provideLinkedEditingRanges(doc, pos, token)).then(value => { if (value && Array.isArray(value.ranges)) { return { ranges: coalesce(value.ranges.map(typeConvert.Range.from)), @@ -1320,7 +1320,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov | SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter | SelectionRangeAdapter | CallHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter - | OnTypeRenameRangeAdapter; + | LinkedEditingRangeAdapter; class AdapterData { constructor( @@ -1562,17 +1562,17 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position, token), undefined); } - // --- on type rename + // --- linked editing - registerOnTypeRenameRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.OnTypeRenameRangeProvider): vscode.Disposable { - const handle = this._addNewAdapter(new OnTypeRenameRangeAdapter(this._documents, provider), extension); - this._proxy.$registerOnTypeRenameRangeProvider(handle, this._transformDocumentSelector(selector)); + registerLinkedEditingRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.LinkedEditingRangeProvider): vscode.Disposable { + const handle = this._addNewAdapter(new LinkedEditingRangeAdapter(this._documents, provider), extension); + this._proxy.$registerLinkedEditingRangeProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } - $provideOnTypeRenameRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise { - return this._withAdapter(handle, OnTypeRenameRangeAdapter, async adapter => { - const res = await adapter.provideOnTypeRenameRanges(URI.revive(resource), position, token); + $provideLinkedEditingRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise { + return this._withAdapter(handle, LinkedEditingRangeAdapter, async adapter => { + const res = await adapter.provideLinkedEditingRanges(URI.revive(resource), position, token); if (res) { return { ranges: res.ranges, diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index d30a2e5f5d3..0c99cdf9d2e 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2879,7 +2879,7 @@ export enum StandardTokenType { } -export class OnTypeRenameRanges { +export class LinkedEditingRanges { constructor(public readonly ranges: Range[], public readonly wordPattern?: RegExp) { } } From e2dd774fa43b88fb57099b9c04c88244f27fcd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Nov 2020 16:33:46 +0100 Subject: [PATCH 0401/1837] fix yarn retry logic --- build/azure-pipelines/darwin/product-build-darwin.yml | 6 +++++- build/azure-pipelines/linux/product-build-alpine.yml | 6 +++++- build/azure-pipelines/linux/product-build-linux.yml | 6 +++++- build/azure-pipelines/product-compile.yml | 9 ++++++--- build/azure-pipelines/web/product-build-web.yml | 6 +++++- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index a9faf84116f..dfc53ed2382 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -89,7 +89,11 @@ steps: for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break - echo "Yarn failed, trying again..." + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." done displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index c2901a85a02..a95fc03488a 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -81,7 +81,11 @@ steps: export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break - echo "Yarn failed, trying again..." + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." done displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 516a0f026ae..9d58ce2323c 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -72,7 +72,11 @@ steps: export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break - echo "Yarn failed, trying again..." + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." done displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 8995a5f6031..4061145d101 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -69,12 +69,15 @@ steps: - script: | set -e + export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break - echo "Yarn failed, trying again..." + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." done - env: - CHILD_CONCURRENCY: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index f979d35f45b..7bcba0d587f 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -71,7 +71,11 @@ steps: export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break - echo "Yarn failed, trying again..." + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." done displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) From cfa02997d23417b122f66fc17ae63ee7248691d4 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2020 16:43:00 +0100 Subject: [PATCH 0402/1837] fixes #111413 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 2 +- src/vs/workbench/contrib/debug/common/debugModel.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index ccc31a6f801..4ff97b08339 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -919,7 +919,7 @@ class CallStackDataSource implements IAsyncDataSource callStack.length && callStack.length > 1) { + if (!thread.reachedEndOfCallStack && thread.stoppedDetails && thread.stoppedDetails.totalFrames && thread.stoppedDetails.totalFrames > callStack.length) { callStack = callStack.concat([new ThreadAndSessionIds(thread.session.getId(), thread.threadId)]); } diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index fe52108c95c..b98b3b89711 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -393,6 +393,7 @@ export class Thread implements IThread { private callStackCancellationTokens: CancellationTokenSource[] = []; public stoppedDetails: IRawStoppedDetails | undefined; public stopped: boolean; + public reachedEndOfCallStack = false; constructor(public session: IDebugSession, public name: string, public threadId: number) { this.callStack = []; @@ -445,6 +446,7 @@ export class Thread implements IThread { if (this.stopped) { const start = this.callStack.length; const callStack = await this.getCallStackImpl(start, levels); + this.reachedEndOfCallStack = callStack.length < levels; if (start < this.callStack.length) { // Set the stack frames for exact position we requested. To make sure no concurrent requests create duplicate stack frames #30660 this.callStack.splice(start, this.callStack.length - start); From e6d66612474860464df539a075e6a3cc05cc6db5 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2020 16:56:25 +0100 Subject: [PATCH 0403/1837] fixes #111410 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 4ff97b08339..70851479da9 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -919,7 +919,7 @@ class CallStackDataSource implements IAsyncDataSource callStack.length) { + if (!thread.reachedEndOfCallStack && thread.stoppedDetails) { callStack = callStack.concat([new ThreadAndSessionIds(thread.session.getId(), thread.threadId)]); } From 1a6d7f3118424b89bf5fbd6525df2a5ee2c43d66 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 17:23:57 +0100 Subject: [PATCH 0404/1837] [json] performance warning message can't be ignored. Fixes #105988 --- .../client/src/jsonClient.ts | 16 ++++++++++++++-- extensions/json-language-features/package.json | 5 +++++ .../json-language-features/package.nls.json | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/extensions/json-language-features/client/src/jsonClient.ts b/extensions/json-language-features/client/src/jsonClient.ts index 18aec8ef32b..0741cb8743b 100644 --- a/extensions/json-language-features/client/src/jsonClient.ts +++ b/extensions/json-language-features/client/src/jsonClient.ts @@ -71,6 +71,7 @@ namespace SettingIds { export const enableFormatter = 'json.format.enable'; export const enableSchemaDownload = 'json.schemaDownload.enable'; export const maxItemsComputed = 'json.maxItemsComputed'; + export const maxItemsExceededInformation = 'json.maxItemsExceededInformation'; } export interface TelemetryReporter { @@ -298,8 +299,19 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua } })); - client.onNotification(ResultLimitReachedNotification.type, message => { - window.showInformationMessage(`${message}\n${localize('configureLimit', 'Use setting \'{0}\' to configure the limit.', SettingIds.maxItemsComputed)}`); + client.onNotification(ResultLimitReachedNotification.type, async message => { + const shouldPrompt = workspace.getConfiguration().get(SettingIds.maxItemsExceededInformation) !== false; + if (shouldPrompt) { + const ok = localize('ok', "Ok"); + const openSettings = localize('goToSetting', 'Open Settings'); + const neverAgain = localize('yes never again', "Don't Show Again"); + const pick = await window.showInformationMessage(`${message}\n${localize('configureLimit', 'Use setting \'{0}\' to configure the limit.', SettingIds.maxItemsComputed)}`, ok, openSettings, neverAgain); + if (pick === neverAgain) { + await workspace.getConfiguration().update(SettingIds.maxItemsExceededInformation, false, true); + } else if (pick === openSettings) { + await commands.executeCommand('workbench.action.openSettings', SettingIds.maxItemsComputed); + } + } }); function updateFormatterRegistration() { diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index db003f05121..5899ebc9fdf 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -97,6 +97,11 @@ "default": 5000, "description": "%json.maxItemsComputed.desc%" }, + "json.maxItemsExceededInformation": { + "type": "boolean", + "default": true, + "description": "%json.maxItemsExceededInformation.desc%" + }, "json.schemaDownload.enable": { "type": "boolean", "default": true, diff --git a/extensions/json-language-features/package.nls.json b/extensions/json-language-features/package.nls.json index 59729a0ee99..9315f7f2fed 100644 --- a/extensions/json-language-features/package.nls.json +++ b/extensions/json-language-features/package.nls.json @@ -13,5 +13,6 @@ "json.schemaResolutionErrorMessage": "Unable to resolve schema.", "json.clickToRetry": "Click to retry.", "json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).", + "json.maxItemsExceededInformation.desc": "Show notification when exceeding the maximum number of outline symbols and folding regions.", "json.enableSchemaDownload.desc": "When enabled, JSON schemas can be fetched from http and https locations." } From 07224f06818efc6fa80fce78cbfce98ddfab9cd3 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Fri, 27 Nov 2020 17:25:29 +0100 Subject: [PATCH 0405/1837] update to latest DAP --- src/vs/workbench/contrib/debug/common/debugProtocol.d.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts index c6ffbcf5507..f11bab4fbb6 100644 --- a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts @@ -712,9 +712,9 @@ declare module DebugProtocol { /** Arguments for 'setExceptionBreakpoints' request. */ export interface SetExceptionBreakpointsArguments { - /** Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. */ + /** 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. */ + /** 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. */ filterOptions?: ExceptionFilterOptions[]; /** Configuration options for selected exceptions. The attribute is only honored by a debug adapter if the capability 'supportsExceptionOptions' is true. @@ -1011,7 +1011,8 @@ declare module DebugProtocol { } /** StackTrace request; value of command field is 'stackTrace'. - The request returns a stacktrace from the current execution state. + 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 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 { // command: 'stackTrace'; @@ -1039,7 +1040,7 @@ declare module DebugProtocol { This means that there is no location information available. */ stackFrames: StackFrame[]; - /** The total number of frames available. */ + /** The total number of frames available in the stack. If omitted or if totalFrames is larger than the available frames, a client is expected to request frames until a request returns less frames than requested (which indicates the end of the stack). Returning monotonically increasing totalFrames values for subsequent requests can be used to enforce paging in the client. */ totalFrames?: number; }; } From 444f79cc3a2d833179a925530943560d78489bca Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2020 17:33:32 +0100 Subject: [PATCH 0406/1837] Improve quiet light diff syntax highlighting. For #107926 --- .../themes/quietlight-color-theme.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index f28d37d3d2f..e395b99e3eb 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -416,16 +416,16 @@ }, { "name": "Extra: Diff From", - "scope": "meta.diff.header.from-file", + "scope": ["meta.diff.header.from-file", "punctuation.definition.from-file.diff"], "settings": { - "foreground": "#434343" + "foreground": "#4B69C6" } }, { "name": "Extra: Diff To", - "scope": "meta.diff.header.to-file", + "scope": ["meta.diff.header.to-file", "punctuation.definition.to-file.diff"], "settings": { - "foreground": "#434343" + "foreground": "#4B69C6" } }, { @@ -434,7 +434,7 @@ "settings": { "foreground": "#C73D20" } - }, + }, { "name": "diff: changed", "scope": "markup.changed.diff", From c5ab321020b9a223102966d32e7c1c22aaa2a12b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2020 17:44:23 +0100 Subject: [PATCH 0407/1837] fix https://github.com/microsoft/vscode/issues/110554 --- .../editor/contrib/suggest/suggestWidget.ts | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 5ac3857408c..02f6233f20c 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -152,43 +152,51 @@ export class SuggestWidget implements IDisposable { this._contentWidget = new SuggestContentWidget(this, editor); this._persistedSize = new PersistedWidgetSize(_storageService, editor); - let persistedSize: dom.Dimension | undefined; - let currentSize: dom.Dimension | undefined; - let persistHeight = false; - let persistWidth = false; + class ResizeState { + constructor( + readonly persistedSize: dom.Dimension | undefined, + readonly currentSize: dom.Dimension, + public persistHeight = false, + public persistWidth = false, + ) { } + } + + let state: ResizeState | undefined; this._disposables.add(this.element.onDidWillResize(() => { this._contentWidget.lockPreference(); - persistedSize = this._persistedSize.restore(); - currentSize = this.element.size; + state = new ResizeState(this._persistedSize.restore(), this.element.size); })); this._disposables.add(this.element.onDidResize(e => { this._resize(e.dimension.width, e.dimension.height); - persistHeight = persistHeight || !!e.north || !!e.south; - persistWidth = persistWidth || !!e.east || !!e.west; - if (e.done) { + if (state) { + state.persistHeight = state.persistHeight || !!e.north || !!e.south; + state.persistWidth = state.persistWidth || !!e.east || !!e.west; + } + + if (!e.done) { + return; + } + + if (state) { // only store width or height value that have changed and also // only store changes that are above a certain threshold - const threshold = Math.floor(this.getLayoutInfo().itemHeight / 2); + const { itemHeight, defaultSize } = this.getLayoutInfo(); + const threshold = Math.round(itemHeight / 2); let { width, height } = this.element.size; - if (persistedSize && currentSize) { - if (!persistHeight || Math.abs(currentSize.height - height) <= threshold) { - height = persistedSize.height; - } - if (!persistWidth || Math.abs(currentSize.width - width) <= threshold) { - width = persistedSize.width; - } + if (!state.persistHeight || Math.abs(state.currentSize.height - height) <= threshold) { + height = state.persistedSize?.height ?? defaultSize.height; + } + if (!state.persistWidth || Math.abs(state.currentSize.width - width) <= threshold) { + width = state.persistedSize?.width ?? defaultSize.width; } this._persistedSize.store(new dom.Dimension(width, height)); - - // reset working state - this._contentWidget.unlockPreference(); - persistedSize = undefined; - currentSize = undefined; - persistHeight = false; - persistWidth = false; } + + // reset working state + this._contentWidget.unlockPreference(); + state = undefined; })); this._messageElement = dom.append(this.element.domNode, dom.$('.message')); @@ -738,7 +746,7 @@ export class SuggestWidget implements IDisposable { if (this._state === State.Empty || this._state === State.Loading) { // showing a message only height = info.itemHeight + info.borderHeight; - width = 230; + width = info.defaultSize.width / 2; this.element.enableSashes(false, false, false, false); this.element.minSize = this.element.maxSize = new dom.Dimension(width, height); this._contentWidget.setPreference(ContentWidgetPositionPreference.BELOW); @@ -749,7 +757,7 @@ export class SuggestWidget implements IDisposable { // width math const maxWidth = bodyBox.width - info.borderHeight - 2 * info.horizontalPadding; if (width === undefined) { - width = 430; + width = info.defaultSize.width; } if (width > maxWidth) { width = maxWidth; @@ -758,7 +766,7 @@ export class SuggestWidget implements IDisposable { // height math const fullHeight = info.statusBarHeight + this._list.contentHeight + info.borderHeight; - const preferredHeight = info.statusBarHeight + 12 * info.itemHeight + info.borderHeight; + const preferredHeight = info.defaultSize.height; const minHeight = info.itemHeight + info.statusBarHeight; const editorBox = dom.getDomNodePagePosition(this.editor.getDomNode()); const cursorBox = this.editor.getScrolledVisiblePosition(this.editor.getPosition()); @@ -842,7 +850,8 @@ export class SuggestWidget implements IDisposable { borderHeight, typicalHalfwidthCharacterWidth: fontInfo.typicalHalfwidthCharacterWidth, verticalPadding: 22, - horizontalPadding: 14 + horizontalPadding: 14, + defaultSize: new dom.Dimension(430, statusBarHeight + 12 * itemHeight + borderHeight) }; } From 8ee75c19bb39c7433a042647d29d34327a3d55f6 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Nov 2020 18:08:50 +0100 Subject: [PATCH 0408/1837] Escape more white space in appendText Fixes #110464 --- src/vs/base/common/htmlContent.ts | 2 +- src/vs/base/test/browser/markdownRenderer.test.ts | 4 ++-- src/vs/base/test/common/markdownString.test.ts | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index 7272e813245..829a3480092 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -49,7 +49,7 @@ export class MarkdownString implements IMarkdownString { // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash this.value += (this.supportThemeIcons ? escapeCodicons(value) : value) .replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') - .replace(/^([ \t]+)(.+)$/gm, (_match, g1, g2) => ' '.repeat(g1.length) + g2) + .replace(/([ \t]+)/g, (_match, g1) => ' '.repeat(g1.length)) .replace(/^>/gm, '\\>') .replace(/\n/g, newlineStyle === MarkdownStringTextNewlineStyle.Break ? '\\\n' : '\n\n'); diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts index 170f1935c09..f4bfa18d1c7 100644 --- a/src/vs/base/test/browser/markdownRenderer.test.ts +++ b/src/vs/base/test/browser/markdownRenderer.test.ts @@ -57,7 +57,7 @@ suite('MarkdownRenderer', () => { mds.appendText('$(zap) $(not a theme icon) $(add)'); let result: HTMLElement = renderMarkdown(mds); - assert.strictEqual(result.innerHTML, `

$(zap) $(not a theme icon) $(add)

`); + assert.strictEqual(result.innerHTML, `

$(zap) $(not a theme icon) $(add)

`); }); test('render appendMarkdown', () => { @@ -85,7 +85,7 @@ suite('MarkdownRenderer', () => { mds.appendText('$(zap) $(not a theme icon) $(add)'); let result: HTMLElement = renderMarkdown(mds); - assert.strictEqual(result.innerHTML, `

$(zap) $(not a theme icon) $(add)

`); + assert.strictEqual(result.innerHTML, `

$(zap) $(not a theme icon) $(add)

`); }); test('render appendMarkdown with escaped icon', () => { diff --git a/src/vs/base/test/common/markdownString.test.ts b/src/vs/base/test/common/markdownString.test.ts index a76c30f2cc5..424c2bd4673 100644 --- a/src/vs/base/test/common/markdownString.test.ts +++ b/src/vs/base/test/common/markdownString.test.ts @@ -11,13 +11,13 @@ suite('MarkdownString', () => { test('Escape leading whitespace', function () { const mds = new MarkdownString(); mds.appendText('Hello\n Not a code block'); - assert.equal(mds.value, 'Hello\n\n    Not a code block'); + assert.equal(mds.value, 'Hello\n\n    Not a code block'); }); test('MarkdownString.appendText doesn\'t escape quote #109040', function () { const mds = new MarkdownString(); mds.appendText('> Text\n>More'); - assert.equal(mds.value, '\\> Text\n\n\\>More'); + assert.equal(mds.value, '\\> Text\n\n\\>More'); }); test('appendText', () => { @@ -25,7 +25,7 @@ suite('MarkdownString', () => { const mds = new MarkdownString(); mds.appendText('# foo\n*bar*'); - assert.equal(mds.value, '\\# foo\n\n\\*bar\\*'); + assert.equal(mds.value, '\\# foo\n\n\\*bar\\*'); }); suite('ThemeIcons', () => { @@ -36,7 +36,7 @@ suite('MarkdownString', () => { const mds = new MarkdownString(undefined, { supportThemeIcons: true }); mds.appendText('$(zap) $(not a theme icon) $(add)'); - assert.equal(mds.value, '\\\\$\\(zap\\) $\\(not a theme icon\\) \\\\$\\(add\\)'); + assert.equal(mds.value, '\\\\$\\(zap\\) $\\(not a theme icon\\) \\\\$\\(add\\)'); }); test('appendMarkdown', () => { @@ -61,7 +61,7 @@ suite('MarkdownString', () => { const mds = new MarkdownString(undefined, { supportThemeIcons: false }); mds.appendText('$(zap) $(not a theme icon) $(add)'); - assert.equal(mds.value, '$\\(zap\\) $\\(not a theme icon\\) $\\(add\\)'); + assert.equal(mds.value, '$\\(zap\\) $\\(not a theme icon\\) $\\(add\\)'); }); test('appendMarkdown', () => { From 7723f2548c26655be9f282ba7a317c9192073c05 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Sat, 28 Nov 2020 10:11:01 +0100 Subject: [PATCH 0409/1837] Fix #109406 --- .../markers/browser/markers.contribution.ts | 5 +- .../contrib/markers/browser/markers.ts | 45 +--------- .../contrib/markers/browser/markersModel.ts | 10 +++ .../contrib/markers/browser/markersView.ts | 89 ++++++++++++------- 4 files changed, 70 insertions(+), 79 deletions(-) diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index b7fcb530df4..208fea76bd4 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -18,8 +18,7 @@ import { ShowProblemsPanelAction } from 'vs/workbench/contrib/markers/browser/ma import Constants from 'vs/workbench/contrib/markers/browser/constants'; import Messages from 'vs/workbench/contrib/markers/browser/messages'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IMarkersWorkbenchService, MarkersWorkbenchService, ActivityUpdater } from 'vs/workbench/contrib/markers/browser/markers'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ActivityUpdater } from 'vs/workbench/contrib/markers/browser/markers'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -35,8 +34,6 @@ import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); - KeybindingsRegistry.registerCommandAndKeybindingRule({ id: Constants.MARKER_OPEN_ACTION_ID, weight: KeybindingWeight.WorkbenchContrib, diff --git a/src/vs/workbench/contrib/markers/browser/markers.ts b/src/vs/workbench/contrib/markers/browser/markers.ts index 383d52fcacf..196235465b2 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.ts @@ -3,55 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { MarkersModel, compareMarkersByUri } from './markersModel'; import { Disposable, MutableDisposable, IDisposable } from 'vs/base/common/lifecycle'; -import { IMarkerService, MarkerSeverity, IMarker } from 'vs/platform/markers/common/markers'; +import { IMarkerService } from 'vs/platform/markers/common/markers'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { localize } from 'vs/nls'; import Constants from './constants'; -import { URI } from 'vs/base/common/uri'; -import { groupBy } from 'vs/base/common/arrays'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { Event } from 'vs/base/common/event'; -import { ResourceMap } from 'vs/base/common/map'; - -export const IMarkersWorkbenchService = createDecorator('markersWorkbenchService'); - -export interface IMarkersWorkbenchService { - readonly _serviceBrand: undefined; - readonly markersModel: MarkersModel; -} - -export class MarkersWorkbenchService extends Disposable implements IMarkersWorkbenchService { - declare readonly _serviceBrand: undefined; - - readonly markersModel: MarkersModel; - - constructor( - @IMarkerService private readonly markerService: IMarkerService, - @IInstantiationService instantiationService: IInstantiationService, - ) { - super(); - this.markersModel = this._register(instantiationService.createInstance(MarkersModel)); - - this.markersModel.setResourceMarkers(groupBy(this.readMarkers(), compareMarkersByUri).map(group => [group[0].resource, group])); - this._register(Event.debounce>(markerService.onMarkerChanged, (resourcesMap, resources) => { - resourcesMap = resourcesMap ? resourcesMap : new ResourceMap(); - resources.forEach(resource => resourcesMap!.set(resource, resource)); - return resourcesMap; - }, 0)(resourcesMap => this.onMarkerChanged([...resourcesMap.values()]))); - } - - private onMarkerChanged(resources: URI[]): void { - this.markersModel.setResourceMarkers(resources.map(resource => [resource, this.readMarkers(resource)])); - } - - private readMarkers(resource?: URI): IMarker[] { - return this.markerService.read({ resource, severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info }); - } - -} export class ActivityUpdater extends Disposable implements IWorkbenchContribution { diff --git a/src/vs/workbench/contrib/markers/browser/markersModel.ts b/src/vs/workbench/contrib/markers/browser/markersModel.ts index f2544a4023e..a12e1658ee8 100644 --- a/src/vs/workbench/contrib/markers/browser/markersModel.ts +++ b/src/vs/workbench/contrib/markers/browser/markersModel.ts @@ -151,6 +151,16 @@ export class MarkersModel { this.resourcesByUri = new Map(); } + reset(): void { + const removed = new Set(); + for (const resourceMarker of this.resourcesByUri.values()) { + removed.add(resourceMarker); + } + this.resourcesByUri.clear(); + this._total = 0; + this._onDidChange.fire({ removed, added: new Set(), updated: new Set() }); + } + private _total: number = 0; get total(): number { return this._total; diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 052477f4b43..8e7ff32342c 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -11,7 +11,7 @@ import { IAction, IActionViewItem, Action, Separator } from 'vs/base/common/acti import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import Constants from 'vs/workbench/contrib/markers/browser/constants'; -import { Marker, ResourceMarkers, RelatedInformation, MarkerChangesEvent } from 'vs/workbench/contrib/markers/browser/markersModel'; +import { Marker, ResourceMarkers, RelatedInformation, MarkerChangesEvent, MarkersModel, compareMarkersByUri } from 'vs/workbench/contrib/markers/browser/markersModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MarkersFilterActionViewItem, MarkersFilters, IMarkersFiltersChangeEvent, IMarkerFilterController } from 'vs/workbench/contrib/markers/browser/markersViewActions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -19,7 +19,6 @@ import Messages from 'vs/workbench/contrib/markers/browser/messages'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { IMarkersWorkbenchService } from 'vs/workbench/contrib/markers/browser/markers'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { localize } from 'vs/nls'; import { IContextKey, IContextKeyService, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -39,7 +38,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { domEvent } from 'vs/base/browser/event'; import { ResourceLabels } from 'vs/workbench/browser/labels'; -import { IMarker } from 'vs/platform/markers/common/markers'; +import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { withUndefinedAsNull } from 'vs/base/common/types'; import { MementoObject, Memento } from 'vs/workbench/common/memento'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; @@ -52,6 +51,9 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { Codicon } from 'vs/base/common/codicons'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { groupBy } from 'vs/base/common/arrays'; +import { ResourceMap } from 'vs/base/common/map'; function createResourceMarkersIterator(resourceMarkers: ResourceMarkers): Iterable> { return Iterable.map(resourceMarkers.markers, m => { @@ -68,7 +70,9 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { private currentActiveResource: URI | null = null; private readonly rangeHighlightDecorations: RangeHighlightDecorations; + private readonly markersModel: MarkersModel; private readonly filter: Filter; + private readonly onVisibleDisposables = this._register(new DisposableStore()); private tree: MarkersTree | undefined; private filterActionBar: ActionBar | undefined; @@ -103,7 +107,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { @IEditorService private readonly editorService: IEditorService, @IConfigurationService configurationService: IConfigurationService, @ITelemetryService telemetryService: ITelemetryService, - @IMarkersWorkbenchService private readonly markersWorkbenchService: IMarkersWorkbenchService, + @IMarkerService private readonly markerService: IMarkerService, @IContextKeyService contextKeyService: IContextKeyService, @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, @IContextMenuService contextMenuService: IContextMenuService, @@ -118,11 +122,9 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { this.smallLayoutContextKey = Constants.MarkersViewSmallLayoutContextKey.bindTo(this.contextKeyService); this.panelState = new Memento(Constants.MARKERS_VIEW_STORAGE_ID, storageService).getMemento(StorageScope.WORKSPACE, StorageTarget.USER); + this.markersModel = this._register(instantiationService.createInstance(MarkersModel)); this.markersViewModel = this._register(instantiationService.createInstance(MarkersViewModel, this.panelState['multiline'])); - for (const resourceMarker of this.markersWorkbenchService.markersModel.resourceMarkers) { - resourceMarker.markers.forEach(marker => this.markersViewModel.add(marker)); - } - this._register(this.markersViewModel.onDidChange(marker => this.onDidChangeViewState(marker))); + this._register(this.onDidChangeVisibility(visible => this.onDidChangeMarkersViewVisibility(visible))); this.setCurrentActiveEditor(); @@ -154,18 +156,9 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { this.createArialLabelElement(container); this.createMessageBox(container); this.createTree(container); - this.createListeners(); this.updateFilter(); - this._register(this.onDidChangeVisibility(visible => { - if (visible) { - this.refreshPanel(); - } else { - this.rangeHighlightDecorations.removeHighlightRange(); - } - })); - this.filterActionBar!.push(new Action(`workbench.actions.treeView.${this.id}.filter`)); this.renderContent(); } @@ -335,7 +328,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { private setTreeSelection(): void { if (this.tree && this.tree.getSelection().length === 0) { - const firstMarker = this.markersWorkbenchService.markersModel.resourceMarkers[0]?.markers[0]; + const firstMarker = this.markersModel.resourceMarkers[0]?.markers[0]; if (firstMarker) { this.tree.setFocus([firstMarker]); this.tree.setSelection([firstMarker]); @@ -354,13 +347,13 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { let resourceMarkers: ResourceMarkers[] = []; if (this.filters.activeFile) { if (this.currentActiveResource) { - const activeResourceMarkers = this.markersWorkbenchService.markersModel.getResourceMarkers(this.currentActiveResource); + const activeResourceMarkers = this.markersModel.getResourceMarkers(this.currentActiveResource); if (activeResourceMarkers) { resourceMarkers = [activeResourceMarkers]; } } } else { - resourceMarkers = this.markersWorkbenchService.markersModel.resourceMarkers; + resourceMarkers = this.markersModel.resourceMarkers; } this.tree.setChildren(null, Iterable.map(resourceMarkers, m => ({ element: m, children: createResourceMarkersIterator(m) }))); } @@ -499,6 +492,8 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } } })); + + this._register(this.tree.onDidChangeSelection(() => this.onSelected())); } private collapseAll(): void { @@ -511,18 +506,45 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } } - private createListeners(): void { - this._register(Event.any(this.markersWorkbenchService.markersModel.onDidChange, this.editorService.onDidActiveEditorChange)(changes => { + private onDidChangeMarkersViewVisibility(visible: boolean): void { + this.onVisibleDisposables.clear(); + if (visible) { + for (const disposable of this.reInitialize()) { + this.onVisibleDisposables.add(disposable); + } + this.refreshPanel(); + } + } + + private reInitialize(): IDisposable[] { + const disposables = []; + + // Markers Model + const readMarkers = (resource?: URI) => this.markerService.read({ resource, severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info }); + this.markersModel.setResourceMarkers(groupBy(readMarkers(), compareMarkersByUri).map(group => [group[0].resource, group])); + disposables.push(Event.debounce>(this.markerService.onMarkerChanged, (resourcesMap, resources) => { + resourcesMap = resourcesMap || new ResourceMap(); + resources.forEach(resource => resourcesMap!.set(resource, resource)); + return resourcesMap; + }, 64)(resourcesMap => { + this.markersModel.setResourceMarkers([...resourcesMap.values()].map(resource => [resource, readMarkers(resource)])); + })); + disposables.push(Event.any(this.markersModel.onDidChange, this.editorService.onDidActiveEditorChange)(changes => { if (changes) { this.onDidChangeModel(changes); } else { this.onActiveEditorChanged(); } })); - if (this.tree) { - this._register(this.tree.onDidChangeSelection(() => this.onSelected())); - } - this._register(this.filters.onDidChange((event: IMarkersFiltersChangeEvent) => { + disposables.push(toDisposable(() => this.markersModel.reset())); + + // Markers View Model + this.markersModel.resourceMarkers.forEach(resourceMarker => resourceMarker.markers.forEach(marker => this.markersViewModel.add(marker))); + disposables.push(this.markersViewModel.onDidChange(marker => this.onDidChangeViewState(marker))); + disposables.push(toDisposable(() => this.markersModel.resourceMarkers.forEach(resourceMarker => this.markersViewModel.remove(resourceMarker.resource)))); + + // Markers Filters + disposables.push(this.filters.onDidChange((event: IMarkersFiltersChangeEvent) => { this.reportFilteringUsed(); if (event.activeFile) { this.refreshPanel(); @@ -530,14 +552,19 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { this.updateFilter(); } })); + disposables.push(toDisposable(() => { this.cachedFilterStats = undefined; })); + + disposables.push(toDisposable(() => this.rangeHighlightDecorations.removeHighlightRange())); + + return disposables; } - private onDidChangeModel(change: MarkerChangesEvent) { + private onDidChangeModel(change: MarkerChangesEvent): void { const resourceMarkers = [...change.added, ...change.removed, ...change.updated]; const resources: URI[] = []; for (const { resource } of resourceMarkers) { this.markersViewModel.remove(resource); - const resourceMarkers = this.markersWorkbenchService.markersModel.getResourceMarkers(resource); + const resourceMarkers = this.markersModel.getResourceMarkers(resource); if (resourceMarkers) { for (const marker of resourceMarkers.markers) { this.markersViewModel.add(marker); @@ -633,7 +660,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } private renderFilterMessageForActiveFile(container: HTMLElement): void { - if (this.currentActiveResource && this.markersWorkbenchService.markersModel.getResourceMarkers(this.currentActiveResource)) { + if (this.currentActiveResource && this.markersModel.getResourceMarkers(this.currentActiveResource)) { this.renderFilteredByFilterMessage(container); } else { this.renderNoProblemsMessageForActiveFile(container); @@ -718,7 +745,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } private getResourceForCurrentActiveResource(): ResourceMarkers | null { - return this.currentActiveResource ? this.markersWorkbenchService.markersModel.getResourceMarkers(this.currentActiveResource) : null; + return this.currentActiveResource ? this.markersModel.getResourceMarkers(this.currentActiveResource) : null; } private hasSelectedMarkerFor(resource: ResourceMarkers): boolean { @@ -846,7 +873,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } } - return { total: this.markersWorkbenchService.markersModel.total, filtered }; + return { total: this.markersModel.total, filtered }; } private getTelemetryData({ source, code }: IMarker): any { From fbf7566d3974c9831eae874afddb1b43beca4c47 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 28 Nov 2020 11:33:23 +0100 Subject: [PATCH 0410/1837] tests - add test suite for native modules --- .../test/electron-main/nativeHelpers.test.ts | 50 --------- .../environment}/test/node/argv.test.ts | 1 + .../test/node/nativeModules.test.ts | 105 ++++++++++++++++++ .../nsfw/test/nsfwWatcherService.test.ts | 24 ++-- .../unix/test/chockidarWatcherService.test.ts | 44 ++++---- .../electron-main/windowsStateStorage.test.ts | 0 .../api/common/extHostApiCommands.ts | 1 - src/vs/workbench/common/theme.ts | 12 +- 8 files changed, 150 insertions(+), 87 deletions(-) delete mode 100644 src/vs/code/test/electron-main/nativeHelpers.test.ts rename src/vs/{code => platform/environment}/test/node/argv.test.ts (99%) create mode 100644 src/vs/platform/environment/test/node/nativeModules.test.ts rename src/vs/{code => platform/windows}/test/electron-main/windowsStateStorage.test.ts (100%) diff --git a/src/vs/code/test/electron-main/nativeHelpers.test.ts b/src/vs/code/test/electron-main/nativeHelpers.test.ts deleted file mode 100644 index 1e5724a810f..00000000000 --- a/src/vs/code/test/electron-main/nativeHelpers.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { isWindows } from 'vs/base/common/platform'; - -suite('Windows Native Helpers', () => { - if (!isWindows) { - return; - } - - test('windows-mutex', async () => { - const mutex = await import('windows-mutex'); - assert.ok(mutex && typeof mutex.isActive === 'function', 'Unable to load windows-mutex dependency.'); - assert.ok(typeof mutex.isActive === 'function', 'Unable to load windows-mutex dependency.'); - }); - - test('windows-foreground-love', async () => { - const foregroundLove = await import('windows-foreground-love'); - assert.ok(foregroundLove && typeof foregroundLove.allowSetForegroundWindow === 'function', 'Unable to load windows-foreground-love dependency.'); - }); - - test('windows-process-tree', async () => { - const processTree = await import('windows-process-tree'); - assert.ok(processTree && typeof processTree.getProcessTree === 'function', 'Unable to load windows-process-tree dependency.'); - }); - - test('vscode-windows-ca-certs', async () => { - // @ts-ignore Windows only - const windowsCerts = await import('vscode-windows-ca-certs'); - const store = new windowsCerts.Crypt32(); - assert.ok(windowsCerts, 'Unable to load vscode-windows-ca-certs dependency.'); - let certCount = 0; - try { - while (store.next()) { - certCount++; - } - } finally { - store.done(); - } - assert(certCount > 0); - }); - - test('vscode-windows-registry', async () => { - const windowsRegistry = await import('vscode-windows-registry'); - assert.ok(windowsRegistry && typeof windowsRegistry.GetStringRegKey === 'function', 'Unable to load vscode-windows-registry dependency.'); - }); -}); diff --git a/src/vs/code/test/node/argv.test.ts b/src/vs/platform/environment/test/node/argv.test.ts similarity index 99% rename from src/vs/code/test/node/argv.test.ts rename to src/vs/platform/environment/test/node/argv.test.ts index 79ce7d22445..61a4b4f2e23 100644 --- a/src/vs/code/test/node/argv.test.ts +++ b/src/vs/platform/environment/test/node/argv.test.ts @@ -2,6 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + import * as assert from 'assert'; import { formatOptions, Option } from 'vs/platform/environment/node/argv'; import { addArg } from 'vs/platform/environment/node/argvHelper'; diff --git a/src/vs/platform/environment/test/node/nativeModules.test.ts b/src/vs/platform/environment/test/node/nativeModules.test.ts new file mode 100644 index 00000000000..34617f575bb --- /dev/null +++ b/src/vs/platform/environment/test/node/nativeModules.test.ts @@ -0,0 +1,105 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { isMacintosh, isWindows } from 'vs/base/common/platform'; + +function testErrorMessage(module: string): string { + return `Unable to load "${module}" dependency. It was probably not compiled for the right operating system architecture or had missing build tools.`; +} + +suite('Native Modules (all platforms)', () => { + + test('native-is-elevated', async () => { + const isElevated = await import('native-is-elevated'); + assert.ok(typeof isElevated === 'function', testErrorMessage('native-is-elevated ')); + }); + + test('native-keymap', async () => { + const keyMap = await import('native-keymap'); + assert.ok(typeof keyMap.getCurrentKeyboardLayout === 'function', testErrorMessage('native-keymap')); + }); + + test('native-watchdog', async () => { + const watchDog = await import('native-watchdog'); + assert.ok(typeof watchDog.start === 'function', testErrorMessage('native-watchdog')); + }); + + test('node-pty', async () => { + const nodePty = await import('node-pty'); + assert.ok(typeof nodePty.spawn === 'function', testErrorMessage('node-pty')); + }); + + test('spdlog', async () => { + const spdlog = await import('spdlog'); + assert.ok(typeof spdlog.createRotatingLogger === 'function', testErrorMessage('spdlog')); + }); + + test('v8-inspect-profiler', async () => { + const profiler = await import('v8-inspect-profiler'); + assert.ok(typeof profiler.startProfiling === 'function', testErrorMessage('v8-inspect-profiler')); + }); + + test('vscode-nsfw', async () => { + const nsfWatcher = await import('vscode-nsfw'); + assert.ok(typeof nsfWatcher === 'function', testErrorMessage('vscode-nsfw')); + }); + + test('vscode-sqlite3', async () => { + const sqlite3 = await import('vscode-sqlite3'); + assert.ok(typeof sqlite3.Database === 'function', testErrorMessage('vscode-sqlite3')); + }); +}); + +(!isMacintosh ? suite.skip : suite)('Native Modules (macOS)', () => { + + test('chokidar (fsevents)', async () => { + const chokidar = await import('chokidar'); + const watcher = chokidar.watch(__dirname); + assert.ok(watcher.options.useFsEvents, testErrorMessage('chokidar (fsevents)')); + + return watcher.close(); + }); +}); + +(!isWindows ? suite.skip : suite)('Native Modules (Windows)', () => { + + 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')); + }); + + test('windows-foreground-love', async () => { + const foregroundLove = await import('windows-foreground-love'); + assert.ok(typeof foregroundLove.allowSetForegroundWindow === 'function', testErrorMessage('windows-foreground-love')); + }); + + test('windows-process-tree', async () => { + const processTree = await import('windows-process-tree'); + assert.ok(typeof processTree.getProcessTree === 'function', testErrorMessage('windows-process-tree')); + }); + + test('vscode-windows-registry', async () => { + const windowsRegistry = await import('vscode-windows-registry'); + assert.ok(typeof windowsRegistry.GetStringRegKey === 'function', testErrorMessage('vscode-windows-registry')); + }); + + test('vscode-windows-ca-certs', async () => { + // @ts-ignore Windows only + const windowsCerts = await import('vscode-windows-ca-certs'); + const store = new windowsCerts.Crypt32(); + assert.ok(windowsCerts, testErrorMessage('vscode-windows-ca-certs')); + let certCount = 0; + try { + while (store.next()) { + certCount++; + } + } finally { + store.done(); + } + assert(certCount > 0); + }); +}); diff --git a/src/vs/platform/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts b/src/vs/platform/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts index de85fd770cf..9ad083fc9a8 100644 --- a/src/vs/platform/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts +++ b/src/vs/platform/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts @@ -5,23 +5,27 @@ import * as assert from 'assert'; import * as platform from 'vs/base/common/platform'; -import { NsfwWatcherService } from 'vs/platform/files/node/watcher/nsfw/nsfwWatcherService'; import { IWatcherRequest } from 'vs/platform/files/node/watcher/nsfw/watcher'; -class TestNsfwWatcherService extends NsfwWatcherService { +suite('NSFW Watcher Service', async () => { - normalizeRoots(roots: string[]): string[] { + // Load `nsfwWatcherService` within the suite to prevent all tests + // from failing to start if `vscode-nsfw` was not properly installed + const { NsfwWatcherService } = await import('vs/platform/files/node/watcher/nsfw/nsfwWatcherService'); - // Work with strings as paths to simplify testing - const requests: IWatcherRequest[] = roots.map(r => { - return { path: r, excludes: [] }; - }); + class TestNsfwWatcherService extends NsfwWatcherService { - return this._normalizeRoots(requests).map(r => r.path); + normalizeRoots(roots: string[]): string[] { + + // Work with strings as paths to simplify testing + const requests: IWatcherRequest[] = roots.map(r => { + return { path: r, excludes: [] }; + }); + + return this._normalizeRoots(requests).map(r => r.path); + } } -} -suite('NSFW Watcher Service', () => { suite('_normalizeRoots', () => { test('should not impacts roots that don\'t overlap', () => { const service = new TestNsfwWatcherService(); diff --git a/src/vs/platform/files/node/watcher/unix/test/chockidarWatcherService.test.ts b/src/vs/platform/files/node/watcher/unix/test/chockidarWatcherService.test.ts index 4fe0f39ca75..4c780ec6b60 100644 --- a/src/vs/platform/files/node/watcher/unix/test/chockidarWatcherService.test.ts +++ b/src/vs/platform/files/node/watcher/unix/test/chockidarWatcherService.test.ts @@ -5,32 +5,36 @@ import * as assert from 'assert'; import * as platform from 'vs/base/common/platform'; -import { normalizeRoots } from 'vs/platform/files/node/watcher/unix/chokidarWatcherService'; import { IWatcherRequest } from 'vs/platform/files/node/watcher/unix/watcher'; -function newRequest(basePath: string, ignored: string[] = []): IWatcherRequest { - return { path: basePath, excludes: ignored }; -} +suite('Chokidar normalizeRoots', async () => { -function assertNormalizedRootPath(inputPaths: string[], expectedPaths: string[]) { - const requests = inputPaths.map(path => newRequest(path)); - const actual = normalizeRoots(requests); - assert.deepEqual(Object.keys(actual).sort(), expectedPaths); -} + // Load `chokidarWatcherService` within the suite to prevent all tests + // from failing to start if `chokidar` was not properly installed + const { normalizeRoots } = await import('vs/platform/files/node/watcher/unix/chokidarWatcherService'); -function assertNormalizedRequests(inputRequests: IWatcherRequest[], expectedRequests: { [path: string]: IWatcherRequest[] }) { - const actual = normalizeRoots(inputRequests); - const actualPath = Object.keys(actual).sort(); - const expectedPaths = Object.keys(expectedRequests).sort(); - assert.deepEqual(actualPath, expectedPaths); - for (let path of actualPath) { - let a = expectedRequests[path].sort((r1, r2) => r1.path.localeCompare(r2.path)); - let e = expectedRequests[path].sort((r1, r2) => r1.path.localeCompare(r2.path)); - assert.deepEqual(a, e); + function newRequest(basePath: string, ignored: string[] = []): IWatcherRequest { + return { path: basePath, excludes: ignored }; + } + + function assertNormalizedRootPath(inputPaths: string[], expectedPaths: string[]) { + const requests = inputPaths.map(path => newRequest(path)); + const actual = normalizeRoots(requests); + assert.deepEqual(Object.keys(actual).sort(), expectedPaths); + } + + function assertNormalizedRequests(inputRequests: IWatcherRequest[], expectedRequests: { [path: string]: IWatcherRequest[] }) { + const actual = normalizeRoots(inputRequests); + const actualPath = Object.keys(actual).sort(); + const expectedPaths = Object.keys(expectedRequests).sort(); + assert.deepEqual(actualPath, expectedPaths); + for (let path of actualPath) { + let a = expectedRequests[path].sort((r1, r2) => r1.path.localeCompare(r2.path)); + let e = expectedRequests[path].sort((r1, r2) => r1.path.localeCompare(r2.path)); + assert.deepEqual(a, e); + } } -} -suite('Chokidar normalizeRoots', () => { test('should not impacts roots that don\'t overlap', () => { if (platform.isWindows) { assertNormalizedRootPath(['C:\\a'], ['C:\\a']); diff --git a/src/vs/code/test/electron-main/windowsStateStorage.test.ts b/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts similarity index 100% rename from src/vs/code/test/electron-main/windowsStateStorage.test.ts rename to src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index c29ab5b9d33..8a9d750e572 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -308,7 +308,6 @@ const newCommands: ApiCommand[] = [ v => !v ? v : typeof v === 'number' ? [v, undefined] : [typeConverters.ViewColumn.from(v.viewColumn), typeConverters.TextEditorOpenOptions.from(v)] ).optional(), ApiCommandArgument.String.with('label', '').optional() - ], ApiCommandResult.Void ), diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index bf2d99cefc6..a3d6dd6bed2 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -395,6 +395,12 @@ export const STATUS_BAR_PROMINENT_ITEM_BACKGROUND = registerColor('statusBarItem hc: Color.black.transparent(0.5), }, nls.localize('statusBarProminentItemBackground', "Status bar prominent items background color. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); +export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.prominentHoverBackground', { + dark: Color.black.transparent(0.3), + light: Color.black.transparent(0.3), + hc: Color.black.transparent(0.3), +}, nls.localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); + export const STATUS_BAR_ERROR_ITEM_BACKGROUND = registerColor('statusBarItem.errorBackground', { dark: Color.red, light: Color.red, @@ -407,12 +413,6 @@ export const STATUS_BAR_ERROR_ITEM_FOREGROUND = registerColor('statusBarItem.err hc: STATUS_BAR_FOREGROUND, }, nls.localize('statusBarErrorItemForeground', "Status bar error items foreground color. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); -export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.prominentHoverBackground', { - dark: Color.black.transparent(0.3), - light: Color.black.transparent(0.3), - hc: Color.black.transparent(0.3), -}, nls.localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); - // < --- Activity Bar --- > export const ACTIVITY_BAR_BACKGROUND = registerColor('activityBar.background', { From ef2a900dec8b6f8343362ed4439857039a4331d6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 28 Nov 2020 12:28:00 +0100 Subject: [PATCH 0411/1837] sandbox - add SH1 to HEX utility using crypto.subtle with fallback to our own solution --- src/vs/base/common/hash.ts | 29 ++++++++++++++-- src/vs/base/test/common/hash.test.ts | 25 ++++++++------ .../tags/browser/workspaceTagsService.ts | 2 +- .../contrib/tags/common/workspaceTags.ts | 2 +- .../tags/electron-browser/workspaceTags.ts | 10 +++--- .../electron-browser/workspaceTagsService.ts | 16 ++++----- .../electron-browser/workspaceTags.test.ts | 34 +++++++++---------- .../sandbox.simpleservices.ts | 2 +- 8 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/vs/base/common/hash.ts b/src/vs/base/common/hash.ts index 13a1847e064..0de970f1218 100644 --- a/src/vs/base/common/hash.ts +++ b/src/vs/base/common/hash.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { VSBuffer } from 'vs/base/common/buffer'; import * as strings from 'vs/base/common/strings'; /** @@ -106,8 +107,14 @@ function leftPad(value: string, length: number, char: string = '0'): string { return value; } -function toHexString(value: number, bitsize: number = 32): string { - return leftPad((value >>> 0).toString(16), bitsize / 4); +function toHexString(buffer: ArrayBuffer): string; +function toHexString(value: number, bitsize?: number): string; +function toHexString(bufferOrValue: ArrayBuffer | number, bitsize: number = 32): string { + if (bufferOrValue instanceof ArrayBuffer) { + return Array.from(new Uint8Array(bufferOrValue)).map(b => b.toString(16).padStart(2, '0')).join(''); + } + + return leftPad((bufferOrValue >>> 0).toString(16), bitsize / 4); } /** @@ -308,3 +315,21 @@ export class StringSHA1 { this._h4 = (this._h4 + e) & 0xffffffff; } } + +export async function sha1Hex(str: string): Promise { + + // Prefer to use browser's crypto module + if (globalThis?.crypto?.subtle) { + const hash = await globalThis.crypto.subtle.digest({ name: 'sha-1' }, VSBuffer.fromString(str).buffer); + + return toHexString(hash); + } + + // Otherwise fallback to `StringSHA1` + else { + const computer = new StringSHA1(); + computer.update(str); + + return computer.digest(); + } +} diff --git a/src/vs/base/test/common/hash.test.ts b/src/vs/base/test/common/hash.test.ts index b5074f4ffa5..bfd8fd942f5 100644 --- a/src/vs/base/test/common/hash.test.ts +++ b/src/vs/base/test/common/hash.test.ts @@ -2,8 +2,9 @@ * 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 { hash, StringSHA1 } from 'vs/base/common/hash'; +import { hash, sha1Hex, StringSHA1 } from 'vs/base/common/hash'; suite('Hash', () => { test('string', () => { @@ -71,28 +72,32 @@ suite('Hash', () => { }); - function checkSHA1(strings: string[], expected: string) { + async function checkSHA1(str: string, expected: string) { + + // Test with StringSHA1 const hash = new StringSHA1(); - for (const str of strings) { - hash.update(str); - } - const actual = hash.digest(); + hash.update(str); + let actual = hash.digest(); + assert.equal(actual, expected); + + // Test with crypto.subtle + actual = await sha1Hex(str); assert.equal(actual, expected); } test('sha1-1', () => { - checkSHA1(['\udd56'], '9bdb77276c1852e1fb067820472812fcf6084024'); + return checkSHA1('\udd56', '9bdb77276c1852e1fb067820472812fcf6084024'); }); test('sha1-2', () => { - checkSHA1(['\udb52'], '9bdb77276c1852e1fb067820472812fcf6084024'); + return checkSHA1('\udb52', '9bdb77276c1852e1fb067820472812fcf6084024'); }); test('sha1-3', () => { - checkSHA1(['\uda02ꑍ'], '9b483a471f22fe7e09d83f221871a987244bbd3f'); + return checkSHA1('\uda02ꑍ', '9b483a471f22fe7e09d83f221871a987244bbd3f'); }); test('sha1-4', () => { - checkSHA1(['hello'], 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'); + return checkSHA1('hello', 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'); }); }); diff --git a/src/vs/workbench/contrib/tags/browser/workspaceTagsService.ts b/src/vs/workbench/contrib/tags/browser/workspaceTagsService.ts index 2aecc6350ce..0fbc6faa520 100644 --- a/src/vs/workbench/contrib/tags/browser/workspaceTagsService.ts +++ b/src/vs/workbench/contrib/tags/browser/workspaceTagsService.ts @@ -16,7 +16,7 @@ export class NoOpWorkspaceTagsService implements IWorkspaceTagsService { return Promise.resolve({}); } - getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined { + async getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): Promise { return undefined; } diff --git a/src/vs/workbench/contrib/tags/common/workspaceTags.ts b/src/vs/workbench/contrib/tags/common/workspaceTags.ts index d1683b97726..487eb6cafb3 100644 --- a/src/vs/workbench/contrib/tags/common/workspaceTags.ts +++ b/src/vs/workbench/contrib/tags/common/workspaceTags.ts @@ -20,7 +20,7 @@ export interface IWorkspaceTagsService { * Returns an id for the workspace, different from the id returned by the context service. A hash based * on the folder uri or workspace configuration, not time-based, and undefined for empty workspaces. */ - getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined; + getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): Promise; getHashedRemotesFromUri(workspaceUri: URI, stripEndingDotGit?: boolean): Promise; } diff --git a/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts b/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts index df781b92ff2..86a913c5ef5 100644 --- a/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts +++ b/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as crypto from 'crypto'; +import { sha1Hex } from 'vs/base/common/hash'; import { onUnexpectedError } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; @@ -20,10 +20,8 @@ import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsSer import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IProductService } from 'vs/platform/product/common/productService'; -export function getHashedRemotesFromConfig(text: string, stripEndingDotGit: boolean = false): string[] { - return getRemotes(text, stripEndingDotGit).map(r => { - return crypto.createHash('sha1').update(r).digest('hex'); - }); +export async function getHashedRemotesFromConfig(text: string, stripEndingDotGit: boolean = false): Promise { + return Promise.all(getRemotes(text, stripEndingDotGit).map(remote => sha1Hex(remote))); } export class WorkspaceTags implements IWorkbenchContribution { @@ -76,7 +74,7 @@ export class WorkspaceTags implements IWorkbenchContribution { private async getWorkspaceInformation(): Promise { const workspace = this.contextService.getWorkspace(); const state = this.contextService.getWorkbenchState(); - const telemetryId = this.workspaceTagsService.getTelemetryWorkspaceId(workspace, state); + const telemetryId = await this.workspaceTagsService.getTelemetryWorkspaceId(workspace, state); return this.telemetryService.getTelemetryInfo().then(info => { return { id: workspace.id, diff --git a/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts b/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts index dffea760b9a..3900fbf25ba 100644 --- a/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts +++ b/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as crypto from 'crypto'; +import { sha1Hex } from 'vs/base/common/hash'; import { IFileService, IResolveFileResult, IFileStat } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -138,9 +138,9 @@ export class WorkspaceTagsService implements IWorkspaceTagsService { return this._tags; } - getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined { - function createHash(uri: URI): string { - return crypto.createHash('sha1').update(uri.scheme === Schemas.file ? uri.fsPath : uri.toString()).digest('hex'); + async getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): Promise { + function createHash(uri: URI): Promise { + return sha1Hex(uri.scheme === Schemas.file ? uri.fsPath : uri.toString()); } let workspaceId: string | undefined; @@ -149,11 +149,11 @@ export class WorkspaceTagsService implements IWorkspaceTagsService { workspaceId = undefined; break; case WorkbenchState.FOLDER: - workspaceId = createHash(workspace.folders[0].uri); + workspaceId = await createHash(workspace.folders[0].uri); break; case WorkbenchState.WORKSPACE: if (workspace.configuration) { - workspaceId = createHash(workspace.configuration); + workspaceId = await createHash(workspace.configuration); } } @@ -292,13 +292,13 @@ export class WorkspaceTagsService implements IWorkspaceTagsService { "workspace.py.playwright" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ - private resolveWorkspaceTags(): Promise { + private async resolveWorkspaceTags(): Promise { const tags: Tags = Object.create(null); const state = this.contextService.getWorkbenchState(); const workspace = this.contextService.getWorkspace(); - tags['workspace.id'] = this.getTelemetryWorkspaceId(workspace, state); + tags['workspace.id'] = await this.getTelemetryWorkspaceId(workspace, state); const { filesToOpenOrCreate, filesToDiff } = this.environmentService.configuration; tags['workbench.filesToOpenOrCreate'] = filesToOpenOrCreate && filesToOpenOrCreate.length || 0; diff --git a/src/vs/workbench/contrib/tags/test/electron-browser/workspaceTags.test.ts b/src/vs/workbench/contrib/tags/test/electron-browser/workspaceTags.test.ts index ed3c428daa4..faad40a9e98 100644 --- a/src/vs/workbench/contrib/tags/test/electron-browser/workspaceTags.test.ts +++ b/src/vs/workbench/contrib/tags/test/electron-browser/workspaceTags.test.ts @@ -13,35 +13,35 @@ function hash(value: string): string { suite('Telemetry - WorkspaceTags', () => { - test('Single remote hashed', function () { - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git')), [hash('github3.com/username/repository.git')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git')), [hash('git.server.org/project.git')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('user@git.server.org:project.git')), [hash('git.server.org/project.git')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('/opt/git/project.git')), []); + test('Single remote hashed', async function () { + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git')), [hash('github3.com/username/repository.git')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git')), [hash('git.server.org/project.git')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('user@git.server.org:project.git')), [hash('git.server.org/project.git')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('/opt/git/project.git')), []); // Strip .git - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git'), true), [hash('github3.com/username/repository')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git'), true), [hash('git.server.org/project')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('user@git.server.org:project.git'), true), [hash('git.server.org/project')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('/opt/git/project.git'), true), []); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git'), true), [hash('github3.com/username/repository')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git'), true), [hash('git.server.org/project')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('user@git.server.org:project.git'), true), [hash('git.server.org/project')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('/opt/git/project.git'), true), []); // Compare Striped .git with no .git - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git'), true), getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository'))); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git'), true), getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project'))); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('user@git.server.org:project.git'), true), [hash('git.server.org/project')]); - assert.deepStrictEqual(getHashedRemotesFromConfig(remote('/opt/git/project.git'), true), getHashedRemotesFromConfig(remote('/opt/git/project'))); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository.git'), true), await getHashedRemotesFromConfig(remote('https://username:password@github3.com/username/repository'))); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project.git'), true), await getHashedRemotesFromConfig(remote('ssh://user@git.server.org/project'))); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('user@git.server.org:project.git'), true), [hash('git.server.org/project')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(remote('/opt/git/project.git'), true), await getHashedRemotesFromConfig(remote('/opt/git/project'))); }); - test('Multiple remotes hashed', function () { + test('Multiple remotes hashed', async function () { const config = ['https://github.com/microsoft/vscode.git', 'https://git.example.com/gitproject.git'].map(remote).join(' '); - assert.deepStrictEqual(getHashedRemotesFromConfig(config), [hash('github.com/microsoft/vscode.git'), hash('git.example.com/gitproject.git')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(config), [hash('github.com/microsoft/vscode.git'), hash('git.example.com/gitproject.git')]); // Strip .git - assert.deepStrictEqual(getHashedRemotesFromConfig(config, true), [hash('github.com/microsoft/vscode'), hash('git.example.com/gitproject')]); + assert.deepStrictEqual(await getHashedRemotesFromConfig(config, true), [hash('github.com/microsoft/vscode'), hash('git.example.com/gitproject')]); // Compare Striped .git with no .git const noDotGitConfig = ['https://github.com/microsoft/vscode', 'https://git.example.com/gitproject'].map(remote).join(' '); - assert.deepStrictEqual(getHashedRemotesFromConfig(config, true), getHashedRemotesFromConfig(noDotGitConfig)); + assert.deepStrictEqual(await getHashedRemotesFromConfig(config, true), await getHashedRemotesFromConfig(noDotGitConfig)); }); function remote(url: string): string { diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index d2ce5a454f8..ada7a23fa4d 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -742,7 +742,7 @@ class SimpleWorkspaceTagsService implements IWorkspaceTagsService { declare readonly _serviceBrand: undefined; async getTags(): Promise { return Object.create(null); } - getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined { return undefined; } + async getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): Promise { return undefined; } async getHashedRemotesFromUri(workspaceUri: URI, stripEndingDotGit?: boolean): Promise { return []; } } From 1efcfbf24275a1f1b1d493d542ce22bd7b5db3b6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 28 Nov 2020 12:30:11 +0100 Subject: [PATCH 0412/1837] api - fix exception in status bar --- src/vs/workbench/api/common/extHostStatusBar.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index 317c788e332..aa0b5df6cdb 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -79,10 +79,6 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { } public get backgroundColor(): ThemeColor | undefined { - if (this._extension) { - checkProposedApiEnabled(this._extension); - } - return this._backgroundColor; } From 673c1adcb0621ddc12e793c56be93d831fe7ff1d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 28 Nov 2020 14:03:38 +0100 Subject: [PATCH 0413/1837] fix layer breaker --- src/vs/base/browser/hash.ts | 25 +++++++++++++++++++ src/vs/base/common/hash.ts | 25 +++---------------- .../test/{common => browser}/hash.test.ts | 3 ++- .../tags/electron-browser/workspaceTags.ts | 2 +- .../electron-browser/workspaceTagsService.ts | 2 +- 5 files changed, 32 insertions(+), 25 deletions(-) create mode 100644 src/vs/base/browser/hash.ts rename src/vs/base/test/{common => browser}/hash.test.ts (97%) diff --git a/src/vs/base/browser/hash.ts b/src/vs/base/browser/hash.ts new file mode 100644 index 00000000000..bf48b614b15 --- /dev/null +++ b/src/vs/base/browser/hash.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 { VSBuffer } from 'vs/base/common/buffer'; +import { StringSHA1, toHexString } from 'vs/base/common/hash'; + +export async function sha1Hex(str: string): Promise { + + // Prefer to use browser's crypto module + if (globalThis?.crypto?.subtle) { + const hash = await globalThis.crypto.subtle.digest({ name: 'sha-1' }, VSBuffer.fromString(str).buffer); + + return toHexString(hash); + } + + // Otherwise fallback to `StringSHA1` + else { + const computer = new StringSHA1(); + computer.update(str); + + return computer.digest(); + } +} diff --git a/src/vs/base/common/hash.ts b/src/vs/base/common/hash.ts index 0de970f1218..b39581a840e 100644 --- a/src/vs/base/common/hash.ts +++ b/src/vs/base/common/hash.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSBuffer } from 'vs/base/common/buffer'; import * as strings from 'vs/base/common/strings'; /** @@ -107,9 +106,9 @@ function leftPad(value: string, length: number, char: string = '0'): string { return value; } -function toHexString(buffer: ArrayBuffer): string; -function toHexString(value: number, bitsize?: number): string; -function toHexString(bufferOrValue: ArrayBuffer | number, bitsize: number = 32): string { +export function toHexString(buffer: ArrayBuffer): string; +export function toHexString(value: number, bitsize?: number): string; +export function toHexString(bufferOrValue: ArrayBuffer | number, bitsize: number = 32): string { if (bufferOrValue instanceof ArrayBuffer) { return Array.from(new Uint8Array(bufferOrValue)).map(b => b.toString(16).padStart(2, '0')).join(''); } @@ -315,21 +314,3 @@ export class StringSHA1 { this._h4 = (this._h4 + e) & 0xffffffff; } } - -export async function sha1Hex(str: string): Promise { - - // Prefer to use browser's crypto module - if (globalThis?.crypto?.subtle) { - const hash = await globalThis.crypto.subtle.digest({ name: 'sha-1' }, VSBuffer.fromString(str).buffer); - - return toHexString(hash); - } - - // Otherwise fallback to `StringSHA1` - else { - const computer = new StringSHA1(); - computer.update(str); - - return computer.digest(); - } -} diff --git a/src/vs/base/test/common/hash.test.ts b/src/vs/base/test/browser/hash.test.ts similarity index 97% rename from src/vs/base/test/common/hash.test.ts rename to src/vs/base/test/browser/hash.test.ts index bfd8fd942f5..68ee17eebd9 100644 --- a/src/vs/base/test/common/hash.test.ts +++ b/src/vs/base/test/browser/hash.test.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { hash, sha1Hex, StringSHA1 } from 'vs/base/common/hash'; +import { hash, StringSHA1 } from 'vs/base/common/hash'; +import { sha1Hex } from 'vs/base/browser/hash'; suite('Hash', () => { test('string', () => { diff --git a/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts b/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts index 86a913c5ef5..726575e8298 100644 --- a/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts +++ b/src/vs/workbench/contrib/tags/electron-browser/workspaceTags.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { sha1Hex } from 'vs/base/common/hash'; +import { sha1Hex } from 'vs/base/browser/hash'; import { onUnexpectedError } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; diff --git a/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts b/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts index 3900fbf25ba..bf203f81c44 100644 --- a/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts +++ b/src/vs/workbench/contrib/tags/electron-browser/workspaceTagsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { sha1Hex } from 'vs/base/common/hash'; +import { sha1Hex } from 'vs/base/browser/hash'; import { IFileService, IResolveFileResult, IFileStat } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; From cedc2850ec5e15961c3e9f8199eec17d1ac5c17b Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 30 Nov 2020 10:25:55 +0100 Subject: [PATCH 0414/1837] Exclude testplan-item label --- .vscode/notebooks/endgame.github-issues | 2 +- .vscode/notebooks/my-endgame.github-issues | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index d01f9ef76e0..35a22f829eb 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -38,7 +38,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan -label:endgame-plan", + "value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan -label:endgame-plan -label:testplan-item", "editable": true }, { diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index a8d1bbbc07d..7e4f06e5720 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -38,7 +38,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan -label:endgame-plan", + "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan -label:endgame-plan -label:testplan-item", "editable": true }, { From a4054cda6db164b2bf6acc0473635484697884d7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 10:40:15 +0100 Subject: [PATCH 0415/1837] update references viewlet, also no more proposed API usage required --- product.json | 3 +-- src/vs/platform/product/common/product.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/product.json b/product.json index 2d2bb2c605a..c8a1e8132b1 100644 --- a/product.json +++ b/product.json @@ -25,7 +25,6 @@ "extensionAllowedProposedApi": [ "ms-vscode.vscode-js-profile-flame", "ms-vscode.vscode-js-profile-table", - "ms-vscode.references-view", "ms-vscode.github-browser", "ms-vscode.github-richnav" ], @@ -62,7 +61,7 @@ }, { "name": "ms-vscode.references-view", - "version": "0.0.73", + "version": "0.0.74", "repo": "https://github.com/microsoft/vscode-reference-view", "metadata": { "id": "dc489f46-520d-4556-ae85-1f9eab3c412d", diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts index a4667fd0b2c..56fbc68add0 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -32,7 +32,6 @@ if (isWeb || typeof require === 'undefined' || typeof require.__$__nodeRequire ! extensionAllowedProposedApi: [ 'ms-vscode.vscode-js-profile-flame', 'ms-vscode.vscode-js-profile-table', - 'ms-vscode.references-view', 'ms-vscode.github-browser' ], }); From 9172ecfad80793f08663a21a58766af4a6a7c95f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 10:44:27 +0100 Subject: [PATCH 0416/1837] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7998a654b6f..4b0bddd622e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "19950a29d290a699141f8328af0c457dc0a9f204", + "distro": "31b3b5d0cd5021b72f02225b9016b1777f94f4d1", "author": { "name": "Microsoft Corporation" }, From b7211aa875a698d43caecd24db462af4a417b602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 30 Nov 2020 10:49:03 +0100 Subject: [PATCH 0417/1837] fixes #107651 --- src/vs/base/common/resourceTree.ts | 12 ++++++------ src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/base/common/resourceTree.ts b/src/vs/base/common/resourceTree.ts index 23f661e1b80..96cdee54c72 100644 --- a/src/vs/base/common/resourceTree.ts +++ b/src/vs/base/common/resourceTree.ts @@ -5,7 +5,7 @@ import { memoize } from 'vs/base/common/decorators'; import * as paths from 'vs/base/common/path'; -import { relativePath, joinPath } from 'vs/base/common/resources'; +import { IExtUri, extUri as defaultExtUri } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { PathIterator } from 'vs/base/common/map'; @@ -95,12 +95,12 @@ export class ResourceTree, C> { return obj instanceof Node; } - constructor(context: C, rootURI: URI = URI.file('/')) { + constructor(context: C, rootURI: URI = URI.file('/'), private extUri: IExtUri = defaultExtUri) { this.root = new Node(rootURI, '', context); } add(uri: URI, element: T): void { - const key = relativePath(this.root.uri, uri) || uri.fsPath; + const key = this.extUri.relativePath(this.root.uri, uri) || uri.path; const iterator = new PathIterator(false).reset(key); let node = this.root; let path = ''; @@ -113,7 +113,7 @@ export class ResourceTree, C> { if (!child) { child = new Node( - joinPath(this.root.uri, path), + this.extUri.joinPath(this.root.uri, path), path, this.root.context, iterator.hasNext() ? undefined : element, @@ -136,7 +136,7 @@ export class ResourceTree, C> { } delete(uri: URI): T | undefined { - const key = relativePath(this.root.uri, uri) || uri.fsPath; + const key = this.extUri.relativePath(this.root.uri, uri) || uri.path; const iterator = new PathIterator(false).reset(key); return this._delete(this.root, iterator); } @@ -168,7 +168,7 @@ export class ResourceTree, C> { } getNode(uri: URI): IResourceNode | undefined { - const key = relativePath(this.root.uri, uri) || uri.fsPath; + const key = this.extUri.relativePath(this.root.uri, uri) || uri.path; const iterator = new PathIterator(false).reset(key); let node = this.root; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 3f54b418d40..ed947e74315 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -888,7 +888,7 @@ class ViewModel { } private createGroupItem(group: ISCMResourceGroup): IGroupItem { - const tree = new ResourceTree(group, group.provider.rootUri || URI.file('/')); + const tree = new ResourceTree(group, group.provider.rootUri || URI.file('/'), this.uriIdentityService.extUri); const resources: ISCMResource[] = [...group.elements]; const disposable = combinedDisposable( group.onDidChange(() => this.tree.refilter()), @@ -1049,7 +1049,7 @@ class ViewModel { for (let j = item.groupItems.length - 1; j >= 0; j--) { const groupItem = item.groupItems[j]; const resource = this.mode === ViewModelMode.Tree - ? groupItem.tree.getNode(uri)?.element // TODO@Joao URI identity? + ? groupItem.tree.getNode(uri)?.element : groupItem.resources.find(r => this.uriIdentityService.extUri.isEqual(r.sourceUri, uri)); if (resource) { From 2018df47d803f44f039955defd66607f2a3045f2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 11:22:45 +0100 Subject: [PATCH 0418/1837] support font features, like ligatures, in code lens, https://github.com/microsoft/vscode/issues/16038 --- src/vs/editor/contrib/codelens/codelensController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index ef85298bbb3..9b3102c61b0 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -96,9 +96,10 @@ export class CodeLensContribution implements IEditorContribution { const { codeLensHeight, fontSize } = this._getLayoutInfo(); const fontFamily = this._editor.getOption(EditorOption.codeLensFontFamily); + const editorFontInfo = this._editor.getOption(EditorOption.fontInfo); let newStyle = ` - .monaco-editor .codelens-decoration.${this._styleClassName} { line-height: ${codeLensHeight}px; font-size: ${fontSize}px; padding-right: ${Math.round(fontSize * 0.5)}px;} + .monaco-editor .codelens-decoration.${this._styleClassName} { line-height: ${codeLensHeight}px; font-size: ${fontSize}px; padding-right: ${Math.round(fontSize * 0.5)}px; font-feature-settings: ${editorFontInfo.fontFeatureSettings} } .monaco-editor .codelens-decoration.${this._styleClassName} span.codicon { line-height: ${codeLensHeight}px; font-size: ${fontSize}px; } `; if (fontFamily) { From eee332ba857029a123d032a21fbb7f5b470dcca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 30 Nov 2020 11:41:47 +0100 Subject: [PATCH 0419/1837] fix misuse of VSCODE_ARCH in builds --- .../azure-pipelines/darwin/product-build-darwin.yml | 2 +- build/azure-pipelines/linux/product-build-linux.yml | 4 ++-- build/azure-pipelines/product-compile.yml | 2 +- build/azure-pipelines/win32/product-build-win32.yml | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index dfc53ed2382..659181ef46f 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -4,7 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $VSCODE_ARCH > .build/arch + echo -n $(VSCODE_ARCH) > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 9d58ce2323c..17d64b58ade 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -4,7 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $VSCODE_ARCH > .build/arch + echo -n $(VSCODE_ARCH) > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -68,7 +68,7 @@ steps: - script: | set -e - export npm_config_arch=$(VSCODE_ARCH) + export npm_config_arch=$(NPM_ARCH) export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 4061145d101..fb1af112c2d 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -4,7 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $VSCODE_ARCH > .build/arch + echo -n $(VSCODE_ARCH) > .build/arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 804c6970ef4..92aed795411 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -4,7 +4,7 @@ steps: "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin - "$env:VSCODE_ARCH" | Out-File -Encoding ascii -NoNewLine .build\arch + "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch displayName: Prepare cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -103,9 +103,9 @@ steps: . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } - exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } + exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-min-ci" } + exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-code-helper" } + exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-inno-updater" } echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" displayName: Build @@ -113,8 +113,8 @@ steps: . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" - exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } - exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-win32-$(VSCODE_ARCH)-min-ci" } + exec { yarn gulp "vscode-reh-web-win32-$(VSCODE_ARCH)-min-ci" } echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(CodeSigningFolderPath),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)" displayName: Build Server condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64')) From a5a37240bc27b74afbcb6773a3ac15df8408d1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 30 Nov 2020 11:51:01 +0100 Subject: [PATCH 0420/1837] fixes #108001 --- extensions/github/src/publish.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index b1719635c96..cf8f306cf2d 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -149,7 +149,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) new Promise(c => quickpick.onDidHide(() => c(undefined))) ]); - if (!result) { + if (!result || result.length === 0) { return; } From 2890fd321f61fb7174a942c3efd651f7ea2cff14 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 30 Nov 2020 11:58:43 +0100 Subject: [PATCH 0421/1837] Fix #111485 --- .../contrib/extensions/browser/extensionsActions.ts | 8 ++++++++ src/vs/workbench/contrib/extensions/common/extensions.ts | 2 +- test/automation/src/extensions.ts | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index b9221cc2a45..503be3e29f8 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -173,6 +173,10 @@ export class ActionWithDropDownAction extends ExtensionAction { private _menuActions: IAction[] = []; get menuActions(): IAction[] { return [...this._menuActions]; } + get extension(): IExtension | null { + return super.extension; + } + set extension(extension: IExtension | null) { this.actions.forEach(a => a.extension = extension); super.extension = extension; @@ -1052,6 +1056,7 @@ export class EnableForWorkspaceAction extends ExtensionAction { @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService ) { super(EnableForWorkspaceAction.ID, EnableForWorkspaceAction.LABEL, ExtensionAction.LABEL_ACTION_CLASS); + this.tooltip = localize('enableForWorkspaceActionToolTip', "Enable this extension only in this workspace"); this.update(); } @@ -1082,6 +1087,7 @@ export class EnableGloballyAction extends ExtensionAction { @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService ) { super(EnableGloballyAction.ID, EnableGloballyAction.LABEL, ExtensionAction.LABEL_ACTION_CLASS); + this.tooltip = localize('enableGloballyActionToolTip', "Enable this extension"); this.update(); } @@ -1113,6 +1119,7 @@ export class DisableForWorkspaceAction extends ExtensionAction { @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService ) { super(DisableForWorkspaceAction.ID, DisableForWorkspaceAction.LABEL, ExtensionAction.LABEL_ACTION_CLASS); + this.tooltip = localize('disableForWorkspaceActionToolTip', "Disable this extension only in this workspace"); this.update(); } @@ -1149,6 +1156,7 @@ export class DisableGloballyAction extends ExtensionAction { @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService ) { super(DisableGloballyAction.ID, DisableGloballyAction.LABEL, ExtensionAction.LABEL_ACTION_CLASS); + this.tooltip = localize('disableGloballyActionToolTip', "Disable this extension"); this.update(); } diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index 8e9b55d097f..ce659f87495 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -130,7 +130,7 @@ export class ExtensionContainers extends Disposable { for (const container of this.containers) { if (extension && container.extension) { if (areSameExtensions(container.extension.identifier, extension.identifier)) { - if (!container.extension.server || !extension.server || container.extension.server === extension.server) { + if (!container.extension.server || !extension.server || container.extension.server === extension.server || (!!container.extension.local !== !!extension.local)) { container.extension = extension; } else if (container.updateWhenCounterExtensionChanges) { container.update(); diff --git a/test/automation/src/extensions.ts b/test/automation/src/extensions.ts index b23f961e754..cd4a7297871 100644 --- a/test/automation/src/extensions.ts +++ b/test/automation/src/extensions.ts @@ -37,6 +37,6 @@ export class Extensions extends Viewlet { async installExtension(id: string): Promise { await this.searchForExtension(id); await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[data-extension-id="${id}"] .extension-list-item .monaco-action-bar .action-item:not(.disabled) .extension-action.install`); - await this.code.waitForElement(`.extension-editor .monaco-action-bar .action-item:not(.disabled) .extension-action.uninstall`); + await this.code.waitForElement(`.extension-editor .monaco-action-bar .action-item:not(.disabled) .extension-action[title="Disable this extension"]`); } } From 8ce73561049510d1333046fbf00ed0d79432b753 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 30 Nov 2020 12:05:00 +0100 Subject: [PATCH 0422/1837] Fix defaultFolderPath so that userhome is correct --- .../services/dialogs/browser/abstractFileDialogService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts index 508de8442bf..a105daa0957 100644 --- a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts @@ -76,10 +76,10 @@ export abstract class AbstractFileDialogService implements IFileDialogService { } if (!candidate) { - candidate = await this.pathService.userHome({ preferLocal: schemeFilter === Schemas.file }); + return this.pathService.userHome({ preferLocal: schemeFilter === Schemas.file }); + } else { + return candidate && resources.dirname(candidate); } - - return candidate && resources.dirname(candidate) || undefined; } async defaultWorkspacePath(schemeFilter = this.getSchemeFilterForWindow(), filename?: string): Promise { From 0f1492d6da90551ade83aa40ec140e0409356fa2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 12:36:11 +0100 Subject: [PATCH 0423/1837] chore - remove unneccessary non null assertions --- .../browser/contrib/find/findController.ts | 2 +- .../browser/diff/notebookTextDiffEditor.ts | 6 ++-- .../notebook/browser/notebookServiceImpl.ts | 6 ++-- .../browser/view/renderers/cellOutput.ts | 10 +++---- .../browser/view/renderers/cellRenderer.ts | 4 +-- .../browser/view/renderers/codeCell.ts | 30 +++++++++---------- .../browser/view/renderers/markdownCell.ts | 2 +- .../browser/viewModel/notebookViewModel.ts | 2 +- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts index 71f74948655..fdabea9f6f1 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts @@ -114,7 +114,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote if (!this._findMatchesStarts) { this.set(this._findMatches, true); } else { - const totalVal = this._findMatchesStarts!.getTotalValue(); + const totalVal = this._findMatchesStarts.getTotalValue(); const nextVal = (this._currentMatch + (previous ? -1 : 1) + totalVal) % totalVal; this._currentMatch = nextVal; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index f76debaba65..13f6973c074 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -163,7 +163,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return; } - if (e.contains(this._model!.modified.resource)) { + if (e.contains(this._model.modified.resource)) { if (this._model.modified.isDirty()) { return; } @@ -179,7 +179,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } } - if (e.contains(this._model!.original.resource)) { + if (e.contains(this._model.original.resource)) { if (this._model.original.isDirty()) { return; } @@ -328,7 +328,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD layoutNotebookCell(cell: CellDiffViewModel, height: number) { const relayout = (cell: CellDiffViewModel, height: number) => { - const viewIndex = this._list!.indexOf(cell); + const viewIndex = this._list.indexOf(cell); this._list?.updateElementHeight(viewIndex, height); }; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index c2c20888e16..ec00de5615a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -993,11 +993,11 @@ export class NotebookService extends Disposable implements INotebookService, ICu if (modelData) { // delete editors and documents const willRemovedEditors: INotebookEditor[] = []; - this._notebookEditors.forEach(editor => { - if (editor.textModel === modelData!.model) { + for (const editor of this._notebookEditors.values()) { + if (editor.textModel === modelData.model) { willRemovedEditors.push(editor); } - }); + } modelData.model.dispose(); modelData.dispose(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index f2dbc30f49e..acf48c84af0 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -286,7 +286,7 @@ export class OutputContainer extends Disposable { this._relayoutCell(); } - this.templateData.outputContainer!.style.display = 'block'; + this.templateData.outputContainer.style.display = 'block'; // there are outputs, we need to calcualte their sizes and trigger relayout // @TODO@rebornix, if there is no resizable output, we should not check their height individually, which hurts the performance const outputsToRender = this._calcuateOutputsToRender(); @@ -312,7 +312,7 @@ export class OutputContainer extends Disposable { // noop this.viewCell.editorHeight = editorHeight; this._relayoutCell(); - this.templateData.outputContainer!.style.display = 'none'; + this.templateData.outputContainer.style.display = 'none'; } this.templateData.outputShowMoreContainer.innerText = ''; @@ -406,9 +406,9 @@ export class OutputContainer extends Disposable { const previousOutputHeight = this.viewCell.layoutInfo.outputTotalHeight; if (this.viewCell.outputs.length) { - this.templateData.outputContainer!.style.display = 'block'; + this.templateData.outputContainer.style.display = 'block'; } else { - this.templateData.outputContainer!.style.display = 'none'; + this.templateData.outputContainer.style.display = 'none'; } const reversedSplices = splices.reverse(); @@ -457,7 +457,7 @@ export class OutputContainer extends Disposable { this.templateData.outputShowMoreContainer.style.display = 'none'; } - const editorHeight = this.templateData.editor!.getContentHeight(); + const editorHeight = this.templateData.editor.getContentHeight(); this.viewCell.editorHeight = editorHeight; if (previousOutputHeight === 0 || this.viewCell.outputs.length === 0) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 853f0351a2d..0709ca09e93 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -454,7 +454,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } private getDragImage(templateData: MarkdownCellRenderTemplate): HTMLElement { - if (templateData.currentRenderedCell!.editState === CellEditState.Editing) { + if (templateData.currentRenderedCell?.editState === CellEditState.Editing) { return this.getEditDragImage(templateData); } else { return this.getMarkdownDragImage(templateData); @@ -501,7 +501,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR templateData.currentRenderedCell = element; templateData.currentEditor = undefined; - templateData.editorPart!.style.display = 'none'; + templateData.editorPart.style.display = 'none'; templateData.cellContainer.innerText = ''; if (height === undefined) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 4c34e365b73..56869eb8308 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -94,10 +94,10 @@ export class CodeCell extends Disposable { })); updateForFocusMode(); - templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel!.metadata).editable) }); + templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel.metadata).editable) }); this._register(viewCell.onDidChangeState((e) => { if (e.metadataChanged) { - templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel!.metadata).editable) }); + templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel.metadata).editable) }); // TODO@rob this isn't nice this.viewCell.layoutChange({}); @@ -115,14 +115,14 @@ export class CodeCell extends Disposable { this._register(viewCell.onDidChangeLayout((e) => { if (e.outerWidth !== undefined) { - const layoutInfo = templateData.editor!.getLayoutInfo(); + const layoutInfo = templateData.editor.getLayoutInfo(); if (layoutInfo.width !== viewCell.layoutInfo.editorWidth) { this.onCellWidthChange(); } } })); - this._register(templateData.editor!.onDidContentSizeChange((e) => { + this._register(templateData.editor.onDidContentSizeChange((e) => { if (e.contentHeightChanged) { if (this.viewCell.layoutInfo.editorHeight !== e.contentHeight) { this.onCellHeightChange(e.contentHeight); @@ -130,16 +130,16 @@ export class CodeCell extends Disposable { } })); - this._register(templateData.editor!.onDidChangeCursorSelection((e) => { + this._register(templateData.editor.onDidChangeCursorSelection((e) => { if (e.source === 'restoreState') { // do not reveal the cell into view if this selection change was caused by restoring editors... return; } - const primarySelection = templateData.editor!.getSelection(); + const primarySelection = templateData.editor.getSelection(); if (primarySelection) { - this.notebookEditor.revealLineInViewAsync(viewCell, primarySelection!.positionLineNumber); + this.notebookEditor.revealLineInViewAsync(viewCell, primarySelection.positionLineNumber); } })); @@ -187,7 +187,7 @@ export class CodeCell extends Disposable { } })); - this._register(templateData.editor!.onMouseDown(e => { + this._register(templateData.editor.onMouseDown(e => { // prevent default on right mouse click, otherwise it will trigger unexpected focus changes // the catch is, it means we don't allow customization of right button mouse down handlers other than the built in ones. if (e.event.rightButton) { @@ -196,11 +196,11 @@ export class CodeCell extends Disposable { })); // Focus Mode - const updateFocusMode = () => viewCell.focusMode = templateData.editor!.hasWidgetFocus() ? CellFocusMode.Editor : CellFocusMode.Container; - this._register(templateData.editor!.onDidFocusEditorWidget(() => { + const updateFocusMode = () => viewCell.focusMode = templateData.editor.hasWidgetFocus() ? CellFocusMode.Editor : CellFocusMode.Container; + this._register(templateData.editor.onDidFocusEditorWidget(() => { updateFocusMode(); })); - this._register(templateData.editor!.onDidBlurEditorWidget(() => { + this._register(templateData.editor.onDidBlurEditorWidget(() => { // this is for a special case: // users click the status bar empty space, which we will then focus the editor // so we don't want to update the focus state too eagerly @@ -268,7 +268,7 @@ export class CodeCell extends Disposable { // } // }; - this._register(this.notebookEditor.viewModel!.notebookDocument.onDidChangeContent(e => { + this._register(this.notebookEditor.viewModel.notebookDocument.onDidChangeContent(e => { if (e.rawEvents.find(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata)) { updatePlaceholder(); // updateUntrustedStatus(); @@ -344,7 +344,7 @@ export class CodeCell extends Disposable { } private onCellWidthChange(): void { - const realContentHeight = this.templateData.editor!.getContentHeight(); + const realContentHeight = this.templateData.editor.getContentHeight(); this.viewCell.editorHeight = realContentHeight; this.relayoutCell(); @@ -360,7 +360,7 @@ export class CodeCell extends Disposable { } private onCellHeightChange(newHeight: number): void { - const viewLayout = this.templateData.editor!.getLayoutInfo(); + const viewLayout = this.templateData.editor.getLayoutInfo(); this.viewCell.editorHeight = newHeight; this.relayoutCell(); this.layoutEditor( @@ -397,7 +397,7 @@ export class CodeCell extends Disposable { this._outputContainerRenderer.dispose(); this._activeCellRunPlaceholder?.dispose(); this._untrustedStatusItem?.dispose(); - this.templateData.focusIndicatorLeft!.style.height = 'initial'; + this.templateData.focusIndicatorLeft.style.height = 'initial'; super.dispose(); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index a22aa498c49..07867e40047 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -388,7 +388,7 @@ export class StatefulMarkdownCell extends Disposable { const primarySelection = editor.getSelection(); if (primarySelection) { - this.notebookEditor.revealLineInViewAsync(this.viewCell, primarySelection!.positionLineNumber); + this.notebookEditor.revealLineInViewAsync(this.viewCell, primarySelection.positionLineNumber); } })); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 86a16531394..d1843f21d34 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -352,7 +352,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD }); })); - this._viewCells = this._notebook!.cells.map(cell => { + this._viewCells = this._notebook.cells.map(cell => { return createCellViewModel(this._instantiationService, this, cell); }); From f5fb75d82916e54ef0ec6488627eb4dc1d56fabf Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 30 Nov 2020 12:43:49 +0100 Subject: [PATCH 0424/1837] fix tests --- src/vs/workbench/contrib/extensions/common/extensions.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index ce659f87495..3cfe2796ce3 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -130,10 +130,12 @@ export class ExtensionContainers extends Disposable { for (const container of this.containers) { if (extension && container.extension) { if (areSameExtensions(container.extension.identifier, extension.identifier)) { - if (!container.extension.server || !extension.server || container.extension.server === extension.server || (!!container.extension.local !== !!extension.local)) { + if (container.extension.server && extension.server && container.extension.server !== extension.server) { + if (container.updateWhenCounterExtensionChanges) { + container.update(); + } + } else { container.extension = extension; - } else if (container.updateWhenCounterExtensionChanges) { - container.update(); } } } else { From 2c5901053adbee967294b446ec777ba155fd0890 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 30 Nov 2020 14:31:39 +0100 Subject: [PATCH 0425/1837] spelling error in command name (fix #111455) --- .../extensions/electron-browser/extensionProfileService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts index 1befb2a7fdc..ff347a59dc5 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts @@ -56,7 +56,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio this._profileSession = null; this._setState(ProfileSessionState.None); - CommandsRegistry.registerCommand('workbench.action.extensionHostProfilder.stop', () => { + CommandsRegistry.registerCommand('workbench.action.extensionHostProfiler.stop', () => { this.stopProfiling(); this._editorService.openEditor(RuntimeExtensionsInput.instance, { revealIfOpened: true, pinned: true }); }); @@ -86,7 +86,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio showProgress: true, ariaLabel: nls.localize('profilingExtensionHost', "Profiling Extension Host"), tooltip: nls.localize('selectAndStartDebug', "Click to stop profiling."), - command: 'workbench.action.extensionHostProfilder.stop' + command: 'workbench.action.extensionHostProfiler.stop' }; const timeStarted = Date.now(); From aa36c6211b9ac78e8a08f9c88792019ed243c6bc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 14:50:31 +0100 Subject: [PATCH 0426/1837] move duplicated code into central place --- src/vs/base/common/collections.ts | 30 ++++++++++++++ .../browser/mainThreadDocumentsAndEditors.ts | 39 ++----------------- .../api/browser/mainThreadNotebook.ts | 39 ++----------------- 3 files changed, 37 insertions(+), 71 deletions(-) diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index 8729b7303ae..f97dc23f638 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -76,7 +76,37 @@ export function fromMap(original: Map): IStringDictionary { return result; } +export function diffSets(before: Set, after: Set): { removed: T[], added: T[] } { + const removed: T[] = []; + const added: T[] = []; + for (let element of before) { + if (!after.has(element)) { + removed.push(element); + } + } + for (let element of after) { + if (!before.has(element)) { + added.push(element); + } + } + return { removed, added }; +} +export function diffMaps(before: Map, after: Map): { removed: V[], added: V[] } { + const removed: V[] = []; + const added: V[] = []; + for (let [index, value] of before) { + if (!after.has(index)) { + removed.push(value); + } + } + for (let [index, value] of after) { + if (!before.has(index)) { + added.push(value); + } + } + return { removed, added }; +} export class SetMap { private map = new Map>(); diff --git a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts index ed55ed547b1..2425212149e 100644 --- a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts @@ -30,41 +30,8 @@ import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/commo import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; +import { diffSets, diffMaps } from 'vs/base/common/collections'; -namespace delta { - - export function ofSets(before: Set, after: Set): { removed: T[], added: T[] } { - const removed: T[] = []; - const added: T[] = []; - for (let element of before) { - if (!after.has(element)) { - removed.push(element); - } - } - for (let element of after) { - if (!before.has(element)) { - added.push(element); - } - } - return { removed, added }; - } - - export function ofMaps(before: Map, after: Map): { removed: V[], added: V[] } { - const removed: V[] = []; - const added: V[] = []; - for (let [index, value] of before) { - if (!after.has(index)) { - removed.push(value); - } - } - for (let [index, value] of after) { - if (!before.has(index)) { - added.push(value); - } - } - return { removed, added }; - } -} class TextEditorSnapshot { @@ -117,8 +84,8 @@ class DocumentAndEditorState { undefined, after.activeEditor ); } - const documentDelta = delta.ofSets(before.documents, after.documents); - const editorDelta = delta.ofMaps(before.textEditors, after.textEditors); + const documentDelta = diffSets(before.documents, after.documents); + const editorDelta = diffMaps(before.textEditors, after.textEditors); const oldActiveEditor = before.activeEditor !== after.activeEditor ? before.activeEditor : undefined; const newActiveEditor = before.activeEditor !== after.activeEditor ? after.activeEditor : undefined; diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 61521a984a2..cbf34422d3d 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -5,6 +5,7 @@ import * as DOM from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { diffMaps, diffSets } from 'vs/base/common/collections'; import { Emitter } from 'vs/base/common/event'; import { IRelativePattern } from 'vs/base/common/glob'; import { combinedDisposable, Disposable, DisposableStore, dispose, IDisposable, IReference } from 'vs/base/common/lifecycle'; @@ -34,38 +35,6 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookModelAddedData, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol'; class DocumentAndEditorState { - static ofSets(before: Set, after: Set): { removed: T[], added: T[] } { - const removed: T[] = []; - const added: T[] = []; - before.forEach(element => { - if (!after.has(element)) { - removed.push(element); - } - }); - after.forEach(element => { - if (!before.has(element)) { - added.push(element); - } - }); - return { removed, added }; - } - - static ofMaps(before: Map, after: Map): { removed: V[], added: V[] } { - const removed: V[] = []; - const added: V[] = []; - before.forEach((value, index) => { - if (!after.has(index)) { - removed.push(value); - } - }); - after.forEach((value, index) => { - if (!before.has(index)) { - added.push(value); - } - }); - return { removed, added }; - } - static compute(before: DocumentAndEditorState | undefined, after: DocumentAndEditorState): INotebookDocumentsAndEditorsDelta { if (!before) { const apiEditors = []; @@ -80,8 +49,8 @@ class DocumentAndEditorState { visibleEditors: [...after.visibleEditors].map(editor => editor[0]) }; } - const documentDelta = DocumentAndEditorState.ofSets(before.documents, after.documents); - const editorDelta = DocumentAndEditorState.ofMaps(before.textEditors, after.textEditors); + const documentDelta = diffSets(before.documents, after.documents); + const editorDelta = diffMaps(before.textEditors, after.textEditors); const addedAPIEditors = editorDelta.added.map(add => ({ id: add.getId(), documentUri: add.uri!, @@ -94,7 +63,7 @@ class DocumentAndEditorState { // const oldActiveEditor = before.activeEditor !== after.activeEditor ? before.activeEditor : undefined; const newActiveEditor = before.activeEditor !== after.activeEditor ? after.activeEditor : undefined; - const visibleEditorDelta = DocumentAndEditorState.ofMaps(before.visibleEditors, after.visibleEditors); + const visibleEditorDelta = diffMaps(before.visibleEditors, after.visibleEditors); return { addedDocuments: documentDelta.added.map((e: NotebookTextModel): INotebookModelAddedData => { From 648090440f8edcce9ccf6c9da0e96d37c37ef82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 30 Nov 2020 14:56:10 +0100 Subject: [PATCH 0427/1837] caching is HARD --- build/azure-pipelines/darwin/product-build-darwin.yml | 7 +++++-- build/azure-pipelines/linux/product-build-alpine.yml | 7 +++++-- build/azure-pipelines/linux/product-build-linux.yml | 7 +++++-- build/azure-pipelines/web/product-build-web.yml | 7 +++++-- build/azure-pipelines/win32/product-build-win32.yml | 7 +++++-- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 659181ef46f..3c11fd0ed0f 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -4,8 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare cache flag + displayName: Prepare compilation cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: @@ -67,6 +66,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index a95fc03488a..8108ff8193d 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -4,8 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n "alpine" > .build/arch - displayName: Prepare cache flag + displayName: Prepare compilation cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: @@ -70,6 +69,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - script: | + echo -n "alpine" > .build/arch + displayName: Prepare yarn cache flags + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 17d64b58ade..904fc6dda02 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -4,8 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare cache flag + displayName: Prepare compilation cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: @@ -60,6 +59,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 7bcba0d587f..1beae9506eb 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -4,8 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n "web" > .build/arch - displayName: Prepare cache flag + displayName: Prepare compilation cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: @@ -60,6 +59,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - script: | + echo -n "web" > .build/arch + displayName: Prepare yarn cache flag + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 92aed795411..5c8806401d5 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -4,8 +4,7 @@ steps: "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin - "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch - displayName: Prepare cache flag + displayName: Prepare compilation cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: @@ -63,6 +62,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + - powershell: | + "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch + displayName: Prepare yarn cache flags + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" From 2afcea867a7fe69ad7e2ce52c32a762b2f80a00a Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 30 Nov 2020 15:02:51 +0100 Subject: [PATCH 0428/1837] Use argparse 1.0.9 in npm extension --- extensions/npm/package.json | 3 +++ extensions/npm/yarn.lock | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/extensions/npm/package.json b/extensions/npm/package.json index d7167b1c8b4..659a8e46cf4 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -30,6 +30,9 @@ "@types/minimatch": "^3.0.3", "@types/node": "^12.11.7" }, + "resolutions": { + "which-pm/load-yaml-file/**/argparse": "1.0.9" + }, "main": "./out/npmMain", "browser": "./dist/browser/npmBrowserMain", "activationEvents": [ diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index 0d0de5ef814..0fa2f344a26 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -26,10 +26,10 @@ agent-base@^4.3.0: dependencies: es6-promisify "^5.0.0" -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== +argparse@1.0.9, argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + integrity sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY= dependencies: sprintf-js "~1.0.2" From 9689508fa5ff7ec4b259278950f70744c99eb345 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 30 Nov 2020 15:05:05 +0100 Subject: [PATCH 0429/1837] Run OSS Tool and make necessary updates --- ThirdPartyNotices.txt | 137 +++++++++++++++++++++++++----------------- cglicenses.json | 32 +++++++++- package.json | 2 +- 3 files changed, 115 insertions(+), 56 deletions(-) diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 074844d813e..f4b36447f47 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -28,44 +28,45 @@ This project incorporates components from the projects listed below. The origina 21. Ionic documentation version 1.2.4 (https://github.com/ionic-team/ionic-site) 22. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar) 23. jeff-hykin/cpp-textmate-grammar version 1.12.11 (https://github.com/jeff-hykin/cpp-textmate-grammar) -24. jeff-hykin/cpp-textmate-grammar version 1.14.15 (https://github.com/jeff-hykin/cpp-textmate-grammar) +24. jeff-hykin/cpp-textmate-grammar version 1.15.3 (https://github.com/jeff-hykin/cpp-textmate-grammar) 25. js-beautify version 1.6.8 (https://github.com/beautify-web/js-beautify) 26. Jxck/assert version 1.0.0 (https://github.com/Jxck/assert) 27. language-docker (https://github.com/moby/moby) 28. language-less version 0.34.2 (https://github.com/atom/language-less) 29. language-php version 0.44.5 (https://github.com/atom/language-php) -30. language-rust version 0.4.12 (https://github.com/zargony/atom-language-rust) -31. MagicStack/MagicPython version 1.1.1 (https://github.com/MagicStack/MagicPython) -32. marked version 0.6.2 (https://github.com/markedjs/marked) -33. mdn-data version 1.1.12 (https://github.com/mdn/data) -34. microsoft/TypeScript-TmLanguage version 0.0.1 (https://github.com/microsoft/TypeScript-TmLanguage) -35. microsoft/vscode-JSON.tmLanguage (https://github.com/microsoft/vscode-JSON.tmLanguage) +30. MagicStack/MagicPython version 1.1.1 (https://github.com/MagicStack/MagicPython) +31. marked version 1.1.0 (https://github.com/markedjs/marked) +32. mdn-data version 1.1.12 (https://github.com/mdn/data) +33. microsoft/TypeScript-TmLanguage version 0.0.1 (https://github.com/microsoft/TypeScript-TmLanguage) +34. microsoft/vscode-JSON.tmLanguage (https://github.com/microsoft/vscode-JSON.tmLanguage) +35. microsoft/vscode-markdown-tm-grammar (https://github.com/microsoft/vscode-markdown-tm-grammar) 36. microsoft/vscode-mssql version 1.9.0 (https://github.com/microsoft/vscode-mssql) 37. mmims/language-batchfile version 0.7.5 (https://github.com/mmims/language-batchfile) 38. octref/language-css version 0.42.11 (https://github.com/octref/language-css) 39. PowerShell/EditorSyntax version 1.0.0 (https://github.com/PowerShell/EditorSyntax) -40. seti-ui version 0.1.0 (https://github.com/jesseweed/seti-ui) -41. shaders-tmLanguage version 0.1.0 (https://github.com/tgjones/shaders-tmLanguage) -42. textmate/asp.vb.net.tmbundle (https://github.com/textmate/asp.vb.net.tmbundle) -43. textmate/c.tmbundle (https://github.com/textmate/c.tmbundle) -44. textmate/diff.tmbundle (https://github.com/textmate/diff.tmbundle) -45. textmate/git.tmbundle (https://github.com/textmate/git.tmbundle) -46. textmate/groovy.tmbundle (https://github.com/textmate/groovy.tmbundle) -47. textmate/html.tmbundle (https://github.com/textmate/html.tmbundle) -48. textmate/ini.tmbundle (https://github.com/textmate/ini.tmbundle) -49. textmate/javascript.tmbundle (https://github.com/textmate/javascript.tmbundle) -50. textmate/lua.tmbundle (https://github.com/textmate/lua.tmbundle) -51. textmate/markdown.tmbundle (https://github.com/textmate/markdown.tmbundle) -52. textmate/perl.tmbundle (https://github.com/textmate/perl.tmbundle) -53. textmate/ruby.tmbundle (https://github.com/textmate/ruby.tmbundle) -54. textmate/yaml.tmbundle (https://github.com/textmate/yaml.tmbundle) -55. TypeScript-TmLanguage version 0.1.8 (https://github.com/microsoft/TypeScript-TmLanguage) -56. TypeScript-TmLanguage version 1.0.0 (https://github.com/microsoft/TypeScript-TmLanguage) -57. Unicode version 12.0.0 (https://home.unicode.org/) -58. vscode-codicons version 0.0.1 (https://github.com/microsoft/vscode-codicons) -59. vscode-logfile-highlighter version 2.8.0 (https://github.com/emilast/vscode-logfile-highlighter) -60. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) -61. Web Background Synchronization (https://github.com/WICG/background-sync) +40. rust-syntax version 0.2.13 (https://github.com/dustypomerleau/rust-syntax) +41. seti-ui version 0.1.0 (https://github.com/jesseweed/seti-ui) +42. shaders-tmLanguage version 0.1.0 (https://github.com/tgjones/shaders-tmLanguage) +43. textmate/asp.vb.net.tmbundle (https://github.com/textmate/asp.vb.net.tmbundle) +44. textmate/c.tmbundle (https://github.com/textmate/c.tmbundle) +45. textmate/diff.tmbundle (https://github.com/textmate/diff.tmbundle) +46. textmate/git.tmbundle (https://github.com/textmate/git.tmbundle) +47. textmate/groovy.tmbundle (https://github.com/textmate/groovy.tmbundle) +48. textmate/html.tmbundle (https://github.com/textmate/html.tmbundle) +49. textmate/ini.tmbundle (https://github.com/textmate/ini.tmbundle) +50. textmate/javascript.tmbundle (https://github.com/textmate/javascript.tmbundle) +51. textmate/lua.tmbundle (https://github.com/textmate/lua.tmbundle) +52. textmate/markdown.tmbundle (https://github.com/textmate/markdown.tmbundle) +53. textmate/perl.tmbundle (https://github.com/textmate/perl.tmbundle) +54. textmate/ruby.tmbundle (https://github.com/textmate/ruby.tmbundle) +55. textmate/yaml.tmbundle (https://github.com/textmate/yaml.tmbundle) +56. TypeScript-TmLanguage version 0.1.8 (https://github.com/microsoft/TypeScript-TmLanguage) +57. TypeScript-TmLanguage version 1.0.0 (https://github.com/microsoft/TypeScript-TmLanguage) +58. Unicode version 12.0.0 (https://home.unicode.org/) +59. vscode-codicons version 0.0.1 (https://github.com/microsoft/vscode-codicons) +60. vscode-logfile-highlighter version 2.8.0 (https://github.com/emilast/vscode-logfile-highlighter) +61. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) +62. Web Background Synchronization (https://github.com/WICG/BackgroundSync) %% atom/language-clojure NOTICES AND INFORMATION BEGIN HERE @@ -1101,31 +1102,6 @@ suitability for any purpose. ========================================= END OF language-php NOTICES AND INFORMATION -%% language-rust NOTICES AND INFORMATION BEGIN HERE -========================================= -The MIT License (MIT) - -Copyright © `2013` `Andreas Neuhaus` `http://zargony.com/` - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -========================================= -END OF language-rust NOTICES AND INFORMATION - %% MagicStack/MagicPython NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License @@ -1164,6 +1140,7 @@ all code is your original work. `` ## Marked +Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/) Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/) Permission is hereby granted, free of charge, to any person obtaining a copy @@ -1632,6 +1609,32 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFT ========================================= END OF microsoft/vscode-JSON.tmLanguage NOTICES AND INFORMATION +%% microsoft/vscode-markdown-tm-grammar NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) Microsoft 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF microsoft/vscode-markdown-tm-grammar NOTICES AND INFORMATION + %% microsoft/vscode-mssql NOTICES AND INFORMATION BEGIN HERE ========================================= ------------------------------------------ START OF LICENSE ----------------------------------------- @@ -1738,6 +1741,32 @@ SOFTWARE. ========================================= END OF PowerShell/EditorSyntax NOTICES AND INFORMATION +%% rust-syntax NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright (c) 2020 Dustin Pomerleau + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF rust-syntax NOTICES AND INFORMATION + %% seti-ui NOTICES AND INFORMATION BEGIN HERE ========================================= Copyright (c) 2014 Jesse Weed diff --git a/cglicenses.json b/cglicenses.json index 56f92bef6c5..a0131e4f911 100644 --- a/cglicenses.json +++ b/cglicenses.json @@ -389,5 +389,35 @@ "", "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." ] + }, + { + // Reason: The license at https://github.com/jquery/esprima/blob/master/LICENSE.BSD + // cannot be found by the OSS tool automatically. + "name": "esprima", + "fullLicenseText": [ + "BSD 2-Clause \"Simplified\" License", + "Copyright JS Foundation and other contributors, https://js.foundation/", + "", + "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:", + " * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.", + " * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.", + "", + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ] + }, + { + // Reason: The license at https://github.com/LinusU/load-yaml-file/blob/master/readme.md + // cannot be found by the OSS tool automatically. + "name": "load-yaml-file", + "fullLicenseText": [ + "MIT License", + "Copyright (C) 2012-2018 by various contributors (see AUTHORS)", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] } -] \ No newline at end of file +] diff --git a/package.json b/package.json index 4b0bddd622e..38d70bcf21e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "31b3b5d0cd5021b72f02225b9016b1777f94f4d1", + "distro": "8afad6b3fea9b04e2f6271c260e84620fbdb6712", "author": { "name": "Microsoft Corporation" }, From bf24f189f1d17f701b6440fa5845900a5885fcc1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 30 Nov 2020 15:17:28 +0100 Subject: [PATCH 0430/1837] Clean up defaultFolderPath --- .../services/dialogs/browser/abstractFileDialogService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts index a105daa0957..222e877c68b 100644 --- a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts @@ -78,7 +78,7 @@ export abstract class AbstractFileDialogService implements IFileDialogService { if (!candidate) { return this.pathService.userHome({ preferLocal: schemeFilter === Schemas.file }); } else { - return candidate && resources.dirname(candidate); + return resources.dirname(candidate); } } From e7f19cf61a578072bbdb6168e675933803ac2d90 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 30 Nov 2020 16:12:42 +0100 Subject: [PATCH 0431/1837] don't validate MessagePort inside iframe as safari seems to have trouble with that --- .../worker/httpWebWorkerExtensionHostIframe.html | 9 ++------- .../worker/httpsWebWorkerExtensionHostIframe.html | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html index a99d3df29df..392b4b4aeaa 100644 --- a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html +++ b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html @@ -1,7 +1,7 @@ - + ', + '', + '' + ] + + const output = [ + '', + '', + '', + '', + '' + ] + + await testRename(input.join('\n'), 'h', output.join('\n')) + }) + + test('Rename Function', async () => { + const input = [ + '', + '', + '', + '', + '' + ] + + const output = [ + '', + '', + '', + '', + '' + ] + + await testRename(input.join('\n'), 'sayName', output.join('\n')) + }) + + test('Rename Function Params', async () => { + const input = [ + '', + '', + '', + '', + '' + ] + + const output = [ + '', + '', + '', + '', + '' + ] + + await testRename(input.join('\n'), 'newName', output.join('\n')) + }) + + test('Rename Class', async () => { + const input = [ + '', + '', + '', + '', + '' + ] + + const output = [ + '', + '', + '', + '', + '' + ] + + await testRename(input.join('\n'), 'Bar', output.join('\n')) + }) + + test('Cannot Rename literal', async () => { + const stringLiteralInput = [ + '', + '', + '', + '', + '' + ] + const numberLiteralInput = [ + '', + '', + '', + '', + '' + ] + + await testNoRename(stringLiteralInput.join('\n'), 'something') + await testNoRename(numberLiteralInput.join('\n'), 'hhhh') + }) +}); From 763b155fe9b0f72d9f0053afa2dc23664f5cd82c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Dec 2020 15:38:31 +0100 Subject: [PATCH 0534/1837] Fix #111574 --- .../contrib/extensions/browser/extensionsActions.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index b10bfdac82a..0aa7ddd1b10 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1429,11 +1429,12 @@ export class ReloadAction extends ExtensionAction { } const isUninstalled = this.extension.state === ExtensionState.Uninstalled; - const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension!.identifier))[0]; - const isSameExtensionRunning = runningExtension && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)); + const runningExtension = this._runningExtensions.find(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension!.identifier)); if (isUninstalled) { - if (isSameExtensionRunning && !this.extensionService.canRemoveExtension(runningExtension)) { + const canRemoveRunningExtension = runningExtension && this.extensionService.canRemoveExtension(runningExtension); + const isSameExtensionRunning = runningExtension && (!this.extension.server || this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension))); + if (!canRemoveRunningExtension && isSameExtensionRunning) { this.enabled = true; this.label = localize('reloadRequired', "Reload Required"); this.tooltip = localize('postUninstallTooltip', "Please reload Visual Studio Code to complete the uninstallation of this extension."); @@ -1442,6 +1443,7 @@ export class ReloadAction extends ExtensionAction { return; } if (this.extension.local) { + const isSameExtensionRunning = runningExtension && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)); const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local); // Extension is running From 65c70884c14dff1deccc3a8ff105d54bc8c74f9a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Dec 2020 15:49:52 +0100 Subject: [PATCH 0535/1837] Fix #106989 --- .../contrib/userDataSync/browser/userDataSync.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 438b3cad3c7..8a1aa13b2d8 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Action } from 'vs/base/common/actions'; -import { toErrorMessage } from 'vs/base/common/errorMessage'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; import { Disposable, DisposableStore, dispose, MutableDisposable, toDisposable, IDisposable } from 'vs/base/common/lifecycle'; @@ -258,7 +257,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo await this.userDataSyncService.accept(syncResource, conflict.remoteResource, undefined, this.userDataAutoSyncEnablementService.isEnabled()); } } catch (e) { - this.notificationService.error(e); + this.notificationService.error(localize('accept failed', "Error while accepting changes. Please check [logs]({0}) for more details.", `command:${SHOW_SYNC_LOG_COMMAND_ID}`)); } } @@ -268,7 +267,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo await this.userDataSyncService.accept(syncResource, conflict.localResource, undefined, this.userDataAutoSyncEnablementService.isEnabled()); } } catch (e) { - this.notificationService.error(e); + this.notificationService.error(localize('accept failed', "Error while accepting changes. Please check [logs]({0}) for more details.", `command:${SHOW_SYNC_LOG_COMMAND_ID}`)); } } @@ -1050,7 +1049,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo await that.turnOff(); } catch (e) { if (!isPromiseCanceledError(e)) { - that.notificationService.error(localize('turn off failed', "Error while turning off sync: {0}", toErrorMessage(e))); + that.notificationService.error(localize('turn off failed', "Error while turning off Settings Sync. Please check [logs]({0}) for more details.", `command:${SHOW_SYNC_LOG_COMMAND_ID}`)); } } } @@ -1254,7 +1253,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio this.notificationService.warn(localize('update conflicts', "Could not resolve conflicts as there is new local version available. Please try again.")); } } else { - this.notificationService.error(e); + this.notificationService.error(localize('accept failed', "Error while accepting changes. Please check [logs]({0}) for more details.", `command:${SHOW_SYNC_LOG_COMMAND_ID}`)); } } } From c8e490e5e683f346d3a1dbc4c99f6d8f253f545e Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 2 Dec 2020 23:00:23 +0800 Subject: [PATCH 0536/1837] chore: optimized code --- .../server/src/modes/javascriptMode.ts | 5 +++-- .../html-language-features/server/src/test/rename.test.ts | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/extensions/html-language-features/server/src/modes/javascriptMode.ts b/extensions/html-language-features/server/src/modes/javascriptMode.ts index 97299fe8ab8..bb630594852 100644 --- a/extensions/html-language-features/server/src/modes/javascriptMode.ts +++ b/extensions/html-language-features/server/src/modes/javascriptMode.ts @@ -191,11 +191,12 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache { diff --git a/extensions/html-language-features/server/src/test/rename.test.ts b/extensions/html-language-features/server/src/test/rename.test.ts index b1578fcd270..2705b56fdf8 100644 --- a/extensions/html-language-features/server/src/test/rename.test.ts +++ b/extensions/html-language-features/server/src/test/rename.test.ts @@ -28,10 +28,6 @@ async function testRename(value: string, newName: string, expectedDocContent: st assert.fail('No workspace edits'); } - if (!workspaceEdit || !workspaceEdit.changes) { - assert.fail('No workspace edits'); - } - const edits = workspaceEdit.changes[document.uri.toString()]; if (!edits) { assert.fail(`No edits for file at ${document.uri.toString()}`); From 16ffa1deffd6a843024686f91fa7fbd6e514b345 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 16:11:15 +0100 Subject: [PATCH 0537/1837] Add GreaterEquals and SmallerEquals and fix implementations --- .../platform/contextkey/common/contextkey.ts | 292 +++++++++++------- .../contextkey/test/common/contextkey.test.ts | 69 +++++ 2 files changed, 244 insertions(+), 117 deletions(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 15802baa72b..5b536419db9 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -33,7 +33,9 @@ export const enum ContextKeyExprType { In = 10, NotIn = 11, Greater = 12, - Less = 13, + GreaterEquals = 13, + Smaller = 14, + SmallerEquals = 15, } export interface IContextKeyExprMapper { @@ -41,6 +43,10 @@ export interface IContextKeyExprMapper { mapNot(key: string): ContextKeyExpression; mapEquals(key: string, value: any): ContextKeyExpression; mapNotEquals(key: string, value: any): ContextKeyExpression; + mapGreater(key: string, value: any): ContextKeyExpression; + mapGreaterEquals(key: string, value: any): ContextKeyExpression; + mapSmaller(key: string, value: any): ContextKeyExpression; + mapSmallerEquals(key: string, value: any): ContextKeyExpression; mapRegex(key: string, regexp: RegExp | null): ContextKeyRegexExpr; mapIn(key: string, valueKey: string): ContextKeyInExpr; } @@ -59,7 +65,9 @@ export interface IContextKeyExpression { export type ContextKeyExpression = ( ContextKeyFalseExpr | ContextKeyTrueExpr | ContextKeyDefinedExpr | ContextKeyNotExpr | ContextKeyEqualsExpr | ContextKeyNotEqualsExpr | ContextKeyRegexExpr - | ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr | ContextKeyNotInExpr | ContextKeyGreaterExpr | ContextKeyLessExpr + | ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr + | ContextKeyNotInExpr | ContextKeyGreaterExpr | ContextKeyGreaterEqualsExpr + | ContextKeySmallerExpr | ContextKeySmallerEqualsExpr ); export abstract class ContextKeyExpr { @@ -109,7 +117,7 @@ export abstract class ContextKeyExpr { } public static less(key: string, value: any): ContextKeyExpression { - return ContextKeyLessExpr.create(key, value); + return ContextKeySmallerExpr.create(key, value); } public static deserialize(serialized: string | null | undefined, strict: boolean = false): ContextKeyExpression | undefined { @@ -153,14 +161,24 @@ export abstract class ContextKeyExpr { return ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim()); } + if (serializedOne.indexOf('>=') >= 0) { + const pieces = serializedOne.split('>='); + return ContextKeyGreaterEqualsExpr.create(pieces[0].trim(), pieces[1].trim()); + } + if (serializedOne.indexOf('>') >= 0) { - let pieces = serializedOne.split('>'); - return ContextKeyGreaterExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict)); + const pieces = serializedOne.split('>'); + return ContextKeyGreaterExpr.create(pieces[0].trim(), pieces[1].trim()); + } + + if (serializedOne.indexOf('<=') >= 0) { + const pieces = serializedOne.split('<='); + return ContextKeySmallerEqualsExpr.create(pieces[0].trim(), pieces[1].trim()); } if (serializedOne.indexOf('<') >= 0) { - let pieces = serializedOne.split('<'); - return ContextKeyLessExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict)); + const pieces = serializedOne.split('<'); + return ContextKeySmallerExpr.create(pieces[0].trim(), pieces[1].trim()); } if (/^\!\s*/.test(serializedOne)) { @@ -322,13 +340,7 @@ export class ContextKeyDefinedExpr implements IContextKeyExpression { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - return 0; + return cmp1(this.key, other.key); } public equals(other: ContextKeyExpression): boolean { @@ -382,19 +394,7 @@ export class ContextKeyEqualsExpr implements IContextKeyExpression { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - if (this.value < other.value) { - return -1; - } - if (this.value > other.value) { - return 1; - } - return 0; + return cmp2(this.key, this.value, other.key, other.value); } public equals(other: ContextKeyExpression): boolean { @@ -442,19 +442,7 @@ export class ContextKeyInExpr implements IContextKeyExpression { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - if (this.valueKey < other.valueKey) { - return -1; - } - if (this.valueKey > other.valueKey) { - return 1; - } - return 0; + return cmp2(this.key, this.valueKey, other.key, other.valueKey); } public equals(other: ContextKeyExpression): boolean { @@ -569,19 +557,7 @@ export class ContextKeyNotEqualsExpr implements IContextKeyExpression { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - if (this.value < other.value) { - return -1; - } - if (this.value > other.value) { - return 1; - } - return 0; + return cmp2(this.key, this.value, other.key, other.value); } public equals(other: ContextKeyExpression): boolean { @@ -633,13 +609,7 @@ export class ContextKeyNotExpr implements IContextKeyExpression { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - return 0; + return cmp1(this.key, other.key); } public equals(other: ContextKeyExpression): boolean { @@ -673,39 +643,21 @@ export class ContextKeyNotExpr implements IContextKeyExpression { export class ContextKeyGreaterExpr implements IContextKeyExpression { public static create(key: string, value: any): ContextKeyExpression { - if (typeof value === 'boolean') { - return (value ? ContextKeyDefinedExpr.create(key) : ContextKeyNotExpr.create(key)); - } - const staticValue = STATIC_VALUES.get(key); - if (typeof staticValue === 'boolean') { - const trueValue = staticValue ? 'true' : 'false'; - return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE); - } return new ContextKeyGreaterExpr(key, value); } public readonly type = ContextKeyExprType.Greater; - private constructor(private readonly key: string, private readonly value: any) { - } + private constructor( + private readonly key: string, + private readonly value: any + ) { } public cmp(other: ContextKeyExpression): number { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - if (this.value < other.value) { - return -1; - } - if (this.value > other.value) { - return 1; - } - return 0; + return cmp2(this.key, this.value, other.key, other.value); } public equals(other: ContextKeyExpression): boolean { @@ -716,11 +668,11 @@ export class ContextKeyGreaterExpr implements IContextKeyExpression { } public evaluate(context: IContext): boolean { - return (Number(context.getValue(this.key)) > this.value); + return (parseFloat(context.getValue(this.key)) > parseFloat(this.value)); } public serialize(): string { - return `${this.key} > '${this.value}'`; + return `${this.key} > ${this.value}`; } public keys(): string[] { @@ -728,50 +680,32 @@ export class ContextKeyGreaterExpr implements IContextKeyExpression { } public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { - return mapFnc.mapEquals(this.key, this.value); + return mapFnc.mapGreater(this.key, this.value); } public negate(): ContextKeyExpression { - return ContextKeyNotEqualsExpr.create(this.key, this.value); + return ContextKeySmallerEqualsExpr.create(this.key, this.value); } } -export class ContextKeyLessExpr implements IContextKeyExpression { +export class ContextKeyGreaterEqualsExpr implements IContextKeyExpression { public static create(key: string, value: any): ContextKeyExpression { - if (typeof value === 'boolean') { - return (value ? ContextKeyDefinedExpr.create(key) : ContextKeyNotExpr.create(key)); - } - const staticValue = STATIC_VALUES.get(key); - if (typeof staticValue === 'boolean') { - const trueValue = staticValue ? 'true' : 'false'; - return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE); - } - return new ContextKeyLessExpr(key, value); + return new ContextKeyGreaterEqualsExpr(key, value); } - public readonly type = ContextKeyExprType.Less; + public readonly type = ContextKeyExprType.GreaterEquals; - private constructor(private readonly key: string, private readonly value: any) { - } + private constructor( + private readonly key: string, + private readonly value: any + ) { } public cmp(other: ContextKeyExpression): number { if (other.type !== this.type) { return this.type - other.type; } - if (this.key < other.key) { - return -1; - } - if (this.key > other.key) { - return 1; - } - if (this.value < other.value) { - return -1; - } - if (this.value > other.value) { - return 1; - } - return 0; + return cmp2(this.key, this.value, other.key, other.value); } public equals(other: ContextKeyExpression): boolean { @@ -782,11 +716,11 @@ export class ContextKeyLessExpr implements IContextKeyExpression { } public evaluate(context: IContext): boolean { - return (Number(context.getValue(this.key)) < this.value); + return (parseFloat(context.getValue(this.key)) >= parseFloat(this.value)); } public serialize(): string { - return `${this.key} < '${this.value}'`; + return `${this.key} >= ${this.value}`; } public keys(): string[] { @@ -794,11 +728,109 @@ export class ContextKeyLessExpr implements IContextKeyExpression { } public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { - return mapFnc.mapEquals(this.key, this.value); + return mapFnc.mapGreaterEquals(this.key, this.value); } public negate(): ContextKeyExpression { - return ContextKeyNotEqualsExpr.create(this.key, this.value); + return ContextKeySmallerExpr.create(this.key, this.value); + } +} + +export class ContextKeySmallerExpr implements IContextKeyExpression { + + public static create(key: string, value: any): ContextKeyExpression { + return new ContextKeySmallerExpr(key, value); + } + + public readonly type = ContextKeyExprType.Smaller; + + private constructor( + private readonly key: string, + private readonly value: any + ) { + } + + public cmp(other: ContextKeyExpression): number { + if (other.type !== this.type) { + return this.type - other.type; + } + return cmp2(this.key, this.value, other.key, other.value); + } + + public equals(other: ContextKeyExpression): boolean { + if (other.type === this.type) { + return (this.key === other.key && this.value === other.value); + } + return false; + } + + public evaluate(context: IContext): boolean { + return (parseFloat(context.getValue(this.key)) < parseFloat(this.value)); + } + + public serialize(): string { + return `${this.key} < ${this.value}`; + } + + public keys(): string[] { + return [this.key]; + } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { + return mapFnc.mapSmaller(this.key, this.value); + } + + public negate(): ContextKeyExpression { + return ContextKeyGreaterEqualsExpr.create(this.key, this.value); + } +} + +export class ContextKeySmallerEqualsExpr implements IContextKeyExpression { + + public static create(key: string, value: any): ContextKeyExpression { + return new ContextKeySmallerEqualsExpr(key, value); + } + + public readonly type = ContextKeyExprType.SmallerEquals; + + private constructor( + private readonly key: string, + private readonly value: any + ) { + } + + public cmp(other: ContextKeyExpression): number { + if (other.type !== this.type) { + return this.type - other.type; + } + return cmp2(this.key, this.value, other.key, other.value); + } + + public equals(other: ContextKeyExpression): boolean { + if (other.type === this.type) { + return (this.key === other.key && this.value === other.value); + } + return false; + } + + public evaluate(context: IContext): boolean { + return (parseFloat(context.getValue(this.key)) <= parseFloat(this.value)); + } + + public serialize(): string { + return `${this.key} <= ${this.value}`; + } + + public keys(): string[] { + return [this.key]; + } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpression { + return mapFnc.mapSmallerEquals(this.key, this.value); + } + + public negate(): ContextKeyExpression { + return ContextKeyGreaterExpr.create(this.key, this.value); } } @@ -1295,3 +1327,29 @@ export interface IContextKeyService { } export const SET_CONTEXT_COMMAND_ID = 'setContext'; + +function cmp1(key1: string, key2: string): number { + if (key1 < key2) { + return -1; + } + if (key1 > key2) { + return 1; + } + return 0; +} + +function cmp2(key1: string, value1: any, key2: string, value2: any): number { + if (key1 < key2) { + return -1; + } + if (key1 > key2) { + return 1; + } + if (value1 < value2) { + return -1; + } + if (value1 > value2) { + return 1; + } + return 0; +} diff --git a/src/vs/platform/contextkey/test/common/contextkey.test.ts b/src/vs/platform/contextkey/test/common/contextkey.test.ts index 2912df4b0ea..5701b9dc86b 100644 --- a/src/vs/platform/contextkey/test/common/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/common/contextkey.test.ts @@ -186,4 +186,73 @@ suite('ContextKeyExpr', () => { ); assert.equal(actual!.equals(expected!), true); }); + + test('Greater, GreaterEquals, Smaller, SmallerEquals evaluate', () => { + function checkEvaluate(expr: string, ctx: any, expected: any): void { + const _expr = ContextKeyExpr.deserialize(expr)!; + assert.equal(_expr.evaluate(createContext(ctx)), expected); + } + + checkEvaluate('a>1', {}, false); + checkEvaluate('a>1', { a: 0 }, false); + checkEvaluate('a>1', { a: 1 }, false); + checkEvaluate('a>1', { a: 2 }, true); + checkEvaluate('a>1', { a: '0' }, false); + checkEvaluate('a>1', { a: '1' }, false); + checkEvaluate('a>1', { a: '2' }, true); + checkEvaluate('a>1', { a: 'a' }, false); + + checkEvaluate('a>10', { a: 2 }, false); + checkEvaluate('a>10', { a: 11 }, true); + checkEvaluate('a>10', { a: '11' }, true); + checkEvaluate('a>10', { a: '2' }, false); + checkEvaluate('a>10', { a: '11' }, true); + + checkEvaluate('a>1.1', { a: 1 }, false); + checkEvaluate('a>1.1', { a: 2 }, true); + checkEvaluate('a>1.1', { a: 11 }, true); + checkEvaluate('a>1.1', { a: '1.1' }, false); + checkEvaluate('a>1.1', { a: '2' }, true); + checkEvaluate('a>1.1', { a: '11' }, true); + + checkEvaluate('a>b', { a: 'b' }, false); + checkEvaluate('a>b', { a: 'c' }, false); + checkEvaluate('a>b', { a: 1000 }, false); + + checkEvaluate('a >= 2', { a: '1' }, false); + checkEvaluate('a >= 2', { a: '2' }, true); + checkEvaluate('a >= 2', { a: '3' }, true); + + checkEvaluate('a < 2', { a: '1' }, true); + checkEvaluate('a < 2', { a: '2' }, false); + checkEvaluate('a < 2', { a: '3' }, false); + + checkEvaluate('a <= 2', { a: '1' }, true); + checkEvaluate('a <= 2', { a: '2' }, true); + checkEvaluate('a <= 2', { a: '3' }, false); + }); + + test('Greater, GreaterEquals, Smaller, SmallerEquals negate', () => { + function checkNegate(expr: string, expected: string): void { + const a = ContextKeyExpr.deserialize(expr)!; + const b = a.negate(); + assert.equal(b.serialize(), expected); + } + + checkNegate('a>1', 'a <= 1'); + checkNegate('a>1.1', 'a <= 1.1'); + checkNegate('a>b', 'a <= b'); + + checkNegate('a>=1', 'a < 1'); + checkNegate('a>=1.1', 'a < 1.1'); + checkNegate('a>=b', 'a < b'); + + checkNegate('a<1', 'a >= 1'); + checkNegate('a<1.1', 'a >= 1.1'); + checkNegate('a= b'); + + checkNegate('a<=1', 'a > 1'); + checkNegate('a<=1.1', 'a > 1.1'); + checkNegate('a<=b', 'a > b'); + }); }); From 94dd681d16553f4e0940289f93eaa84a83054114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 2 Dec 2020 16:12:10 +0100 Subject: [PATCH 0538/1837] more fixes for #95697 --- src/vs/base/browser/ui/tree/abstractTree.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index f0e111e3f15..4df19745cfe 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -1117,9 +1117,7 @@ class TreeNodeListMouseController extends MouseController< expandOnlyOnTwistieClick = !!this.tree.expandOnlyOnTwistieClick; } - const clickedOnFocus = this.tree.getFocus()[0] === node.element; - - if (expandOnlyOnTwistieClick && !onTwistie && e.browserEvent.detail !== 2 && !(clickedOnFocus && !node.collapsed)) { + if (expandOnlyOnTwistieClick && !onTwistie && e.browserEvent.detail !== 2) { return super.onViewPointer(e); } From f2ae4927f9419eebf6951564dc6b78b24c13905c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 16:18:31 +0100 Subject: [PATCH 0539/1837] update distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c4a391eee6f..4f5198a1b1f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "7c9caf8254b4e707f8f7637661df05d1397f2181", + "distro": "525b7677232e7f810dd09678a784247f93df7845", "author": { "name": "Microsoft Corporation" }, @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From e16d1f06d738ef620ded7a31e6a682e76017bd6d Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 2 Dec 2020 16:19:05 +0100 Subject: [PATCH 0540/1837] Add default URI if not provided in dialog API Fixes #111585 --- .../workbench/api/browser/mainThreadDialogs.ts | 16 ++++++++++++---- .../services/dialogs/browser/simpleFileDialog.ts | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadDialogs.ts b/src/vs/workbench/api/browser/mainThreadDialogs.ts index 938cb20c18b..afa4240f39e 100644 --- a/src/vs/workbench/api/browser/mainThreadDialogs.ts +++ b/src/vs/workbench/api/browser/mainThreadDialogs.ts @@ -23,12 +23,20 @@ export class MainThreadDialogs implements MainThreadDiaglogsShape { // } - $showOpenDialog(options?: MainThreadDialogOpenOptions): Promise { - return Promise.resolve(this._fileDialogService.showOpenDialog(MainThreadDialogs._convertOpenOptions(options))); + async $showOpenDialog(options?: MainThreadDialogOpenOptions): Promise { + const convertedOptions = MainThreadDialogs._convertOpenOptions(options); + if (!convertedOptions.defaultUri) { + convertedOptions.defaultUri = await this._fileDialogService.defaultFilePath(); + } + return Promise.resolve(this._fileDialogService.showOpenDialog(convertedOptions)); } - $showSaveDialog(options?: MainThreadDialogSaveOptions): Promise { - return Promise.resolve(this._fileDialogService.showSaveDialog(MainThreadDialogs._convertSaveOptions(options))); + async $showSaveDialog(options?: MainThreadDialogSaveOptions): Promise { + const convertedOptions = MainThreadDialogs._convertSaveOptions(options); + if (!convertedOptions.defaultUri) { + convertedOptions.defaultUri = await this._fileDialogService.defaultFilePath(); + } + return Promise.resolve(this._fileDialogService.showSaveDialog(convertedOptions)); } private static _convertOpenOptions(options?: MainThreadDialogOpenOptions): IOpenDialogOptions { diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index ff3fe29fd60..e0eca9ebe37 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -221,7 +221,7 @@ export class SimpleFileDialog { } private getScheme(available: readonly string[] | undefined, defaultUri: URI | undefined): string { - if (available) { + if (available && available.length > 0) { if (defaultUri && (available.indexOf(defaultUri.scheme) >= 0)) { return defaultUri.scheme; } From af29768f18350bdb9deb0cbf81982eddff285321 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Dec 2020 16:18:56 +0100 Subject: [PATCH 0541/1837] Fix #110844 --- .../contrib/markers/browser/markersView.ts | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 8e7ff32342c..8836c8371b2 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -54,6 +54,7 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/ur import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { groupBy } from 'vs/base/common/arrays'; import { ResourceMap } from 'vs/base/common/map'; +import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; function createResourceMarkersIterator(resourceMarkers: ResourceMarkers): Iterable> { return Iterable.map(resourceMarkers.markers, m => { @@ -327,11 +328,15 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { } private setTreeSelection(): void { - if (this.tree && this.tree.getSelection().length === 0) { - const firstMarker = this.markersModel.resourceMarkers[0]?.markers[0]; - if (firstMarker) { - this.tree.setFocus([firstMarker]); - this.tree.setSelection([firstMarker]); + if (this.tree && this.tree.isVisible() && this.tree.getSelection().length === 0) { + const firstVisibleElement = this.tree.firstVisibleElement; + const marker = firstVisibleElement ? + firstVisibleElement instanceof ResourceMarkers ? firstVisibleElement.markers[0] : + firstVisibleElement instanceof Marker ? firstVisibleElement : undefined + : undefined; + if (marker) { + this.tree.setFocus([marker]); + this.tree.setSelection([marker]); } } } @@ -603,7 +608,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { private setCurrentActiveEditor(): void { const activeEditor = this.editorService.activeEditor; - this.currentActiveResource = activeEditor ? withUndefinedAsNull(activeEditor.resource) : null; + this.currentActiveResource = activeEditor ? withUndefinedAsNull(EditorResourceAccessor.getOriginalUri(activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY })) : null; } private onSelected(): void { @@ -946,6 +951,10 @@ class MarkersTree extends WorkbenchObjectTree { this.container.classList.toggle('hidden', hide); } + isVisible(): boolean { + return !this.container.classList.contains('hidden'); + } + } registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { From 49ef641300f992f091af92605cc0a1d6366e3763 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Dec 2020 16:27:53 +0100 Subject: [PATCH 0542/1837] fixes #111639 --- src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 7d0e8f2635e..f4ac30ca099 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -95,7 +95,7 @@ class CopyOperation implements IFileOperation { const stat = await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token); const folder = this.options.folder || (stat.length === 1 && stat[0].isDirectory); - return this._instaService.createInstance(DeleteOperation, this.newUri, { recursive: true, folder, ...this.options }, { isUndoing: true }, true); + return this._instaService.createInstance(DeleteOperation, this.newUri, { recursive: true, folder, ...this.options }, { isUndoing: true }, false); } toString(): string { From 97646e138af481ae7ec6bc794806cb88006f1ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 2 Dec 2020 16:31:21 +0100 Subject: [PATCH 0543/1837] workbench.tree.expandMode related to #95697 --- src/vs/platform/list/browser/listService.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index 3bcc1cd12ad..b553a05811c 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -126,7 +126,7 @@ const automaticKeyboardNavigationSettingKey = 'workbench.list.automaticKeyboardN const treeIndentKey = 'workbench.tree.indent'; const treeRenderIndentGuidesKey = 'workbench.tree.renderIndentGuides'; const listSmoothScrolling = 'workbench.list.smoothScrolling'; -const treeExpandOnFolderClick = 'workbench.tree.expandOnFolderClick'; +const treeExpandMode = 'workbench.tree.expandMode'; function useAltAsMultipleSelectionModifier(configurationService: IConfigurationService): boolean { return configurationService.getValue(multiSelectModifierSettingKey) === 'alt'; @@ -849,7 +849,7 @@ function workbenchTreeDataPreamble(treeExpandOnFolderClick) + expandOnlyOnTwistieClick: options.expandOnlyOnTwistieClick ?? (configurationService.getValue<'singleClick' | 'doubleClick'>(treeExpandMode) === 'doubleClick') } as TOptions }; } @@ -951,8 +951,8 @@ class WorkbenchTreeInternals { if (e.affectsConfiguration(openModeSettingKey)) { newOptions = { ...newOptions, expandOnlyOnDoubleClick: configurationService.getValue(openModeSettingKey) === 'doubleClick' }; } - if (e.affectsConfiguration(treeExpandOnFolderClick) && options.expandOnlyOnTwistieClick === undefined) { - newOptions = { ...newOptions, expandOnlyOnTwistieClick: !configurationService.getValue(treeExpandOnFolderClick) }; + if (e.affectsConfiguration(treeExpandMode) && options.expandOnlyOnTwistieClick === undefined) { + newOptions = { ...newOptions, expandOnlyOnTwistieClick: configurationService.getValue<'singleClick' | 'doubleClick'>(treeExpandMode) === 'doubleClick' }; } if (Object.keys(newOptions).length > 0) { tree.updateOptions(newOptions); @@ -1058,10 +1058,11 @@ configurationRegistry.registerConfiguration({ 'default': true, markdownDescription: localize('automatic keyboard navigation setting', "Controls whether keyboard navigation in lists and trees is automatically triggered simply by typing. If set to `false`, keyboard navigation is only triggered when executing the `list.toggleKeyboardNavigation` command, for which you can assign a keyboard shortcut.") }, - [treeExpandOnFolderClick]: { - type: 'boolean', - default: true, - description: localize('list expand on folder click setting', "Controls whether tree folders are expanded when clicking the folder names."), + [treeExpandMode]: { + type: 'string', + enum: ['singleClick', 'doubleClick'], + default: 'singleClick', + description: localize('expand mode', "Controls how tree folders are expanded when clicking the folder names."), } } }); From 383dc83e7f61724717c274d850246eed5fcd7aee Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 16:42:36 +0100 Subject: [PATCH 0544/1837] Fix the standalone editor build --- src/vs/editor/common/config/editorOptions.ts | 2 -- src/vs/monaco.d.ts | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 4a30547c6b1..1c6b481c702 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -266,12 +266,10 @@ export interface IEditorOptions { wordWrap?: 'off' | 'on' | 'wordWrapColumn' | 'bounded'; /** * Override the `wordWrap` setting. - * @internal */ wordWrapOverride1?: 'off' | 'on' | 'inherit'; /** * Override the `wordWrapOverride1` setting. - * @internal */ wordWrapOverride2?: 'off' | 'on' | 'inherit'; /** diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 85e7066269a..3aaef2a4771 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2811,6 +2811,14 @@ declare namespace monaco.editor { * Defaults to "off". */ wordWrap?: 'off' | 'on' | 'wordWrapColumn' | 'bounded'; + /** + * Override the `wordWrap` setting. + */ + wordWrapOverride1?: 'off' | 'on' | 'inherit'; + /** + * Override the `wordWrapOverride1` setting. + */ + wordWrapOverride2?: 'off' | 'on' | 'inherit'; /** * Control the wrapping of the editor. * When `wordWrap` = "off", the lines will never wrap. From 9cd45f96de363dbf86e8ce99c906ea0a892eaa93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 2 Dec 2020 16:43:48 +0100 Subject: [PATCH 0545/1837] fixes #111710 --- .../workbench/browser/actions/listCommands.ts | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/browser/actions/listCommands.ts b/src/vs/workbench/browser/actions/listCommands.ts index 5c8d8c70d1e..b71489ac38e 100644 --- a/src/vs/workbench/browser/actions/listCommands.ts +++ b/src/vs/workbench/browser/actions/listCommands.ts @@ -356,19 +356,13 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ // List if (focused instanceof List || focused instanceof PagedList) { - const list = focused; - - list.focusPreviousPage(); - list.reveal(list.getFocus()[0]); + focused.focusPreviousPage(); } // Tree else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) { - const list = focused; - const fakeKeyboardEvent = new KeyboardEvent('keydown'); - list.focusPreviousPage(fakeKeyboardEvent); - list.reveal(list.getFocus()[0]); + focused.focusPreviousPage(fakeKeyboardEvent); } // Ensure DOM Focus @@ -386,19 +380,13 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ // List if (focused instanceof List || focused instanceof PagedList) { - const list = focused; - - list.focusNextPage(); - list.reveal(list.getFocus()[0]); + focused.focusNextPage(); } // Tree else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) { - const list = focused; - const fakeKeyboardEvent = new KeyboardEvent('keydown'); - list.focusNextPage(fakeKeyboardEvent); - list.reveal(list.getFocus()[0]); + focused.focusNextPage(fakeKeyboardEvent); } // Ensure DOM Focus From bbdbcd333bdf449f86c1084bc96c92785e2e0b41 Mon Sep 17 00:00:00 2001 From: Eno Yao <2587575267@qq.com> Date: Wed, 2 Dec 2020 16:58:10 +0100 Subject: [PATCH 0546/1837] Update contextkey.ts --- src/vs/platform/contextkey/common/contextkey.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 5b536419db9..e3d3599f614 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -7,6 +7,7 @@ import { Event } from 'vs/base/common/event'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { isMacintosh, isLinux, isWindows, isWeb } from 'vs/base/common/platform'; +import { isEdge, isOpera, isFirefox, isWebKit, isChrome, isSafari, isWebkitWebView, isIPad, isEdgeWebView, isStandalone } from 'vs/base/browser/browser'; const STATIC_VALUES = new Map(); STATIC_VALUES.set('false', false); @@ -16,6 +17,16 @@ STATIC_VALUES.set('isLinux', isLinux); STATIC_VALUES.set('isWindows', isWindows); STATIC_VALUES.set('isWeb', isWeb); STATIC_VALUES.set('isMacNative', isMacintosh && !isWeb); +STATIC_VALUES.set('isEdge', isEdge); +STATIC_VALUES.set('isOpera', isOpera); +STATIC_VALUES.set('isFirefox', isFirefox); +STATIC_VALUES.set('isWebKit', isWebKit); +STATIC_VALUES.set('isChrome', isChrome); +STATIC_VALUES.set('isSafari', isSafari); +STATIC_VALUES.set('isWebkitWebView', isWebkitWebView); +STATIC_VALUES.set('isIPad', isIPad); +STATIC_VALUES.set('isEdgeWebView', isEdgeWebView); +STATIC_VALUES.set('isStandalone', isStandalone); const hasOwnProperty = Object.prototype.hasOwnProperty; From d79110a329157c9c726514790fe0b44b93a70570 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 17:06:52 +0100 Subject: [PATCH 0547/1837] Avoid layer breaker --- .../platform/contextkey/common/contextkey.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index e3d3599f614..d0f00ed362b 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -6,9 +6,9 @@ import { Event } from 'vs/base/common/event'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { isMacintosh, isLinux, isWindows, isWeb } from 'vs/base/common/platform'; -import { isEdge, isOpera, isFirefox, isWebKit, isChrome, isSafari, isWebkitWebView, isIPad, isEdgeWebView, isStandalone } from 'vs/base/browser/browser'; +import { userAgent, isMacintosh, isLinux, isWindows, isWeb } from 'vs/base/common/platform'; +let _userAgent = userAgent || ''; const STATIC_VALUES = new Map(); STATIC_VALUES.set('false', false); STATIC_VALUES.set('true', true); @@ -17,16 +17,11 @@ STATIC_VALUES.set('isLinux', isLinux); STATIC_VALUES.set('isWindows', isWindows); STATIC_VALUES.set('isWeb', isWeb); STATIC_VALUES.set('isMacNative', isMacintosh && !isWeb); -STATIC_VALUES.set('isEdge', isEdge); -STATIC_VALUES.set('isOpera', isOpera); -STATIC_VALUES.set('isFirefox', isFirefox); -STATIC_VALUES.set('isWebKit', isWebKit); -STATIC_VALUES.set('isChrome', isChrome); -STATIC_VALUES.set('isSafari', isSafari); -STATIC_VALUES.set('isWebkitWebView', isWebkitWebView); -STATIC_VALUES.set('isIPad', isIPad); -STATIC_VALUES.set('isEdgeWebView', isEdgeWebView); -STATIC_VALUES.set('isStandalone', isStandalone); +STATIC_VALUES.set('isEdge', _userAgent.indexOf('Edg/') >= 0); +STATIC_VALUES.set('isFirefox', _userAgent.indexOf('Firefox') >= 0); +STATIC_VALUES.set('isChrome', _userAgent.indexOf('Chrome') >= 0); +STATIC_VALUES.set('isSafari', _userAgent.indexOf('Safari') >= 0); +STATIC_VALUES.set('isIPad', _userAgent.indexOf('iPad') >= 0); const hasOwnProperty = Object.prototype.hasOwnProperty; From df2c328e595101df8b96a7df17e3bd7349765d2a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 2 Dec 2020 17:23:57 +0100 Subject: [PATCH 0548/1837] string literal does not work with status bar item [background] color (fix #111687) --- src/vs/vscode.proposed.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 292af786ee1..19e8d8f1032 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2307,12 +2307,12 @@ declare module 'vscode' { /** * The background color for this entry. * - * Note: the supported colors for background are currently limited to - * `ThemeColors` with id `statusBarItem.errorBackground`. Other `ThemeColors` - * will be ignored. + * Note: only `new ThemeColor('statusBarItem.errorBackground')` is + * supported for now. More background colors may be supported in the + * future. * - * When setting the background color to `statusBarItem.errorBackground`, the - * `color` property will automatically be set to `statusBarItem.errorForeground`. + * Note: when a background color is set, the statusbar may override + * the `color` choice to ensure the entry is readable in all themes. */ backgroundColor: ThemeColor | undefined; } From 0ac5e95251d92554d82a252420222834eec8e1c7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Dec 2020 17:48:16 +0100 Subject: [PATCH 0549/1837] Fix #109644 --- test/automation/src/keybindings.ts | 14 +++++++------- .../src/areas/preferences/preferences.test.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/automation/src/keybindings.ts b/test/automation/src/keybindings.ts index 1de40d42bc9..4978ad09cd4 100644 --- a/test/automation/src/keybindings.ts +++ b/test/automation/src/keybindings.ts @@ -11,7 +11,7 @@ export class KeybindingsEditor { constructor(private code: Code) { } - async updateKeybinding(command: string, keybinding: string, title: string): Promise { + async updateKeybinding(command: string, commandName: string | undefined, keybinding: string, keybindingTitle: string): Promise { if (process.platform === 'darwin') { await this.code.dispatchKeybinding('cmd+k cmd+s'); } else { @@ -19,16 +19,16 @@ export class KeybindingsEditor { } await this.code.waitForActiveElement(SEARCH_INPUT); - await this.code.waitForSetValue(SEARCH_INPUT, command); + await this.code.waitForSetValue(SEARCH_INPUT, `@command:${command}`); - await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item'); - await this.code.waitForElement('.keybindings-list-container .monaco-list-row.keybinding-item.focused.selected'); + const commandTitle = commandName ? `${commandName} (${command})` : command; + await this.code.waitAndClick(`.keybindings-list-container .monaco-list-row.keybinding-item .command span.monaco-highlighted-label[title="${commandTitle}"]`); + await this.code.waitForElement(`.keybindings-list-container .monaco-list-row.keybinding-item.focused.selected .command span.monaco-highlighted-label[title="${commandTitle}"]`); + await this.code.dispatchKeybinding('enter'); - await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .codicon-keybindings-add'); await this.code.waitForActiveElement('.defineKeybindingWidget .monaco-inputbox input'); - await this.code.dispatchKeybinding(keybinding); await this.code.dispatchKeybinding('enter'); - await this.code.waitForElement(`.keybindings-list-container .keybinding-label div[title="${title}"]`); + await this.code.waitForElement(`.keybindings-list-container .keybinding-label div[title="${keybindingTitle}"]`); } } diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 1ea98dc7481..69652142369 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -22,7 +22,7 @@ export function setup() { const app = this.app as Application; await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.LEFT); - await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', 'ctrl+u', 'Control+U'); + await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', 'View: Toggle Side Bar Position', 'ctrl+u', 'Control+U'); await app.code.dispatchKeybinding('ctrl+u'); await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.RIGHT); From 2b179bff4ab1d305e095659ba0e4c736ebd03d38 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 17:42:25 +0100 Subject: [PATCH 0550/1837] Extract `_undo`, `_redo` --- .../undoRedo/common/undoRedoService.ts | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/undoRedo/common/undoRedoService.ts b/src/vs/platform/undoRedo/common/undoRedoService.ts index 8246ccbf1be..70ead9becd0 100644 --- a/src/vs/platform/undoRedo/common/undoRedoService.ts +++ b/src/vs/platform/undoRedo/common/undoRedoService.ts @@ -811,7 +811,7 @@ export class UndoRedoService implements IUndoRedoService { if (element.canSplit()) { this._splitPastWorkspaceElement(element, ignoreResources); this._notificationService.info(message); - return new WorkspaceVerificationError(this.undo(strResource)); + return new WorkspaceVerificationError(this._undo(strResource)); } else { // Cannot safely split this workspace element => flush all undo/redo stacks for (const strResource of element.strResources) { @@ -959,7 +959,7 @@ export class UndoRedoService implements IUndoRedoService { if (result.choice === 1) { // choice: undo this file this._splitPastWorkspaceElement(element, null); - return this.undo(strResource); + return this._undo(strResource); } // choice: undo in all files @@ -1044,16 +1044,22 @@ export class UndoRedoService implements IUndoRedoService { const [, matchedStrResource] = this._findClosestUndoElementInGroup(groupId); if (matchedStrResource) { - return this.undo(matchedStrResource); + return this._undo(matchedStrResource); } } - public undo(resourceOrSource: URI | UndoRedoSource | string): Promise | void { + public undo(resourceOrSource: URI | UndoRedoSource): Promise | void { if (resourceOrSource instanceof UndoRedoSource) { const [, matchedStrResource] = this._findClosestUndoElementWithSource(resourceOrSource.id); - return matchedStrResource ? this.undo(matchedStrResource) : undefined; + return matchedStrResource ? this._undo(matchedStrResource) : undefined; } - const strResource = typeof resourceOrSource === 'string' ? resourceOrSource : this.getUriComparisonKey(resourceOrSource); + if (typeof resourceOrSource === 'string') { + return this._undo(resourceOrSource); + } + return this._undo(this.getUriComparisonKey(resourceOrSource)); + } + + private _undo(strResource: string): Promise | void { if (!this._editStacks.has(strResource)) { return; } @@ -1069,7 +1075,7 @@ export class UndoRedoService implements IUndoRedoService { const [matchedElement, matchedStrResource] = this._findClosestUndoElementInGroup(element.groupId); if (element !== matchedElement && matchedStrResource) { // there is an element in the same group that should be undone before this one - return this.undo(matchedStrResource); + return this._undo(matchedStrResource); } } @@ -1128,7 +1134,7 @@ export class UndoRedoService implements IUndoRedoService { if (element.canSplit()) { this._splitFutureWorkspaceElement(element, ignoreResources); this._notificationService.info(message); - return new WorkspaceVerificationError(this.redo(strResource)); + return new WorkspaceVerificationError(this._redo(strResource)); } else { // Cannot safely split this workspace element => flush all undo/redo stacks for (const strResource of element.strResources) { @@ -1300,16 +1306,22 @@ export class UndoRedoService implements IUndoRedoService { const [, matchedStrResource] = this._findClosestRedoElementInGroup(groupId); if (matchedStrResource) { - return this.redo(matchedStrResource); + return this._redo(matchedStrResource); } } public redo(resourceOrSource: URI | UndoRedoSource | string): Promise | void { if (resourceOrSource instanceof UndoRedoSource) { const [, matchedStrResource] = this._findClosestRedoElementWithSource(resourceOrSource.id); - return matchedStrResource ? this.redo(matchedStrResource) : undefined; + return matchedStrResource ? this._redo(matchedStrResource) : undefined; } - const strResource = typeof resourceOrSource === 'string' ? resourceOrSource : this.getUriComparisonKey(resourceOrSource); + if (typeof resourceOrSource === 'string') { + return this._redo(resourceOrSource); + } + return this._redo(this.getUriComparisonKey(resourceOrSource)); + } + + private _redo(strResource: string): Promise | void { if (!this._editStacks.has(strResource)) { return; } @@ -1325,7 +1337,7 @@ export class UndoRedoService implements IUndoRedoService { const [matchedElement, matchedStrResource] = this._findClosestRedoElementInGroup(element.groupId); if (element !== matchedElement && matchedStrResource) { // there is an element in the same group that should be redone before this one - return this.redo(matchedStrResource); + return this._redo(matchedStrResource); } } From 0db0fa8fc9676dd85a72956035659cc6671e47d8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 17:52:04 +0100 Subject: [PATCH 0551/1837] Prompt when hitting a different UndoRedoSrouce when undoing (#111640) --- .../undoRedo/common/undoRedoService.ts | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/undoRedo/common/undoRedoService.ts b/src/vs/platform/undoRedo/common/undoRedoService.ts index 70ead9becd0..2fb802fbce9 100644 --- a/src/vs/platform/undoRedo/common/undoRedoService.ts +++ b/src/vs/platform/undoRedo/common/undoRedoService.ts @@ -1051,7 +1051,7 @@ export class UndoRedoService implements IUndoRedoService { public undo(resourceOrSource: URI | UndoRedoSource): Promise | void { if (resourceOrSource instanceof UndoRedoSource) { const [, matchedStrResource] = this._findClosestUndoElementWithSource(resourceOrSource.id); - return matchedStrResource ? this._undo(matchedStrResource) : undefined; + return matchedStrResource ? this._undo(matchedStrResource, resourceOrSource.id) : undefined; } if (typeof resourceOrSource === 'string') { return this._undo(resourceOrSource); @@ -1059,7 +1059,7 @@ export class UndoRedoService implements IUndoRedoService { return this._undo(this.getUriComparisonKey(resourceOrSource)); } - private _undo(strResource: string): Promise | void { + private _undo(strResource: string, sourceId: number = 0): Promise | void { if (!this._editStacks.has(strResource)) { return; } @@ -1079,6 +1079,11 @@ export class UndoRedoService implements IUndoRedoService { } } + if (element.sourceId !== sourceId) { + // Hit a different source, prompt for confirmation + return this._confirmDifferentSourceAndContinueUndo(strResource, element); + } + try { if (element.type === UndoRedoElementType.Workspace) { return this._workspaceUndo(strResource, element); @@ -1092,6 +1097,28 @@ export class UndoRedoService implements IUndoRedoService { } } + private async _confirmDifferentSourceAndContinueUndo(strResource: string, element: StackElement): Promise { + const result = await this._dialogService.show( + Severity.Info, + nls.localize('confirmDifferentSource', "Would you like to undo '{0}'?", element.label), + [ + nls.localize('confirmDifferentSource.ok', "Undo"), + nls.localize('cancel', "Cancel"), + ], + { + cancelId: 1 + } + ); + + if (result.choice === 1) { + // choice: cancel + return; + } + + // choice: undo + return this._undo(strResource, element.sourceId); + } + private _findClosestRedoElementWithSource(sourceId: number): [StackElement | null, string | null] { if (!sourceId) { return [null, null]; From acaecbdc869c69794cbd28b802535ddfac602512 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Dec 2020 17:56:53 +0100 Subject: [PATCH 0552/1837] fixes #111602 --- .../contrib/files/browser/fileActions.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 85ae6b84699..d26e1048b03 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -1303,24 +1303,24 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { return { source: fileToPaste, target: targetFile }; })); - // Move/Copy File - if (pasteShouldMove) { - const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target)); - const options = { - progressLabel: sourceTargetPairs.length > 1 ? nls.localize('movingBulkEdit', "Moving {0} files", sourceTargetPairs.length) : nls.localize('movingFileBulkEdit', "Moving {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), - undoLabel: sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) - }; - await explorerService.applyBulkEdit(resourceFileEdits, options); - } else { - const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target, { copy: true })); - const options = { - progressLabel: sourceTargetPairs.length > 1 ? nls.localize('copyingBulkEdit', "Copying {0} files", sourceTargetPairs.length) : nls.localize('copyingFileBulkEdit', "Copying {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), - undoLabel: sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) - }; - await explorerService.applyBulkEdit(resourceFileEdits, options); - } - if (sourceTargetPairs.length >= 1) { + // Move/Copy File + if (pasteShouldMove) { + const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target)); + const options = { + progressLabel: sourceTargetPairs.length > 1 ? nls.localize('movingBulkEdit', "Moving {0} files", sourceTargetPairs.length) : nls.localize('movingFileBulkEdit', "Moving {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + }; + await explorerService.applyBulkEdit(resourceFileEdits, options); + } else { + const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target, { copy: true })); + const options = { + progressLabel: sourceTargetPairs.length > 1 ? nls.localize('copyingBulkEdit', "Copying {0} files", sourceTargetPairs.length) : nls.localize('copyingFileBulkEdit', "Copying {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + }; + await explorerService.applyBulkEdit(resourceFileEdits, options); + } + const pair = sourceTargetPairs[0]; await explorerService.select(pair.target); if (sourceTargetPairs.length === 1) { From efd8b0141ecdcd4a8c499fd0c1f65b62ed3cc996 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Dec 2020 18:01:42 +0100 Subject: [PATCH 0553/1837] explorer: update creation labels #111640 --- src/vs/workbench/contrib/files/browser/fileActions.ts | 4 ++-- .../workbench/contrib/files/browser/views/explorerViewer.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index d26e1048b03..6261006fef3 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -914,8 +914,8 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole try { const resourceToCreate = resources.joinPath(folder.resource, value); await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], { - progressLabel: nls.localize('newBulkEdit', "New {0}", value), - undoLabel: nls.localize('newBulkEdit', "New {0}", value) + undoLabel: nls.localize('createBulkEdit', "Create {0}", value), + progressLabel: nls.localize('creatingBulkEdit', "Creating {0}", value) }); await refreshIfSeparator(value, explorerService); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 9245c9733c7..f50916aee92 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -1074,7 +1074,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } await this.explorerService.applyBulkEdit([new ResourceFileEdit(joinPath(target.resource, entry.name), undefined, { recursive: true })], { - undoLabel: localize('overwrite', "Overwriting {0}", entry.name), + undoLabel: localize('overwrite', "Overwrite {0}", entry.name), progressLabel: localize('overwriting', "Overwriting {0}", entry.name), }); From a2193cb8271ad3b9b2c1daff82a914aa9e4e2b1e Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 2 Dec 2020 10:10:21 -0800 Subject: [PATCH 0554/1837] fix #111714 --- .../src/features/smartSelect.ts | 8 ++-- .../src/test/smartSelect.test.ts | 39 ++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/extensions/markdown-language-features/src/features/smartSelect.ts b/extensions/markdown-language-features/src/features/smartSelect.ts index ae6b79faa34..12b2bdd78b3 100644 --- a/extensions/markdown-language-features/src/features/smartSelect.ts +++ b/extensions/markdown-language-features/src/features/smartSelect.ts @@ -34,7 +34,7 @@ export default class MarkdownSmartSelect implements vscode.SelectionRangeProvide const tokens = await this.engine.parse(document); - const blockTokens = getBlockTokensForPosition(tokens, position); + const blockTokens = getBlockTokensForPosition(tokens, position, headerRange); if (blockTokens.length === 0) { return undefined; @@ -91,13 +91,13 @@ function createHeaderRange(header: TocEntry, isClosestHeaderToPosition: boolean, // of this header then all content then header return new vscode.SelectionRange(contentRange.with(undefined, startOfChildRange), new vscode.SelectionRange(contentRange, (new vscode.SelectionRange(range, parent)))); } else { - // no children and not on this header line so select content then header + // not on this header line so select content then header return new vscode.SelectionRange(contentRange, new vscode.SelectionRange(range, parent)); } } -function getBlockTokensForPosition(tokens: Token[], position: vscode.Position): Token[] { - const enclosingTokens = tokens.filter(token => token.map && (token.map[0] <= position.line && token.map[1] > position.line) && isBlockElement(token)); +function getBlockTokensForPosition(tokens: Token[], position: vscode.Position, parent?: vscode.SelectionRange): Token[] { + const enclosingTokens = tokens.filter(token => token.map && (token.map[0] <= position.line && token.map[1] > position.line) && (!parent || (token.map[0] >= parent.range.start.line && token.map[1] <= parent.range.end.line + 1)) && isBlockElement(token)); if (enclosingTokens.length === 0) { return []; } diff --git a/extensions/markdown-language-features/src/test/smartSelect.test.ts b/extensions/markdown-language-features/src/test/smartSelect.test.ts index 15fb24e32ff..cb6b8a401e2 100644 --- a/extensions/markdown-language-features/src/test/smartSelect.test.ts +++ b/extensions/markdown-language-features/src/test/smartSelect.test.ts @@ -588,11 +588,48 @@ suite('markdown.SmartSelect', () => { )); assertNestedRangesEqual(ranges![0], [0, 27, 0, 48], [0, 25, 0, 50], [0, 12, 0, 63], [0, 11, 0, 64], [0, 0, 0, 75]); }); + test('Third level header from release notes', async () => { + const ranges = await getSelectionRangesForDocument( + joinLines( + `---`, + `Order: 60`, + `TOCTitle: October 2020`, + `PageTitle: Visual Studio Code October 2020`, + `MetaDescription: Learn what is new in the Visual Studio Code October 2020 Release (1.51)`, + `MetaSocialImage: 1_51/release-highlights.png`, + `Date: 2020-11-6`, + `DownloadVersion: 1.51.1`, + `---`, + `# October 2020 (version 1.51)`, + ``, + `**Update 1.51.1**: The update addresses these [issues](https://github.com/microsoft/vscode/issues?q=is%3Aissue+milestone%3A%22October+2020+Recovery%22+is%3Aclosed+).`, + ``, + ``, + ``, + `---`, + ``, + `Welcome to the October 2020 release of Visual Studio Code. As announced in the [October iteration plan](https://github.com/microsoft/vscode/issues/108473), we focused on housekeeping GitHub issues and pull requests as documented in our issue grooming guide.`, + ``, + `We also worked with our partners at GitHub on GitHub Codespaces, which ended up being more involved than originally anticipated. To that end, we'll continue working on housekeeping for part of the November iteration.`, + ``, + `During this housekeeping milestone, we also addressed several feature requests and community [pull requests](#thank-you). Read on to learn about new features and settings.`, + ``, + `## Workbench`, + ``, + `### More prominent pinned tabs`, + ``, + `${CURSOR}Pinned tabs will now always show their pin icon, even while inactive, to make them easier to identify. If an editor is both pinned and contains unsaved changes, the icon reflects both states.`, + ``, + `![Inactive pinned tabs showing pin icons](images/1_51/pinned-tabs.png)` + ) + ); + assertNestedRangesEqual(ranges![0], [27, 0, 27, 201], [26, 0, 29, 70], [25, 0, 29, 70], [24, 0, 29, 70], [23, 0, 29, 70], [10, 0, 29, 70], [9, 0, 29, 70]); + }); }); function assertNestedLineNumbersEqual(range: vscode.SelectionRange, ...expectedRanges: [number, number][]) { const lineage = getLineage(range); - assert.strictEqual(lineage.length, expectedRanges.length, `expected depth: ${expectedRanges.length}, but was ${lineage.length}`); + assert.strictEqual(lineage.length, expectedRanges.length, `expected depth: ${expectedRanges.length}, but was ${lineage.length} ${getValues(getLineage(range))}`); for (let i = 0; i < lineage.length; i++) { assertLineNumbersEqual(lineage[i], expectedRanges[i][0], expectedRanges[i][1], `parent at a depth of ${i}`); } From 4884986dd6c5c62a8b3f57779f92748e7662b686 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 2 Dec 2020 10:13:02 -0800 Subject: [PATCH 0555/1837] tweak smart select test --- .../markdown-language-features/src/test/smartSelect.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/markdown-language-features/src/test/smartSelect.test.ts b/extensions/markdown-language-features/src/test/smartSelect.test.ts index cb6b8a401e2..6e77d56c23c 100644 --- a/extensions/markdown-language-features/src/test/smartSelect.test.ts +++ b/extensions/markdown-language-features/src/test/smartSelect.test.ts @@ -629,7 +629,7 @@ suite('markdown.SmartSelect', () => { function assertNestedLineNumbersEqual(range: vscode.SelectionRange, ...expectedRanges: [number, number][]) { const lineage = getLineage(range); - assert.strictEqual(lineage.length, expectedRanges.length, `expected depth: ${expectedRanges.length}, but was ${lineage.length} ${getValues(getLineage(range))}`); + assert.strictEqual(lineage.length, expectedRanges.length, `expected depth: ${expectedRanges.length}, but was ${lineage.length} ${getValues(lineage)}`); for (let i = 0; i < lineage.length; i++) { assertLineNumbersEqual(lineage[i], expectedRanges[i][0], expectedRanges[i][1], `parent at a depth of ${i}`); } From a9100d686c431f3483e3ad081515b158fdbb6b84 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 2 Dec 2020 11:32:58 -0800 Subject: [PATCH 0556/1837] Update verification notebook milestone --- .vscode/notebooks/verification.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 67db0cb97d4..582859397ef 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -14,7 +14,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"October 2020\"", + "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"November 2020\"", "editable": true }, { From 44dafcc8408a3645e61b87af76e05c063b428f40 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 2 Dec 2020 20:48:44 +0100 Subject: [PATCH 0557/1837] Allow an `EncodedTokensProvider` to also provide a tokenize method --- .../standalone/browser/standaloneLanguages.ts | 25 ++++++++++++++----- src/vs/monaco.d.ts | 4 +++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 9bb40fa3750..dbf225a6c12 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -75,9 +75,11 @@ export function setLanguageConfiguration(languageId: string, configuration: Lang */ export class EncodedTokenizationSupport2Adapter implements modes.ITokenizationSupport { + private readonly _languageIdentifier: modes.LanguageIdentifier; private readonly _actual: EncodedTokensProvider; - constructor(actual: EncodedTokensProvider) { + constructor(languageIdentifier: modes.LanguageIdentifier, actual: EncodedTokensProvider) { + this._languageIdentifier = languageIdentifier; this._actual = actual; } @@ -86,6 +88,9 @@ export class EncodedTokenizationSupport2Adapter implements modes.ITokenizationSu } public tokenize(line: string, state: modes.IState, offsetDelta: number): TokenizationResult { + if (typeof this._actual.tokenize === 'function') { + return TokenizationSupport2Adapter.adaptTokenize(this._languageIdentifier.language, <{ tokenize(line: string, state: modes.IState): ILineTokens; }>this._actual, line, state, offsetDelta); + } throw new Error('Not supported!'); } @@ -114,7 +119,7 @@ export class TokenizationSupport2Adapter implements modes.ITokenizationSupport { return this._actual.getInitialState(); } - private _toClassicTokens(tokens: IToken[], language: string, offsetDelta: number): Token[] { + private static _toClassicTokens(tokens: IToken[], language: string, offsetDelta: number): Token[] { let result: Token[] = []; let previousStartIndex: number = 0; for (let i = 0, len = tokens.length; i < len; i++) { @@ -137,9 +142,9 @@ export class TokenizationSupport2Adapter implements modes.ITokenizationSupport { return result; } - public tokenize(line: string, state: modes.IState, offsetDelta: number): TokenizationResult { - let actualResult = this._actual.tokenize(line, state); - let tokens = this._toClassicTokens(actualResult.tokens, this._languageIdentifier.language, offsetDelta); + public static adaptTokenize(language: string, actual: { tokenize(line: string, state: modes.IState): ILineTokens; }, line: string, state: modes.IState, offsetDelta: number): TokenizationResult { + let actualResult = actual.tokenize(line, state); + let tokens = TokenizationSupport2Adapter._toClassicTokens(actualResult.tokens, language, offsetDelta); let endState: modes.IState; // try to save an object if possible @@ -152,6 +157,10 @@ export class TokenizationSupport2Adapter implements modes.ITokenizationSupport { return new TokenizationResult(tokens, endState); } + public tokenize(line: string, state: modes.IState, offsetDelta: number): TokenizationResult { + return TokenizationSupport2Adapter.adaptTokenize(this._languageIdentifier.language, this._actual, line, state, offsetDelta); + } + private _toBinaryTokens(tokens: IToken[], offsetDelta: number): Uint32Array { const languageId = this._languageIdentifier.id; const tokenTheme = this._standaloneThemeService.getColorTheme().tokenTheme; @@ -287,6 +296,10 @@ export interface EncodedTokensProvider { * Tokenize a line given the state at the beginning of the line. */ tokenizeEncoded(line: string, state: modes.IState): IEncodedLineTokens; + /** + * Tokenize a line given the state at the beginning of the line. + */ + tokenize?(line: string, state: modes.IState): ILineTokens; } function isEncodedTokensProvider(provider: TokensProvider | EncodedTokensProvider): provider is EncodedTokensProvider { @@ -307,7 +320,7 @@ export function setTokensProvider(languageId: string, provider: TokensProvider | } const create = (provider: TokensProvider | EncodedTokensProvider) => { if (isEncodedTokensProvider(provider)) { - return new EncodedTokenizationSupport2Adapter(provider); + return new EncodedTokenizationSupport2Adapter(languageIdentifier!, provider); } else { return new TokenizationSupport2Adapter(StaticServices.standaloneThemeService.get(), languageIdentifier!, provider); } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 3aaef2a4771..012344fa2da 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5061,6 +5061,10 @@ declare namespace monaco.languages { * Tokenize a line given the state at the beginning of the line. */ tokenizeEncoded(line: string, state: IState): IEncodedLineTokens; + /** + * Tokenize a line given the state at the beginning of the line. + */ + tokenize?(line: string, state: IState): ILineTokens; } /** From 9d9ae54aa87749c07f83ff0687f7f2277297f1dc Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 2 Dec 2020 11:59:10 -0800 Subject: [PATCH 0558/1837] Add jpg to vscodeResources in order to bring gettingStarted images into the bundle --- build/gulpfile.vscode.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 6e556444fe1..1d02cbe067a 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -58,7 +58,7 @@ const vscodeResources = [ 'out-build/bootstrap-node.js', 'out-build/bootstrap-window.js', 'out-build/paths.js', - 'out-build/vs/**/*.{svg,png,html}', + 'out-build/vs/**/*.{svg,png,html,jpg}', '!out-build/vs/code/browser/**/*.html', '!out-build/vs/editor/standalone/**/*.svg', 'out-build/vs/base/common/performance.js', @@ -201,7 +201,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true }); - const jsFilter = util.filter(data => !data.isDirectory() &&/\.js$/.test(data.path)); + const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path)); const root = path.resolve(path.join(__dirname, '..')); const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])); From b122603b86b17dc9f12883959338e1d645ddab5f Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 2 Dec 2020 12:21:03 -0800 Subject: [PATCH 0559/1837] Fix comment decoration weirdness, fixes https://github.com/microsoft/vscode-pull-request-github/issues/2309 --- src/vs/workbench/contrib/comments/browser/media/review.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index cfa7d955f41..da9c9f970d8 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -397,7 +397,7 @@ div.preview.inline .monaco-editor .comment-range-glyph { } .monaco-editor .margin-view-overlays > div:hover > .comment-range-glyph.comment-diff-added:before { - content: "💬"; + content: "+"; } .monaco-editor .comment-range-glyph.comment-thread { From 1fc36c35bb2468164e1c7722fbba9a94b397d08f Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 2 Dec 2020 13:32:56 -0800 Subject: [PATCH 0560/1837] remove extrenouus log fixes #111759 --- .../services/gettingStarted/common/gettingStartedService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts index 6e0476e5ccc..243926c63d7 100644 --- a/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedService.ts @@ -166,7 +166,6 @@ export class GettingStartedService implements IGettingStartedService { progressByEvent(event: string): void { const listening = this.eventListeners.get(event) ?? []; - console.log(event, listening, this.eventListeners); listening.forEach(id => this.progressTask(id)); } } From 253844006ab7159acdb6b8b34f175b12c4561567 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 2 Dec 2020 15:54:32 -0800 Subject: [PATCH 0561/1837] fix #111735. --- .../notebook/browser/contrib/find/findController.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts index fdabea9f6f1..2c2c46b895a 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts @@ -43,6 +43,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote private _currentMatchDecorations: ICellModelDecorations[] = []; private _showTimeout: number | null = null; private _hideTimeout: number | null = null; + private _previousFocusElement?: HTMLElement; constructor( private readonly _notebookEditor: INotebookEditor, @@ -65,6 +66,10 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote this._register(this._state.onFindReplaceStateChange(() => { this.onInputChanged(); })); + + this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { + this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; + }, true)); } private _onFindInputKeyDown(e: IKeyboardEvent): void { @@ -167,6 +172,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote } protected onFocusTrackerBlur() { + this._previousFocusElement = undefined; this._findWidgetFocused.reset(); } @@ -324,6 +330,11 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote } else { // no op } + + if (this._previousFocusElement && this._previousFocusElement.offsetParent) { + this._previousFocusElement.focus(); + this._previousFocusElement = undefined; + } } clear() { From 5b121903fc01e4ca36e4eeefdb17cf37ceff95f8 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 2 Dec 2020 16:44:11 -0800 Subject: [PATCH 0562/1837] Fix issue preventing cells from leaving "running" state Fix #110973 --- .../contrib/notebook/browser/view/renderers/cellRenderer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index ecc1655a00f..2fccd56c7b9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -1034,6 +1034,7 @@ export class RunStateRenderer { clear() { if (this.spinnerTimer) { clearTimeout(this.spinnerTimer); + this.spinnerTimer = undefined; } } From 5215161c8844ce4766cdbb39bd05efbd00371764 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Thu, 3 Dec 2020 00:49:27 +0000 Subject: [PATCH 0563/1837] fixes #108712 --- .../browser/parts/titlebar/menubarControl.ts | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 139b4530057..99fcf2b6ebe 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -11,7 +11,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IAction, Action, SubmenuAction, Separator } from 'vs/base/common/actions'; import * as DOM from 'vs/base/browser/dom'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { isMacintosh, isWeb, isIOS } from 'vs/base/common/platform'; +import { isMacintosh, isWeb, isIOS, isNative } from 'vs/base/common/platform'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -199,13 +199,27 @@ export abstract class MenubarControl extends Disposable { if (event.affectsConfiguration('editor.accessibilitySupport')) { this.notifyUserOfCustomMenubarAccessibility(); } + + // Since we try not update when hidden, we should + // try to update the recently opened list on visibility changes + if (event.affectsConfiguration('window.menuBarVisibility')) { + this.onRecentlyOpenedChange(); + } + } + + private get menubarHidden(): boolean { + return isMacintosh && isNative ? false : getMenuBarVisibility(this.configurationService) === 'hidden'; } protected onRecentlyOpenedChange(): void { - this.workspacesService.getRecentlyOpened().then(recentlyOpened => { - this.recentlyOpened = recentlyOpened; - this.updateMenubar(); - }); + + // Do not update recently opened when the menubar is hidden #108712 + if (!this.menubarHidden) { + this.workspacesService.getRecentlyOpened().then(recentlyOpened => { + this.recentlyOpened = recentlyOpened; + this.updateMenubar(); + }); + } } private createOpenRecentMenuAction(recent: IRecent): IAction & { uri: URI } { From 2012817c0d2576dda7310981512064fd4667d2bd Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 2 Dec 2020 17:14:44 -0800 Subject: [PATCH 0564/1837] Fix #111699: workbench.startupEditor setting not showing Getting Started tab --- .../workbench/contrib/welcome/page/browser/welcomePage.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts index 4a6da704a94..37a7512d408 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts @@ -105,7 +105,9 @@ export class WelcomePageContribution implements IWorkbenchContribution { }); } else { const startupEditorTypeID = startupEditorSetting === 'gettingStarted' ? gettingStartedInputTypeId : welcomeInputTypeId; - const startupEditorCtor = startupEditorSetting === 'gettingStarted' ? GettingStartedPage : WelcomePage; + const launchEditor = startupEditorSetting === 'gettingStarted' + ? instantiationService.createInstance(GettingStartedPage, {}) + : instantiationService.createInstance(WelcomePage); let options: IEditorOptions; let editor = editorService.activeEditor; @@ -118,7 +120,7 @@ export class WelcomePageContribution implements IWorkbenchContribution { } else { options = { pinned: false }; } - return instantiationService.createInstance(startupEditorCtor).openEditor(options); + return launchEditor.openEditor(options); } } return undefined; From af63e8263a14d7e1a1d469a51d5476502931806b Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 2 Dec 2020 17:27:22 -0800 Subject: [PATCH 0565/1837] Fix #111706: Getting started: images need alt text --- .../gettingStarted/browser/gettingStarted.ts | 6 +++++- .../gettingStarted/common/gettingStartedContent.ts | 14 +++++++------- .../common/gettingStartedRegistry.ts | 12 ++++++++---- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index ad2d3527c2a..1eeb91b1558 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -176,11 +176,15 @@ export class GettingStartedPage extends Disposable { } this.editorInput.selectedTask = id; const taskToExpand = assertIsDefined(this.currentCategory.content.items.find(task => task.id === id)); - mediaElement.setAttribute('src', taskToExpand.media.toString()); + console.log(taskToExpand.media.path, taskToExpand.media.path.toString()); + + mediaElement.setAttribute('src', taskToExpand.media.path.toString()); + mediaElement.setAttribute('alt', taskToExpand.media.altText); taskElement.parentElement?.querySelectorAll('.expanded').forEach(node => node.classList.remove('expanded')); taskElement.classList.add('expanded'); } else { mediaElement.setAttribute('src', ''); + mediaElement.setAttribute('alt', ''); } } diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts index 65d59be4589..64e01b6746b 100644 --- a/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts @@ -12,7 +12,7 @@ type GettingStartedItem = { button: { title: string, command: string }, doneOn: { commandExecuted: string, eventFired?: never } | { eventFired: string, commandExecuted?: never, } when?: string, - media: string, + media: { type: 'image', path: string, altText: string }, }; type GettingStartedCategory = { @@ -43,7 +43,7 @@ export const content: GettingStartedContent = [ title: localize('pickColorTask.title', "Color Theme"), button: { title: localize('pickColorTask.button', "Find a Theme"), command: 'workbench.action.selectTheme' }, doneOn: { eventFired: 'themeSelected' }, - media: 'ColorTheme.jpg' + media: { type: 'image', altText: 'ColorTheme', path: 'ColorTheme.jpg', } }, { @@ -55,7 +55,7 @@ export const content: GettingStartedContent = [ command: 'workbench.extensions.action.showRecommendedKeymapExtensions' }, doneOn: { commandExecuted: 'workbench.extensions.action.showRecommendedKeymapExtensions' }, - media: 'Extensions.jpg', + media: { type: 'image', altText: 'Extensions', path: 'Extensions.jpg', } }, { @@ -67,7 +67,7 @@ export const content: GettingStartedContent = [ command: 'workbench.extensions.action.showLanguageExtensions', }, doneOn: { commandExecuted: 'workbench.extensions.action.showLanguageExtensions' }, - media: 'Languages.jpg', + media: { type: 'image', altText: 'Languages', path: 'Languages.jpg', } }, { @@ -80,7 +80,7 @@ export const content: GettingStartedContent = [ command: 'workbench.action.files.openFileFolder' }, doneOn: { commandExecuted: 'workbench.action.files.openFileFolder' }, - media: 'OpenFolder.jpg' + media: { type: 'image', altText: 'OpenFolder', path: 'OpenFolder.jpg' } }, { @@ -93,7 +93,7 @@ export const content: GettingStartedContent = [ command: 'workbench.action.files.openFolder' }, doneOn: { commandExecuted: 'workbench.action.files.openFolder' }, - media: 'OpenFolder.png' + media: { type: 'image', altText: 'OpenFolder', path: 'OpenFolder.jpg' } } ] } @@ -116,7 +116,7 @@ export const content: GettingStartedContent = [ command: 'workbench.action.showCommands' }, doneOn: { commandExecuted: 'workbench.action.showCommands' }, - media: 'https://code.visualstudio.com/assets/updates/1_51/custom-tree-hover.gif', + media: { type: 'image', altText: 'gif of a custom tree hover', path: 'https://code.visualstudio.com/assets/updates/1_51/custom-tree-hover.gif' }, } ] } diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts index ace92e7ef45..5272c631147 100644 --- a/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedRegistry.ts @@ -25,7 +25,7 @@ export interface IGettingStartedTask { order: number, button: { title: string, command: string }, doneOn: { commandExecuted: string, eventFired?: never } | { eventFired: string, commandExecuted?: never, } - media: URI + media: { type: 'image', path: URI, altText: string }, } export interface IGettingStartedCategoryDescriptor { @@ -134,9 +134,13 @@ content.forEach(category => { category: category.id, order: index, when: ContextKeyExpr.deserialize(item.when) ?? ContextKeyExpr.true(), - media: item.media.startsWith('https://') - ? URI.parse(item.media, true) - : FileAccess.asFileUri('vs/workbench/services/gettingStarted/common/media/' + item.media, require) + media: { + type: item.media.type, + altText: item.media.altText, + path: item.media.path.startsWith('https://') + ? URI.parse(item.media.path, true) + : FileAccess.asFileUri('vs/workbench/services/gettingStarted/common/media/' + item.media.path, require) + } }); }); } From f603b548c5b98e0de999d9a11ba438eed18b517e Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 2 Dec 2020 17:48:52 -0800 Subject: [PATCH 0566/1837] Polish getting started styles (#111774) * Polish getting started styling * Update margins for task description --- .../gettingStarted/browser/gettingStarted.css | 98 +++++++++---------- .../gettingStarted/browser/gettingStarted.ts | 2 +- .../browser/vs_code_editor_getting_started.ts | 7 +- 3 files changed, 50 insertions(+), 57 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 8e16b49a24c..766c3af7ccd 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -17,16 +17,15 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .header { - text-align: center; -} - -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .title { - display: inline-block; + margin-top: 32px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-title { - margin-top: 6px; - margin-bottom: 2px; + margin-bottom: 4px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-description-container { @@ -34,12 +33,12 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-description { - font-size: 12pt; + font-size: 12px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-progress { - margin-top: 6px; - font-size: 8pt; + margin-top: 12px; + font-size: 12px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories progress { @@ -51,14 +50,13 @@ display: flex; flex-wrap: wrap; justify-content: center; - width: 70%; max-width: 900px; - margin: 20px auto; + margin: 32px auto; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category { width: 330px; - min-height: 100px; + min-height: 80px; text-align: left; display: flex; } @@ -68,21 +66,20 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category .codicon { - margin: 10px 8px 0 0; + margin-right: 10px; font-size: 32px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category { width: 330px; - height: 100px; display: flex; + padding: 40px 0 20px; margin-left: 12px; - + min-height: auto; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category .codicon { margin-left:0; - margin-top: 28px; font-size: 22pt; } @@ -94,34 +91,35 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task { + display: flex; width: 100%; - height: 26pt; overflow: hidden; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) .task-description, +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) button, +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) a { + display: none; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task.expanded { width: 100%; height: unset; } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-description-container { - padding-left: 30px; - padding-right: 4px; -} - .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-title { - margin-bottom: 4px; font-size: 14pt; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-description { - font-size: 11pt; + margin-top: 4px; + font-size: 13px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-next { float: right; - margin-top: 16px; + margin-top: 24px; margin-right: 25px; } @@ -130,15 +128,12 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .codicon { - float: left; - font-size: 20pt; - position: relative; - top: -4px; - left: -1px; + margin-right: 8px; + font-size: 20px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task-action { - margin: 10px 0 0; + margin: 20px 0 0; padding: 4px 8px; font-size: 11pt; min-width: 100px; @@ -146,7 +141,7 @@ .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-left { min-width: 330px; - width: 33%; + width: 40%; max-width: 400px; } @@ -162,7 +157,15 @@ margin: 10px; color: inherit; text-align: left; - padding: 10px; + padding: 16px; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:hover { + cursor: pointer; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:focus { + outline-style: solid; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button { @@ -177,16 +180,6 @@ top: 2px; } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .product-icon { - background-image: url('../../../../browser/media/code-icon.svg'); - width: 75px; - height: 75px; - background-size: contain; - display: inline-block; - margin-right: 20px; -} - - .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .skip { display: block; width: 150px; @@ -195,25 +188,28 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h1 { - font-size: 32pt; + font-size: 32px; font-weight: normal; border-bottom: none; - margin-bottom: 0; + margin: 0; + padding: 0; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h2 { font-weight: normal; + margin: 0 0 4px 0; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide h3 { - font-weight: normal; - margin-top: 0; - margin-bottom: 0; + font-size: 18px; + font-weight: bold; + margin: 0; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .subtitle { - font-size: 18pt; - margin-top: 0; + font-size: 16px; + margin: 0; + padding: 0; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .footer { diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 1eeb91b1558..fbdb9a257e3 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -288,7 +288,7 @@ export class GettingStartedPage extends Disposable { const categoryElements = category.content.items.map( (task, i, arr) => $('button.getting-started-task', { 'x-dispatch': 'selectTask:' + task.id, id: 'getting-started-task-' + task.id }, - $('.codicon' + (task.done ? '.codicon-star-full' : '.codicon-star-empty'), { id: 'done-task-' + task.id }), + $('.codicon' + (task.done ? '.codicon-pass-filled' : '.codicon-circle-large-outline'), { id: 'done-task-' + task.id }), $('.task-description-container', {}, $('h3.task-title', {}, task.title), $('.task-description.description', {}, task.description), diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index d002501a8ef..f823a50031c 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -11,11 +11,8 @@ export default () => `
-
-
-

${escape(localize('gettingStarted.vscode', "Visual Studio Code"))}

-

${escape(localize({ key: 'gettingStarted.editingRedefined', comment: ['Shown as subtitle on the Welcome page.'] }, "Code editing. Redefined"))}

-
+

${escape(localize('gettingStarted.vscode', "Visual Studio Code"))}

+

${escape(localize({ key: 'gettingStarted.editingRedefined', comment: ['Shown as subtitle on the Welcome page.'] }, "Code editing. Redefined"))}

From 92192baf760315ac47fb2caaf3ce6d0778962352 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 2 Dec 2020 19:56:11 -0800 Subject: [PATCH 0567/1837] Bring content closer to center vertical when space permitting Ref #111753 --- .../welcome/gettingStarted/browser/gettingStarted.css | 10 ++++++++++ .../browser/vs_code_editor_getting_started.ts | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 766c3af7ccd..f41c4c53565 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -16,6 +16,16 @@ left: 0; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories { + height: calc(100% - 50px); + display: flex; + flex-direction: column; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .gap { + flex: 150px 0 1 +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .header { margin-top: 32px; display: flex; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index f823a50031c..dd62545272f 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -10,11 +10,13 @@ export default () => `
+

${escape(localize('gettingStarted.vscode', "Visual Studio Code"))}

${escape(localize({ key: 'gettingStarted.editingRedefined', comment: ['Shown as subtitle on the Welcome page.'] }, "Code editing. Redefined"))}

+
Date: Wed, 2 Dec 2020 21:50:52 -0800 Subject: [PATCH 0568/1837] Slightly darken list active bg on light theme (fixes #111750) --- src/vs/platform/theme/common/colorRegistry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index 70f67e0f33e..b5239353a96 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -358,7 +358,7 @@ export const diffDiagonalFill = registerColor('diffEditor.diagonalFill', { dark: */ export const listFocusBackground = registerColor('list.focusBackground', { dark: '#062F4A', light: '#D6EBFF', hc: null }, nls.localize('listFocusBackground', "List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")); export const listFocusForeground = registerColor('list.focusForeground', { dark: null, light: null, hc: null }, nls.localize('listFocusForeground', "List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")); -export const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#094771', light: '#0074E8', hc: null }, nls.localize('listActiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")); +export const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#094771', light: '#0060C0', hc: null }, nls.localize('listActiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")); export const listActiveSelectionForeground = registerColor('list.activeSelectionForeground', { dark: Color.white, light: Color.white, hc: null }, nls.localize('listActiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")); export const listInactiveSelectionBackground = registerColor('list.inactiveSelectionBackground', { dark: '#37373D', light: '#E4E6F1', hc: null }, nls.localize('listInactiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); export const listInactiveSelectionForeground = registerColor('list.inactiveSelectionForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); From 4f33022639f6bb6db626520939f58a0dc6de6a92 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 3 Dec 2020 09:50:46 +0100 Subject: [PATCH 0569/1837] add verification query for issues from non-vscode team members --- .vscode/notebooks/my-endgame.github-issues | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 402ef474e56..5222481a470 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -182,7 +182,7 @@ { "kind": 1, "language": "markdown", - "value": "## Issues filed by others", + "value": "## Issues filed by VSCode members", "editable": true }, { @@ -191,6 +191,18 @@ "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, + { + "kind": 1, + "language": "markdown", + "value": "## Issues filed by others", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli, -author:alexdima, -author:alexr00, -author:AmandaSilver, -author:bamurtaugh, -author:bpasero, -author:btholt, -author:chrisdias, -author:chrmarti, -author:Chuxel, -author:connor4312, -author:dbaeumer, -author:deepak1556, -author:devinvalenciano, -author:digitarald, -author:eamodio, -author:egamma, -author:fiveisprime, -author:gregvanl, -author:isidorn, -author:ItalyPaleAle, -author:JacksonKearl, -author:joaomoreno, -author:jrieken, -author:kieferrm, -author:lszomoru, -author:meganrogge, -author:misolori, -author:mjbvz, -author:ornellaalt, -author:orta, -author:rebornix, -author:RMacfarlane, -author:roblourens, -author:rzhao271, -author:sana-ajani, -author:sandy081, -author:sbatten, -author:stevencl, -author:Tyriar, -author:weinand", + "editable": true + }, { "kind": 1, "language": "markdown", From 0ea221b3252e5e25da182eeec3bbee78f6f18912 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 3 Dec 2020 09:52:37 +0100 Subject: [PATCH 0570/1837] fix query, remove commas --- .vscode/notebooks/my-endgame.github-issues | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 5222481a470..eb8380541ac 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -182,13 +182,13 @@ { "kind": 1, "language": "markdown", - "value": "## Issues filed by VSCode members", + "value": "## Issues filed from outside team", "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:bamurtaugh -author:bpasero -author:btholt -author:chrisdias -author:chrmarti -author:Chuxel -author:connor4312 -author:dbaeumer -author:deepak1556 -author:devinvalenciano -author:digitarald -author:eamodio -author:egamma -author:fiveisprime -author:gregvanl -author:isidorn -author:ItalyPaleAle -author:JacksonKearl -author:joaomoreno -author:jrieken -author:kieferrm -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:ornellaalt -author:orta -author:rebornix -author:RMacfarlane -author:roblourens -author:rzhao271 -author:sana-ajani -author:sandy081 -author:sbatten -author:stevencl -author:Tyriar -author:weinand", "editable": true }, { @@ -200,7 +200,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE is:issue is:closed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli, -author:alexdima, -author:alexr00, -author:AmandaSilver, -author:bamurtaugh, -author:bpasero, -author:btholt, -author:chrisdias, -author:chrmarti, -author:Chuxel, -author:connor4312, -author:dbaeumer, -author:deepak1556, -author:devinvalenciano, -author:digitarald, -author:eamodio, -author:egamma, -author:fiveisprime, -author:gregvanl, -author:isidorn, -author:ItalyPaleAle, -author:JacksonKearl, -author:joaomoreno, -author:jrieken, -author:kieferrm, -author:lszomoru, -author:meganrogge, -author:misolori, -author:mjbvz, -author:ornellaalt, -author:orta, -author:rebornix, -author:RMacfarlane, -author:roblourens, -author:rzhao271, -author:sana-ajani, -author:sandy081, -author:sbatten, -author:stevencl, -author:Tyriar, -author:weinand", + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed -author:@me sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found", "editable": true }, { From 4095701c702325729497b077713177ac13913cd3 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Thu, 3 Dec 2020 10:40:32 +0100 Subject: [PATCH 0571/1837] Exclude endgame-plan issues from query --- .vscode/notebooks/my-endgame.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index eb8380541ac..54ec5328eba 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -122,7 +122,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:issue is:open", + "value": "$REPOS $MILESTONE $MINE is:issue is:open -label:endgame-plan", "editable": true }, { From 09a7ad2ae7f34f1cfbfb145e8b5d87fb1b752abf Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 3 Dec 2020 11:23:22 +0100 Subject: [PATCH 0572/1837] fix raw timers telemetry event --- .../services/timer/browser/timerService.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 0dab9f40ed0..53ad8e85e5f 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -375,16 +375,9 @@ export abstract class AbstractTimerService implements ITimerService { this._telemetryService.publicLog('startupTimeVaried', metrics); // report raw timers as telemetry - const entries: Record = Object.create(null); - for (const entry of perf.getEntries()) { - entries[entry.name] = entry.startTime; - } - /* __GDPR__ - "startupRawTimers" : { - "entries": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } - } - */ - this._telemetryService.publicLog('startupRawTimers', { entries }); + type Durations = { entries: string; }; + type DurationsClassification = { entries: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; + this._telemetryService.publicLog2('startup.timers.raw', { entries: JSON.stringify(perf.getEntries()) }); } private async _computeStartupMetrics(): Promise { From 87e43299ade57a5e2d0db24c38842c84f3cf5269 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 3 Dec 2020 12:46:02 +0100 Subject: [PATCH 0573/1837] update DAP to 1.43 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4f5198a1b1f..faabdc484fd 100644 --- a/package.json +++ b/package.json @@ -176,7 +176,7 @@ "vinyl": "^2.0.0", "vinyl-fs": "^3.0.0", "vsce": "1.48.0", - "vscode-debugprotocol": "1.41.0", + "vscode-debugprotocol": "1.43.0", "vscode-nls-dev": "^3.3.1", "webpack": "^4.43.0", "webpack-cli": "^3.3.12", diff --git a/yarn.lock b/yarn.lock index 2ea65eb0188..dd5e3e4eea8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10010,10 +10010,10 @@ vsce@1.48.0: yauzl "^2.3.1" yazl "^2.2.2" -vscode-debugprotocol@1.41.0: - version "1.41.0" - resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.41.0.tgz#fc99b01dee26e9f25cbb5708318fc0081002808c" - integrity sha512-Sxp7kDDuhpEZiDaIfhM0jLF3RtMqvc6CpoESANE77t351uezsd/oDoqALLcOnmmsDzTgQ3W0sCvM4gErnjDFpA== +vscode-debugprotocol@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.43.0.tgz#fe5bcfa7021c250e78c3cf203d392e98b5de268c" + integrity sha512-pnj+9wVS3yPYz/RXoYSN1tCv+D4139ueaY2WC7V6fUd9QZU8IE5s4r/lZUMJ9gAEGz2km/Iv4qcI7Fdlz5xS9w== vscode-nls-dev@^3.3.1: version "3.3.1" From 07333dec483e7784ebecd73739db7f08314109fc Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 3 Dec 2020 12:49:38 +0100 Subject: [PATCH 0574/1837] node-debug@1.44.15 --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index f62018b387c..d413a31fc43 100644 --- a/product.json +++ b/product.json @@ -31,7 +31,7 @@ "builtInExtensions": [ { "name": "ms-vscode.node-debug", - "version": "1.44.14", + "version": "1.44.15", "repo": "https://github.com/microsoft/vscode-node-debug", "metadata": { "id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6", From 79fb30f5b6d33cdbc5886accfa7a69afa15d237a Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Dec 2020 14:45:27 +0100 Subject: [PATCH 0575/1837] Fix resolveTreeItem called twice Fixes #111749 --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 9f87da0c342..44c56834ff0 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -206,16 +206,23 @@ export class IconLabel extends Disposable { const hoverDelay = isMacintosh ? 1500 : 500; let hoverOptions: IHoverDelegateOptions | undefined; let mouseX: number | undefined; + let isHovering = false; function mouseOver(this: HTMLElement, e: MouseEvent): any { - let isHovering = true; - function mouseMove(this: HTMLElement, e: MouseEvent): any { - mouseX = e.x; + if (isHovering) { + return; } function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): any { isHovering = false; + mouseLeaveDisposable.dispose(); + mouseDownDisposable.dispose(); } const mouseLeaveDisposable = domEvent(htmlElement, dom.EventType.MOUSE_LEAVE, true)(mouseLeaveOrDown.bind(htmlElement)); const mouseDownDisposable = domEvent(htmlElement, dom.EventType.MOUSE_DOWN, true)(mouseLeaveOrDown.bind(htmlElement)); + isHovering = true; + + function mouseMove(this: HTMLElement, e: MouseEvent): any { + mouseX = e.x; + } const mouseMoveDisposable = domEvent(htmlElement, dom.EventType.MOUSE_MOVE, true)(mouseMove.bind(htmlElement)); setTimeout(async () => { if (isHovering && tooltip) { @@ -234,7 +241,8 @@ export class IconLabel extends Disposable { }; } } - if (hoverOptions) { + // awaiting the tooltip could take a while. Make sure we're still hovering. + if (hoverOptions && isHovering) { if (mouseX !== undefined) { (hoverOptions.target).x = mouseX + 10; } @@ -242,8 +250,6 @@ export class IconLabel extends Disposable { } } mouseMoveDisposable.dispose(); - mouseLeaveDisposable.dispose(); - mouseDownDisposable.dispose(); }, hoverDelay); } const mouseOverDisposable = this._register(domEvent(htmlElement, dom.EventType.MOUSE_OVER, true)(mouseOver.bind(htmlElement))); From 044741569781be2f5842ae01bb5ceba4b26f1cc3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 3 Dec 2020 15:18:59 +0100 Subject: [PATCH 0576/1837] Hide the editor's cursor when doing composition (fixes #106663) --- .../browser/controller/textAreaHandler.ts | 2 ++ .../viewParts/viewCursors/viewCursors.ts | 17 ++++++++++++++++- src/vs/editor/common/view/viewEvents.ts | 16 +++++++++++++++- .../common/viewModel/viewEventHandler.ts | 19 ++++++++++++++++++- src/vs/editor/common/viewModel/viewModel.ts | 2 ++ .../editor/common/viewModel/viewModelImpl.ts | 8 ++++++++ 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 07eadee8415..2f26618aa4b 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -276,6 +276,7 @@ export class TextAreaHandler extends ViewPart { this.textArea.setClassName(`inputarea ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ime-input`); this._viewController.compositionStart(); + this._context.model.onCompositionStart(); })); this._register(this._textAreaInput.onCompositionUpdate((e: ICompositionData) => { @@ -297,6 +298,7 @@ export class TextAreaHandler extends ViewPart { this.textArea.setClassName(`inputarea ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`); this._viewController.compositionEnd(); + this._context.model.onCompositionEnd(); })); this._register(this._textAreaInput.onFocus(() => { diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index ef3f6e301b4..ec5077ea0c7 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -25,6 +25,7 @@ export class ViewCursors extends ViewPart { private _cursorStyle: TextEditorCursorStyle; private _cursorSmoothCaretAnimation: boolean; private _selectionIsEmpty: boolean; + private _isComposingInput: boolean; private _isVisible: boolean; @@ -49,6 +50,7 @@ export class ViewCursors extends ViewPart { this._cursorStyle = options.get(EditorOption.cursorStyle); this._cursorSmoothCaretAnimation = options.get(EditorOption.cursorSmoothCaretAnimation); this._selectionIsEmpty = true; + this._isComposingInput = false; this._isVisible = false; @@ -83,7 +85,16 @@ export class ViewCursors extends ViewPart { } // --- begin event handlers - + public onCompositionStart(e: viewEvents.ViewCompositionStartEvent): boolean { + this._isComposingInput = true; + this._updateBlinking(); + return true; + } + public onCompositionEnd(e: viewEvents.ViewCompositionEndEvent): boolean { + this._isComposingInput = false; + this._updateBlinking(); + return true; + } public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { const options = this._context.configuration.options; @@ -195,6 +206,10 @@ export class ViewCursors extends ViewPart { // ---- blinking logic private _getCursorBlinking(): TextEditorCursorBlinkingStyle { + if (this._isComposingInput) { + // avoid double cursors + return TextEditorCursorBlinkingStyle.Hidden; + } if (!this._editorHasFocus) { return TextEditorCursorBlinkingStyle.Hidden; } diff --git a/src/vs/editor/common/view/viewEvents.ts b/src/vs/editor/common/view/viewEvents.ts index 804d1b977f5..bcdc69bb34f 100644 --- a/src/vs/editor/common/view/viewEvents.ts +++ b/src/vs/editor/common/view/viewEvents.ts @@ -11,6 +11,8 @@ import { ScrollType } from 'vs/editor/common/editorCommon'; import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents'; export const enum ViewEventType { + ViewCompositionStart, + ViewCompositionEnd, ViewConfigurationChanged, ViewCursorStateChanged, ViewDecorationsChanged, @@ -29,6 +31,16 @@ export const enum ViewEventType { ViewZonesChanged, } +export class ViewCompositionStartEvent { + public readonly type = ViewEventType.ViewCompositionStart; + constructor() { } +} + +export class ViewCompositionEndEvent { + public readonly type = ViewEventType.ViewCompositionEnd; + constructor() { } +} + export class ViewConfigurationChangedEvent { public readonly type = ViewEventType.ViewConfigurationChanged; @@ -285,7 +297,9 @@ export class ViewZonesChangedEvent { } export type ViewEvent = ( - ViewConfigurationChangedEvent + ViewCompositionStartEvent + | ViewCompositionEndEvent + | ViewConfigurationChangedEvent | ViewCursorStateChangedEvent | ViewDecorationsChangedEvent | ViewFlushedEvent diff --git a/src/vs/editor/common/viewModel/viewEventHandler.ts b/src/vs/editor/common/viewModel/viewEventHandler.ts index aad7a0b4957..e73ba9679b8 100644 --- a/src/vs/editor/common/viewModel/viewEventHandler.ts +++ b/src/vs/editor/common/viewModel/viewEventHandler.ts @@ -33,10 +33,15 @@ export class ViewEventHandler extends Disposable { // --- begin event handlers + public onCompositionStart(e: viewEvents.ViewCompositionStartEvent): boolean { + return false; + } + public onCompositionEnd(e: viewEvents.ViewCompositionEndEvent): boolean { + return false; + } public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { return false; } - public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { return false; } @@ -94,6 +99,18 @@ export class ViewEventHandler extends Disposable { switch (e.type) { + case viewEvents.ViewEventType.ViewCompositionStart: + if (this.onCompositionStart(e)) { + shouldRender = true; + } + break; + + case viewEvents.ViewEventType.ViewCompositionEnd: + if (this.onCompositionEnd(e)) { + shouldRender = true; + } + break; + case viewEvents.ViewEventType.ViewConfigurationChanged: if (this.onConfigurationChanged(e)) { shouldRender = true; diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index c69c16ea48c..125cb5880ae 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -164,6 +164,8 @@ export interface IViewModel extends ICursorSimpleModel { setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void; tokenizeViewport(): void; setHasFocus(hasFocus: boolean): void; + onCompositionStart(): void; + onCompositionEnd(): void; onDidColorThemeChange(): void; getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[]; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 316e4f43e1b..932f6917e55 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -183,6 +183,14 @@ export class ViewModel extends Disposable implements IViewModel { this._eventDispatcher.emitOutgoingEvent(new FocusChangedEvent(!hasFocus, hasFocus)); } + public onCompositionStart(): void { + this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewCompositionStartEvent()); + } + + public onCompositionEnd(): void { + this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewCompositionEndEvent()); + } + public onDidColorThemeChange(): void { this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewThemeChangedEvent()); } From 6d222ba7850df20ed1077596806d82b80bbb9d2b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 3 Dec 2020 15:42:21 +0100 Subject: [PATCH 0577/1837] Fixes #97196: Clear out semantic tokens when there are no more providers --- src/vs/editor/common/model.ts | 7 ++++++- src/vs/editor/common/model/textModel.ts | 8 ++++++-- src/vs/editor/common/model/tokensStore.ts | 4 ++++ src/vs/editor/common/services/modelServiceImpl.ts | 4 ++++ .../viewportSemanticTokens/viewportSemanticTokens.ts | 8 +++++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 98ce23d7b0e..52bd1b39fe7 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -855,7 +855,12 @@ export interface ITextModel { /** * @internal */ - hasSemanticTokens(): boolean; + hasCompleteSemanticTokens(): boolean; + + /** + * @internal + */ + hasSomeSemanticTokens(): boolean; /** * Flush all tokenization state. diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 2ba7cb4ee89..81f46885438 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -1880,12 +1880,16 @@ export class TextModel extends Disposable implements model.ITextModel { }); } - public hasSemanticTokens(): boolean { + public hasCompleteSemanticTokens(): boolean { return this._tokens2.isComplete(); } + public hasSomeSemanticTokens(): boolean { + return !this._tokens2.isEmpty(); + } + public setPartialSemanticTokens(range: Range, tokens: MultilineTokens2[]): void { - if (this.hasSemanticTokens()) { + if (this.hasCompleteSemanticTokens()) { return; } const changedRange = this._tokens2.setPartial(range, tokens); diff --git a/src/vs/editor/common/model/tokensStore.ts b/src/vs/editor/common/model/tokensStore.ts index a49ef27a71e..bbec0e36959 100644 --- a/src/vs/editor/common/model/tokensStore.ts +++ b/src/vs/editor/common/model/tokensStore.ts @@ -884,6 +884,10 @@ export class TokensStore2 { this._isComplete = false; } + public isEmpty(): boolean { + return (this._pieces.length === 0); + } + public set(pieces: MultilineTokens2[] | null, isComplete: boolean): void { this._pieces = pieces || []; this._isComplete = isComplete; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 7836fa5de72..8667276868a 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -790,6 +790,10 @@ class ModelSemanticColoring extends Disposable { } const provider = this._getSemanticColoringProvider(); if (!provider) { + if (this._currentDocumentResponse) { + // there are semantic tokens set + this._model.setSemanticTokens(null, false); + } return; } this._currentDocumentRequestCancellationTokenSource = new CancellationTokenSource(); diff --git a/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts b/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts index 0a317fd6f3a..44ca583901c 100644 --- a/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts +++ b/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts @@ -92,14 +92,20 @@ class ViewportSemanticTokensContribution extends Disposable implements IEditorCo return; } const model = this._editor.getModel(); - if (model.hasSemanticTokens()) { + if (model.hasCompleteSemanticTokens()) { return; } if (!isSemanticColoringEnabled(model, this._themeService, this._configurationService)) { + if (model.hasSomeSemanticTokens()) { + model.setSemanticTokens(null, false); + } return; } const provider = ViewportSemanticTokensContribution._getSemanticColoringProvider(model); if (!provider) { + if (model.hasSomeSemanticTokens()) { + model.setSemanticTokens(null, false); + } return; } const styling = this._modelService.getSemanticTokensProviderStyling(provider); From 3c4bbf6da24091e26a18175cca375950e054e53a Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Dec 2020 15:42:51 +0100 Subject: [PATCH 0578/1837] Fix ports view listener leak Same kind of cause as https://github.com/microsoft/vscode/issues/107903 Fixes #111772 --- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index e27ba8dc03f..033bdde9a17 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -292,6 +292,9 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer Date: Thu, 3 Dec 2020 15:53:01 +0100 Subject: [PATCH 0579/1837] Add paren, bracket, and brace to autoclosing pairs for make Fixes #89191 --- extensions/make/language-configuration.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/extensions/make/language-configuration.json b/extensions/make/language-configuration.json index f3c19d01120..82645b84dfb 100644 --- a/extensions/make/language-configuration.json +++ b/extensions/make/language-configuration.json @@ -17,6 +17,18 @@ ] ], "autoClosingPairs": [ + [ + "{", + "}" + ], + [ + "[", + "]" + ], + [ + "(", + ")" + ], { "open": "'", "close": "'", From 15f38fe338a791de62b1c448f0035b199ba27a04 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Dec 2020 17:57:12 +0100 Subject: [PATCH 0580/1837] Fix ports view order in remote explorer Fixes #111830 --- src/vs/workbench/contrib/remote/browser/remote.ts | 2 +- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 2df1d1cfaf2..29ab926a392 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -574,7 +574,7 @@ Registry.as(Extensions.ViewContainersRegistry).register matches = /^details(@(\d+))?$/.exec(group); if (matches) { - return -500; + return -500 + Number(matches[2]); } matches = /^help(@(\d+))?$/.exec(group); diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 033bdde9a17..7ed9fa790e0 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -729,7 +729,10 @@ export class TunnelPanelDescriptor implements IViewDescriptor { readonly canToggleVisibility = true; readonly hideByDefault = false; readonly workspace = true; + // group is not actually used for views that are not extension contributed. Use order instead. readonly group = 'details@0'; + // -500 comes from the remote explorer viewOrderDelegate + readonly order = -500; readonly remoteAuthority?: string | string[]; readonly canMoveView = true; readonly containerIcon = Codicon.plug; From ae93d489024e2dd110220adcaec5495145996e87 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 3 Dec 2020 17:58:49 +0100 Subject: [PATCH 0581/1837] fixes #111583 --- .../files/browser/views/explorerViewer.ts | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index f50916aee92..7110cae9482 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -1013,24 +1013,28 @@ export class FileDragAndDrop implements ITreeDragAndDrop { if (data instanceof NativeDragAndDropData) { const cts = new CancellationTokenSource(); - // Indicate progress globally - try { - if (isWeb) { - const dropPromise = this.progressService.withProgress({ - location: ProgressLocation.Window, - delay: 800, - cancellable: true, - title: localize('uploadingFiles', "Uploading") - }, async progress => { - this.handleWebExternalDrop(resolvedTarget, originalEvent, progress, cts.token); - }, () => cts.dispose(true)); - // Also indicate progress in the files view - this.progressService.withProgress({ location: VIEW_ID, delay: 500 }, () => dropPromise); - } else { + if (isWeb) { + // Indicate progress globally + const dropPromise = this.progressService.withProgress({ + location: ProgressLocation.Window, + delay: 800, + cancellable: true, + title: localize('uploadingFiles', "Uploading") + }, async progress => { + try { + await this.handleWebExternalDrop(resolvedTarget, originalEvent, progress, cts.token); + } catch (error) { + this.notificationService.warn(error); + } + }, () => cts.dispose(true)); + // Also indicate progress in the files view + this.progressService.withProgress({ location: VIEW_ID, delay: 500 }, () => dropPromise); + } else { + try { this.handleExternalDrop(resolvedTarget, originalEvent, cts.token); + } catch (error) { + this.notificationService.warn(error); } - } catch (error) { - this.notificationService.warn(error); } } // In-Explorer DND (Move/Copy file) @@ -1311,6 +1315,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } private async addResources(target: ExplorerItem, resources: URI[], token: CancellationToken): Promise { + console.log('ADDING RESOURCE'); if (resources && resources.length > 0) { // Resolve target to check for name collisions and ask user From 95f6cfa0ae1f9b684f14c2521bd412616f77dba6 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Dec 2020 10:20:14 -0800 Subject: [PATCH 0582/1837] =?UTF-8?q?More=20=F0=9F=92=85:=20adjust=20overa?= =?UTF-8?q?ll=20padding=20&=20sizing=20(refs=20#111753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gettingStarted/browser/gettingStarted.css | 33 +++++++++++-------- .../gettingStarted/browser/gettingStarted.ts | 27 +++++++-------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index f41c4c53565..7c199b89de8 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -27,7 +27,6 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .header { - margin-top: 32px; display: flex; align-items: center; justify-content: center; @@ -42,10 +41,6 @@ width: 100% } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-description { - font-size: 12px; -} - .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .category-progress { margin-top: 12px; font-size: 12px; @@ -67,6 +62,7 @@ .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category { width: 330px; min-height: 80px; + margin: 12px; text-align: left; display: flex; } @@ -97,7 +93,7 @@ display: flex; height: 100%; justify-content: center; - padding: 30px; + padding: 44px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task { @@ -107,6 +103,7 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) .task-description, +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) .actions, .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) button, .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task:not(.expanded) a { display: none; @@ -127,10 +124,14 @@ font-size: 13px; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .actions { + margin-top: 12px; + display: flex; + align-items: center; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .task-next { - float: right; - margin-top: 24px; - margin-right: 25px; + margin-left: auto; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task .codicon.hidden { @@ -143,8 +144,7 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task-action { - margin: 20px 0 0; - padding: 4px 8px; + padding: 6px 12px; font-size: 11pt; min-width: 100px; } @@ -158,18 +158,21 @@ .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-right { width: 66%; text-align: center; - padding: 35px; + padding-left: 44px; margin-bottom: 50px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button { border: none; - margin: 10px; color: inherit; text-align: left; padding: 16px; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:not(:first-child) { + margin-top: 12px; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:hover { cursor: pointer; } @@ -185,6 +188,10 @@ margin: 10px; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button:hover { + cursor: pointer; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button .codicon { position: relative; top: 2px; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index fbdb9a257e3..123bd38bbd9 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -292,19 +292,20 @@ export class GettingStartedPage extends Disposable { $('.task-description-container', {}, $('h3.task-title', {}, task.title), $('.task-description.description', {}, task.description), - ...( - task.button - ? [$('button.emphasis.getting-started-task-action', { 'x-dispatch': 'runTaskAction:' + task.id }, - task.button.title + this.getKeybindingLabel(task.button.command) - )] - : []), - ...( - arr[i + 1] - ? [ - $('a.task-next', - { 'x-dispatch': 'selectTask:' + arr[i + 1].id }, localize('next', "Next")), - ] : [] - ) + $('.actions', {}, + ...( + task.button + ? [$('button.emphasis.getting-started-task-action', { 'x-dispatch': 'runTaskAction:' + task.id }, + task.button.title + this.getKeybindingLabel(task.button.command) + )] + : []), + ...( + arr[i + 1] + ? [ + $('a.task-next', + { 'x-dispatch': 'selectTask:' + arr[i + 1].id }, localize('next', "Next")), + ] : [] + )) ))); const detailContainer = assertIsDefined(document.getElementById('getting-started-detail-container')); From 564ff91763a0517e13351c2bb8ae88212a2603c7 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 3 Dec 2020 19:49:42 +0100 Subject: [PATCH 0583/1837] fixes #111832 --- .../contrib/files/browser/explorerService.ts | 74 +++++++++++-------- .../files/browser/views/explorerViewer.ts | 1 - 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/explorerService.ts b/src/vs/workbench/contrib/files/browser/explorerService.ts index 6398736b046..a1a537578e0 100644 --- a/src/vs/workbench/contrib/files/browser/explorerService.ts +++ b/src/vs/workbench/contrib/files/browser/explorerService.ts @@ -21,13 +21,14 @@ import { UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; import { IExplorerView, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { RunOnceScheduler } from 'vs/base/common/async'; export const UNDO_REDO_SOURCE = new UndoRedoSource(); export class ExplorerService implements IExplorerService { declare readonly _serviceBrand: undefined; - private static readonly EXPLORER_FILE_CHANGES_REACT_DELAY = 500; // delay in ms to react to file changes to give our internal events a chance to react first + private static readonly EXPLORER_FILE_CHANGES_REACT_DELAY = 1000; // delay in ms to react to file changes to give our internal events a chance to react first private readonly disposables = new DisposableStore(); private editable: { stat: ExplorerItem, data: IEditableData } | undefined; @@ -35,6 +36,8 @@ export class ExplorerService implements IExplorerService { private cutItems: ExplorerItem[] | undefined; private view: IExplorerView | undefined; private model: ExplorerModel; + private onFileChangesScheduler: RunOnceScheduler; + private fileChangeEvents: FileChangesEvent[] = []; constructor( @IFileService private fileService: IFileService, @@ -51,7 +54,36 @@ export class ExplorerService implements IExplorerService { this.model = new ExplorerModel(this.contextService, this.uriIdentityService, this.fileService); this.disposables.add(this.model); this.disposables.add(this.fileService.onDidRunOperation(e => this.onDidRunOperation(e))); - this.disposables.add(this.fileService.onDidFilesChange(e => this.onDidFilesChange(e))); + + this.onFileChangesScheduler = new RunOnceScheduler(async () => { + const events = this.fileChangeEvents; + this.fileChangeEvents = []; + + // Filter to the ones we care + const types = [FileChangeType.ADDED, FileChangeType.DELETED]; + if (this._sortOrder === SortOrder.Modified) { + types.push(FileChangeType.UPDATED); + } + + let shouldRefresh = false; + this.roots.forEach(r => { + if (this.view && !shouldRefresh) { + shouldRefresh = doesFileEventAffect(r, this.view, events, types); + } + }); + + if (shouldRefresh) { + await this.refresh(false); + } + + }, ExplorerService.EXPLORER_FILE_CHANGES_REACT_DELAY); + + this.disposables.add(this.fileService.onDidFilesChange(e => { + this.fileChangeEvents.push(e); + if (!this.onFileChangesScheduler.isScheduled()) { + this.onFileChangesScheduler.schedule(); + } + })); this.disposables.add(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getValue()))); this.disposables.add(Event.any<{ scheme: string }>(this.fileService.onDidChangeFileSystemProviderRegistrations, this.fileService.onDidChangeFileSystemProviderCapabilities)(async e => { let affected = false; @@ -296,32 +328,6 @@ export class ExplorerService implements IExplorerService { } } - private onDidFilesChange(e: FileChangesEvent): void { - // Check if an explorer refresh is necessary (delayed to give internal events a chance to react first) - // Note: there is no guarantee when the internal events are fired vs real ones. Code has to deal with the fact that one might - // be fired first over the other or not at all. - setTimeout(async () => { - // Filter to the ones we care - const types = [FileChangeType.ADDED, FileChangeType.DELETED]; - if (this._sortOrder === SortOrder.Modified) { - types.push(FileChangeType.UPDATED); - } - - const allResolvedDirectories: ExplorerItem[] = []; - this.roots.forEach(r => { - allResolvedDirectories.push(r); - if (this.view) { - getAllNonFilteredDescendants(r, allResolvedDirectories, this.view); - } - }); - - const shouldRefresh = allResolvedDirectories.some(r => e.affects(r.resource, ...types)); - if (shouldRefresh) { - await this.refresh(false); - } - }, ExplorerService.EXPLORER_FILE_CHANGES_REACT_DELAY); - } - private async onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): Promise { const configSortOrder = configuration?.explorer?.sortOrder || 'default'; if (this._sortOrder !== configSortOrder) { @@ -338,13 +344,19 @@ export class ExplorerService implements IExplorerService { } } -function getAllNonFilteredDescendants(item: ExplorerItem, result: ExplorerItem[], view: IExplorerView): void { +function doesFileEventAffect(item: ExplorerItem, view: IExplorerView, events: FileChangesEvent[], types: FileChangeType[]): boolean { + if (events.some(e => e.affects(item.resource, ...types))) { + return true; + } for (let [_name, child] of item.children) { if (view.isItemVisible(child)) { if (child.isDirectory && child.isDirectoryResolved) { - result.push(child); - getAllNonFilteredDescendants(child, result, view); + if (doesFileEventAffect(child, view, events, types)) { + return true; + } } } } + + return false; } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 7110cae9482..6ec1d861c37 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -1315,7 +1315,6 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } private async addResources(target: ExplorerItem, resources: URI[], token: CancellationToken): Promise { - console.log('ADDING RESOURCE'); if (resources && resources.length > 0) { // Resolve target to check for name collisions and ask user From a82ae0c9b7608650c341bb016a58c94f57aa1afb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 3 Dec 2020 20:10:44 +0100 Subject: [PATCH 0584/1837] Fix #108266 --- .../editor/contrib/hover/modesContentHover.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 8b1f88e7b39..ad2d6b27263 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -31,7 +31,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener'; import { MarkerController, NextMarkerAction } from 'vs/editor/contrib/gotoError/gotoError'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; +import { CancelablePromise, createCancelablePromise, disposableTimeout } from 'vs/base/common/async'; import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction'; import { QuickFixAction, QuickFixController } from 'vs/editor/contrib/codeAction/codeActionCommands'; import { CodeActionKind, CodeActionTrigger } from 'vs/editor/contrib/codeAction/types'; @@ -578,6 +578,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { return hoverElement; } + private recentMarkerCodeActionsInfo: { marker: IMarker, hasCodeActions: boolean } | undefined = undefined; private renderMarkerStatusbar(markerHover: MarkerHover): HTMLElement { const hoverElement = $('div.hover-row.status-bar'); const disposables = new DisposableStore(); @@ -596,24 +597,28 @@ export class ModesContentHoverWidget extends ContentHoverWidget { if (!this._editor.getOption(EditorOption.readOnly)) { const quickfixPlaceholderElement = dom.append(actionsElement, $('div')); - quickfixPlaceholderElement.style.opacity = '0'; - quickfixPlaceholderElement.style.transition = 'opacity 0.2s'; - setTimeout(() => quickfixPlaceholderElement.style.opacity = '1', 200); - quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."); - disposables.add(toDisposable(() => quickfixPlaceholderElement.remove())); - + if (this.recentMarkerCodeActionsInfo) { + if (IMarkerData.makeKey(this.recentMarkerCodeActionsInfo.marker) === IMarkerData.makeKey(markerHover.marker)) { + if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { + quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available"); + } + } else { + this.recentMarkerCodeActionsInfo = undefined; + } + } + const updatePlaceholderDisposable = disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 64)); const codeActionsPromise = this.getCodeActions(markerHover.marker); disposables.add(toDisposable(() => codeActionsPromise.cancel())); codeActionsPromise.then(actions => { - quickfixPlaceholderElement.style.transition = ''; - quickfixPlaceholderElement.style.opacity = '1'; + updatePlaceholderDisposable.dispose(); + this.recentMarkerCodeActionsInfo = { marker: markerHover.marker, hasCodeActions: actions.validActions.length > 0 }; - if (!actions.validActions.length) { + if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { actions.dispose(); quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available"); return; } - quickfixPlaceholderElement.remove(); + quickfixPlaceholderElement.style.display = 'none'; let showing = false; disposables.add(toDisposable(() => { From 061e84830d7865f53d61731333830dae4229f3d6 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 3 Dec 2020 20:13:34 +0100 Subject: [PATCH 0585/1837] fixes #110775 --- src/vs/platform/actions/browser/menuEntryActionViewItem.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index 9268e3d4ca4..1344ea90093 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -20,7 +20,8 @@ import { isWindows, isLinux } from 'vs/base/common/platform'; export function createAndFillInContextMenuActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, isPrimaryGroup?: (group: string) => boolean): IDisposable { const groups = menu.getActions(options); - const useAlternativeActions = ModifierKeyEmitter.getInstance().keyStatus.altKey; + const modifierKeyEmitter = ModifierKeyEmitter.getInstance(); + const useAlternativeActions = modifierKeyEmitter.keyStatus.altKey || ((isWindows || isLinux) && modifierKeyEmitter.keyStatus.shiftKey); fillInActions(groups, target, useAlternativeActions, isPrimaryGroup); return asDisposable(groups); } From 2964a69479ba7f9f6af695d3e65f7dadc299d7d6 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 3 Dec 2020 11:15:18 -0800 Subject: [PATCH 0586/1837] Fix #111798: Getting Started: capitalized "Editor" looks weird --- .../services/gettingStarted/common/gettingStartedContent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts index 64e01b6746b..3869a6cea3e 100644 --- a/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/services/gettingStarted/common/gettingStartedContent.ts @@ -33,7 +33,7 @@ export const content: GettingStartedContent = [ id: 'Beginner', title: localize('gettingStarted.beginner.title', "Get Started"), codicon: 'lightbulb', - description: localize('gettingStarted.beginner.description', "Get to know your new Editor"), + description: localize('gettingStarted.beginner.description', "Get to know your new editor"), content: { type: 'items', items: [ From 450ae69a335c3b9b005e4c26aa444fc0c9659d74 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 3 Dec 2020 20:15:48 +0100 Subject: [PATCH 0587/1837] Fix #111835 --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 0aa7ddd1b10..36dbf7c75ba 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -150,7 +150,7 @@ class PromptExtensionInstallFailureAction extends Action { }) }); } - const checkLogsMessage = localize('check logs', "Please check [logs]({0}) for more details.", `command:${Constants.showWindowLogActionId}`); + const checkLogsMessage = localize('check logs', "Please check the [log]({0}) for more details.", `command:${Constants.showWindowLogActionId}`); this.notificationService.prompt(Severity.Error, `${operationMessage} ${checkLogsMessage}`, promptChoices); } } From 7ecce71a487455c782eef943fb22af450ba07267 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 3 Dec 2020 20:39:33 +0100 Subject: [PATCH 0588/1837] Fixes #110376 --- .../common/controller/cursorMoveCommands.ts | 12 +++++-- .../test/browser/controller/cursor.test.ts | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/controller/cursorMoveCommands.ts b/src/vs/editor/common/controller/cursorMoveCommands.ts index bc9bbb1c390..909a2255d4d 100644 --- a/src/vs/editor/common/controller/cursorMoveCommands.ts +++ b/src/vs/editor/common/controller/cursorMoveCommands.ts @@ -412,7 +412,11 @@ export class CursorMoveCommands { const skipWrappingPointStop = hasMultipleCursors || !cursor.viewState.hasSelection(); let newViewState = MoveOperations.moveLeft(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns); - if (skipWrappingPointStop && noOfColumns === 1 && newViewState.position.lineNumber !== cursor.viewState.position.lineNumber) { + if (skipWrappingPointStop + && noOfColumns === 1 + && cursor.viewState.position.column === viewModel.getLineMinColumn(cursor.viewState.position.lineNumber) + && newViewState.position.lineNumber !== cursor.viewState.position.lineNumber + ) { // moved over to the previous view line const newViewModelPosition = viewModel.coordinatesConverter.convertViewPositionToModelPosition(newViewState.position); if (newViewModelPosition.lineNumber === cursor.modelState.position.lineNumber) { @@ -445,7 +449,11 @@ export class CursorMoveCommands { const skipWrappingPointStop = hasMultipleCursors || !cursor.viewState.hasSelection(); let newViewState = MoveOperations.moveRight(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns); - if (skipWrappingPointStop && noOfColumns === 1 && newViewState.position.lineNumber !== cursor.viewState.position.lineNumber) { + if (skipWrappingPointStop + && noOfColumns === 1 + && cursor.viewState.position.column === viewModel.getLineMaxColumn(cursor.viewState.position.lineNumber) + && newViewState.position.lineNumber !== cursor.viewState.position.lineNumber + ) { // moved over to the next view line const newViewModelPosition = viewModel.coordinatesConverter.convertViewPositionToModelPosition(newViewState.position); if (newViewModelPosition.lineNumber === cursor.modelState.position.lineNumber) { diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index ac2fa484062..cb202a3f872 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -2208,6 +2208,42 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #110376: multiple selections with wordwrap behave differently', () => { + // a single model line => 4 view lines + withTestCodeEditor([ + [ + 'just a sentence. just a ', + 'sentence. just a sentence.', + ].join('') + ], { wordWrap: 'wordWrapColumn', wordWrapColumn: 25 }, (editor, viewModel) => { + viewModel.setSelections('test', [ + new Selection(1, 1, 1, 16), + new Selection(1, 18, 1, 33), + new Selection(1, 35, 1, 50), + ]); + + moveLeft(editor, viewModel); + assertCursor(viewModel, [ + new Selection(1, 1, 1, 1), + new Selection(1, 18, 1, 18), + new Selection(1, 35, 1, 35), + ]); + + viewModel.setSelections('test', [ + new Selection(1, 1, 1, 16), + new Selection(1, 18, 1, 33), + new Selection(1, 35, 1, 50), + ]); + + moveRight(editor, viewModel); + assertCursor(viewModel, [ + new Selection(1, 16, 1, 16), + new Selection(1, 33, 1, 33), + new Selection(1, 50, 1, 50), + ]); + }); + }); + test('issue #98320: Multi-Cursor, Wrap lines and cursorSelectRight ==> cursors out of sync', () => { // a single model line => 4 view lines withTestCodeEditor([ From 7b1154d4479b5ced0d2f72cac4789d2cbc4e6ca9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Dec 2020 11:50:21 -0800 Subject: [PATCH 0589/1837] update resolve time stats even if they are the same. --- .../contrib/notebook/common/notebookEditorModel.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index fd79380d7c9..b66fc62a1f0 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -17,6 +17,7 @@ import { Schemas } from 'vs/base/common/network'; import { IFileStatWithMetadata, IFileService } from 'vs/platform/files/common/files'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ILabelService } from 'vs/platform/label/common/label'; +import { ILogService } from 'vs/platform/log/common/log'; export interface INotebookLoadOptions { @@ -51,6 +52,7 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM @IBackupFileService private readonly _backupFileService: IBackupFileService, @IFileService private readonly _fileService: IFileService, @INotificationService private readonly _notificationService: INotificationService, + @ILogService private readonly _logService: ILogService, @ILabelService labelService: ILabelService, ) { super(); @@ -199,6 +201,11 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM private async _assertStat() { const stats = await this._resolveStats(this.resource); if (this._lastResolvedFileStat && stats && stats.mtime > this._lastResolvedFileStat.mtime) { + this._logService.debug(`noteboook file on disk is newer: +LastResolvedStat: ${this._lastResolvedFileStat ? JSON.stringify(this._lastResolvedFileStat) : undefined}. +Current stat: ${JSON.stringify(stats)} +`); + this._lastResolvedFileStat = stats; return new Promise<'overwrite' | 'revert' | 'none'>(resolve => { const handle = this._notificationService.prompt( Severity.Info, @@ -221,6 +228,9 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM resolve('none'); }); }); + } else if (!this._lastResolvedFileStat && stats) { + // finally get a stats + this._lastResolvedFileStat = stats; } return 'overwrite'; @@ -271,7 +281,9 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM } try { + this._logService.debug(`start checking stats for ${resource.toString()}`); const newStats = await this._fileService.resolve(this.resource, { resolveMetadata: true }); + this._logService.debug(`${resource.toString()} latest file stats: ${JSON.stringify(newStats)}`); return newStats; } catch (e) { return undefined; From 41eb987d0915f985c617b3ce35601ae56e982270 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Dec 2020 11:53:47 -0800 Subject: [PATCH 0590/1837] add log for save/saveas --- .../workbench/contrib/notebook/common/notebookEditorModel.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index b66fc62a1f0..c0746dbc1e5 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -199,6 +199,7 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM } private async _assertStat() { + this._logService.debug('start assert stat'); const stats = await this._resolveStats(this.resource); if (this._lastResolvedFileStat && stats && stats.mtime > this._lastResolvedFileStat.mtime) { this._logService.debug(`noteboook file on disk is newer: @@ -237,6 +238,7 @@ Current stat: ${JSON.stringify(stats)} } async save(): Promise { + this._logService.debug(`start saving notebook ${this.resource.toString()}`); const result = await this._assertStat(); if (result === 'none') { return false; @@ -249,6 +251,7 @@ Current stat: ${JSON.stringify(stats)} const tokenSource = new CancellationTokenSource(); await this._notebookService.save(this.notebook.viewType, this.notebook.uri, tokenSource.token); + this._logService.debug(`notebook ${this.resource.toString()} saved. update file stats`); const newStats = await this._resolveStats(this.resource); this._lastResolvedFileStat = newStats; this.setDirty(false); @@ -256,6 +259,7 @@ Current stat: ${JSON.stringify(stats)} } async saveAs(targetResource: URI): Promise { + this._logService.debug(`start saving notebook ${this.resource.toString()}`); const result = await this._assertStat(); if (result === 'none') { @@ -269,6 +273,7 @@ Current stat: ${JSON.stringify(stats)} const tokenSource = new CancellationTokenSource(); await this._notebookService.saveAs(this.notebook.viewType, this.notebook.uri, targetResource, tokenSource.token); + this._logService.debug(`notebook ${this.resource.toString()} saved. update file stats`); const newStats = await this._resolveStats(this.resource); this._lastResolvedFileStat = newStats; this.setDirty(false); From 370e092880953d3092b2a8de4bd2fc5b28a966ea Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Dec 2020 12:13:41 -0800 Subject: [PATCH 0591/1837] extJupyter --- .github/commands.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/commands.json b/.github/commands.json index 7a1220f7d43..980b2906bf5 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -202,6 +202,19 @@ "addLabel": "*caused-by-extension", "comment": "It looks like this is caused by the Python extension. Please file it with the repository [here](https://github.com/microsoft/vscode-python). Make sure to check their issue reporting template and provide them relevant information such as the extension version you're using. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines for more information.\n\nHappy Coding!" }, + { + "type": "comment", + "name": "extJupyter", + "allowUsers": [ + "cleidigh", + "usernamehw", + "gjsjohnmurray", + "IllusionMH" + ], + "action": "close", + "addLabel": "*caused-by-extension", + "comment": "It looks like this is caused by the Jupyter extension. Please file it with the repository [here](https://github.com/microsoft/vscode-jupyter). Make sure to check their issue reporting template and provide them relevant information such as the extension version you're using. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines for more information.\n\nHappy Coding!" + }, { "type": "comment", "name": "extC", From 62b119aa2234571d4e46a83961e48b43ba5ba048 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 3 Dec 2020 15:27:18 -0500 Subject: [PATCH 0592/1837] Fixes bad has implementation Since a node could still exist, because it has a left or right --- src/vs/base/common/map.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 37e3c3bc570..0e08876e537 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -377,7 +377,8 @@ export class TernarySearchTree { } has(key: K): boolean { - return !!this._getNode(key); + const node = this._getNode(key); + return !(node?.value === undefined && node?.mid === undefined); } delete(key: K): void { From 39fb92c6c529b5f12465e2820324a8448b3bb613 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 3 Dec 2020 12:32:11 -0800 Subject: [PATCH 0593/1837] Remove redundant when clauses --- .../browser/searchEditor.contribution.ts | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index ebcd6ca4eb1..cc6faa97d74 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -234,7 +234,6 @@ registerAction2(class extends Action2 { title: { value: localize('searchEditor.deleteResultBlock', "Delete File Results"), original: 'Delete File Results' }, keybinding: { weight: KeybindingWeight.EditorContrib, - when: SearchEditorConstants.InSearchEditor, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Backspace, }, precondition: SearchEditorConstants.InSearchEditor, @@ -361,13 +360,10 @@ registerAction2(class extends Action2 { id: FocusQueryEditorWidgetCommandId, title: { value: localize('search.action.focusQueryEditorWidget', "Focus Search Editor Input"), original: 'Focus Search Editor Input' }, category, - menu: { - id: MenuId.CommandPalette, - when: ActiveEditorContext.isEqualTo(SearchEditorConstants.SearchEditorID) - }, + f1: true, + precondition: SearchEditorConstants.InSearchEditor, keybinding: { primary: KeyCode.Escape, - when: SearchEditorConstants.InSearchEditor, weight: KeybindingWeight.EditorContrib } }); @@ -388,10 +384,10 @@ registerAction2(class extends Action2 { title: { value: localize('searchEditor.action.toggleSearchEditorCaseSensitive', "Toggle Match Case"), original: 'Toggle Match Case' }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: Object.assign({ weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor, SearchConstants.SearchInputBoxFocusedKey), + when: SearchConstants.SearchInputBoxFocusedKey, }, ToggleCaseSensitiveKeybinding) }); } @@ -407,10 +403,10 @@ registerAction2(class extends Action2 { title: { value: localize('searchEditor.action.toggleSearchEditorWholeWord', "Toggle Match Whole Word"), original: 'Toggle Match Whole Word' }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: Object.assign({ weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor, SearchConstants.SearchInputBoxFocusedKey), + when: SearchConstants.SearchInputBoxFocusedKey, }, ToggleWholeWordKeybinding) }); } @@ -426,10 +422,10 @@ registerAction2(class extends Action2 { title: { value: localize('searchEditor.action.toggleSearchEditorRegex', "Toggle Use Regular Expression"), original: 'Toggle Use Regular Expression"' }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: Object.assign({ weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor, SearchConstants.SearchInputBoxFocusedKey), + when: SearchConstants.SearchInputBoxFocusedKey, }, ToggleRegexKeybinding) }); } @@ -445,10 +441,9 @@ registerAction2(class extends Action2 { title: { value: localize('searchEditor.action.toggleSearchEditorContextLines', "Toggle Context Lines"), original: 'Toggle Context Lines"' }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: { weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), primary: KeyMod.Alt | KeyCode.KEY_L, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_L } } @@ -466,10 +461,9 @@ registerAction2(class extends Action2 { title: { original: 'Increase Context Lines', value: localize('searchEditor.action.increaseSearchEditorContextLines', "Increase Context Lines") }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: { weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), primary: KeyMod.Alt | KeyCode.US_EQUAL } }); @@ -484,10 +478,9 @@ registerAction2(class extends Action2 { title: { original: 'Decrease Context Lines', value: localize('searchEditor.action.decreaseSearchEditorContextLines', "Decrease Context Lines") }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: { weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), primary: KeyMod.Alt | KeyCode.US_MINUS } }); @@ -502,10 +495,9 @@ registerAction2(class extends Action2 { title: { original: 'Select All Matches', value: localize('searchEditor.action.selectAllSearchEditorMatches', "Select All Matches") }, category, f1: true, - precondition: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), + precondition: SearchEditorConstants.InSearchEditor, keybinding: { weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_L, } }); From 1c1c59fd0fb1acab24181222907bc6bab78038da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 3 Dec 2020 12:45:01 -0800 Subject: [PATCH 0594/1837] Kill code processes after each integration test suite run (#111844) * bring back linux integration tests * no empty functions * hmm --- .../linux/product-build-linux.yml | 56 ++++++++++--------- package.json | 4 +- scripts/test-integration.sh | 25 +++++++++ 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 58bb954d35c..1f7884a1c83 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -130,35 +130,37 @@ steps: displayName: Run unit tests (Browser) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - # - script: | - # # Figure out the full absolute path of the product we just built - # # including the remote server and configure the integration tests - # # to run with these builds instead of running out of sources. - # set -e - # APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - # APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - # INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - # VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - # DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" - # displayName: Run integration tests (Electron) - # condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + # Figure out the full absolute path of the product we just built + # including the remote server and configure the integration tests + # to run with these builds instead of running out of sources. + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_APP_NAME="$APP_NAME" \ + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" + displayName: Run integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - # - script: | - # set -e - # VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ - # DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium - # displayName: Run integration tests (Browser) - # condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium + displayName: Run integration tests (Browser) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - # - script: | - # set -e - # APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) - # APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") - # INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ - # VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ - # DISPLAY=:10 ./resources/server/test/test-remote-integration.sh - # displayName: Run remote integration tests (Electron) - # condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH) + APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName") + INTEGRATION_TEST_APP_NAME="$APP_NAME" \ + INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \ + VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ + DISPLAY=:10 ./resources/server/test/test-remote-integration.sh + displayName: Run remote integration tests (Electron) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - task: PublishPipelineArtifact@0 inputs: diff --git a/package.json b/package.json index faabdc484fd..f4c487c9076 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.52.0", - "distro": "525b7677232e7f810dd09678a784247f93df7845", + "distro": "11fd6f1230738827638f000f641d01b2b178db20", "author": { "name": "Microsoft Corporation" }, @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index b302ce28db9..b82dbec1137 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -46,21 +46,46 @@ else echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build." fi +if [ -z "$INTEGRATION_TEST_APP_NAME" ]; then + after_suite() { true; } +else + after_suite() { killall $INTEGRATION_TEST_APP_NAME || true; } +fi + # Integration tests in AMD ./scripts/test.sh --runGlob **/*.integrationTest.js "$@" +after_suite # Tests in the extension host "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + #"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/typescript-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/typescript-language-features --extensionTestsPath=$ROOT/extensions/typescript-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +# after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite + "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +after_suite # Tests in commonJS (CSS, HTML) cd $ROOT/extensions/css-language-features/server && $ROOT/scripts/node-electron.sh test/index.js +after_suite + cd $ROOT/extensions/html-language-features/server && $ROOT/scripts/node-electron.sh test/index.js +after_suite rm -rf $VSCODEUSERDATADIR From 53eac52308c4611000a171cc7bf1214293473c78 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 3 Dec 2020 21:57:22 +0100 Subject: [PATCH 0595/1837] Fixes #111499 --- src/vs/editor/browser/viewParts/minimap/minimap.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 6001fb4f7c2..7ca33211a3c 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -237,6 +237,7 @@ class MinimapLayout { options: MinimapOptions, viewportStartLineNumber: number, viewportEndLineNumber: number, + viewportStartLineNumberVerticalOffset: number, viewportHeight: number, viewportContainsWhitespaceGaps: boolean, lineCount: number, @@ -331,7 +332,8 @@ class MinimapLayout { } const endLineNumber = Math.min(lineCount, startLineNumber + minimapLinesFitting - 1); - const sliderTopAligned = (scrollTop / lineHeight - startLineNumber + 1) * minimapLineHeight / pixelRatio; + const partialLine = (scrollTop - viewportStartLineNumberVerticalOffset) / lineHeight; + const sliderTopAligned = (viewportStartLineNumber - startLineNumber + partialLine) * minimapLineHeight / pixelRatio; return new MinimapLayout(scrollTop, scrollHeight, true, computedSliderRatio, sliderTopAligned, sliderHeight, startLineNumber, endLineNumber); } @@ -505,6 +507,7 @@ interface IMinimapRenderingContext { readonly viewportStartLineNumber: number; readonly viewportEndLineNumber: number; + readonly viewportStartLineNumberVerticalOffset: number; readonly scrollTop: number; readonly scrollLeft: number; @@ -891,6 +894,7 @@ export class Minimap extends ViewPart implements IMinimapModel { viewportStartLineNumber: viewportStartLineNumber, viewportEndLineNumber: viewportEndLineNumber, + viewportStartLineNumberVerticalOffset: ctx.getVerticalOffsetForLineNumber(viewportStartLineNumber), scrollTop: ctx.scrollTop, scrollLeft: ctx.scrollLeft, @@ -1344,6 +1348,7 @@ class InnerMinimap extends Disposable { this._model.options, renderingCtx.viewportStartLineNumber, renderingCtx.viewportEndLineNumber, + renderingCtx.viewportStartLineNumberVerticalOffset, renderingCtx.viewportHeight, renderingCtx.viewportContainsWhitespaceGaps, this._model.getLineCount(), From 9d5c351c71e48b97e7f4ca69e1ff46f92feb0c09 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Dec 2020 15:11:42 -0800 Subject: [PATCH 0596/1837] notebook list view scrollbar should be below cell toolbar --- 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 3547b989dd4..c2b2830c4c9 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -536,7 +536,7 @@ } .monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible { - z-index: 50; + z-index: 25; cursor: default; } From 1aa26c377587c862f74f298937604631b854884d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 4 Dec 2020 00:02:52 +0100 Subject: [PATCH 0597/1837] Fixes #105808 --- src/vs/editor/browser/editorBrowser.ts | 7 ++++++- .../editor/browser/widget/codeEditorWidget.ts | 12 ++++++++++++ src/vs/editor/common/model.ts | 15 ++++++++++----- src/vs/editor/common/model/editStack.ts | 17 +++++++++++++++++ src/vs/editor/common/model/textModel.ts | 4 ++++ .../editor/contrib/indentation/indentation.ts | 10 ++++++---- .../contrib/linkedEditing/linkedEditing.ts | 1 + src/vs/monaco.d.ts | 16 ++++++++++++---- 8 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 13552a60ec0..43305c283eb 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -684,10 +684,15 @@ export interface ICodeEditor extends editorCommon.IEditor { executeCommand(source: string | null | undefined, command: editorCommon.ICommand): void; /** - * Push an "undo stop" in the undo-redo stack. + * Create an "undo stop" in the undo-redo stack. */ pushUndoStop(): boolean; + /** + * Remove the "undo stop" in the undo-redo stack. + */ + popUndoStop(): boolean; + /** * Execute edits on the editor. * The edits will land on the undo-redo stack, but no "undo stop" will be pushed. diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index e39d4773399..4c87ce2bb2d 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -1122,6 +1122,18 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return true; } + public popUndoStop(): boolean { + if (!this._modelData) { + return false; + } + if (this._configuration.options.get(EditorOption.readOnly)) { + // read only editor => sorry! + return false; + } + this._modelData.model.popStackElement(); + return true; + } + public executeEdits(source: string | null | undefined, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean { if (!this._modelData) { return false; diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 52bd1b39fe7..8f4d53a8447 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -1099,12 +1099,17 @@ export interface ITextModel { detectIndentation(defaultInsertSpaces: boolean, defaultTabSize: number): void; /** - * Push a stack element onto the undo stack. This acts as an undo/redo point. - * The idea is to use `pushEditOperations` to edit the model and then to - * `pushStackElement` to create an undo/redo stop point. + * Close the current undo-redo element. + * This offers a way to create an undo/redo stop point. */ pushStackElement(): void; + /** + * Open the current undo-redo element. + * This offers a way to remove the current undo/redo stop point. + */ + popStackElement(): void; + /** * Push edit operations, basically editing the model. This is the preferred way * of editing the model. The edit operations will land on the undo stack. @@ -1148,7 +1153,7 @@ export interface ITextModel { _applyRedo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void; /** - * Undo edit operations until the first previous stop point created by `pushStackElement`. + * Undo edit operations until the previous undo/redo point. * The inverse edit operations will be pushed on the redo stack. * @internal */ @@ -1161,7 +1166,7 @@ export interface ITextModel { canUndo(): boolean; /** - * Redo edit operations until the next stop point created by `pushStackElement`. + * Redo edit operations until the next undo/redo point. * The inverse edit operations will be pushed on the undo stack. * @internal */ diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index 0928d7d0e9b..d06f447b05e 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -199,6 +199,12 @@ export class SingleModelEditStackElement implements IResourceUndoRedoElement { } } + public open(): void { + if (!(this._data instanceof SingleModelEditStackData)) { + this._data = SingleModelEditStackData.deserialize(this._data); + } + } + public undo(): void { if (URI.isUri(this.model)) { // don't have a model @@ -315,6 +321,10 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement { this._isOpen = false; } + public open(): void { + // cannot reopen + } + public undo(): void { this._isOpen = false; @@ -386,6 +396,13 @@ export class EditStack { } } + public popStackElement(): void { + const lastElement = this._undoRedoService.getLastElement(this._model.uri); + if (isEditStackElement(lastElement)) { + lastElement.open(); + } + } + public clear(): void { this._undoRedoService.removeElements(this._model.uri); } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 81f46885438..35dd466403a 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -1225,6 +1225,10 @@ export class TextModel extends Disposable implements model.ITextModel { this._commandManager.pushStackElement(); } + public popStackElement(): void { + this._commandManager.popStackElement(); + } + public pushEOL(eol: model.EndOfLineSequence): void { const currentEOL = (this.getEOL() === '\n' ? model.EndOfLineSequence.LF : model.EndOfLineSequence.CRLF); if (currentEOL === eol) { diff --git a/src/vs/editor/contrib/indentation/indentation.ts b/src/vs/editor/contrib/indentation/indentation.ts index dcdcadea52b..720c8e76916 100644 --- a/src/vs/editor/contrib/indentation/indentation.ts +++ b/src/vs/editor/contrib/indentation/indentation.ts @@ -472,7 +472,6 @@ export class AutoIndentOnPaste implements IEditorContribution { } const autoIndent = this.editor.getOption(EditorOption.autoIndent); const { tabSize, indentSize, insertSpaces } = model.getOptions(); - this.editor.pushUndoStop(); let textEdits: TextEdit[] = []; let indentConverter = { @@ -583,9 +582,12 @@ export class AutoIndentOnPaste implements IEditorContribution { } } - let cmd = new AutoIndentOnPasteCommand(textEdits, this.editor.getSelection()!); - this.editor.executeCommand('autoIndentOnPaste', cmd); - this.editor.pushUndoStop(); + if (textEdits.length > 0) { + this.editor.pushUndoStop(); + let cmd = new AutoIndentOnPasteCommand(textEdits, this.editor.getSelection()!); + this.editor.executeCommand('autoIndentOnPaste', cmd); + this.editor.pushUndoStop(); + } } private shouldIgnoreLine(model: ITextModel, lineNumber: number): boolean { diff --git a/src/vs/editor/contrib/linkedEditing/linkedEditing.ts b/src/vs/editor/contrib/linkedEditing/linkedEditing.ts index 9c984b987b7..441460812f4 100644 --- a/src/vs/editor/contrib/linkedEditing/linkedEditing.ts +++ b/src/vs/editor/contrib/linkedEditing/linkedEditing.ts @@ -220,6 +220,7 @@ export class LinkedEditingContribution extends Disposable implements IEditorCont } try { + this._editor.popUndoStop(); this._ignoreChangeEvent = true; const prevEditOperationType = this._editor._getViewModel().getPrevEditOperationType(); this._editor.executeEdits('linkedEditing', edits); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 012344fa2da..2cb6913f72a 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1890,11 +1890,15 @@ declare namespace monaco.editor { */ detectIndentation(defaultInsertSpaces: boolean, defaultTabSize: number): void; /** - * Push a stack element onto the undo stack. This acts as an undo/redo point. - * The idea is to use `pushEditOperations` to edit the model and then to - * `pushStackElement` to create an undo/redo stop point. + * Close the current undo-redo element. + * This offers a way to create an undo/redo stop point. */ pushStackElement(): void; + /** + * Open the current undo-redo element. + * This offers a way to remove the current undo/redo stop point. + */ + popStackElement(): void; /** * Push edit operations, basically editing the model. This is the preferred way * of editing the model. The edit operations will land on the undo stack. @@ -4740,9 +4744,13 @@ declare namespace monaco.editor { */ executeCommand(source: string | null | undefined, command: ICommand): void; /** - * Push an "undo stop" in the undo-redo stack. + * Create an "undo stop" in the undo-redo stack. */ pushUndoStop(): boolean; + /** + * Remove the "undo stop" in the undo-redo stack. + */ + popUndoStop(): boolean; /** * Execute edits on the editor. * The edits will land on the undo-redo stack, but no "undo stop" will be pushed. From b617b725a06169c39dcae398ee7c21d44bebe6b2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Dec 2020 16:18:51 -0800 Subject: [PATCH 0598/1837] update notebook execute kb shortcut tooltip for windows. --- .../contrib/notebook/browser/view/renderers/cellWidgets.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index 5560bbeb119..6be1604eea1 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -12,6 +12,7 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { isWindows } from 'vs/base/common/platform'; import { extUri } from 'vs/base/common/resources'; import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; import { IDimension } from 'vs/editor/common/editorCommon'; @@ -352,8 +353,8 @@ export function getExecuteCellPlaceholder(viewCell: BaseCellViewModel) { command: undefined, // text: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`, // tooltip: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`, - text: 'Ctrl + Enter to run', - tooltip: 'Ctrl + Enter to run', + text: isWindows ? 'Ctrl + Alt + Enter' : 'Ctrl + Enter to run', + tooltip: isWindows ? 'Ctrl + Alt + Enter' : 'Ctrl + Enter to run', visible: true, opacity: '0.7' }; From ff824f2776bad21c65c96cb9b7a13c7269c6f8b5 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 3 Dec 2020 16:32:45 -0800 Subject: [PATCH 0599/1837] Bump actions --- .github/workflows/author-verified.yml | 2 +- .github/workflows/commands.yml | 2 +- .github/workflows/deep-classifier-monitor.yml | 2 +- .github/workflows/deep-classifier-runner.yml | 2 +- .github/workflows/deep-classifier-scraper.yml | 2 +- .github/workflows/english-please.yml | 2 +- .github/workflows/feature-request.yml | 2 +- .github/workflows/latest-release-monitor.yml | 2 +- .github/workflows/locker.yml | 2 +- .github/workflows/needs-more-info-closer.yml | 2 +- .github/workflows/on-label.yml | 2 +- .github/workflows/on-open.yml | 2 +- .github/workflows/release-pipeline-labeler.yml | 2 +- .github/workflows/test-plan-item-validator.yml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/author-verified.yml b/.github/workflows/author-verified.yml index a066c194d99..6924d9650af 100644 --- a/.github/workflows/author-verified.yml +++ b/.github/workflows/author-verified.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'author-verification-requested') diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index bda1b25092d..c2b8f95e0e6 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -13,7 +13,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Commands diff --git a/.github/workflows/deep-classifier-monitor.yml b/.github/workflows/deep-classifier-monitor.yml index 439d2f2a46b..2734f6b7892 100644 --- a/.github/workflows/deep-classifier-monitor.yml +++ b/.github/workflows/deep-classifier-monitor.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/deep-classifier-runner.yml b/.github/workflows/deep-classifier-runner.yml index ffa11badc9c..1aaf05a875d 100644 --- a/.github/workflows/deep-classifier-runner.yml +++ b/.github/workflows/deep-classifier-runner.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/deep-classifier-scraper.yml b/.github/workflows/deep-classifier-scraper.yml index 1ce6faed4b2..42b5f1b6335 100644 --- a/.github/workflows/deep-classifier-scraper.yml +++ b/.github/workflows/deep-classifier-scraper.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/english-please.yml b/.github/workflows/english-please.yml index 7336c429df1..5253fb73dc8 100644 --- a/.github/workflows/english-please.yml +++ b/.github/workflows/english-please.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions if: contains(github.event.issue.labels.*.name, '*english-please') diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml index 4a3c30065f7..ec3bbb5e101 100644 --- a/.github/workflows/feature-request.yml +++ b/.github/workflows/feature-request.yml @@ -18,7 +18,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') run: npm install --production --prefix ./actions diff --git a/.github/workflows/latest-release-monitor.yml b/.github/workflows/latest-release-monitor.yml index 190da52ba32..b27d79fda4a 100644 --- a/.github/workflows/latest-release-monitor.yml +++ b/.github/workflows/latest-release-monitor.yml @@ -14,7 +14,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions run: npm install --production --prefix ./actions - name: Install Storage Module diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml index abfce92748b..dca0f5be6f6 100644 --- a/.github/workflows/locker.yml +++ b/.github/workflows/locker.yml @@ -14,7 +14,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Locker diff --git a/.github/workflows/needs-more-info-closer.yml b/.github/workflows/needs-more-info-closer.yml index 3475b3ae878..75b7af42393 100644 --- a/.github/workflows/needs-more-info-closer.yml +++ b/.github/workflows/needs-more-info-closer.yml @@ -14,7 +14,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Needs More Info Closer diff --git a/.github/workflows/on-label.yml b/.github/workflows/on-label.yml index f06ba0f4ea0..67b8ec94ced 100644 --- a/.github/workflows/on-label.yml +++ b/.github/workflows/on-label.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/on-open.yml b/.github/workflows/on-open.yml index 9e9076c11fa..ebfa1cb3445 100644 --- a/.github/workflows/on-open.yml +++ b/.github/workflows/on-open.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/release-pipeline-labeler.yml b/.github/workflows/release-pipeline-labeler.yml index b4a4f355fb5..e5ea1a26b81 100644 --- a/.github/workflows/release-pipeline-labeler.yml +++ b/.github/workflows/release-pipeline-labeler.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v2 with: repository: "microsoft/vscode-github-triage-actions" - ref: v40 + ref: v41 path: ./actions - name: Checkout Repo if: github.event_name != 'issues' diff --git a/.github/workflows/test-plan-item-validator.yml b/.github/workflows/test-plan-item-validator.yml index 57fcaa53165..6c2752107bc 100644 --- a/.github/workflows/test-plan-item-validator.yml +++ b/.github/workflows/test-plan-item-validator.yml @@ -14,7 +14,7 @@ jobs: with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: v40 + ref: v41 - name: Install Actions if: contains(github.event.issue.labels.*.name, 'testplan-item') || contains(github.event.issue.labels.*.name, 'invalid-testplan-item') run: npm install --production --prefix ./actions From ff66544ada8e87a5ec75271b0d606c0c1b425afc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Dec 2020 16:48:39 -0800 Subject: [PATCH 0600/1837] Allow using upper case hex characters for color --- src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts index 4acc3c1326a..26cdc77ae04 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts @@ -33,7 +33,7 @@ export const suggestMoreInfoIcon = registerIcon('suggest-more-info', Codicon.che const _completionItemColor = new class ColorExtractor { - private static _regexRelaxed = /(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))/; + private static _regexRelaxed = /(#([\da-fA-F]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))/; private static _regexStrict = new RegExp(`^${ColorExtractor._regexRelaxed.source}$`, 'i'); extract(item: CompletionItem, out: string[]): boolean { From c70d984fa2488cd589810d67f6695eafad87b137 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 1 Dec 2020 10:07:44 -0800 Subject: [PATCH 0601/1837] debug: bump js-debug --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index d413a31fc43..ee6e68b480e 100644 --- a/product.json +++ b/product.json @@ -91,7 +91,7 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.51.0", + "version": "1.52.1", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", From 63137db51ca56394a27bedd1f315fac73a9e29cd Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 3 Dec 2020 22:07:19 -0800 Subject: [PATCH 0602/1837] debug: fix auto attach not turning on if reselecting current state Fixes https://github.com/microsoft/vscode/issues/111021 --- extensions/debug-auto-launch/src/extension.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extensions/debug-auto-launch/src/extension.ts b/extensions/debug-auto-launch/src/extension.ts index 440b3296e57..b47641f2db2 100644 --- a/extensions/debug-auto-launch/src/extension.ts +++ b/extensions/debug-auto-launch/src/extension.ts @@ -156,7 +156,7 @@ async function toggleAutoAttachSetting(context: vscode.ExtensionContext, scope?: quickPick.show(); - const result = await new Promise(resolve => { + let result = await new Promise(resolve => { quickPick.onDidAccept(() => resolve(quickPick.selectedItems[0])); quickPick.onDidHide(() => resolve(undefined)); quickPick.onDidTriggerButton(() => { @@ -179,7 +179,11 @@ async function toggleAutoAttachSetting(context: vscode.ExtensionContext, scope?: } if ('state' in result) { - section.update(SETTING_STATE, result.state, scope); + if (result.state !== current) { + section.update(SETTING_STATE, result.state, scope); + } else if (isTemporarilyDisabled) { + result = { setTempDisabled: false }; + } } if ('setTempDisabled' in result) { From c2f68baa78d90f135cc6800cfa7e7140d6d09933 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 3 Dec 2020 22:44:41 -0800 Subject: [PATCH 0603/1837] search: fix handle empty results from ripgrep https://github.com/microsoft/vscode/issues/100569 --- .../search/node/ripgrepTextSearchEngine.ts | 12 +++++++++ .../test/node/ripgrepTextSearchEngine.test.ts | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index 53c6ae8fd67..074d3528f29 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -283,6 +283,18 @@ export class RipgrepParser extends EventEmitter { let prevMatchEnd = 0; let prevMatchEndCol = 0; let prevMatchEndLine = lineNumber; + + // it looks like certain regexes can match a line, but cause rg to not + // emit any specific submatches for that line. + // https://github.com/microsoft/vscode/issues/100569#issuecomment-738496991 + if (data.submatches.length === 0) { + data.submatches.push( + fullText.length + ? { start: 0, end: 1, match: { text: fullText[0] } } + : { start: 0, end: 0, match: { text: '' } } + ); + } + const ranges = coalesce(data.submatches.map((match, i) => { if (this.hitLimit) { return null; diff --git a/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts b/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts index 9e15c6dc9bb..3815dee816b 100644 --- a/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts +++ b/src/vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts @@ -226,5 +226,32 @@ suite('RipgrepTextSearchEngine', () => { } ]); }); + + + test('empty result (#100569)', () => { + testParser( + [ + makeRgMatch('file1.js', 'foobar', 4, []), + makeRgMatch('file1.js', '', 5, []), + ], + [ + { + preview: { + text: 'foobar', + matches: [new Range(0, 0, 0, 1)] + }, + uri: joinPath(TEST_FOLDER, 'file1.js'), + ranges: [new Range(3, 0, 3, 1)] + }, + { + preview: { + text: '', + matches: [new Range(0, 0, 0, 0)] + }, + uri: joinPath(TEST_FOLDER, 'file1.js'), + ranges: [new Range(4, 0, 4, 0)] + } + ]); + }); }); }); From 6a58335d0278f34281bb75351d832e8d551d3a73 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 4 Dec 2020 09:15:16 +0100 Subject: [PATCH 0604/1837] explorerViewer drop await --- .../workbench/contrib/files/browser/views/explorerViewer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 6ec1d861c37..9e8330b3dd8 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -982,7 +982,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { } } - drop(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void { + async drop(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): Promise { this.compressedDropTargetDisposable.dispose(); // Find compressed target @@ -1031,7 +1031,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { this.progressService.withProgress({ location: VIEW_ID, delay: 500 }, () => dropPromise); } else { try { - this.handleExternalDrop(resolvedTarget, originalEvent, cts.token); + await this.handleExternalDrop(resolvedTarget, originalEvent, cts.token); } catch (error) { this.notificationService.warn(error); } From 7256c3ab262940e62fc755ad25758ba7c1875a52 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2020 10:32:26 +0100 Subject: [PATCH 0605/1837] :lipstick: code lens font --- src/vs/editor/contrib/codelens/codelensController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index 9b3102c61b0..c2ec93d9f7c 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -103,7 +103,7 @@ export class CodeLensContribution implements IEditorContribution { .monaco-editor .codelens-decoration.${this._styleClassName} span.codicon { line-height: ${codeLensHeight}px; font-size: ${fontSize}px; } `; if (fontFamily) { - newStyle += `.monaco-editor .codelens-decoration.${this._styleClassName} { font-family: ${fontFamily}}`; + newStyle += `.monaco-editor .codelens-decoration.${this._styleClassName} { font-family: '${fontFamily}}'`; } this._styleElement.textContent = newStyle; From 5e350b1b79675cecdff224eb00f7bf62ae8789fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 4 Dec 2020 10:36:27 +0100 Subject: [PATCH 0606/1837] build: create asset should still try to add asset --- build/azure-pipelines/common/createAsset.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index d7e62629cb8..127993e6230 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -93,16 +93,12 @@ async function main(): Promise { const blobExists = await doesAssetExist(blobService, quality, blobName); if (blobExists) { - console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`); - return; + console.log(`Blob ${quality}, ${blobName} already exists, not uploading again.`); + } else { + await uploadBlob(blobService, quality, blobName, filePath, fileName); + console.log('Blobs successfully uploaded.'); } - console.log('Uploading blobs to Azure storage...'); - - await uploadBlob(blobService, quality, blobName, filePath, fileName); - - console.log('Blobs successfully uploaded.'); - const asset: Asset = { platform, type, From 60bf040b98f966dcc7b25380c587abd9ab13dc06 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2020 10:47:46 +0100 Subject: [PATCH 0607/1837] workaround for https://github.com/microsoft/vscode/issues/111871, fixes https://github.com/microsoft/vscode/issues/111666 --- .../services/extensionManagement/browser/extensionBisect.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts index 9498ec70955..7a93a52904d 100644 --- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts @@ -21,6 +21,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; +import { timeout } from 'vs/base/common/async'; // --- bisect service @@ -288,7 +289,8 @@ registerAction2(class extends Action2 { await extensionEnablementService.disableExtension({ id: done.id }, undefined); } if (res.choice === 0) { - await issueService.openReporter({ extensionId: done.id }); + issueService.openReporter({ extensionId: done.id }); + await timeout(750); // workaround for https://github.com/microsoft/vscode/issues/111871 } } await bisectService.reset(); From 6a1ad5b9b8fd6260ad98c613101fdff9c55c7400 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2020 10:53:13 +0100 Subject: [PATCH 0608/1837] :lipstick: code lens font fix --- src/vs/editor/contrib/codelens/codelensController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index c2ec93d9f7c..3fddfdff3c1 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -103,7 +103,7 @@ export class CodeLensContribution implements IEditorContribution { .monaco-editor .codelens-decoration.${this._styleClassName} span.codicon { line-height: ${codeLensHeight}px; font-size: ${fontSize}px; } `; if (fontFamily) { - newStyle += `.monaco-editor .codelens-decoration.${this._styleClassName} { font-family: '${fontFamily}}'`; + newStyle += `.monaco-editor .codelens-decoration.${this._styleClassName} { font-family: '${fontFamily}'}`; } this._styleElement.textContent = newStyle; From 0c947cb4ee4a35f04aa6c5117a9727be35b3c828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 4 Dec 2020 11:43:10 +0100 Subject: [PATCH 0609/1837] fixes #96264 --- extensions/git/src/commands.ts | 6 +++--- extensions/git/src/repository.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index f3b830a6b04..2c24d9095b4 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -54,7 +54,7 @@ class CheckoutRemoteHeadItem extends CheckoutItem { return localize('remote branch at', "Remote branch at {0}", this.shortCommit); } - async run(repository: Repository): Promise { + async run(repository: Repository, opts?: { detached?: boolean }): Promise { if (!this.ref.name) { return; } @@ -62,9 +62,9 @@ class CheckoutRemoteHeadItem extends CheckoutItem { const branches = await repository.findTrackingBranches(this.ref.name); if (branches.length > 0) { - await repository.checkout(branches[0].name!); + await repository.checkout(branches[0].name!, opts); } else { - await repository.checkoutTracking(this.ref.name); + await repository.checkoutTracking(this.ref.name, opts); } } } diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index f7948563a01..87f24395d6d 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1264,8 +1264,8 @@ export class Repository implements Disposable { await this.run(Operation.Checkout, () => this.repository.checkout(treeish, [], opts)); } - async checkoutTracking(treeish: string): Promise { - await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { track: true })); + async checkoutTracking(treeish: string, opts: { detached?: boolean } = {}): Promise { + await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { ...opts, track: true })); } async findTrackingBranches(upstreamRef: string): Promise { From 6ed64df49277a45dcb87dade020b6c43c8c26684 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 4 Dec 2020 11:51:35 +0100 Subject: [PATCH 0610/1837] repl: font family --- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 16593506851..74467fa8078 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -305,7 +305,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { if (this.styleElement) { const debugConsole = this.configurationService.getValue('debug').console; const fontSize = debugConsole.fontSize; - const fontFamily = debugConsole.fontFamily === 'default' ? 'var(--monaco-monospace-font)' : debugConsole.fontFamily; + const fontFamily = debugConsole.fontFamily === 'default' ? 'var(--monaco-monospace-font)' : `'${debugConsole.fontFamily}'`; const lineHeight = debugConsole.lineHeight ? `${debugConsole.lineHeight}px` : '1.4em'; const backgroundColor = this.themeService.getColorTheme().getColor(this.getBackgroundColor()); From 8f410da37f1bddb0462a790f59a3f1dda19f7bab Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 4 Dec 2020 11:57:07 +0100 Subject: [PATCH 0611/1837] Revert "fixes #110353" This reverts commit f27d73be72368973bb8970015f417332c4d79b83. --- .../files/electron-sandbox/fileActions.contribution.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index 8fdd7c5b600..e4716da51f5 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -14,6 +14,8 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; +import { IListService } from 'vs/platform/list/browser/listService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-sandbox/fileCommands'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; @@ -35,9 +37,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ win: { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_R }, - handler: (accessor: ServicesAccessor, _resource: URI | object) => { - const explorerService = accessor.get(IExplorerService); - const resources = explorerService.getContext(false).map(item => item.resource); + handler: (accessor: ServicesAccessor, resource: URI | object) => { + const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService)); revealResourcesInOS(resources, accessor.get(INativeHostService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService)); } }); From de3dd1383ca5528ede42e01b9c6b77579f8e62fd Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 4 Dec 2020 12:03:39 +0100 Subject: [PATCH 0612/1837] Active indent lines do not render in High Contrast theme. Fixes #111137 --- .../theme-defaults/themes/hc_black_defaults.json | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index d0382cec294..ea03fb3fa41 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -9,21 +9,14 @@ "statusBarItem.remoteBackground": "#00000000", "sideBarTitle.foreground": "#FFFFFF" }, - "settings": [ - { - "settings": { - "foreground": "#FFFFFF", - "background": "#000000" - } - }, + "tokenColors": [ { "scope": [ "meta.embedded", "source.groovy.embedded" ], "settings": { - "foreground": "#FFFFFF", - "background": "#000000" + "foreground": "#FFFFFF" } }, { From 2e3236827e58c58c91917cffd17d3ab88e772ee7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2020 12:47:27 +0100 Subject: [PATCH 0613/1837] suppress refactor preview from onWill-handler, workaround for https://github.com/microsoft/vscode/issues/111873 --- src/vs/editor/browser/services/bulkEditService.ts | 1 + src/vs/workbench/api/browser/mainThreadBulkEdits.ts | 8 +++++++- .../workbench/contrib/bulkEdit/browser/bulkEditService.ts | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts index 6b0867d496c..a9e8b99dc6f 100644 --- a/src/vs/editor/browser/services/bulkEditService.ts +++ b/src/vs/editor/browser/services/bulkEditService.ts @@ -69,6 +69,7 @@ export interface IBulkEditOptions { progress?: IProgress; token?: CancellationToken; showPreview?: boolean; + suppressPreview?: boolean; label?: string; quotableLabel?: string; undoRedoSource?: UndoRedoSource; diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts index 5e1331caaad..70fb045d7aa 100644 --- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts @@ -39,6 +39,12 @@ export class MainThreadBulkEdits implements MainThreadBulkEditsShape { $tryApplyWorkspaceEdit(dto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise { const edits = reviveWorkspaceEditDto2(dto); - return this._bulkEditService.apply(edits, { undoRedoGroupId }).then(() => true, _err => false); + return this._bulkEditService.apply(edits, { + // having a undoRedoGroupId means that this is a nested workspace edit, + // e.g one from a onWill-handler and for now we need to forcefully suppress + // refactor previewing, see: https://github.com/microsoft/vscode/issues/111873#issuecomment-738739852 + undoRedoGroupId, + suppressPreview: typeof undoRedoGroupId === 'number' ? true : undefined + }).then(() => true, _err => false); } } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts index ca55a105790..ffc54667e07 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts @@ -139,7 +139,7 @@ export class BulkEditService implements IBulkEditService { return { ariaSummary: localize('nothing', "Made no edits") }; } - if (this._previewHandler && (options?.showPreview || edits.some(value => value.metadata?.needsConfirmation))) { + if (this._previewHandler && !options?.suppressPreview && (options?.showPreview || edits.some(value => value.metadata?.needsConfirmation))) { edits = await this._previewHandler(edits, options); } From 7fcdba7fea333353783d41442cade69e7063b161 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 4 Dec 2020 14:00:36 +0100 Subject: [PATCH 0614/1837] Add heuristic for when to notify about forwarded port Fixes microsoft/vscode-remote-release#4133 --- .../contrib/remote/browser/remoteExplorer.ts | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 0c477522326..6a6252ed394 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -213,21 +213,48 @@ class ForwardedPortNotifier extends Disposable { this.lastNotifyTime.setFullYear(this.lastNotifyTime.getFullYear() - 1); } - public notify(tunnels: RemoteTunnel[]) { - if (Date.now() - this.lastNotifyTime.getTime() > ForwardedPortNotifier.COOL_DOWN) { - this.showNotification(tunnels); + public async notify(tunnels: RemoteTunnel[]) { + const tunnel = await this.portNumberHeuristicDelay(tunnels); + if (tunnel) { + if (Date.now() - this.lastNotifyTime.getTime() > ForwardedPortNotifier.COOL_DOWN) { + this.showNotification(tunnel); + } } } - private showNotification(tunnels: RemoteTunnel[]) { + private newerTunnel: RemoteTunnel | undefined; + private async portNumberHeuristicDelay(tunnels: RemoteTunnel[]): Promise { if (tunnels.length === 0) { return; } tunnels = tunnels.sort((a, b) => a.tunnelRemotePort - b.tunnelRemotePort); const firstTunnel = tunnels.shift()!; - const address = makeAddress(firstTunnel.tunnelRemoteHost, firstTunnel.tunnelRemotePort); + // Heuristic. + if (firstTunnel.tunnelRemotePort % 1000 === 0) { + this.newerTunnel = firstTunnel; + return firstTunnel; + // 9229 is the node inspect port + } else if (firstTunnel.tunnelRemotePort < 10000 && firstTunnel.tunnelRemotePort !== 9229) { + this.newerTunnel = firstTunnel; + return firstTunnel; + } + + this.newerTunnel = undefined; + return new Promise(resolve => { + setTimeout(() => { + if (this.newerTunnel) { + resolve(undefined); + } else { + resolve(firstTunnel); + } + }, 3000); + }); + } + + private showNotification(tunnel: RemoteTunnel) { + const address = makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort); const message = nls.localize('remote.tunnelsView.automaticForward', "Your service running on port {0} is available. [See all forwarded ports](command:{1}.focus)", - firstTunnel.tunnelRemotePort, TunnelPanel.ID); + tunnel.tunnelRemotePort, TunnelPanel.ID); const browserChoice: IPromptChoice = { label: OpenPortInBrowserAction.LABEL, run: () => OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, this.openerService, address) From d298a8d5d68f47df222cd67a7e00d94ac5a1f193 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 4 Dec 2020 15:09:50 +0100 Subject: [PATCH 0615/1837] Fix timing issue with environment tunnels Fixes microsoft/vscode-remote-release#4112 --- .../contrib/remote/browser/remoteExplorer.ts | 21 +++++++----- .../remote/common/remoteExplorerService.ts | 33 ++++++++++++------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 6a6252ed394..3813ddcc697 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -348,24 +348,24 @@ class LinuxAutomaticPortForwarding extends Disposable { ) { super(); this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService); - this._register(configurationService.onDidChangeConfiguration((e) => { + this._register(configurationService.onDidChangeConfiguration(async (e) => { if (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING)) { - this.startStopCandidateListener(); + await this.startStopCandidateListener(); } })); - this.contextServiceListener = this._register(this.contextKeyService.onDidChangeContext(e => { + this.contextServiceListener = this._register(this.contextKeyService.onDidChangeContext(async (e) => { if (e.affectsSome(new Set(forwardedPortsViewEnabled.keys()))) { - this.startStopCandidateListener(); + await this.startStopCandidateListener(); } })); this.startStopCandidateListener(); } - private startStopCandidateListener() { + private async startStopCandidateListener() { if (this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING)) { - this.startCandidateListener(); + await this.startCandidateListener(); } else { this.stopCandidateListener(); } @@ -378,7 +378,7 @@ class LinuxAutomaticPortForwarding extends Disposable { } } - private startCandidateListener() { + private async startCandidateListener() { if (this.candidateListener || !forwardedPortsViewEnabled.getValue(this.contextKeyService)) { return; } @@ -386,9 +386,14 @@ class LinuxAutomaticPortForwarding extends Disposable { this.contextServiceListener.dispose(); } - this.candidateListener = this._register(this.remoteExplorerService.tunnelModel.onCandidatesChanged(this.handleCandidateUpdate, this)); + if (!this.remoteExplorerService.tunnelModel.environmentTunnelsSet) { + await new Promise(resolve => this.remoteExplorerService.tunnelModel.onEnvironmentTunnelsSet(() => resolve())); + } + // Capture list of starting candidates so we don't auto forward them later. this.setInitialCandidates(); + + this.candidateListener = this._register(this.remoteExplorerService.tunnelModel.onCandidatesChanged(this.handleCandidateUpdate, this)); } private setInitialCandidates() { diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index be29f38f980..ec449745fd2 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -119,6 +119,9 @@ export class TunnelModel extends Disposable { public onCandidatesChanged: Event> = this._onCandidatesChanged.event; private _candidateFilter: ((candidates: { host: string, port: number, detail: string }[]) => Promise<{ host: string, port: number, detail: string }[]>) | undefined; private tunnelRestoreValue: string | undefined; + private _onEnvironmentTunnelsSet: Emitter = new Emitter(); + public onEnvironmentTunnelsSet: Event = this._onEnvironmentTunnelsSet.event; + private _environmentTunnelsSet: boolean = false; constructor( @ITunnelService private readonly tunnelService: ITunnelService, @@ -247,16 +250,24 @@ export class TunnelModel extends Disposable { return (this.forwarded.get(key) || this.detected.get(key))?.localAddress; } - addEnvironmentTunnels(tunnels: TunnelDescription[]): void { - tunnels.forEach(tunnel => { - this.detected.set(makeAddress(tunnel.remoteAddress.host, tunnel.remoteAddress.port), { - remoteHost: tunnel.remoteAddress.host, - remotePort: tunnel.remoteAddress.port, - localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port), - closeable: false, - runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.remoteAddress.host, tunnel.remoteAddress.port)?.detail + public get environmentTunnelsSet(): boolean { + return this._environmentTunnelsSet; + } + + addEnvironmentTunnels(tunnels: TunnelDescription[] | undefined): void { + if (tunnels) { + tunnels.forEach(tunnel => { + this.detected.set(makeAddress(tunnel.remoteAddress.host, tunnel.remoteAddress.port), { + remoteHost: tunnel.remoteAddress.host, + remotePort: tunnel.remoteAddress.port, + localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port), + closeable: false, + runningProcess: mapHasAddressLocalhostOrAllInterfaces(this._candidates, tunnel.remoteAddress.host, tunnel.remoteAddress.port)?.detail + }); }); - }); + } + this._environmentTunnelsSet = true; + this._onEnvironmentTunnelsSet.fire(); this._onForwardPort.fire(); } @@ -386,9 +397,7 @@ class RemoteExplorerService implements IRemoteExplorerService { } setTunnelInformation(tunnelInformation: TunnelInformation | undefined): void { - if (tunnelInformation && tunnelInformation.environmentTunnels) { - this.tunnelModel.addEnvironmentTunnels(tunnelInformation.environmentTunnels); - } + this.tunnelModel.addEnvironmentTunnels(tunnelInformation?.environmentTunnels); } setEditable(tunnelItem: ITunnelItem | undefined, data: IEditableData | null): void { From 478c7b633f1e8ce6e2649566f6f4d76c2a807ec1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 4 Dec 2020 15:23:39 +0100 Subject: [PATCH 0616/1837] Make welcome buttons look better in wide pane Fixes #111744 --- src/vs/workbench/browser/parts/views/media/views.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index 7ff3318d576..8f2df0476e3 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -68,6 +68,11 @@ margin-right: auto; } +.monaco-workbench .pane > .pane-body.wide > .welcome-view .monaco-button { + margin-left: inherit; + max-width: 260px; +} + .monaco-workbench .pane > .pane-body .welcome-view-content { padding: 0 20px 0 20px; box-sizing: border-box; From 8e5a1da05eab6cad2cfb5208098154509c97e049 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 4 Dec 2020 15:48:26 +0100 Subject: [PATCH 0617/1837] Update doc comment for resolveTreeItem Related to #111715 --- src/vs/vscode.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 46671b11482..e1c2dd30ccb 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -8862,6 +8862,8 @@ declare module 'vscode' { * * Will only ever be called once per TreeItem. * + * onDidChangeTreeData should not be triggered from within resolveTreeItem. + * * *Note* that this function is called when tree items are already showing in the UI. * Because of that, no property that changes the presentation (label, description, command, etc.) * can be changed. From 528ca4c9ea884058308eb477572d52b7283b6218 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 4 Dec 2020 16:13:42 +0100 Subject: [PATCH 0618/1837] fix duplicate imports //cc @isidorn --- .../contrib/files/electron-sandbox/fileActions.contribution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index e4716da51f5..72211dd04ca 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -14,7 +14,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; +import { getMultiSelectedResources, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IListService } from 'vs/platform/list/browser/listService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-sandbox/fileCommands'; @@ -23,7 +23,6 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution'; import { SideBySideEditor, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { ContextKeyOrExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS'; const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in File Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder"); From b8aa4141d28dfa6ba667df8a19e9d71b13858331 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 4 Dec 2020 16:45:38 +0100 Subject: [PATCH 0619/1837] Fixes #111128: Do not touch current line's indentation when pressing Enter --- .../editor/common/controller/cursorTypeOperations.ts | 11 ++--------- src/vs/editor/test/browser/controller/cursor.test.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 75da04850bb..0c618026dfc 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -351,13 +351,6 @@ export class TypeOperations { if (ir) { let oldEndViewColumn = CursorColumns.visibleColumnFromColumn2(config, model, range.getEndPosition()); const oldEndColumn = range.endColumn; - - let beforeText = '\n'; - if (indentation !== config.normalizeIndentation(ir.beforeEnter)) { - beforeText = config.normalizeIndentation(ir.beforeEnter) + lineText.substring(indentation.length, range.startColumn - 1) + '\n'; - range = new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn); - } - const newLineContent = model.getLineContent(range.endLineNumber); const firstNonWhitespace = strings.firstNonWhitespaceIndex(newLineContent); if (firstNonWhitespace >= 0) { @@ -367,7 +360,7 @@ export class TypeOperations { } if (keepPosition) { - return new ReplaceCommandWithoutChangingPosition(range, beforeText + config.normalizeIndentation(ir.afterEnter), true); + return new ReplaceCommandWithoutChangingPosition(range, '\n' + config.normalizeIndentation(ir.afterEnter), true); } else { let offset = 0; if (oldEndColumn <= firstNonWhitespace + 1) { @@ -376,7 +369,7 @@ export class TypeOperations { } offset = Math.min(oldEndViewColumn + 1 - config.normalizeIndentation(ir.afterEnter).length - 1, 0); } - return new ReplaceCommandWithOffsetCursorState(range, beforeText + config.normalizeIndentation(ir.afterEnter), 0, offset, true); + return new ReplaceCommandWithOffsetCursorState(range, '\n' + config.normalizeIndentation(ir.afterEnter), 0, offset, true); } } } diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index cb202a3f872..9dc368f6998 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -4169,6 +4169,18 @@ suite('Editor Controller - Indentation Rules', () => { model.dispose(); mode.dispose(); }); + + test('issue #111128: Multicursor `Enter` issue with indentation', () => { + const model = createTextModel(' let a, b, c;', { detectIndentation: false, insertSpaces: false, tabSize: 4 }, mode.getLanguageIdentifier()); + withTestCodeEditor(null, { model: model }, (editor, viewModel) => { + editor.setSelections([ + new Selection(1, 11, 1, 11), + new Selection(1, 14, 1, 14), + ]); + viewModel.type('\n', 'keyboard'); + assert.equal(model.getValue(), ' let a,\n\t b,\n\t c;'); + }); + }); }); interface ICursorOpts { From 7413cc249353cb8c645957ab96d03c55906fd047 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 4 Dec 2020 16:50:44 +0100 Subject: [PATCH 0620/1837] yarn gulp vscode --- build/gulpfile.vscode.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 1d02cbe067a..42a9c2b2709 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -338,7 +338,7 @@ BUILD_TARGETS.forEach(buildTarget => { const arch = buildTarget.arch; const opts = buildTarget.opts; - ['', 'min'].forEach(minified => { + const [vscode, vscodeMin] = ['', 'min'].map(minified => { const sourceFolderName = `out-vscode${dashed(minified)}`; const destinationFolderName = `VSCode${dashed(platform)}${dashed(arch)}`; @@ -355,7 +355,14 @@ BUILD_TARGETS.forEach(buildTarget => { vscodeTaskCI )); gulp.task(vscodeTask); + + return vscodeTask; }); + + if (process.platform === platform && process.arch === arch) { + gulp.task(task.define('vscode', task.series(vscode))); + gulp.task(task.define('vscode-min', task.series(vscodeMin))); + } }); // Transifex Localizations From 9254ec3b286d8b6dc31ac4c04ee1d897c839c5f0 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 4 Dec 2020 16:53:03 +0100 Subject: [PATCH 0621/1837] fixes #111577 --- src/vs/workbench/contrib/files/browser/fileActions.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 6261006fef3..46aacd31f37 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -1025,7 +1025,7 @@ export const cutFileHandler = async (accessor: ServicesAccessor) => { }; export const DOWNLOAD_COMMAND_ID = 'explorer.download'; -const downloadFileHandler = (accessor: ServicesAccessor) => { +const downloadFileHandler = async (accessor: ServicesAccessor) => { const logService = accessor.get(ILogService); const fileService = accessor.get(IFileService); const fileDialogService = accessor.get(IFileDialogService); @@ -1037,7 +1037,7 @@ const downloadFileHandler = (accessor: ServicesAccessor) => { const cts = new CancellationTokenSource(); - const downloadPromise = progressService.withProgress({ + await progressService.withProgress({ location: ProgressLocation.Window, delay: 800, cancellable: isWeb, @@ -1257,9 +1257,6 @@ const downloadFileHandler = (accessor: ServicesAccessor) => { } })); }, () => cts.dispose(true)); - - // Also indicate progress in the files view - progressService.withProgress({ location: VIEW_ID, delay: 800 }, () => downloadPromise); }; CommandsRegistry.registerCommand({ From 707ca0a06c621e09d7fc7988e607afd4de42fb7a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2020 17:02:56 +0100 Subject: [PATCH 0622/1837] nested worker in worker --- .../extensions/worker/extensionHostWorker.ts | 97 +---------------- .../extensions/worker/polyfillNestedWorker.ts | 103 ++++++++++++++++++ 2 files changed, 106 insertions(+), 94 deletions(-) create mode 100644 src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 975c292cf8c..8c0e24af843 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -10,6 +10,7 @@ import { isMessageOfType, MessageType, createMessageOfType } from 'vs/workbench/ import { IInitData } from 'vs/workbench/api/common/extHost.protocol'; import { ExtensionHostMain } from 'vs/workbench/services/extensions/common/extensionHostMain'; import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; +import { NestedWorker } from 'vs/workbench/services/extensions/worker/polyfillNestedWorker'; import * as path from 'vs/base/common/path'; import 'vs/workbench/api/common/extHost.common.services'; @@ -58,101 +59,9 @@ if ((self).Worker) { }; } else { - - function _bootstrapFn(workerUrl: string) { - - const listener: EventListener = (event: Event): void => { - // uninstall handler - self.removeEventListener('message', listener); - - // get data - const port = (event).data; - - // postMessage - Object.defineProperty(self, 'postMessage', { - value(data: any, transferOrOptions?: any) { - port.postMessage(data, transferOrOptions); - } - }); - - // onmessage - let onmessage: Function | null = null; - Object.defineProperty(self, 'onmessage', { - get() { return onmessage; }, - set(value) { onmessage = value; }, - }); - port.onmessage = function (msg: MessageEvent) { - self.dispatchEvent(new MessageEvent('message', { data: msg.data })); - if (typeof onmessage === 'function') { - onmessage(msg.data); - } - }; - - // load module - importScripts(workerUrl); - }; - - self.addEventListener('message', listener); - } - - // NO support for workers from worker - (self).Worker = class extends EventTarget implements Worker { - - onmessage: ((this: Worker, ev: MessageEvent) => any) | null = null; - onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null = null; - onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null = null; - - readonly terminate: () => void; - readonly postMessage: (message: any, options?: any) => void; - + (self).Worker = class extends NestedWorker { constructor(stringOrUrl: string | URL, options?: WorkerOptions) { - super(); - - // create bootstrap script - const bootstrap = `((${_bootstrapFn.toString()})('${stringOrUrl}'))`; - const blob = new Blob([bootstrap], { type: 'application/javascript' }); - const blobUrl = URL.createObjectURL(blob); - - const channel = new MessageChannel(); - const id = blobUrl; // works because blob url is unique, needs ID pool otherwise - - nativePostMessage({ - type: '_newWorker', - id, - port: channel.port2, - url: blobUrl, - options: { name: path.basename(String(stringOrUrl)), ...options }, - }, [channel.port2]); - - // worker-impl: functions - this.postMessage = channel.port1.postMessage.bind(channel.port1); - this.terminate = () => { - channel.port1.postMessage({ type: '_terminateWorker', id }); - URL.revokeObjectURL(blobUrl); - }; - - // worker-impl: events - let _onmessage: ((ev: MessageEvent) => any) | null = null; - Object.defineProperties(this, { - 'onmessage': { - get() { - return _onmessage; - }, - set(value: ((ev: MessageEvent) => any) | null) { - _onmessage = value; - } - } - // TODO - define error, messageerror event - }); - - channel.port1.onmessageerror = evt => this.dispatchEvent(evt); - channel.port1.onmessage = (evt) => { - const msgEvent = new MessageEvent('message', { data: evt.data }); - if (_onmessage) { - _onmessage(msgEvent.data); - } - this.dispatchEvent(msgEvent); - }; + super(nativePostMessage, stringOrUrl, { name: path.basename(stringOrUrl.toString()), ...options }); } }; } diff --git a/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts b/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts new file mode 100644 index 00000000000..5421f913afb --- /dev/null +++ b/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +declare function postMessage(data: any, transferables?: Transferable[]): void; + +const _bootstrapFnSource = (function _bootstrapFn(workerUrl: string) { + + const listener: EventListener = (event: Event): void => { + // uninstall handler + self.removeEventListener('message', listener); + + // get data + const port = (event).data; + + // postMessage + Object.defineProperty(self, 'postMessage', { + value(data: any, transferOrOptions?: any) { + port.postMessage(data, transferOrOptions); + } + }); + + // onmessage + let onmessage: Function | null = null; + Object.defineProperty(self, 'onmessage', { + get() { return onmessage; }, + set(value) { onmessage = value; }, + }); + port.onmessage = function (msg: MessageEvent) { + self.dispatchEvent(new MessageEvent('message', { data: msg.data })); + if (typeof onmessage === 'function') { + onmessage(msg.data); + } + }; + + // load module + importScripts(workerUrl); + }; + + self.addEventListener('message', listener); +}).toString(); + +export class NestedWorker extends EventTarget implements Worker { + + onmessage: ((this: Worker, ev: MessageEvent) => any) | null = null; + onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null = null; + onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null = null; + + readonly terminate: () => void; + readonly postMessage: (message: any, options?: any) => void; + + constructor(nativePostMessage: typeof postMessage, stringOrUrl: string | URL, options?: WorkerOptions) { + super(); + + // create bootstrap script + const bootstrap = `((${_bootstrapFnSource})('${stringOrUrl}'))`; + const blob = new Blob([bootstrap], { type: 'application/javascript' }); + const blobUrl = URL.createObjectURL(blob); + + const channel = new MessageChannel(); + const id = blobUrl; // works because blob url is unique, needs ID pool otherwise + + nativePostMessage({ + type: '_newWorker', + id, + port: channel.port2, + url: blobUrl, + options, + }, [channel.port2]); + + // worker-impl: functions + this.postMessage = channel.port1.postMessage.bind(channel.port1); + this.terminate = () => { + channel.port1.postMessage({ type: '_terminateWorker', id }); + URL.revokeObjectURL(blobUrl); + }; + + // worker-impl: events + let _onmessage: ((ev: MessageEvent) => any) | null = null; + Object.defineProperties(this, { + 'onmessage': { + get() { + return _onmessage; + }, + set(value: ((ev: MessageEvent) => any) | null) { + _onmessage = value; + } + } + // TODO - define error, messageerror event + }); + + channel.port1.onmessageerror = evt => this.dispatchEvent(evt); + channel.port1.onmessage = (evt) => { + const msgEvent = new MessageEvent('message', { data: evt.data }); + if (_onmessage) { + _onmessage(msgEvent.data); + } + this.dispatchEvent(msgEvent); + }; + } +} From acbe8f273e8555c78761fdab0e7ad17385040b12 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 4 Dec 2020 17:21:36 +0100 Subject: [PATCH 0623/1837] Only render `vscode-remote://` extensions as remote --- .../extensions/browser/abstractRuntimeExtensionsEditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index a00d0ce22bb..96c54f0a83a 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -361,7 +361,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { data.msgContainer.appendChild(el); } - if (element.description.extensionLocation.scheme !== Schemas.file) { + if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { const el = $('span', undefined, ...renderCodicons(`$(remote) ${element.description.extensionLocation.authority}`)); data.msgContainer.appendChild(el); From 97e4af4d208fac6c4c9b59dea541f8cfe49cb741 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 4 Dec 2020 19:21:01 +0100 Subject: [PATCH 0624/1837] Fixes #111899: Maintain compatibility for context keys like `vim.use` --- src/vs/platform/contextkey/common/contextkey.ts | 8 ++++---- .../contextkey/test/common/contextkey.test.ts | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index d0f00ed362b..ea7c83876ff 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -167,22 +167,22 @@ export abstract class ContextKeyExpr { return ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim()); } - if (serializedOne.indexOf('>=') >= 0) { + if (/^[^<=>]+>=[^<=>]+$/.test(serializedOne)) { const pieces = serializedOne.split('>='); return ContextKeyGreaterEqualsExpr.create(pieces[0].trim(), pieces[1].trim()); } - if (serializedOne.indexOf('>') >= 0) { + if (/^[^<=>]+>[^<=>]+$/.test(serializedOne)) { const pieces = serializedOne.split('>'); return ContextKeyGreaterExpr.create(pieces[0].trim(), pieces[1].trim()); } - if (serializedOne.indexOf('<=') >= 0) { + if (/^[^<=>]+<=[^<=>]+$/.test(serializedOne)) { const pieces = serializedOne.split('<='); return ContextKeySmallerEqualsExpr.create(pieces[0].trim(), pieces[1].trim()); } - if (serializedOne.indexOf('<') >= 0) { + if (/^[^<=>]+<[^<=>]+$/.test(serializedOne)) { const pieces = serializedOne.split('<'); return ContextKeySmallerExpr.create(pieces[0].trim(), pieces[1].trim()); } diff --git a/src/vs/platform/contextkey/test/common/contextkey.test.ts b/src/vs/platform/contextkey/test/common/contextkey.test.ts index 5701b9dc86b..91a548be66c 100644 --- a/src/vs/platform/contextkey/test/common/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/common/contextkey.test.ts @@ -255,4 +255,15 @@ suite('ContextKeyExpr', () => { checkNegate('a<=1.1', 'a > 1.1'); checkNegate('a<=b', 'a > b'); }); + + test('issue #111899: context keys can use `<` or `>` ', () => { + const actual = ContextKeyExpr.deserialize('editorTextFocus && vim.active && vim.use')!; + assert.ok(actual.equals( + ContextKeyExpr.and( + ContextKeyExpr.has('editorTextFocus'), + ContextKeyExpr.has('vim.active'), + ContextKeyExpr.has('vim.use'), + )! + )); + }); }); From dc8ac78031bd6828bbb5e81d96a7e1d3a95798d0 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Dec 2020 11:44:55 -0800 Subject: [PATCH 0625/1837] fix #111910. Avoid notebook save race condition. --- .../notebook/common/notebookEditorModel.ts | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index c0746dbc1e5..1ad9b60a8b6 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -18,6 +18,7 @@ import { IFileStatWithMetadata, IFileService } from 'vs/platform/files/common/fi import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ILabelService } from 'vs/platform/label/common/label'; import { ILogService } from 'vs/platform/log/common/log'; +import { TaskSequentializer } from 'vs/base/common/async'; export interface INotebookLoadOptions { @@ -41,6 +42,7 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM private readonly _name: string; private readonly _workingCopyResource: URI; + private readonly saveSequentializer = new TaskSequentializer(); private _dirty = false; @@ -199,10 +201,10 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM } private async _assertStat() { - this._logService.debug('start assert stat'); + this._logService.debug('[notebook editor model] start assert stat'); const stats = await this._resolveStats(this.resource); if (this._lastResolvedFileStat && stats && stats.mtime > this._lastResolvedFileStat.mtime) { - this._logService.debug(`noteboook file on disk is newer: + this._logService.debug(`[notebook editor model] noteboook file on disk is newer: LastResolvedStat: ${this._lastResolvedFileStat ? JSON.stringify(this._lastResolvedFileStat) : undefined}. Current stat: ${JSON.stringify(stats)} `); @@ -238,28 +240,48 @@ Current stat: ${JSON.stringify(stats)} } async save(): Promise { - this._logService.debug(`start saving notebook ${this.resource.toString()}`); - const result = await this._assertStat(); - if (result === 'none') { - return false; + let versionId = this._notebook.versionId; + this._logService.debug(`[notebook editor model] save(${versionId}) - enter with versionId ${versionId}`, this.resource.toString(true)); + + if (this.saveSequentializer.hasPending(versionId)) { + this._logService.debug(`[notebook editor model] save(${versionId}) - exit - found a pending save for versionId ${versionId}`, this.resource.toString(true)); + return this.saveSequentializer.pending.then(() => { + return true; + }); } - if (result === 'revert') { - await this.revert(); + if (this.saveSequentializer.hasPending()) { + return this.saveSequentializer.setNext(async () => { + await this.save(); + }).then(() => { + return true; + }); + } + + return this.saveSequentializer.setPending(versionId, (async () => { + const result = await this._assertStat(); + if (result === 'none') { + return; + } + + if (result === 'revert') { + await this.revert(); + return; + } + + const tokenSource = new CancellationTokenSource(); + await this._notebookService.save(this.notebook.viewType, this.notebook.uri, tokenSource.token); + this._logService.debug(`[notebook editor model] save(${versionId}) - document saved saved, start updating file stats`, this.resource.toString(true)); + const newStats = await this._resolveStats(this.resource); + this._lastResolvedFileStat = newStats; + this.setDirty(false); + })()).then(() => { return true; - } - - const tokenSource = new CancellationTokenSource(); - await this._notebookService.save(this.notebook.viewType, this.notebook.uri, tokenSource.token); - this._logService.debug(`notebook ${this.resource.toString()} saved. update file stats`); - const newStats = await this._resolveStats(this.resource); - this._lastResolvedFileStat = newStats; - this.setDirty(false); - return true; + }); } async saveAs(targetResource: URI): Promise { - this._logService.debug(`start saving notebook ${this.resource.toString()}`); + this._logService.debug(`[notebook editor model] saveAs - enter`, this.resource.toString(true)); const result = await this._assertStat(); if (result === 'none') { @@ -273,7 +295,7 @@ Current stat: ${JSON.stringify(stats)} const tokenSource = new CancellationTokenSource(); await this._notebookService.saveAs(this.notebook.viewType, this.notebook.uri, targetResource, tokenSource.token); - this._logService.debug(`notebook ${this.resource.toString()} saved. update file stats`); + this._logService.debug(`[notebook editor model] saveAs - document saved, start updating file stats`, this.resource.toString(true)); const newStats = await this._resolveStats(this.resource); this._lastResolvedFileStat = newStats; this.setDirty(false); @@ -286,9 +308,9 @@ Current stat: ${JSON.stringify(stats)} } try { - this._logService.debug(`start checking stats for ${resource.toString()}`); + this._logService.debug(`[notebook editor model] _resolveStats`, this.resource.toString(true)); const newStats = await this._fileService.resolve(this.resource, { resolveMetadata: true }); - this._logService.debug(`${resource.toString()} latest file stats: ${JSON.stringify(newStats)}`); + this._logService.debug(`[notebook editor model] _resolveStats - latest file stats: ${JSON.stringify(newStats)}`, this.resource.toString(true)); return newStats; } catch (e) { return undefined; From 39f33b588ad5dcb79ee075e2db8fcb36bfe59763 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Dec 2020 13:15:05 -0800 Subject: [PATCH 0626/1837] wrap font faimly with quotes --- .../workbench/contrib/comments/browser/commentThreadWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 8f8c4ffcfde..ffab7e07c3a 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -951,7 +951,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget const fontInfo = this.editor.getOption(EditorOption.fontInfo); content.push(`.monaco-editor .review-widget .body code { - font-family: ${fontInfo.fontFamily}; + font-family: '${fontInfo.fontFamily}'; font-size: ${fontInfo.fontSize}px; font-weight: ${fontInfo.fontWeight}; }`); From 532ba43c78c82b24bdf94f9edde30cdf9b9bfa12 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Fri, 4 Dec 2020 14:14:31 -0800 Subject: [PATCH 0627/1837] Remove console.log --- .../contrib/welcome/gettingStarted/browser/gettingStarted.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 123bd38bbd9..637330e06db 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -176,7 +176,6 @@ export class GettingStartedPage extends Disposable { } this.editorInput.selectedTask = id; const taskToExpand = assertIsDefined(this.currentCategory.content.items.find(task => task.id === id)); - console.log(taskToExpand.media.path, taskToExpand.media.path.toString()); mediaElement.setAttribute('src', taskToExpand.media.path.toString()); mediaElement.setAttribute('alt', taskToExpand.media.altText); From 423bdb2e26307200b11867ff20fc09f52883a0db Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 4 Dec 2020 23:51:44 +0100 Subject: [PATCH 0628/1837] Fixes #104004: Only run tests if the tests belong to a known extension --- .../api/common/extHostExtensionService.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 328b9327207..2f3857ac7f3 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -35,6 +35,8 @@ import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelServ import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; import { Emitter, Event } from 'vs/base/common/event'; import { IExtensionActivationHost, checkActivateWorkspaceContainsExtension } from 'vs/workbench/api/common/shared/workspaceContains'; +import { isEqualOrParent } from 'vs/base/common/extpath'; +import { isLinux } from 'vs/base/common/platform'; interface ITestRunner { /** Old test runner API, as exported from `vscode/lib/testrunner` */ @@ -537,6 +539,20 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme const extensionTestsPath = originalFSPath(extensionTestsLocationURI); + let knowsExtension = false; + for (const extension of this._registry.getAllExtensionDescriptions()) { + if (extension.extensionLocation.scheme === Schemas.file) { + const extensionPath = originalFSPath(extension.extensionLocation); + if (isEqualOrParent(extensionTestsPath, extensionPath, !isLinux)) { + knowsExtension = true; + } + } + } + + if (!knowsExtension) { + return Promise.resolve(undefined); + } + // Require the test runner via node require from the provided path let testRunner: ITestRunner | INewTestRunner | undefined; let requireError: Error | undefined; From 962bedc4f47b26e4a6ddc917ee2a4d9445531fb9 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Fri, 4 Dec 2020 17:15:30 -0800 Subject: [PATCH 0629/1837] Update version to 1.53.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f4c487c9076..20019343577 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "code-oss-dev", - "version": "1.52.0", + "version": "1.53.0", "distro": "11fd6f1230738827638f000f641d01b2b178db20", "author": { "name": "Microsoft Corporation" @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From 94142bd7e0dbc073fe6abf130d7b7066a7beb1d6 Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 5 Dec 2020 01:54:58 -0800 Subject: [PATCH 0630/1837] chore: bump electron@11.0.3 (#111931) * chore: bump electron@11.0.3 This reverts commit 155691d0bec4acfac0e3bbccb362f61278a132de. * chore: bump x64 build image * chore: rebuild remote with older gcc toolchain * chore: bump electron@11.0.3 * ci: remove condition for remote step * chore: disable an integration test --- .yarnrc | 2 +- .../darwin/continuous-build-darwin.yml | 2 +- .../darwin/helper-plugin-entitlements.plist | 10 - .../darwin/product-build-darwin.yml | 4 +- build/azure-pipelines/distro-build.yml | 2 +- build/azure-pipelines/exploration-build.yml | 2 +- .../linux/continuous-build-linux.yml | 2 +- .../linux/product-build-alpine.yml | 2 +- .../linux/product-build-linux.yml | 23 ++- .../linux/snap-build-linux.yml | 2 +- build/azure-pipelines/product-build.yml | 11 +- build/azure-pipelines/product-compile.yml | 2 +- .../publish-types/publish-types.yml | 2 +- build/azure-pipelines/sync-mooncake.yml | 2 +- .../azure-pipelines/web/product-build-web.yml | 2 +- .../win32/continuous-build-win32.yml | 2 +- .../win32/product-build-win32.yml | 2 +- build/darwin/sign.ts | 10 - cgmanifest.json | 12 +- package.json | 10 +- remote/.yarnrc | 2 +- remote/package.json | 6 +- remote/yarn.lock | 26 +-- scripts/test-integration.sh | 6 +- src/vs/code/electron-main/window.ts | 6 +- .../test/node/nativeModules.test.ts | 2 +- .../platform/menubar/electron-main/menubar.ts | 6 +- .../electron-main/webviewProtocolProvider.ts | 13 +- .../services/extensions/node/proxyResolver.ts | 2 +- yarn.lock | 187 +++++++++--------- 30 files changed, 179 insertions(+), 183 deletions(-) delete mode 100644 build/azure-pipelines/darwin/helper-plugin-entitlements.plist diff --git a/.yarnrc b/.yarnrc index 264a5e3a3d6..7b0e7edfcbf 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://electronjs.org/headers" -target "9.3.5" +target "11.0.3" runtime "electron" diff --git a/build/azure-pipelines/darwin/continuous-build-darwin.yml b/build/azure-pipelines/darwin/continuous-build-darwin.yml index 55efe5f32eb..75c28106c5e 100644 --- a/build/azure-pipelines/darwin/continuous-build-darwin.yml +++ b/build/azure-pipelines/darwin/continuous-build-darwin.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/darwin/helper-plugin-entitlements.plist b/build/azure-pipelines/darwin/helper-plugin-entitlements.plist deleted file mode 100644 index 7cd9df032bd..00000000000 --- a/build/azure-pipelines/darwin/helper-plugin-entitlements.plist +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.cs.allow-unsigned-executable-memory - - com.apple.security.cs.disable-library-validation - - - diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 6f7dec16aca..e2107fd73c9 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -22,7 +22,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: @@ -78,7 +78,7 @@ steps: - script: | set -e - npm install -g node-gyp@7.1.0 + npm install -g node-gyp@latest node-gyp --version displayName: Update node-gyp condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml index 99bad6b72cd..331fbf9675e 100644 --- a/build/azure-pipelines/distro-build.yml +++ b/build/azure-pipelines/distro-build.yml @@ -8,7 +8,7 @@ pr: steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - 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 4a7acf129b3..e0bb30a7e02 100644 --- a/build/azure-pipelines/exploration-build.yml +++ b/build/azure-pipelines/exploration-build.yml @@ -6,7 +6,7 @@ trigger: none steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/linux/continuous-build-linux.yml b/build/azure-pipelines/linux/continuous-build-linux.yml index e777f821d76..44cb9829472 100644 --- a/build/azure-pipelines/linux/continuous-build-linux.yml +++ b/build/azure-pipelines/linux/continuous-build-linux.yml @@ -10,7 +10,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 9a54bc2bc8a..8108ff8193d 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -22,7 +22,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 1f7884a1c83..5d7e8cdb24f 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -22,7 +22,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: @@ -69,6 +69,13 @@ steps: targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" + - script: | + set -e + npm install -g node-gyp@latest + node-gyp --version + displayName: Update node-gyp + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + - script: | set -e export npm_config_arch=$(NPM_ARCH) @@ -97,6 +104,14 @@ steps: displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + - script: | + set -e + export CC=$(which gcc-4.8) + export CXX=$(which g++-4.8) + cd remote + node-gyp rebuild + displayName: Rebuild remote modules with gcc-4.8 + - script: | set -e node build/azure-pipelines/mixin @@ -112,12 +127,6 @@ steps: yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci displayName: Build - - script: | - set -e - service xvfb start - displayName: Start xvfb - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - - script: | set -e DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index f08c7b3c3e6..e0f2d2c6e2a 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: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index ebe2fe6abef..2b3d87d119d 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -11,8 +11,9 @@ schedules: resources: containers: - container: vscode-x64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:x64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic-x64 endpoint: VSCodeHub + options: --user 0:0 - container: vscode-arm64 image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64 endpoint: VSCodeHub @@ -27,7 +28,7 @@ stages: jobs: - job: Compile pool: - vmImage: "Ubuntu-16.04" + vmImage: "Ubuntu-18.04" container: vscode-x64 variables: VSCODE_ARCH: x64 @@ -70,7 +71,7 @@ stages: - Compile condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) pool: - vmImage: "Ubuntu-16.04" + vmImage: "Ubuntu-18.04" jobs: - job: Linux condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) @@ -179,7 +180,7 @@ stages: - macOSARM64 condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) pool: - vmImage: "Ubuntu-16.04" + vmImage: "Ubuntu-18.04" jobs: - job: SyncMooncake displayName: Sync Mooncake @@ -194,7 +195,7 @@ stages: - macOSARM64 condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) pool: - vmImage: "Ubuntu-16.04" + vmImage: "Ubuntu-18.04" jobs: - job: BuildService displayName: Build Service diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index eaf0a65e8aa..66baef772c8 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -17,7 +17,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml index 5f1cf6c28a4..0e3f4e4daa4 100644 --- a/build/azure-pipelines/publish-types/publish-types.yml +++ b/build/azure-pipelines/publish-types/publish-types.yml @@ -9,7 +9,7 @@ pr: none steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/sync-mooncake.yml b/build/azure-pipelines/sync-mooncake.yml index 109709418ff..280c9e6372d 100644 --- a/build/azure-pipelines/sync-mooncake.yml +++ b/build/azure-pipelines/sync-mooncake.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 33282adbe46..1beae9506eb 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -22,7 +22,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/win32/continuous-build-win32.yml b/build/azure-pipelines/win32/continuous-build-win32.yml index 87b820cb009..7bd18707381 100644 --- a/build/azure-pipelines/win32/continuous-build-win32.yml +++ b/build/azure-pipelines/win32/continuous-build-win32.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 1992ac1affb..5c8806401d5 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -22,7 +22,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "12.14.1" + versionSpec: "12.18.3" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: diff --git a/build/darwin/sign.ts b/build/darwin/sign.ts index 538dc97adf1..f1908b14749 100644 --- a/build/darwin/sign.ts +++ b/build/darwin/sign.ts @@ -29,7 +29,6 @@ async function main(): Promise { const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks'); const helperAppBaseName = product.nameShort; const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app'; - const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app'; const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app'; const defaultOpts: codesign.SignOptions = { @@ -51,7 +50,6 @@ async function main(): Promise { // TODO(deepak1556): Incorrectly declared type in electron-osx-sign ignore: (filePath: string) => { return filePath.includes(gpuHelperAppName) || - filePath.includes(pluginHelperAppName) || filePath.includes(rendererHelperAppName); } }; @@ -63,13 +61,6 @@ async function main(): Promise { 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), }; - const pluginHelperOpts: codesign.SignOptions = { - ...defaultOpts, - app: path.join(appFrameworkPath, pluginHelperAppName), - entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), - 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), - }; - const rendererHelperOpts: codesign.SignOptions = { ...defaultOpts, app: path.join(appFrameworkPath, rendererHelperAppName), @@ -78,7 +69,6 @@ async function main(): Promise { }; await codesign.signAsync(gpuHelperOpts); - await codesign.signAsync(pluginHelperOpts); await codesign.signAsync(rendererHelperOpts); await codesign.signAsync(appOpts as any); } diff --git a/cgmanifest.json b/cgmanifest.json index 656e3f821bf..5575cb4b04c 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "894fb9eb56c6cbda65e3c3ae9ada6d4cb5850cc9" + "commitHash": "0387c513f0319231a8ca6dd0a265102af3d4455e" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "83.0.4103.122" + "version": "87.0.4280.67" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "9622fed3fb2cffcea9efff6c8cb4cc2def99d75d" + "commitHash": "e3e0927bb93ed92bcdfe81e7ad9af3d78ccc74fb" } }, "isOnlyProductionDependency": true, - "version": "12.14.1" + "version": "12.18.3" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "415c1f9e9b35d9599b1a8ad1200476afa47a3323" + "commitHash": "b0862a6e63173c4c919bd5ed27d257235bbfe7d2" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "9.3.5" + "version": "11.0.3" }, { "component": { diff --git a/package.json b/package.json index 20019343577..6a714c44190 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "compile-web": "gulp compile-web --max_old_space_size=4095", "watch-web": "gulp watch-web --max_old_space_size=4095", "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", - "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.2" + "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.3" }, "dependencies": { "applicationinsights": "1.0.8", @@ -60,7 +60,7 @@ "native-is-elevated": "0.4.1", "native-keymap": "2.2.1", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta17", + "node-pty": "0.10.0-beta18", "spdlog": "^0.11.1", "sudo-prompt": "9.1.1", "tas-client-umd": "0.1.2", @@ -112,7 +112,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "9.3.5", + "electron": "11.0.3", "electron-rebuild": "2.0.3", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", @@ -191,10 +191,10 @@ "url": "https://github.com/microsoft/vscode/issues" }, "optionalDependencies": { - "vscode-windows-ca-certs": "0.2.0", + "vscode-windows-ca-certs": "^0.3.0", "vscode-windows-registry": "1.0.3", "windows-foreground-love": "0.2.0", "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file diff --git a/remote/.yarnrc b/remote/.yarnrc index c1a32ce532a..cd436416b56 100644 --- a/remote/.yarnrc +++ b/remote/.yarnrc @@ -1,3 +1,3 @@ disturl "http://nodejs.org/dist" -target "12.14.1" +target "12.18.3" runtime "node" diff --git a/remote/package.json b/remote/package.json index f68deac647c..57710a189ba 100644 --- a/remote/package.json +++ b/remote/package.json @@ -12,15 +12,15 @@ "jschardet": "2.2.1", "minimist": "^1.2.5", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta17", + "node-pty": "0.10.0-beta18", "spdlog": "^0.11.1", "tas-client-umd": "0.1.2", "vscode-nsfw": "1.2.9", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", + "vscode-regexpp": "^3.1.0", "vscode-ripgrep": "^1.11.1", "vscode-textmate": "5.2.0", - "vscode-regexpp": "^3.1.0", "xterm": "4.10.0-beta.4", "xterm-addon-search": "0.8.0-beta.3", "xterm-addon-unicode11": "0.3.0-beta.3", @@ -29,7 +29,7 @@ "yazl": "^2.4.3" }, "optionalDependencies": { - "vscode-windows-ca-certs": "0.2.0", + "vscode-windows-ca-certs": "0.3.0", "vscode-windows-registry": "1.0.2" } } diff --git a/remote/yarn.lock b/remote/yarn.lock index 22d8ebe3fc5..e15eb9d9839 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -299,15 +299,15 @@ native-watchdog@1.3.0: resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.3.0.tgz#88cee94c9dc766b85c8506eda14c8bd8c9618e27" integrity sha512-WOjGRNGkYZ5MXsntcvCYrKtSYMaewlbCFplbcUVo9bE80LPVt8TAVFHYWB8+a6fWCGYheq21+Wtt6CJrUaCJhw== -node-addon-api@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" - integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== +node-addon-api@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" + integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== -node-pty@0.10.0-beta17: - version "0.10.0-beta17" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" - integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== +node-pty@0.10.0-beta18: + version "0.10.0-beta18" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta18.tgz#7ed2d3f4a06b2b23fe2abdf5b41655e9dffc25d5" + integrity sha512-vpK4yB3A3VzgkvdOWegL7GcPapt45jfA4b3ejUe8k4RmqdWBRvFJngew8T3qAxmLhTkfo93psaN6izTlfkc6FA== dependencies: nan "^2.14.0" @@ -438,12 +438,12 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-windows-ca-certs@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.2.0.tgz#086f0f4de57e2760a35ac6920831bff246237115" - integrity sha512-YBrJRT0zos+Yb1Qdn73GD8QZr7pa2IE96b5Y1hmmp6XeR8aYB7Iiq5gDAF/+/AxL+caSR9KPZQ6jiYWh5biD7w== +vscode-windows-ca-certs@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.3.0.tgz#324e1f8ba842bbf048a39e7c0ee8fe655e9adfcc" + integrity sha512-CYrpCEKmAFQJoZNReOrelNL+VKyebOVRCqL9evrBlVcpWQDliliJgU5RggGS8FPGtQ3jAKLQt9frF0qlxYYPKA== dependencies: - node-addon-api "1.6.2" + node-addon-api "^3.0.2" vscode-windows-registry@1.0.2: version "1.0.2" diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index b82dbec1137..609a2bf6121 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -60,8 +60,10 @@ after_suite "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR after_suite -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR -after_suite +# TODO(deepak1556): Disable workspace test temporarily +# https://github.com/microsoft/vscode/issues/111288 +#"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +#after_suite "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR after_suite diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index a9f47be8153..f6b98e72c98 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -9,7 +9,7 @@ import * as nls from 'vs/nls'; import * as perf from 'vs/base/common/performance'; import { Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; -import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, Details } from 'electron'; +import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, RenderProcessGoneDetails } from 'electron'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -544,8 +544,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { } private onWindowError(error: WindowError.UNRESPONSIVE): void; - private onWindowError(error: WindowError.CRASHED, details: Details): void; - private onWindowError(error: WindowError, details?: Details): void { + private onWindowError(error: WindowError.CRASHED, details: RenderProcessGoneDetails): void; + private onWindowError(error: WindowError, details?: RenderProcessGoneDetails): void { this.logService.error(error === WindowError.CRASHED ? `[VS Code]: renderer process crashed (detail: ${details?.reason})` : '[VS Code]: detected unresponsive'); // If we run extension tests from CLI, showing a dialog is not diff --git a/src/vs/platform/environment/test/node/nativeModules.test.ts b/src/vs/platform/environment/test/node/nativeModules.test.ts index b64282f626f..34617f575bb 100644 --- a/src/vs/platform/environment/test/node/nativeModules.test.ts +++ b/src/vs/platform/environment/test/node/nativeModules.test.ts @@ -90,7 +90,7 @@ suite('Native Modules (all platforms)', () => { test('vscode-windows-ca-certs', async () => { // @ts-ignore Windows only const windowsCerts = await import('vscode-windows-ca-certs'); - const store = windowsCerts(); + const store = new windowsCerts.Crypt32(); assert.ok(windowsCerts, testErrorMessage('vscode-windows-ca-certs')); let certCount = 0; try { diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 3039b01a1cf..90fba9c3fb1 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { isMacintosh, language } from 'vs/base/common/platform'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; -import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, KeyboardEvent } from 'electron'; +import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, KeyboardEvent } from 'electron'; import { getTitleBarStyle, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -62,7 +62,7 @@ export class Menubar { private keybindings: { [commandId: string]: IMenubarKeybinding }; - private readonly fallbackMenuHandlers: { [id: string]: (menuItem: MenuItem, browserWindow: BrowserWindow | undefined, event: Event) => void } = Object.create(null); + private readonly fallbackMenuHandlers: { [id: string]: (menuItem: MenuItem, browserWindow: BrowserWindow | undefined, event: KeyboardEvent) => void } = Object.create(null); constructor( @IUpdateService private readonly updateService: IUpdateService, @@ -639,7 +639,7 @@ export class Menubar { private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): MenuItem; private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): MenuItem { const label = this.mnemonicLabel(arg1); - const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: MenuItem & IMenuItemWithKeybinding, win: BrowserWindow, event: Event) => { + const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: MenuItem & IMenuItemWithKeybinding, win: BrowserWindow, event: KeyboardEvent) => { const userSettingsLabel = menuItem ? menuItem.userSettingsLabel : null; let commandId = arg2; if (Array.isArray(arg2)) { diff --git a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts index a019d267e69..ce6233924b0 100644 --- a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts +++ b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts @@ -125,7 +125,10 @@ export class WebviewProtocolProvider extends Disposable { } } - private async handleWebviewRequest(request: Electron.Request, callback: any) { + private async handleWebviewRequest( + request: Electron.ProtocolRequest, + callback: (response: string | Electron.ProtocolResponse) => void + ) { try { const uri = URI.parse(request.url); const entry = WebviewProtocolProvider.validWebviewFilePaths.get(uri.path); @@ -144,8 +147,8 @@ export class WebviewProtocolProvider extends Disposable { } private async handleWebviewResourceRequest( - request: Electron.Request, - callback: (stream?: NodeJS.ReadableStream | Electron.StreamProtocolResponse | undefined) => void + request: Electron.ProtocolRequest, + callback: (stream: NodeJS.ReadableStream | Electron.ProtocolResponse) => void ) { try { const uri = URI.parse(request.url); @@ -220,14 +223,14 @@ export class WebviewProtocolProvider extends Disposable { if (result.type === WebviewResourceResponse.Type.AccessDenied) { console.error('Webview: Cannot load resource outside of protocol root'); - return callback({ data: null, statusCode: 401 }); + return callback({ data: undefined, statusCode: 401 }); } } } catch { // noop } - return callback({ data: null, statusCode: 404 }); + return callback({ data: undefined, statusCode: 404 }); } public didLoadResource(requestId: number, content: VSBuffer | undefined) { diff --git a/src/vs/workbench/services/extensions/node/proxyResolver.ts b/src/vs/workbench/services/extensions/node/proxyResolver.ts index 3050bc6e2d6..80177b1fad9 100644 --- a/src/vs/workbench/services/extensions/node/proxyResolver.ts +++ b/src/vs/workbench/services/extensions/node/proxyResolver.ts @@ -498,7 +498,7 @@ async function readWindowsCaCertificates() { const winCA = await import('vscode-windows-ca-certs'); let ders: any[] = []; - const store = winCA(); + const store = new winCA.Crypt32(); try { let der: any; while (der = store.next()) { diff --git a/yarn.lock b/yarn.lock index dd5e3e4eea8..8adc7c55ed3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -141,15 +141,14 @@ to-fast-properties "^2.0.0" "@electron/get@^1.0.1": - version "1.12.2" - resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" - integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg== + version "1.7.2" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.7.2.tgz#286436a9fb56ff1a1fcdf0e80131fd65f4d1e0fd" + integrity sha512-LSE4LZGMjGS9TloDx0yO44D2UTbaeKRk+QjlhWLiQlikV6J4spgDCjb6z4YIcqmPAwNzlNCnWF4dubytwI+ATA== dependencies: debug "^4.1.1" env-paths "^2.2.0" fs-extra "^8.1.0" got "^9.6.0" - progress "^2.0.3" sanitize-filename "^1.6.2" sumchecker "^3.0.1" optionalDependencies: @@ -279,9 +278,9 @@ integrity sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ== "@types/node@^12.0.12": - version "12.19.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.7.tgz#cf8b6ac088dd9182ac9a1d765f787a8d12490c04" - integrity sha512-zvjOU1g4CpPilbTDUATnZCUb/6lARMRAqzT7ILwl1P3YvU2leEcZ2+fw9+Jrw/paXB1CgQyXTrN4hWDtqT9O2A== + version "12.12.24" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.24.tgz#d4606afd8cf6c609036b854360367d1b2c78931f" + integrity sha512-1Ciqv9pqwVtW6FsIUKSZNB82E5Cu1I2bBTj1xuIHXLe/1zYLl3956Nbhg2MzSYHVfl9/rmanjbQIb7LibfCnug== "@types/node@^12.11.7": version "12.12.14" @@ -1312,10 +1311,10 @@ boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -boolean@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570" - integrity sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g== +boolean@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.0.tgz#fab78d5907dbae6216ab46d32733bb7b76b99e76" + integrity sha512-OElxJ1lUSinuoUnkpOgLmxp0DC4ytEhODEL6QJU0NpxE/mI4rUSh8h1P1Wkvfi3xQEBcxXR2gBIPNYNuaFcAbQ== boom@4.x.x: version "4.3.1" @@ -2114,7 +2113,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.2: +concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -2237,10 +2236,10 @@ copy-webpack-plugin@^4.5.2: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js@^3.6.5: - version "3.8.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.0.tgz#0fc2d4941cadf80538b030648bb64d230b4da0ce" - integrity sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA== +core-js@^3.4.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.1.tgz#39d5e2e346258cc01eb7d44345b1c3c014ca3f05" + integrity sha512-186WjSik2iTGfDjfdCZAxv2ormxtKgemjC3SI6PL31qOA0j5LhTDVjHChccoc7brwLvpvLPiMyRlcO88C4l1QQ== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -2476,6 +2475,13 @@ debug@2.2.0: dependencies: ms "0.7.1" +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -2490,13 +2496,6 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -2571,9 +2570,9 @@ defaults@^1.0.3: clone "^1.0.2" defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.1.tgz#88ae694b93f67b81815a2c8c769aef6574ac8f2f" + integrity sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ== define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" @@ -2858,10 +2857,10 @@ electron-to-chromium@^1.2.7: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@9.3.5: - version "9.3.5" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.5.tgz#7967146b81e6d9b484773243fd4a4f671a50b884" - integrity sha512-EPmDsp7sO0UPtw7nLD1ufse/nBskP+ifXzBgUg9psCUlapkzuwYi6pmLAzKLW/bVjwgyUKwh1OKWILWfOeLGcQ== +electron@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.0.3.tgz#c29eaacda38ce561890e59906ca5f507c72b3ec4" + integrity sha512-nNfbLi7Q1xfJXOEO2adck5TS6asY4Jxc332E4Te8XfQ9hcaC3GiCdeEqk9FndNCwxhJA5Lr9jfSGRTwWebFa/w== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -3042,10 +3041,10 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== eslint-plugin-jsdoc@^19.1.0: version "19.1.0" @@ -3421,14 +3420,14 @@ extglob@^2.0.4: to-regex "^3.0.1" extract-zip@^1.0.3: - version "1.7.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" - integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= dependencies: - concat-stream "^1.6.2" - debug "^2.6.9" - mkdirp "^0.5.4" - yauzl "^2.10.0" + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" extract-zip@^2.0.1: version "2.0.1" @@ -4092,17 +4091,17 @@ glob@^7.1.4, glob@^7.1.6: path-is-absolute "^1.0.0" global-agent@^2.0.2: - version "2.1.12" - resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195" - integrity sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg== + version "2.1.7" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.7.tgz#12d7bc2b07cd862d0fa76b0f1b2c48cd5ffcf150" + integrity sha512-ooK7eqGYZku+LgnbfH/Iv0RJ74XfhrBZDlke1QSzcBt0bw1PmJcnRADPAQuFE+R45pKKDTynAr25SBasY2kvow== dependencies: - boolean "^3.0.1" - core-js "^3.6.5" + boolean "^3.0.0" + core-js "^3.4.1" es6-error "^4.1.1" - matcher "^3.0.0" - roarr "^2.15.3" - semver "^7.3.2" - serialize-error "^7.0.1" + matcher "^2.0.0" + roarr "^2.14.5" + semver "^6.3.0" + serialize-error "^5.0.0" global-modules@^1.0.0: version "1.0.0" @@ -4167,7 +4166,7 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globalthis@^1.0.1: +globalthis@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== @@ -4683,9 +4682,9 @@ html-escaper@^2.0.0: readable-stream "^2.0.2" http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" + integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== http-proxy-agent@^2.1.0: version "2.1.0" @@ -5942,12 +5941,12 @@ matchdep@^2.0.0: resolve "^1.4.0" stack-trace "0.0.10" -matcher@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" - integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng== +matcher@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.1.0.tgz#64e1041c15b993e23b786f93320a7474bf833c28" + integrity sha512-o+nZr+vtJtgPNklyeUKkkH42OsK8WAfdgaJE2FNxcjLPg+5QbeEoT6vRj8Xq/iv18JlQ9cmKsEu0b94ixWf1YQ== dependencies: - escape-string-regexp "^4.0.0" + escape-string-regexp "^2.0.0" math-expression-evaluator@^1.2.14: version "1.2.17" @@ -6110,7 +6109,12 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0, mimic-response@^1.0.1: +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + integrity sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4= + +mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== @@ -6252,7 +6256,7 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd dependencies: minimist "0.0.8" -mkdirp@^0.5.3, mkdirp@^0.5.4: +mkdirp@^0.5.3: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -6431,12 +6435,7 @@ node-abi@^2.19.1, node-abi@^2.7.0: dependencies: semver "^5.4.1" -node-addon-api@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" - integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== - -node-addon-api@^3.0.0: +node-addon-api@^3.0.0, node-addon-api@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== @@ -6502,10 +6501,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-pty@0.10.0-beta17: - version "0.10.0-beta17" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" - integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== +node-pty@0.10.0-beta18: + version "0.10.0-beta18" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta18.tgz#7ed2d3f4a06b2b23fe2abdf5b41655e9dffc25d5" + integrity sha512-vpK4yB3A3VzgkvdOWegL7GcPapt45jfA4b3ejUe8k4RmqdWBRvFJngew8T3qAxmLhTkfo93psaN6izTlfkc6FA== dependencies: nan "^2.14.0" @@ -8368,14 +8367,14 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -roarr@^2.15.3: - version "2.15.4" - resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd" - integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A== +roarr@^2.14.5: + version "2.14.6" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.14.6.tgz#cebe8ad7ecbfd15bfa37b02dacf00809dd633912" + integrity sha512-qjbw0BEesKA+3XFBPt+KVe1PC/Z6ShfJ4wPlx2XifqH5h2Lj8/KQT5XJTsy3n1Es5kai+BwKALaECW3F70B1cg== dependencies: - boolean "^3.0.1" + boolean "^3.0.0" detect-node "^2.0.4" - globalthis "^1.0.1" + globalthis "^1.0.0" json-stringify-safe "^5.0.1" semver-compare "^1.0.0" sprintf-js "^1.1.2" @@ -8528,12 +8527,12 @@ semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -serialize-error@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" - integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== +serialize-error@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac" + integrity sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA== dependencies: - type-fest "^0.13.1" + type-fest "^0.8.0" serialize-javascript@^1.4.0: version "1.5.0" @@ -9573,12 +9572,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-fest@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" - integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== - -type-fest@^0.8.1: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -10083,12 +10077,12 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-windows-ca-certs@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.2.0.tgz#086f0f4de57e2760a35ac6920831bff246237115" - integrity sha512-YBrJRT0zos+Yb1Qdn73GD8QZr7pa2IE96b5Y1hmmp6XeR8aYB7Iiq5gDAF/+/AxL+caSR9KPZQ6jiYWh5biD7w== +vscode-windows-ca-certs@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.3.0.tgz#324e1f8ba842bbf048a39e7c0ee8fe655e9adfcc" + integrity sha512-CYrpCEKmAFQJoZNReOrelNL+VKyebOVRCqL9evrBlVcpWQDliliJgU5RggGS8FPGtQ3jAKLQt9frF0qlxYYPKA== dependencies: - node-addon-api "1.6.2" + node-addon-api "^3.0.2" vscode-windows-registry@1.0.3: version "1.0.3" @@ -10558,6 +10552,13 @@ yaserver@^0.2.0: resolved "https://registry.yarnpkg.com/yaserver/-/yaserver-0.2.0.tgz#56393027dc13f3c1bb89d20e0bd17269aa927802" integrity sha512-onsELrl7Y42M4P3T9R0N/ZJNJRu4cGwzhDyOWIFRMJvPUIrGKInYGh+DJBefrbr1qoyDu7DSCLl9BL5hSSVfDA== +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= + dependencies: + fd-slicer "~1.0.1" + yauzl@^2.10.0, yauzl@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From b0d4a08e3e047f98141a5bfbc4660cd60a362c29 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 5 Dec 2020 02:01:28 -0800 Subject: [PATCH 0631/1837] chore: bump distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6a714c44190..973e06910a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "11fd6f1230738827638f000f641d01b2b178db20", + "distro": "94d3db103b67147ef00f22eee17c18f9250abe21", "author": { "name": "Microsoft Corporation" }, @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From 7a7d27397a32b8d03b4cca85e02a3e0e89edca70 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 5 Dec 2020 07:03:28 -0800 Subject: [PATCH 0632/1837] chore: fix cache condition for native modules --- build/.cachesalt | 2 +- build/azure-pipelines/darwin/product-build-darwin.yml | 1 - build/azure-pipelines/linux/product-build-linux.yml | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/build/.cachesalt b/build/.cachesalt index a7a4d508274..661e359818e 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-11-30T16:21:34.566Z +2020-12-05T15:02:48.675Z diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index e2107fd73c9..28da2b70ee0 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -81,7 +81,6 @@ steps: npm install -g node-gyp@latest node-gyp --version displayName: Update node-gyp - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | set -e diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 5d7e8cdb24f..489842b3b39 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -74,7 +74,6 @@ steps: npm install -g node-gyp@latest node-gyp --version displayName: Update node-gyp - condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | set -e @@ -108,8 +107,9 @@ steps: set -e export CC=$(which gcc-4.8) export CXX=$(which g++-4.8) - cd remote - node-gyp rebuild + export npm_config_node_gyp=$(which node-gyp) + cd remote && rm -rf node_modules/ + yarn displayName: Rebuild remote modules with gcc-4.8 - script: | From 86d779284b6a817f6b071e946df0ec98c3cec534 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 5 Dec 2020 13:26:12 -0800 Subject: [PATCH 0633/1837] ci: fix condition for linux builds --- build/azure-pipelines/linux/product-build-linux.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 489842b3b39..6e56d99bf7d 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -74,9 +74,12 @@ steps: npm install -g node-gyp@latest node-gyp --version displayName: Update node-gyp + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - script: | set -e + export CC=$(which gcc-5) + export CXX=$(which g++-5) export npm_config_arch=$(NPM_ARCH) export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin @@ -111,6 +114,7 @@ steps: cd remote && rm -rf node_modules/ yarn displayName: Rebuild remote modules with gcc-4.8 + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - script: | set -e From eb189c703c711e327bac94d45a46b153601a6d73 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Sun, 6 Dec 2020 18:52:57 +0100 Subject: [PATCH 0634/1837] Fix #111946 --- resources/web/code-web.js | 4 +- .../userDataSync/common/extensionsSync.ts | 38 +++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/resources/web/code-web.js b/resources/web/code-web.js index 9be3bc2d811..5646d658ae5 100644 --- a/resources/web/code-web.js +++ b/resources/web/code-web.js @@ -380,7 +380,9 @@ async function handleRoot(req, res) { const webConfigJSON = { folderUri: folderUri, staticExtensions, - enableSyncByDefault: args['enable-sync'], + settingsSyncOptions: { + enabled: args['enable-sync'] + }, webWorkerExtensionHostIframeSrc: `${SCHEME}://${HOST}:${SECONDARY_PORT}/static/out/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html` }; if (args['wrap-iframe']) { diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index e716e1355f4..2158147262b 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -528,10 +528,32 @@ export class ExtensionsInitializer extends AbstractInitializer { } else { toInstall.names.push(extension.identifier.id); } + if (extension.disabled) { + toDisable.push(extension.identifier); + } } } } + // 1. Initialise already installed extensions state + for (const extensionToSync of installedExtensionsToSync) { + if (extensionToSync.state) { + const extensionState = JSON.parse(this.storageService.get(extensionToSync.identifier.id, StorageScope.GLOBAL) || '{}'); + forEach(extensionToSync.state, ({ key, value }) => extensionState[key] = value); + this.storageService.store(extensionToSync.identifier.id, JSON.stringify(extensionState), StorageScope.GLOBAL, StorageTarget.MACHINE); + } + } + + // 2. Initialise extensions enablement + if (toDisable.length) { + for (const identifier of toDisable) { + this.logService.trace(`Disabling extension...`, identifier.id); + await this.extensionEnablementService.disableExtension(identifier); + this.logService.info(`Disabling extension`, identifier.id); + } + } + + // 3. Install extensions if (toInstall.names.length || toInstall.uuids.length) { const galleryExtensions = (await this.galleryService.query({ ids: toInstall.uuids, names: toInstall.names, pageSize: toInstall.uuids.length + toInstall.names.length }, CancellationToken.None)).firstPage; for (const galleryExtension of galleryExtensions) { @@ -552,22 +574,6 @@ export class ExtensionsInitializer extends AbstractInitializer { } } - if (toDisable.length) { - for (const identifier of toDisable) { - this.logService.trace(`Enabling extension...`, identifier.id); - await this.extensionEnablementService.disableExtension(identifier); - this.logService.info(`Enabled extension`, identifier.id); - } - } - - for (const extensionToSync of installedExtensionsToSync) { - if (extensionToSync.state) { - const extensionState = JSON.parse(this.storageService.get(extensionToSync.identifier.id, StorageScope.GLOBAL) || '{}'); - forEach(extensionToSync.state, ({ key, value }) => extensionState[key] = value); - this.storageService.store(extensionToSync.identifier.id, JSON.stringify(extensionState), StorageScope.GLOBAL, StorageTarget.MACHINE); - } - } - return newlyEnabledExtensions; } From eeed0fd5692cfdf9d1d43795086d0a479f3269fd Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Sun, 6 Dec 2020 18:56:35 +0100 Subject: [PATCH 0635/1837] update distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 973e06910a8..13c521e2dec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "94d3db103b67147ef00f22eee17c18f9250abe21", + "distro": "1aaf2adfd4fd7c35c133724c4d97e103f2fa331f", "author": { "name": "Microsoft Corporation" }, @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file From fc9ff5d569b34222dcff2ca0bfdc62de86dbd112 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 5 Dec 2020 17:18:36 -0800 Subject: [PATCH 0636/1837] ci: avoid overwriting CC variables for arm arch --- build/azure-pipelines/linux/product-build-linux.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 6e56d99bf7d..6c9d24da74f 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -78,8 +78,11 @@ steps: - script: | set -e - export CC=$(which gcc-5) - export CXX=$(which g++-5) + if [ -z "$CC" || -z "$CXX" ] + then + export CC=$(which gcc-5) + export CXX=$(which g++-5) + fi export npm_config_arch=$(NPM_ARCH) export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin From f5da8e346fcf7c4820c85da1f9e253360c7699a4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:37:17 +0100 Subject: [PATCH 0637/1837] :lipsticky: async --- src/vs/base/node/pfs.ts | 6 ++-- .../quickinput/browser/quickInputList.ts | 3 +- src/vs/base/parts/storage/common/storage.ts | 22 +++++++------- src/vs/platform/files/common/files.ts | 4 +-- src/vs/platform/storage/node/storageIpc.ts | 4 +-- .../workspacesMainService.test.ts | 2 +- .../contrib/outline/browser/outlinePane.ts | 3 +- .../common/notificationService.ts | 4 +-- .../test/browser/workbenchTestServices.ts | 30 +++++++++---------- 9 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 3a17bd3fc78..fa07dcb9b7e 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -459,13 +459,13 @@ export function whenDeleted(path: string): Promise { export async function move(source: string, target: string): Promise { if (source === target) { - return Promise.resolve(); + return; } async function updateMtime(path: string): Promise { const stat = await lstat(path); if (stat.isDirectory() || stat.isSymbolicLink()) { - return Promise.resolve(); // only for files + return; // only for files } const fd = await promisify(fs.open)(path, 'a'); @@ -510,7 +510,7 @@ export async function copy(source: string, target: string, copiedSourcesIn?: { [ } if (copiedSources[source]) { - return Promise.resolve(); // escape when there are cycles (can happen with symlinks) + return; // escape when there are cycles (can happen with symlinks) } copiedSources[source] = true; // remember as copied diff --git a/src/vs/base/parts/quickinput/browser/quickInputList.ts b/src/vs/base/parts/quickinput/browser/quickInputList.ts index ba8bbd0239f..0973f0c1446 100644 --- a/src/vs/base/parts/quickinput/browser/quickInputList.ts +++ b/src/vs/base/parts/quickinput/browser/quickInputList.ts @@ -190,12 +190,11 @@ class ListElementRenderer implements IListRenderer { + const action = new Action(`id-${index}`, '', cssClasses, true, async () => { element.fireButtonTriggered({ button, item: element.item }); - return Promise.resolve(); }); action.tooltip = button.tooltip || ''; return action; diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts index 8b55819cc54..c2f5ff5a5cd 100644 --- a/src/vs/base/parts/storage/common/storage.ts +++ b/src/vs/base/parts/storage/common/storage.ts @@ -200,9 +200,9 @@ export class Storage extends Disposable implements IStorage { return parseInt(value, 10); } - set(key: string, value: string | boolean | number | null | undefined): Promise { + async set(key: string, value: string | boolean | number | null | undefined): Promise { if (this.state === StorageState.Closed) { - return Promise.resolve(); // Return early if we are already closed + return; // Return early if we are already closed } // We remove the key for undefined/null values @@ -216,7 +216,7 @@ export class Storage extends Disposable implements IStorage { // Return early if value already set const currentValue = this.cache.get(key); if (currentValue === valueStr) { - return Promise.resolve(); + return; } // Update in cache and pending @@ -231,15 +231,15 @@ export class Storage extends Disposable implements IStorage { return this.flushDelayer.trigger(() => this.flushPending()); } - delete(key: string): Promise { + async delete(key: string): Promise { if (this.state === StorageState.Closed) { - return Promise.resolve(); // Return early if we are already closed + return; // Return early if we are already closed } // Remove from cache and add to pending const wasDeleted = this.cache.delete(key); if (!wasDeleted) { - return Promise.resolve(); // Return early if value already deleted + return; // Return early if value already deleted } if (!this.pendingDeletes.has(key)) { @@ -257,7 +257,7 @@ export class Storage extends Disposable implements IStorage { async close(): Promise { if (this.state === StorageState.Closed) { - return Promise.resolve(); // return if already closed + return; // return if already closed } // Update state @@ -282,9 +282,9 @@ export class Storage extends Disposable implements IStorage { return this.pendingInserts.size > 0 || this.pendingDeletes.size > 0; } - private flushPending(): Promise { + private async flushPending(): Promise { if (!this.hasPending) { - return Promise.resolve(); // return early if nothing to do + return; // return early if nothing to do } // Get pending data @@ -305,9 +305,9 @@ export class Storage extends Disposable implements IStorage { }); } - whenFlushed(): Promise { + async whenFlushed(): Promise { if (!this.hasPending) { - return Promise.resolve(); // return early if nothing to do + return; // return early if nothing to do } return new Promise(resolve => this.whenFlushedCallbacks.push(resolve)); diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 4ae15434563..784bd056d94 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -947,9 +947,9 @@ export function etag(stat: { mtime: number | undefined, size: number | undefined return stat.mtime.toString(29) + stat.size.toString(31); } -export function whenProviderRegistered(file: URI, fileService: IFileService): Promise { +export async function whenProviderRegistered(file: URI, fileService: IFileService): Promise { if (fileService.canHandleResource(URI.from({ scheme: file.scheme }))) { - return Promise.resolve(); + return; } return new Promise(resolve => { diff --git a/src/vs/platform/storage/node/storageIpc.ts b/src/vs/platform/storage/node/storageIpc.ts index 8645255d9e7..67195995c28 100644 --- a/src/vs/platform/storage/node/storageIpc.ts +++ b/src/vs/platform/storage/node/storageIpc.ts @@ -200,12 +200,10 @@ export class GlobalStorageDatabaseChannelClient extends Disposable implements IS return this.channel.call('updateItems', serializableRequest); } - close(): Promise { + async close(): Promise { // when we are about to close, we start to ignore main-side changes since we close anyway dispose(this.onDidChangeItemsOnMainListener); - - return Promise.resolve(); // global storage is closed on the main side } dispose(): void { diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 07304aa32b0..59454446692 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -389,7 +389,7 @@ suite('WorkspacesMainService', () => { test.skip('rewriteWorkspaceFileForNewLocation (unc paths)', async () => { if (!isWindows) { - return Promise.resolve(); + return; } const workspaceLocation = path.join(os.tmpdir(), 'wsloc'); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index ab48b16b7ca..3062e937dce 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -149,10 +149,9 @@ class SimpleToggleAction extends Action { private readonly _listener: IDisposable; constructor(state: OutlineViewState, label: string, isChecked: () => boolean, callback: (action: SimpleToggleAction) => any, className?: string) { - super(`simple` + defaultGenerator.nextId(), label, className, true, () => { + super(`simple` + defaultGenerator.nextId(), label, className, true, async () => { this.checked = !this.checked; callback(this); - return Promise.resolve(); }); this.checked = isChecked(); this._listener = state.onDidChange(() => this.checked = isChecked()); diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index 70b48e53088..2c52dc75ffe 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -76,15 +76,13 @@ export class NotificationService extends Disposable implements INotificationServ const neverShowAgainAction = toDispose.add(new Action( 'workbench.notification.neverShowAgain', nls.localize('neverShowAgain', "Don't Show Again"), - undefined, true, () => { + undefined, true, async () => { // Close notification handle.close(); // Remember choice this.storageService.store(id, true, scope, StorageTarget.USER); - - return Promise.resolve(); })); // Insert as primary or secondary action diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 83f8f0d0e05..d3b078b1f08 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -446,16 +446,16 @@ export class TestLayoutService implements IWorkbenchLayoutService { isActivityBarHidden(): boolean { return false; } setActivityBarHidden(_hidden: boolean): void { } isSideBarHidden(): boolean { return false; } - setEditorHidden(_hidden: boolean): Promise { return Promise.resolve(); } - setSideBarHidden(_hidden: boolean): Promise { return Promise.resolve(); } + async setEditorHidden(_hidden: boolean): Promise { } + async setSideBarHidden(_hidden: boolean): Promise { } isPanelHidden(): boolean { return false; } - setPanelHidden(_hidden: boolean): Promise { return Promise.resolve(); } + async setPanelHidden(_hidden: boolean): Promise { } toggleMaximizedPanel(): void { } isPanelMaximized(): boolean { return false; } getMenubarVisibility(): MenuBarVisibility { throw new Error('not implemented'); } getSideBarPosition() { return 0; } getPanelPosition() { return 0; } - setPanelPosition(_position: PartPosition): Promise { return Promise.resolve(); } + async setPanelPosition(_position: PartPosition): Promise { } addClass(_clazz: string): void { } removeClass(_clazz: string): void { } getMaximumEditorDimensions(): Dimension { throw new Error('not implemented'); } @@ -631,10 +631,10 @@ export class TestEditorGroupView implements IEditorGroupView { isActive(_editor: IEditorInput): boolean { return false; } moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IMoveEditorOptions): void { } copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: ICopyEditorOptions): void { } - closeEditor(_editor?: IEditorInput, options?: ICloseEditorOptions): Promise { return Promise.resolve(); } - closeEditors(_editors: IEditorInput[] | ICloseEditorsFilter, options?: ICloseEditorOptions): Promise { return Promise.resolve(); } - closeAllEditors(options?: ICloseAllEditorsOptions): Promise { return Promise.resolve(); } - replaceEditors(_editors: IEditorReplacement[]): Promise { return Promise.resolve(); } + async closeEditor(_editor?: IEditorInput, options?: ICloseEditorOptions): Promise { } + async closeEditors(_editors: IEditorInput[] | ICloseEditorsFilter, options?: ICloseEditorOptions): Promise { } + async closeAllEditors(options?: ICloseAllEditorsOptions): Promise { } + async replaceEditors(_editors: IEditorReplacement[]): Promise { } pinEditor(_editor?: IEditorInput): void { } stickEditor(editor?: IEditorInput | undefined): void { } unstickEditor(editor?: IEditorInput | undefined): void { } @@ -870,7 +870,7 @@ export class TestFileService implements IFileService { return false; } - del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean }): Promise { return Promise.resolve(); } + async del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean }): Promise { } readonly watches: URI[] = []; watch(_resource: URI): IDisposable { @@ -894,13 +894,13 @@ export class TestBackupFileService implements IBackupFileService { hasBackups(): Promise { return Promise.resolve(false); } hasBackup(_resource: URI): Promise { return Promise.resolve(false); } hasBackupSync(resource: URI, versionId?: number): boolean { return false; } - registerResourceForBackup(_resource: URI): Promise { return Promise.resolve(); } - deregisterResourceForBackup(_resource: URI): Promise { return Promise.resolve(); } - backup(_resource: URI, _content?: ITextSnapshot, versionId?: number, meta?: T): Promise { return Promise.resolve(); } + async registerResourceForBackup(_resource: URI): Promise { } + async deregisterResourceForBackup(_resource: URI): Promise { } + async backup(_resource: URI, _content?: ITextSnapshot, versionId?: number, meta?: T): Promise { } getBackups(): Promise { return Promise.resolve([]); } resolve(_backup: URI): Promise | undefined> { return Promise.resolve(undefined); } - discardBackup(_resource: URI): Promise { return Promise.resolve(); } - discardBackups(): Promise { return Promise.resolve(); } + async discardBackup(_resource: URI): Promise { } + async discardBackups(): Promise { } parseBackupContent(textBufferFactory: ITextBufferFactory): string { const textBuffer = textBufferFactory.create(DefaultEndOfLine.LF); const lineCount = textBuffer.getLineCount(); @@ -925,7 +925,7 @@ export class TestLifecycleService implements ILifecycleService { private readonly _onShutdown = new Emitter(); get onShutdown(): Event { return this._onShutdown.event; } - when(): Promise { return Promise.resolve(); } + async when(): Promise { } fireShutdown(reason = ShutdownReason.QUIT): void { this._onWillShutdown.fire({ From 428d5b1d302e6bb3cdf5509a0258d09bb5b67f50 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:38:44 +0100 Subject: [PATCH 0638/1837] proxy - remove old proxy auth dialog //cc @joaomoreno --- build/gulpfile.vscode.js | 1 - src/vs/code/electron-main/app.ts | 9 +- src/vs/code/electron-main/auth.ts | 102 ------------------ src/vs/code/electron-sandbox/proxy/auth.html | 83 -------------- src/vs/code/electron-sandbox/proxy/auth.js | 48 --------- src/vs/platform/windows/common/windows.ts | 1 - .../browser/relauncher.contribution.ts | 7 -- .../electron-sandbox/desktop.contribution.ts | 6 -- 8 files changed, 2 insertions(+), 255 deletions(-) delete mode 100644 src/vs/code/electron-main/auth.ts delete mode 100644 src/vs/code/electron-sandbox/proxy/auth.html delete mode 100644 src/vs/code/electron-sandbox/proxy/auth.js diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 42a9c2b2709..bb8b2454a9b 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -80,7 +80,6 @@ const vscodeResources = [ 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', 'out-build/vs/code/electron-sandbox/issue/issueReporter.js', 'out-build/vs/code/electron-sandbox/processExplorer/processExplorer.js', - 'out-build/vs/code/electron-sandbox/proxy/auth.js', '!**/test/**' ]; diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 759c85bc747..4ac339bce4b 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -33,7 +33,6 @@ import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; import { getDelayedChannel, StaticRouter, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import product from 'vs/platform/product/common/product'; -import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { ProxyAuthHandler2 } from 'vs/code/electron-main/auth2'; import { FileProtocolHandler } from 'vs/code/electron-main/protocol'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -454,12 +453,8 @@ export class CodeApplication extends Disposable { this._register(server); } - // Setup Auth Handler (TODO@ben remove old auth handler eventually) - if (this.configurationService.getValue('window.enableExperimentalProxyLoginDialog') === false) { - this._register(new ProxyAuthHandler()); - } else { - this._register(appInstantiationService.createInstance(ProxyAuthHandler2)); - } + // Setup Auth Handler + this._register(appInstantiationService.createInstance(ProxyAuthHandler2)); // Open Windows const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient, fileProtocolHandler)); diff --git a/src/vs/code/electron-main/auth.ts b/src/vs/code/electron-main/auth.ts deleted file mode 100644 index b4096018623..00000000000 --- a/src/vs/code/electron-main/auth.ts +++ /dev/null @@ -1,102 +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 { localize } from 'vs/nls'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { Event } from 'vs/base/common/event'; -import { FileAccess } from 'vs/base/common/network'; -import { BrowserWindow, BrowserWindowConstructorOptions, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron'; - -type LoginEvent = { - event: ElectronEvent; - webContents: WebContents; - req: Request; - authInfo: AuthInfo; - cb: (username: string, password: string) => void; -}; - -type Credentials = { - username: string; - password: string; -}; - -export class ProxyAuthHandler extends Disposable { - - declare readonly _serviceBrand: undefined; - - private retryCount = 0; - - constructor() { - super(); - - this.registerListeners(); - } - - private registerListeners(): void { - const onLogin = Event.fromNodeEventEmitter(app, 'login', (event, webContents, req, authInfo, cb) => ({ event, webContents, req, authInfo, cb })); - this._register(onLogin(this.onLogin, this)); - } - - private onLogin({ event, authInfo, cb }: LoginEvent): void { - if (!authInfo.isProxy) { - return; - } - - if (this.retryCount++ > 1) { - return; - } - - event.preventDefault(); - - const opts: BrowserWindowConstructorOptions = { - alwaysOnTop: true, - skipTaskbar: true, - resizable: false, - width: 450, - height: 225, - show: true, - title: 'VS Code', - webPreferences: { - preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath, - sandbox: true, - contextIsolation: true, - enableWebSQL: false, - enableRemoteModule: false, - spellcheck: false, - devTools: false - } - }; - - const focusedWindow = BrowserWindow.getFocusedWindow(); - if (focusedWindow) { - opts.parent = focusedWindow; - opts.modal = true; - } - - const win = new BrowserWindow(opts); - const windowUrl = FileAccess.asBrowserUri('vs/code/electron-sandbox/proxy/auth.html', require); - const proxyUrl = `${authInfo.host}:${authInfo.port}`; - const title = localize('authRequire', "Proxy Authentication Required"); - const message = localize('proxyauth', "The proxy {0} requires authentication.", proxyUrl); - - const onWindowClose = () => cb('', ''); - win.on('close', onWindowClose); - - win.setMenu(null); - win.webContents.on('did-finish-load', () => { - const data = { title, message }; - win.webContents.send('vscode:openProxyAuthDialog', data); - }); - win.webContents.on('ipc-message', (event, channel, credentials: Credentials) => { - if (channel === 'vscode:proxyAuthResponse') { - const { username, password } = credentials; - cb(username, password); - win.removeListener('close', onWindowClose); - win.close(); - } - }); - win.loadURL(windowUrl.toString(true)); - } -} diff --git a/src/vs/code/electron-sandbox/proxy/auth.html b/src/vs/code/electron-sandbox/proxy/auth.html deleted file mode 100644 index 788b68fce72..00000000000 --- a/src/vs/code/electron-sandbox/proxy/auth.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - -

-
-

-
-

-

-

- - -

-
-
- - - - - diff --git a/src/vs/code/electron-sandbox/proxy/auth.js b/src/vs/code/electron-sandbox/proxy/auth.js deleted file mode 100644 index 5e0db3c2dc7..00000000000 --- a/src/vs/code/electron-sandbox/proxy/auth.js +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -const { ipcRenderer } = window.vscode; - -function promptForCredentials(data) { - return new Promise((c, e) => { - const $title = document.getElementById('title'); - const $username = document.getElementById('username'); - const $password = document.getElementById('password'); - const $form = document.getElementById('form'); - const $cancel = document.getElementById('cancel'); - const $message = document.getElementById('message'); - - function submit() { - c({ username: $username.value, password: $password.value }); - return false; - } - - function cancel() { - c({ username: '', password: '' }); - return false; - } - - $form.addEventListener('submit', submit); - $cancel.addEventListener('click', cancel); - - document.body.addEventListener('keydown', function (e) { - switch (e.keyCode) { - case 27: e.preventDefault(); e.stopPropagation(); return cancel(); - case 13: e.preventDefault(); e.stopPropagation(); return submit(); - } - }); - - $title.textContent = data.title; - $message.textContent = data.message; - $username.focus(); - }); -} - -ipcRenderer.on('vscode:openProxyAuthDialog', async (event, data) => { - const response = await promptForCredentials(data); - ipcRenderer.send('vscode:proxyAuthResponse', response); -}); diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index 40c952136ec..ca3e63d96ed 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -115,7 +115,6 @@ export interface IWindowSettings { enableMenuBarMnemonics: boolean; closeWhenEmpty: boolean; clickThroughInactive: boolean; - enableExperimentalProxyLoginDialog: boolean; } export function getTitleBarStyle(configurationService: IConfigurationService): 'native' | 'custom' { diff --git a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts index c5a10561fec..9f8bede88ca 100644 --- a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts +++ b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts @@ -36,7 +36,6 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo private updateMode: string | undefined; private debugConsoleWordWrap: boolean | undefined; private accessibilitySupport: 'on' | 'off' | 'auto' | undefined; - private enableExperimentalProxyLoginDialog = true; // default constructor( @IHostService private readonly hostService: IHostService, @@ -98,12 +97,6 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo changed = true; } } - - // Experimental proxy login dialog - if (typeof config.window?.enableExperimentalProxyLoginDialog === 'boolean' && config.window.enableExperimentalProxyLoginDialog !== this.enableExperimentalProxyLoginDialog) { - this.enableExperimentalProxyLoginDialog = config.window.enableExperimentalProxyLoginDialog; - changed = true; - } } // Notify only when changed and we are the focused window (avoids notification spam across windows) diff --git a/src/vs/workbench/electron-sandbox/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts index 63bc327faa9..9dd8fb5be0c 100644 --- a/src/vs/workbench/electron-sandbox/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -293,12 +293,6 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('window.clickThroughInactive', "If enabled, clicking on an inactive window will both activate the window and trigger the element under the mouse if it is clickable. If disabled, clicking anywhere on an inactive window will activate it only and a second click is required on the element."), 'included': isMacintosh - }, - 'window.enableExperimentalProxyLoginDialog': { - 'type': 'boolean', - 'default': true, - 'scope': ConfigurationScope.APPLICATION, - 'description': nls.localize('window.enableExperimentalProxyLoginDialog', "Enables a new login dialog for proxy authentication. Requires a restart to take effect."), } } }); From 25cbe382515cd2ca5911662429e08e0c922ebdec Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:39:39 +0100 Subject: [PATCH 0639/1837] proxy - rename proxy2 to proxy --- src/vs/code/electron-main/app.ts | 4 ++-- src/vs/code/electron-main/{auth2.ts => auth.ts} | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/vs/code/electron-main/{auth2.ts => auth.ts} (96%) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 4ac339bce4b..0ab687799f9 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -33,7 +33,7 @@ import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; import { getDelayedChannel, StaticRouter, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import product from 'vs/platform/product/common/product'; -import { ProxyAuthHandler2 } from 'vs/code/electron-main/auth2'; +import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { FileProtocolHandler } from 'vs/code/electron-main/protocol'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; @@ -454,7 +454,7 @@ export class CodeApplication extends Disposable { } // Setup Auth Handler - this._register(appInstantiationService.createInstance(ProxyAuthHandler2)); + this._register(appInstantiationService.createInstance(ProxyAuthHandler)); // Open Windows const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient, fileProtocolHandler)); diff --git a/src/vs/code/electron-main/auth2.ts b/src/vs/code/electron-main/auth.ts similarity index 96% rename from src/vs/code/electron-main/auth2.ts rename to src/vs/code/electron-main/auth.ts index 1b84d4bc4d9..b9669f983c7 100644 --- a/src/vs/code/electron-main/auth2.ts +++ b/src/vs/code/electron-main/auth.ts @@ -54,7 +54,7 @@ enum ProxyAuthState { LoginDialogShown } -export class ProxyAuthHandler2 extends Disposable { +export class ProxyAuthHandler extends Disposable { private static PROXY_CREDENTIALS_SERVICE_KEY = `${product.urlProtocol}.proxy-credentials`; @@ -153,7 +153,7 @@ export class ProxyAuthHandler2 extends Disposable { let storedUsername: string | undefined = undefined; let storedPassword: string | undefined = undefined; try { - const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, ProxyAuthHandler2.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash); + const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash); if (encryptedSerializedProxyCredentials) { const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials)); @@ -211,9 +211,9 @@ export class ProxyAuthHandler2 extends Disposable { try { if (reply.remember) { const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials)); - await this.nativeHostMainService.setPassword(undefined, ProxyAuthHandler2.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials); + await this.nativeHostMainService.setPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials); } else { - await this.nativeHostMainService.deletePassword(undefined, ProxyAuthHandler2.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash); + await this.nativeHostMainService.deletePassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash); } } catch (error) { this.logService.error(error); // handle gracefully From 878bf135043770f5e2270378b2376bc5e3f8deac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:42:17 +0100 Subject: [PATCH 0640/1837] debt - shuffle some electron-main code to better layers --- src/vs/code/electron-main/app.ts | 21 +++++++--------- src/vs/code/electron-main/main.ts | 6 ++--- src/vs/code/electron-main/sharedProcess.ts | 11 ++++---- src/vs/code/electron-main/window.ts | 3 ++- .../electron-main/extensionHostDebugIpc.ts | 2 +- .../{dialogs.ts => dialogMainService.ts} | 0 .../issue/electron-main/issueMainService.ts | 2 +- .../launch/electron-main/launchMainService.ts | 25 +++++++++---------- .../platform/menubar/electron-main/menubar.ts | 2 +- .../electron-main/nativeHostMainService.ts | 4 +-- .../windows/{node => electron-main}/window.ts | 0 .../platform/windows/electron-main/windows.ts | 2 +- .../electron-main/windowsMainService.ts | 4 +-- .../{node => electron-main}/window.test.ts | 2 +- .../electron-main/windowsStateStorage.test.ts | 2 -- .../electron-main/workspacesMainService.ts | 4 +-- .../workspacesMainService.test.ts | 2 +- 17 files changed, 44 insertions(+), 48 deletions(-) rename src/vs/platform/dialogs/electron-main/{dialogs.ts => dialogMainService.ts} (100%) rename src/vs/platform/windows/{node => electron-main}/window.ts (100%) rename src/vs/platform/windows/test/{node => electron-main}/window.test.ts (98%) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 0ab687799f9..6eb685b7926 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -7,7 +7,7 @@ import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindo import { IProcessEnvironment, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { resolveShellEnv } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; @@ -70,7 +70,7 @@ import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/ext import { ElectronExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/electron-main/extensionHostDebugIpc'; import { INativeHostMainService, NativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService'; import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService'; -import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { withNullAsUndefined } from 'vs/base/common/types'; import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels'; import { WebviewMainService } from 'vs/platform/webview/electron-main/webviewMainService'; @@ -897,7 +897,12 @@ export class CodeApplication extends Disposable { this.lifecycleMainService.phase = LifecycleMainPhase.AfterWindowOpen; // Remote Authorities - this.handleRemoteAuthorities(); + protocol.registerHttpProtocol(Schemas.vscodeRemoteResource, (request, callback) => { + callback({ + url: request.url.replace(/^vscode-remote-resource:/, 'http:'), + method: request.method + }); + }); // Initialize update service const updateService = accessor.get(IUpdateService); @@ -929,19 +934,11 @@ export class CodeApplication extends Disposable { '}' ]; const newArgvString = argvString.substring(0, argvString.length - 2).concat(',\n', additionalArgvContent.join('\n')); + await this.fileService.writeFile(this.environmentService.argvResource, VSBuffer.fromString(newArgvString)); } } catch (error) { this.logService.error(error); } } - - private handleRemoteAuthorities(): void { - protocol.registerHttpProtocol(Schemas.vscodeRemoteResource, (request, callback) => { - callback({ - url: request.url.replace(/^vscode-remote-resource:/, 'http:'), - method: request.method - }); - }); - } } diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 783ac6fb565..38464e58e5c 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -5,7 +5,8 @@ import 'vs/platform/update/common/update.config.contribution'; import { app, dialog } from 'electron'; -import * as fs from 'fs'; +import { unlinkSync } from 'fs'; +import { localize } from 'vs/nls'; import { isWindows, IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import product from 'vs/platform/product/common/product'; import { parseMainProcessArgv, addArg } from 'vs/platform/environment/node/argvHelper'; @@ -29,7 +30,6 @@ import { ConfigurationService } from 'vs/platform/configuration/common/configura import { IRequestService } from 'vs/platform/request/common/request'; import { RequestMainService } from 'vs/platform/request/electron-main/requestMainService'; import { CodeApplication } from 'vs/code/electron-main/app'; -import { localize } from 'vs/nls'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { BufferLogService } from 'vs/platform/log/common/bufferLog'; @@ -256,7 +256,7 @@ class CodeMain { // let's delete it, since we can't connect to it and then // retry the whole thing try { - fs.unlinkSync(environmentService.mainIPCHandle); + unlinkSync(environmentService.mainIPCHandle); } catch (error) { logService.warn('Could not delete obsolete instance handle', error); diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index dd721db92ad..1329bd72590 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -17,12 +17,11 @@ import { FileAccess } from 'vs/base/common/network'; export class SharedProcess implements ISharedProcess { - private barrier = new Barrier(); + private readonly barrier = new Barrier(); + private readonly _whenReady: Promise; private window: BrowserWindow | null = null; - private readonly _whenReady: Promise; - constructor( private readonly machineId: string, private userEnv: NodeJS.ProcessEnv, @@ -52,6 +51,7 @@ export class SharedProcess implements ISharedProcess { disableBlinkFeatures: 'Auxclick' // do NOT change, allows us to identify this window as shared-process in the process explorer } }); + const config = { appRoot: this.environmentService.appRoot, machineId: this.machineId, @@ -110,7 +110,8 @@ export class SharedProcess implements ISharedProcess { }, 0); }); - return new Promise(c => { + return new Promise(resolve => { + // send payload once shared process is ready to receive it disposables.add(Event.once(Event.fromNodeEventEmitter(ipcMain, 'vscode:shared-process->electron-main=ready-for-payload', ({ sender }: { sender: WebContents }) => sender))(sender => { sender.send('vscode:electron-main->shared-process=payload', { @@ -125,7 +126,7 @@ export class SharedProcess implements ISharedProcess { disposables.add(toDisposable(() => sender.send('vscode:electron-main->shared-process=exit'))); // complete IPC-ready promise when shared process signals this to us - ipcMain.once('vscode:shared-process->electron-main=ipc-ready', () => c(undefined)); + ipcMain.once('vscode:shared-process->electron-main=ipc-ready', () => resolve(undefined)); })); }); } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index f6b98e72c98..e09fb03efd2 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -28,7 +28,7 @@ import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/commo import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService'; import { RunOnceScheduler } from 'vs/base/common/async'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; @@ -648,6 +648,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.currentMenuBarVisibility = newMenuBarVisibility; this.setMenuBarVisibility(newMenuBarVisibility); } + // Do not set to empty configuration at startup if setting is empty to not override configuration through CLI options: const env = process.env; let newHttpProxy = (this.configurationService.getValue('http.proxy') || '').trim() diff --git a/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts b/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts index d05bd7ca0c4..7cc40f9086d 100644 --- a/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts +++ b/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts @@ -9,7 +9,7 @@ import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { createServer, AddressInfo } from 'net'; import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; export class ElectronExtensionHostDebugBroadcastChannel extends ExtensionHostDebugBroadcastChannel { diff --git a/src/vs/platform/dialogs/electron-main/dialogs.ts b/src/vs/platform/dialogs/electron-main/dialogMainService.ts similarity index 100% rename from src/vs/platform/dialogs/electron-main/dialogs.ts rename to src/vs/platform/dialogs/electron-main/dialogMainService.ts diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index da98e2f94f6..1279430a182 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -17,7 +17,7 @@ import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowState } from 'vs/platform/windows/electron-main/windows'; import { listProcesses } from 'vs/base/node/ps'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows'; import { FileAccess } from 'vs/base/common/network'; diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 9b3d6566394..61e66f0fd6a 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -9,7 +9,7 @@ import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWindowSettings } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { whenDeleted } from 'vs/base/node/pfs'; import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; @@ -113,7 +113,7 @@ export class LaunchMainService implements ILaunchMainService { } } - private startOpenWindow(args: NativeParsedArgs, userEnv: IProcessEnvironment): Promise { + private async startOpenWindow(args: NativeParsedArgs, userEnv: IProcessEnvironment): Promise { const context = isLaunchedFromCli(userEnv) ? OpenContext.CLI : OpenContext.DESKTOP; let usedWindows: ICodeWindow[] = []; @@ -205,17 +205,15 @@ export class LaunchMainService implements ILaunchMainService { whenDeleted(waitMarkerFileURI.fsPath) ]).then(() => undefined, () => undefined); } - - return Promise.resolve(undefined); } - getMainProcessId(): Promise { + async getMainProcessId(): Promise { this.logService.trace('Received request for process ID from other instance.'); - return Promise.resolve(process.pid); + return process.pid; } - getMainProcessInfo(): Promise { + async getMainProcessInfo(): Promise { this.logService.trace('Received request for main process info from other instance.'); const windows: IWindowInfo[] = []; @@ -228,18 +226,18 @@ export class LaunchMainService implements ILaunchMainService { } }); - return Promise.resolve({ + return { mainPID: process.pid, mainArguments: process.argv.slice(1), windows, screenReader: !!app.accessibilitySupportEnabled, gpuFeatureStatus: app.getGPUFeatureStatus() - }); + }; } - getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]> { + async getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]> { const windows = this.windowsMainService.getWindows(); - const promises: Promise[] = windows.map(window => { + const diagnostics: Array = await Promise.all(windows.map(window => { return new Promise((resolve) => { const remoteAuthority = window.remoteAuthority; if (remoteAuthority) { @@ -267,9 +265,9 @@ export class LaunchMainService implements ILaunchMainService { resolve(undefined); } }); - }); + })); - return Promise.all(promises).then(diagnostics => diagnostics.filter((x): x is IRemoteDiagnosticInfo | IRemoteDiagnosticError => !!x)); + return diagnostics.filter((x): x is IRemoteDiagnosticInfo | IRemoteDiagnosticError => !!x); } private getFolderURIs(window: ICodeWindow): URI[] { @@ -296,6 +294,7 @@ export class LaunchMainService implements ILaunchMainService { private codeWindowToInfo(window: ICodeWindow): IWindowInfo { const folderURIs = this.getFolderURIs(window); + return this.browserWindowToInfo(window.win, folderURIs, window.remoteAuthority); } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 90fba9c3fb1..215be10e210 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -8,7 +8,7 @@ import { isMacintosh, language } from 'vs/base/common/platform'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, KeyboardEvent } from 'electron'; import { getTitleBarStyle, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService, StateType } from 'vs/platform/update/common/update'; diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index e24efa83cf1..57b2a5c8822 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -6,7 +6,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme } from 'electron'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; @@ -15,7 +15,7 @@ import { ICommonNativeHostService, IOSProperties, IOSStatistics } from 'vs/platf import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { AddFirstParameterToFunctions } from 'vs/base/common/types'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { dirExists } from 'vs/base/node/pfs'; import { URI } from 'vs/base/common/uri'; import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/platform/windows/node/window.ts b/src/vs/platform/windows/electron-main/window.ts similarity index 100% rename from src/vs/platform/windows/node/window.ts rename to src/vs/platform/windows/electron-main/window.ts diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 83eccca73c4..e77f247e08a 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IWindowOpenable, IOpenEmptyWindowOptions, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/node/window'; +import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 6bcedb5c761..0fe8e924f00 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -18,7 +18,7 @@ import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMai import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri, OpenContext } from 'vs/platform/windows/node/window'; +import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri, OpenContext } from 'vs/platform/windows/electron-main/window'; import { Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode, IOpenEmptyConfiguration } from 'vs/platform/windows/electron-main/windows'; @@ -34,7 +34,7 @@ import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { withNullAsUndefined } from 'vs/base/common/types'; import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware } from 'vs/base/common/extpath'; import { CharCode } from 'vs/base/common/charCode'; diff --git a/src/vs/platform/windows/test/node/window.test.ts b/src/vs/platform/windows/test/electron-main/window.test.ts similarity index 98% rename from src/vs/platform/windows/test/node/window.test.ts rename to src/vs/platform/windows/test/electron-main/window.test.ts index 576d30d134a..b8135be8b42 100644 --- a/src/vs/platform/windows/test/node/window.test.ts +++ b/src/vs/platform/windows/test/electron-main/window.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import * as path from 'vs/base/common/path'; -import { IBestWindowOrFolderOptions, IWindowContext, findBestWindowOrFolderForFile, OpenContext } from 'vs/platform/windows/node/window'; +import { IBestWindowOrFolderOptions, IWindowContext, findBestWindowOrFolderForFile, OpenContext } from 'vs/platform/windows/electron-main/window'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { URI } from 'vs/base/common/uri'; diff --git a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts b/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts index 419caee0d71..e776f85c227 100644 --- a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts +++ b/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts @@ -286,7 +286,5 @@ suite('Windows State Storing', () => { } }; assertEqualWindowsState(expected, windowsState, 'v1_32_empty_window'); - }); - }); diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index f4fa065fbb5..d5ff4b46d4b 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -25,8 +25,8 @@ import product from 'vs/platform/product/common/product'; import { MessageBoxOptions, BrowserWindow } from 'electron'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; -import { findWindowOnWorkspace } from 'vs/platform/windows/node/window'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; +import { findWindowOnWorkspace } from 'vs/platform/windows/electron-main/window'; export const IWorkspacesMainService = createDecorator('workspacesMainService'); diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 59454446692..e8510db9a24 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -18,7 +18,7 @@ import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { isWindows } from 'vs/base/common/platform'; import { normalizeDriveLetter } from 'vs/base/common/labels'; import { dirname, joinPath } from 'vs/base/common/resources'; -import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { IBackupMainService, IWorkspaceBackupInfo } from 'vs/platform/backup/electron-main/backup'; import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; From 04b9a571b84c58cc57c7f40ec2478495d22e3fe2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:42:49 +0100 Subject: [PATCH 0641/1837] fix #111898 on master --- src/vs/workbench/browser/actions/workspaceCommands.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/actions/workspaceCommands.ts b/src/vs/workbench/browser/actions/workspaceCommands.ts index 92794740270..7f43e0fb0e5 100644 --- a/src/vs/workbench/browser/actions/workspaceCommands.ts +++ b/src/vs/workbench/browser/actions/workspaceCommands.ts @@ -131,7 +131,7 @@ interface IOpenFolderAPICommandOptions { CommandsRegistry.registerCommand({ id: 'vscode.openFolder', - handler: (accessor: ServicesAccessor, uri?: URI, arg: boolean | IOpenFolderAPICommandOptions = {}) => { + handler: (accessor: ServicesAccessor, uri?: URI, arg?: boolean | IOpenFolderAPICommandOptions) => { const commandService = accessor.get(ICommandService); // Be compatible to previous args by converting to options @@ -141,15 +141,15 @@ CommandsRegistry.registerCommand({ // Without URI, ask to pick a folder or workpsace to open if (!uri) { - return commandService.executeCommand('_files.pickFolderAndOpen', { forceNewWindow: arg.forceNewWindow }); + return commandService.executeCommand('_files.pickFolderAndOpen', { forceNewWindow: arg?.forceNewWindow }); } uri = URI.revive(uri); const options: IOpenWindowOptions = { - forceNewWindow: arg.forceNewWindow, - forceReuseWindow: arg.forceReuseWindow, - noRecentEntry: arg.noRecentEntry + forceNewWindow: arg?.forceNewWindow, + forceReuseWindow: arg?.forceReuseWindow, + noRecentEntry: arg?.noRecentEntry }; const uriToOpen: IWindowOpenable = (hasWorkspaceFileExtension(uri) || uri.scheme === Schemas.untitled) ? { workspaceUri: uri } : { folderUri: uri }; From 267188e90de303bccb6fa031ff0c0e8f724dab39 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 11:45:32 +0100 Subject: [PATCH 0642/1837] highlightModifiedTabs and pinned tabs issue (fix #111641) --- .../parts/editor/media/tabstitlecontrol.css | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index a9158b796e4..637279fe48c 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -3,6 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* + ################################### z-index explainer ################################### + + Tabs have various levels of z-index depending on state, typically: + - scrollbar should be above all + - sticky (compact, shrink) tabs need to be above non-sticky tabs for scroll under effect + including non-sticky tabs-top borders, otherwise these borders would not scroll under + (https://github.com/microsoft/vscode/issues/111641) + - bottom-border needs to be above tabs bottom border to win but also support sticky tabs + (https://github.com/microsoft/vscode/issues/99084) <- this currently cannot be done and + is still broken. putting sticky-tabs above tabs bottom border would not render this + border at all for sticky tabs. + + On top of that there is 2 borders with a z-index for a general border below tabs + - tabs bottom border + - editor title bottom border (when breadcrumbs are disabled, this border will appear + same as tabs bottom border) + + The following tabls shows the current stacking order: + + [z-index] [kind] + 7 scrollbar + 6 active-tab border-bottom + 5 tabs, title border bottom + 4 sticky-tab + 2 active/dirty-tab border top + 0 tab + + ########################################################################################## +*/ + /* Title Container */ .monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container { @@ -30,7 +61,7 @@ } .monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element .scrollbar { - z-index: 3; /* on top of tabs */ + z-index: 7; cursor: default; } @@ -89,7 +120,7 @@ /** Sticky compact/shrink tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */ position: sticky; - z-index: 1; + z-index: 4; /** Sticky compact/shrink tabs are even and never grow */ flex-basis: 0; @@ -167,24 +198,26 @@ display: block; position: absolute; left: 0; - z-index: 6; /* over possible title border */ pointer-events: none; width: 100%; } .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container { + z-index: 2; top: 0; height: 1px; background-color: var(--tab-border-top-color); } .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container { + z-index: 6; bottom: 0; height: 1px; background-color: var(--tab-border-bottom-color); } .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container { + z-index: 2; top: 0; height: 2px; background-color: var(--tab-dirty-border-top-color); From ea0b7fd29af51136688960c9ded4209964e3fe99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 7 Dec 2020 11:57:52 +0100 Subject: [PATCH 0643/1837] Revert "build: create asset should still try to add asset" This reverts commit 5e350b1b79675cecdff224eb00f7bf62ae8789fc. --- build/azure-pipelines/common/createAsset.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index 127993e6230..d7e62629cb8 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -93,12 +93,16 @@ async function main(): Promise { const blobExists = await doesAssetExist(blobService, quality, blobName); if (blobExists) { - console.log(`Blob ${quality}, ${blobName} already exists, not uploading again.`); - } else { - await uploadBlob(blobService, quality, blobName, filePath, fileName); - console.log('Blobs successfully uploaded.'); + console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`); + return; } + console.log('Uploading blobs to Azure storage...'); + + await uploadBlob(blobService, quality, blobName, filePath, fileName); + + console.log('Blobs successfully uploaded.'); + const asset: Asset = { platform, type, From 64f63a3dd708a8da72905a1126aa44b26d293a81 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Dec 2020 12:20:59 +0100 Subject: [PATCH 0644/1837] Fix #108266 --- src/vs/editor/contrib/hover/modesContentHover.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index ad2d6b27263..57f95fe179f 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Color, RGBA } from 'vs/base/common/color'; import { IMarkdownString, MarkdownString, isEmptyMarkdownString, markedStringsEquals } from 'vs/base/common/htmlContent'; -import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; @@ -606,7 +606,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this.recentMarkerCodeActionsInfo = undefined; } } - const updatePlaceholderDisposable = disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 64)); + const updatePlaceholderDisposable = this.recentMarkerCodeActionsInfo && !this.recentMarkerCodeActionsInfo.hasCodeActions ? Disposable.None : disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 200)); const codeActionsPromise = this.getCodeActions(markerHover.marker); disposables.add(toDisposable(() => codeActionsPromise.cancel())); codeActionsPromise.then(actions => { From 3835563e123aefda53337fce7b215cc81a535047 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Dec 2020 13:47:20 +0100 Subject: [PATCH 0645/1837] Fix #112012 --- src/vs/workbench/browser/web.main.ts | 6 ++--- .../electron-browser/desktop.main.ts | 4 ++-- .../electron-sandbox/desktop.main.ts | 4 ++-- .../sandbox.simpleservices.ts | 5 +++- .../configuration/browser/configuration.ts | 4 ++++ .../browser/configurationService.ts | 23 +++++++++++++++---- .../configuration/common/configuration.ts | 11 +++++++++ 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index e7d260b00ce..20df4472969 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -24,7 +24,7 @@ import { IFileService, IFileSystemProvider } from 'vs/platform/files/common/file import { FileService } from 'vs/platform/files/common/fileService'; import { Schemas } from 'vs/base/common/network'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { onUnexpectedError } from 'vs/base/common/errors'; import { setFullscreen } from 'vs/base/browser/browser'; import { isIOS, isMacintosh } from 'vs/base/common/platform'; @@ -158,7 +158,7 @@ class BrowserMain extends Disposable { }, undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); } - private async initServices(): Promise<{ serviceCollection: ServiceCollection, configurationService: IConfigurationService, logService: ILogService, storageService: BrowserStorageService }> { + private async initServices(): Promise<{ serviceCollection: ServiceCollection, configurationService: IWorkbenchConfigurationService, logService: ILogService, storageService: BrowserStorageService }> { const serviceCollection = new ServiceCollection(); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -212,7 +212,7 @@ class BrowserMain extends Disposable { serviceCollection.set(IWorkspaceContextService, service); // Configuration - serviceCollection.set(IConfigurationService, service); + serviceCollection.set(IWorkbenchConfigurationService, service); return service; }), diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index 5f159a168dc..fdcd679f8b8 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -28,7 +28,7 @@ import { Schemas } from 'vs/base/common/network'; import { sanitizeFilePath } from 'vs/base/common/extpath'; import { GlobalStorageDatabaseChannelClient } from 'vs/platform/storage/node/storageIpc'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { Disposable } from 'vs/base/common/lifecycle'; import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver'; @@ -270,7 +270,7 @@ class DesktopMain extends Disposable { serviceCollection.set(IWorkspaceContextService, service); // Configuration - serviceCollection.set(IConfigurationService, service); + serviceCollection.set(IWorkbenchConfigurationService, service); return service; }), diff --git a/src/vs/workbench/electron-sandbox/desktop.main.ts b/src/vs/workbench/electron-sandbox/desktop.main.ts index eddd5ab64aa..dc8f60572cc 100644 --- a/src/vs/workbench/electron-sandbox/desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/desktop.main.ts @@ -16,7 +16,7 @@ import { reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspa import { ILogService } from 'vs/platform/log/common/log'; import { Schemas } from 'vs/base/common/network'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { Disposable } from 'vs/base/common/lifecycle'; import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; @@ -239,7 +239,7 @@ class DesktopMain extends Disposable { serviceCollection.set(IWorkspaceContextService, service); // Configuration - serviceCollection.set(IConfigurationService, new SimpleConfigurationService()); + serviceCollection.set(IWorkbenchConfigurationService, new SimpleConfigurationService()); return service; }), diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index ada7a23fa4d..f7112d49068 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -56,6 +56,7 @@ import { Schemas } from 'vs/base/common/network'; import { BrowserKeyboardLayoutService } from 'vs/workbench/services/keybinding/browser/keyboardLayoutService'; import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; //#region Environment @@ -191,7 +192,9 @@ export class SimpleStorageService extends InMemoryStorageService { } //#region Configuration -export class SimpleConfigurationService extends BaseSimpleConfigurationService { } +export class SimpleConfigurationService extends BaseSimpleConfigurationService implements IWorkbenchConfigurationService { + async whenRemoteConfigurationLoaded() { } +} //#endregion diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 973ef52ffc5..87318b454bb 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -187,6 +187,9 @@ export class RemoteUserConfiguration extends Disposable { private readonly _onDidChangeConfiguration: Emitter = this._register(new Emitter()); public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; + private readonly _onDidInitialize = this._register(new Emitter()); + public readonly onDidInitialize = this._onDidInitialize.event; + constructor( remoteAuthority: string, configurationCache: IConfigurationCache, @@ -205,6 +208,7 @@ export class RemoteUserConfiguration extends Disposable { this._userConfiguration.dispose(); this._userConfiguration = userConfiguration; this.onDidUserConfigurationChange(configurationModel); + this._onDidInitialize.fire(configurationModel); } }); } diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 7a1b2cd45b1..49a78f4d185 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -12,9 +12,9 @@ import { Queue, Barrier, runWhenIdle } from 'vs/base/common/async'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IWorkspaceContextService, Workspace as BaseWorkspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent, WorkspaceFolder, toWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ConfigurationModel, DefaultConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent, mergeChanges } from 'vs/platform/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData, IConfigurationService, IConfigurationValue, IConfigurationChange } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData, IConfigurationValue, IConfigurationChange } from 'vs/platform/configuration/common/configuration'; import { Configuration } from 'vs/workbench/services/configuration/common/configurationModels'; -import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId, IConfigurationCache, machineSettingsSchemaId, LOCAL_MACHINE_SCOPES } from 'vs/workbench/services/configuration/common/configuration'; +import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId, IConfigurationCache, machineSettingsSchemaId, LOCAL_MACHINE_SCOPES, IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings, machineOverridableSettings } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; @@ -38,11 +38,12 @@ class Workspace extends BaseWorkspace { initialized: boolean = false; } -export class WorkspaceService extends Disposable implements IConfigurationService, IWorkspaceContextService { +export class WorkspaceService extends Disposable implements IWorkbenchConfigurationService, IWorkspaceContextService { public _serviceBrand: undefined; private workspace!: Workspace; + private initRemoteUserConfigurationBarrier: Barrier; private completeWorkspaceBarrier: Barrier; private readonly configurationCache: IConfigurationCache; private _configuration: Configuration; @@ -93,6 +94,7 @@ export class WorkspaceService extends Disposable implements IConfigurationServic configurationRegistry.registerDefaultConfigurations([environmentService.options.configurationDefaults]); } + this.initRemoteUserConfigurationBarrier = new Barrier(); this.completeWorkspaceBarrier = new Barrier(); this.defaultConfiguration = new DefaultConfigurationModel(); this.configurationCache = configurationCache; @@ -104,9 +106,16 @@ export class WorkspaceService extends Disposable implements IConfigurationServic this.localUserConfiguration = this._register(new UserConfiguration(environmentService.settingsResource, remoteAuthority ? LOCAL_MACHINE_SCOPES : undefined, fileService)); this._register(this.localUserConfiguration.onDidChangeConfiguration(userConfiguration => this.onLocalUserConfigurationChanged(userConfiguration))); if (remoteAuthority) { - this.remoteUserConfiguration = this._register(new RemoteUserConfiguration(remoteAuthority, configurationCache, fileService, remoteAgentService)); - this._register(this.remoteUserConfiguration.onDidChangeConfiguration(userConfiguration => this.onRemoteUserConfigurationChanged(userConfiguration))); + const remoteUserConfiguration = this.remoteUserConfiguration = this._register(new RemoteUserConfiguration(remoteAuthority, configurationCache, fileService, remoteAgentService)); + this._register(remoteUserConfiguration.onDidInitialize(remoteUserConfigurationModel => { + this._register(remoteUserConfiguration.onDidChangeConfiguration(remoteUserConfigurationModel => this.onRemoteUserConfigurationChanged(remoteUserConfigurationModel))); + this.onRemoteUserConfigurationChanged(remoteUserConfigurationModel); + this.initRemoteUserConfigurationBarrier.open(); + })); + } else { + this.initRemoteUserConfigurationBarrier.open(); } + this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService)); this._register(this.workspaceConfiguration.onDidUpdateConfiguration(() => { this.onWorkspaceConfigurationChanged().then(() => { @@ -336,6 +345,10 @@ export class WorkspaceService extends Disposable implements IConfigurationServic return this._configuration.keys(); } + public async whenRemoteConfigurationLoaded(): Promise { + await this.initRemoteUserConfigurationBarrier.wait(); + } + async initialize(arg: IWorkspaceInitializationPayload): Promise { mark('willInitWorkspaceService'); diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index edec7c0032b..e54d141f447 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -5,6 +5,8 @@ import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { URI } from 'vs/base/common/uri'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const FOLDER_CONFIG_FOLDER_NAME = '.vscode'; export const FOLDER_SETTINGS_NAME = 'settings'; @@ -43,4 +45,13 @@ export interface IConfigurationCache { } +export const IWorkbenchConfigurationService = createDecorator('configurationService'); +export interface IWorkbenchConfigurationService extends IConfigurationService { + /** + * A promise that resolves when the remote configuration is loaded in a remote window. + * The promise is resolved immediately if the window is not remote. + */ + whenRemoteConfigurationLoaded(): Promise; +} + export const TASKS_DEFAULT = '{\n\t\"version\": \"2.0.0\",\n\t\"tasks\": []\n}'; From c4d77ea6193e639dfad1431fe92a6c611d697a28 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Dec 2020 14:02:32 +0100 Subject: [PATCH 0646/1837] #89559 Set logsPath in window configuration --- src/vs/code/electron-main/window.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index e09fb03efd2..4379b1a8d6e 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -781,6 +781,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { windowConfiguration.windowId = this._win.id; windowConfiguration.sessionId = `window:${this._win.id}`; windowConfiguration.logLevel = this.logService.getLevel(); + windowConfiguration.logsPath = this.environmentService.logsPath; // Set zoomlevel const windowConfig = this.configurationService.getValue('window'); From 66aab34216f488c803b49ff14d50dec90147ad6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 7 Dec 2020 14:42:27 +0100 Subject: [PATCH 0647/1837] retry createAsset sproc due to ECONNRESET --- build/azure-pipelines/common/createAsset.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index d7e62629cb8..666bf05bf68 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -66,6 +66,20 @@ function getEnv(name: string): string { return result; } +async function retry(fn: () => Promise): Promise { + for (let run = 1; run <= 10; run++) { + try { + return await fn(); + } catch (err) { + if (!/ECONNRESET/.test(err.message)) { + throw err; + } + } + } + + throw new Error('Retried too many times'); +} + async function main(): Promise { const [, , platform, type, fileName, filePath] = process.argv; const quality = getEnv('VSCODE_QUALITY'); @@ -121,7 +135,7 @@ async function main(): Promise { const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); const scripts = client.database('builds').container(quality).scripts; - await scripts.storedProcedure('createAsset').execute('', [commit, asset, true]); + await retry(() => scripts.storedProcedure('createAsset').execute('', [commit, asset, true])); } main().then(() => { From 36628d73b916f872ad2cf3679b38d6a1b32f44ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 7 Dec 2020 15:02:48 +0100 Subject: [PATCH 0648/1837] add exponential backoff --- build/azure-pipelines/common/createAsset.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index 666bf05bf68..b6d4c966f67 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -74,6 +74,9 @@ async function retry(fn: () => Promise): Promise { if (!/ECONNRESET/.test(err.message)) { throw err; } + + // maximum delay is 10th retry: ~3 seconds + await new Promise(c => setTimeout(c, (Math.random() * 200) + (50 * Math.pow(1.5, run)))); } } From ffdc1096fa5a1f16a01eff8a6d666100f13b181b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 15:16:49 +0100 Subject: [PATCH 0649/1837] Windows - Taskbar entry context menu is empty (fix #111177) --- .../workspaces/electron-main/workspacesHistoryMainService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index 7a5baa225e5..e0609a560b2 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -370,7 +370,7 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa return { type: 'task', title, - description, + description: description.substr(0, 255), // https://github.com/microsoft/vscode/issues/111177 program: process.execPath, args, iconPath: 'explorer.exe', // simulate folder icon From de22e951f9ed9f985aa1d6773d3a2d2c43a576d6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Dec 2020 15:22:04 +0100 Subject: [PATCH 0650/1837] more cleanup for #111177 --- .../workspacesHistoryMainService.ts | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index e0609a560b2..91d62d0ff95 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -330,57 +330,53 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa }); // Recent Workspaces - try { - if (this.getRecentlyOpened().workspaces.length > 0) { + if (this.getRecentlyOpened().workspaces.length > 0) { - // The user might have meanwhile removed items from the jump list and we have to respect that - // so we need to update our list of recent paths with the choice of the user to not add them again - // Also: Windows will not show our custom category at all if there is any entry which was removed - // by the user! See https://github.com/microsoft/vscode/issues/15052 - let toRemove: URI[] = []; - for (let item of app.getJumpListSettings().removedItems) { - const args = item.args; - if (args) { - const match = /^--(folder|file)-uri\s+"([^"]+)"$/.exec(args); - if (match) { - toRemove.push(URI.parse(match[2])); - } + // The user might have meanwhile removed items from the jump list and we have to respect that + // so we need to update our list of recent paths with the choice of the user to not add them again + // Also: Windows will not show our custom category at all if there is any entry which was removed + // by the user! See https://github.com/microsoft/vscode/issues/15052 + let toRemove: URI[] = []; + for (let item of app.getJumpListSettings().removedItems) { + const args = item.args; + if (args) { + const match = /^--(folder|file)-uri\s+"([^"]+)"$/.exec(args); + if (match) { + toRemove.push(URI.parse(match[2])); } } - this.removeRecentlyOpened(toRemove); - - // Add entries - jumpList.push({ - type: 'custom', - name: nls.localize('recentFolders', "Recent Workspaces"), - items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { - const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; - const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); - - let description; - let args; - if (isSingleFolderWorkspaceIdentifier(workspace)) { - description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); - args = `--folder-uri "${workspace.toString()}"`; - } else { - description = nls.localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); - args = `--file-uri "${workspace.configPath.toString()}"`; - } - - return { - type: 'task', - title, - description: description.substr(0, 255), // https://github.com/microsoft/vscode/issues/111177 - program: process.execPath, - args, - iconPath: 'explorer.exe', // simulate folder icon - iconIndex: 0 - }; - })) - }); } - } catch (error) { - this.logService.warn('updateWindowsJumpList#recentWorkspaces', error); // https://github.com/microsoft/vscode/issues/111177 + this.removeRecentlyOpened(toRemove); + + // Add entries + jumpList.push({ + type: 'custom', + name: nls.localize('recentFolders', "Recent Workspaces"), + items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { + const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; + const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); + + let description; + let args; + if (isSingleFolderWorkspaceIdentifier(workspace)) { + description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); + args = `--folder-uri "${workspace.toString()}"`; + } else { + description = nls.localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); + args = `--file-uri "${workspace.configPath.toString()}"`; + } + + return { + type: 'task', + title: title.substr(0, 255), // Windows seems to be picky around the length of entries + description: description.substr(0, 255), // (see https://github.com/microsoft/vscode/issues/111177) + program: process.execPath, + args, + iconPath: 'explorer.exe', // simulate folder icon + iconIndex: 0 + }; + })) + }); } // Recent From d0475711090b596bbf44e9afc90b074b9eb1082f Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Dec 2020 15:33:52 +0100 Subject: [PATCH 0651/1837] Prompt to save untitled file before run/debug fixes #111850 --- src/vs/workbench/contrib/debug/browser/debugService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index e05a471f57b..586c15415e0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -289,7 +289,7 @@ export class DebugService implements IDebugService { // make sure to save all files and that the configuration is up to date await this.extensionService.activateByEvent('onDebug'); if (!options?.parentSession) { - await this.editorService.saveAll(); + await this.editorService.saveAll({ includeUntitled: true }); } await this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined); await this.extensionService.whenInstalledExtensionsRegistered(); From 4250e343e0fc3af2a2de719a0f49cb40fbe8e32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 7 Dec 2020 16:15:57 +0100 Subject: [PATCH 0652/1837] use proper repos for linux arm --- build/gulpfile.vscode.linux.js | 1 + resources/linux/debian/postinst.template | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index 2833bb14a20..9de7f9bb62c 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -98,6 +98,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@ARCHITECTURE@@', debArch)) .pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@')) .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) + .pipe(replace('@@REPOSITORY_NAME@@', arch === 'x64' ? 'vscode' : 'code')) .pipe(rename('DEBIAN/postinst')); const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, workspaceMime, icon, bash_completion, zsh_completion, code); diff --git a/resources/linux/debian/postinst.template b/resources/linux/debian/postinst.template index 9f26b350999..e1b201b4f9a 100755 --- a/resources/linux/debian/postinst.template +++ b/resources/linux/debian/postinst.template @@ -73,6 +73,6 @@ NdCFTW7wY0Fb1fWJ+/KTsC4= if [ "$WRITE_SOURCE" -eq "1" ]; then echo "### THIS FILE IS AUTOMATICALLY CONFIGURED ### # You may comment out this entry, but any other modifications may be lost. -deb [arch=amd64] http://packages.microsoft.com/repos/vscode stable main" > $CODE_SOURCE_PART +deb [arch=amd64] http://packages.microsoft.com/repos/@@REPOSITORY_NAME@@ stable main" > $CODE_SOURCE_PART fi fi From c2de3a602e8ee704180f1ee95c4240f733fd92ac Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 7 Dec 2020 16:34:55 +0100 Subject: [PATCH 0653/1837] Tweak candidates notebook query --- .vscode/notebooks/endgame.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index e749a11c4be..6f09e38c443 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -104,7 +104,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE label:candidate", + "value": "$REPOS $MILESTONE is:issue is:open label:candidate", "editable": true } ] \ No newline at end of file From cf8ed37206e161a30151defa4fc9ea58c32335bc Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Dec 2020 16:56:54 +0100 Subject: [PATCH 0654/1837] fixes #111850 --- src/vs/workbench/contrib/debug/browser/debugService.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 586c15415e0..2dc02fc743b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -289,7 +289,12 @@ export class DebugService implements IDebugService { // make sure to save all files and that the configuration is up to date await this.extensionService.activateByEvent('onDebug'); if (!options?.parentSession) { - await this.editorService.saveAll({ includeUntitled: true }); + await this.editorService.saveAll(); + const activeEditor = this.editorService.activeEditorPane; + if (activeEditor) { + // Make sure to save the active editor in case it is in untitled file it wont be saved as part of saveAll #111850 + await this.editorService.save({ editor: activeEditor.input, groupId: activeEditor.group.id }); + } } await this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined); await this.extensionService.whenInstalledExtensionsRegistered(); From ab8c8dbd8e5de3fd6f0650a7f23ed660b0211b6a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Dec 2020 17:54:11 +0100 Subject: [PATCH 0655/1837] Fix #112030 --- .../src/configurationEditingMain.ts | 4 ++-- .../configuration-editing/src/extensionsProposals.ts | 4 ++-- .../src/settingsDocumentHelper.ts | 11 ++++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/extensions/configuration-editing/src/configurationEditingMain.ts b/extensions/configuration-editing/src/configurationEditingMain.ts index 966073e23f8..a3ef34f3d83 100644 --- a/extensions/configuration-editing/src/configurationEditingMain.ts +++ b/extensions/configuration-editing/src/configurationEditingMain.ts @@ -81,7 +81,7 @@ function registerExtensionsCompletionsInExtensionsDocument(): vscode.Disposable const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); if (location.path[0] === 'recommendations') { const extensionsContent = parse(document.getText()); - return provideInstalledExtensionProposals(extensionsContent && extensionsContent.recommendations || [], range, false); + return provideInstalledExtensionProposals(extensionsContent && extensionsContent.recommendations || [], '', range, false); } return []; } @@ -95,7 +95,7 @@ function registerExtensionsCompletionsInWorkspaceConfigurationDocument(): vscode const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); if (location.path[0] === 'extensions' && location.path[1] === 'recommendations') { const extensionsContent = parse(document.getText())['extensions']; - return provideInstalledExtensionProposals(extensionsContent && extensionsContent.recommendations || [], range, false); + return provideInstalledExtensionProposals(extensionsContent && extensionsContent.recommendations || [], '', range, false); } return []; } diff --git a/extensions/configuration-editing/src/extensionsProposals.ts b/extensions/configuration-editing/src/extensionsProposals.ts index 60533ae2975..7fef9836bdc 100644 --- a/extensions/configuration-editing/src/extensionsProposals.ts +++ b/extensions/configuration-editing/src/extensionsProposals.ts @@ -8,14 +8,14 @@ import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -export function provideInstalledExtensionProposals(existing: string[], range: vscode.Range, includeBuiltinExtensions: boolean): vscode.ProviderResult { +export function provideInstalledExtensionProposals(existing: string[], additionalText: string, range: vscode.Range, includeBuiltinExtensions: boolean): vscode.ProviderResult { if (Array.isArray(existing)) { const extensions = includeBuiltinExtensions ? vscode.extensions.all : vscode.extensions.all.filter(e => !(e.id.startsWith('vscode.') || e.id === 'Microsoft.vscode-markdown')); const knownExtensionProposals = extensions.filter(e => existing.indexOf(e.id) === -1); if (knownExtensionProposals.length) { return knownExtensionProposals.map(e => { const item = new vscode.CompletionItem(e.id); - const insertText = `"${e.id}"`; + const insertText = `"${e.id}"${additionalText}`; item.kind = vscode.CompletionItemKind.Value; item.insertText = insertText; item.range = range; diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts index 5e466c2eb6f..f3461f0c3b5 100644 --- a/extensions/configuration-editing/src/settingsDocumentHelper.ts +++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts @@ -48,7 +48,16 @@ export class SettingsDocument { try { ignoredExtensions = parse(this.document.getText())['settingsSync.ignoredExtensions']; } catch (e) {/* ignore error */ } - return provideInstalledExtensionProposals(ignoredExtensions, range, true); + return provideInstalledExtensionProposals(ignoredExtensions, '', range, true); + } + + // remote.extensionKind + if (location.path[0] === 'remote.extensionKind' && location.path.length === 2 && location.isAtPropertyKey) { + let alreadyConfigured: string[] = []; + try { + alreadyConfigured = Object.keys(parse(this.document.getText())['remote.extensionKind']); + } catch (e) {/* ignore error */ } + return provideInstalledExtensionProposals(alreadyConfigured, `: [\n\t"ui"\n]`, range, true); } return this.provideLanguageOverridesCompletionItems(location, position); From 3136ecb1d317fdfed941ae6e28be1a61b1e7e721 Mon Sep 17 00:00:00 2001 From: Konstantin Solomatov Date: Mon, 7 Dec 2020 09:22:25 -0800 Subject: [PATCH 0656/1837] Do not ignore errors from $spawnExtHostProcess --- src/vs/workbench/api/browser/mainThreadTerminalService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 8e54cb8f41e..651014c5e64 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -260,7 +260,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape request.cols, request.rows, request.isWorkspaceShellAllowed - ).then(request.callback); + ).then(request.callback, request.callback); proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data)); proxy.onResize(dimensions => this._proxy.$acceptProcessResize(proxy.terminalId, dimensions.cols, dimensions.rows)); From 3655a82edcbac3158ce6d26c3cb8cd0401ab70d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 7 Dec 2020 19:56:05 +0100 Subject: [PATCH 0657/1837] add log to createAsset retry --- build/azure-pipelines/common/createAsset.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index b6d4c966f67..f422d358b50 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -75,8 +75,11 @@ async function retry(fn: () => Promise): Promise { throw err; } + const millis = (Math.random() * 200) + (50 * Math.pow(1.5, run)); + console.log(`Creating build asset failed with ECONNRESET, retrying in ${millis}ms...`); + // maximum delay is 10th retry: ~3 seconds - await new Promise(c => setTimeout(c, (Math.random() * 200) + (50 * Math.pow(1.5, run)))); + await new Promise(c => setTimeout(c, millis)); } } From f79bb79d2b6db5c14dca88578999d21f0be42260 Mon Sep 17 00:00:00 2001 From: Greg Van Liew Date: Mon, 7 Dec 2020 13:57:02 -0800 Subject: [PATCH 0658/1837] Suggest a different description (#112049) --- .../gettingStarted/browser/gettingStarted.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts index b53ddab8504..8f80d2b98bb 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts @@ -44,7 +44,7 @@ if (product.quality !== 'stable') { properties: { 'workbench.experimental.gettingStarted': { type: 'boolean', - description: localize('gettingStartedDescription', "Enables an experimental Getting Started page, accesible via the Help menu."), + description: localize('gettingStartedDescription', "Enables an experimental Getting Started page, available via the Help menu."), default: false, } } From 91c7834e926533bd119b1a4c188b87ed7e2d4f8b Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 7 Dec 2020 16:00:00 -0800 Subject: [PATCH 0659/1837] debug: update js-debug --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index ee6e68b480e..207bcf8f512 100644 --- a/product.json +++ b/product.json @@ -91,7 +91,7 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.52.1", + "version": "1.52.2", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", From aa18ca682765edd34edb0c231053577c5d5835d8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 08:38:03 +0100 Subject: [PATCH 0660/1837] Unable to find the registered languages while saving the file. (fix #111788) --- .../services/dialogs/browser/abstractFileDialogService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts index 222e877c68b..1cd34887e54 100644 --- a/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/abstractFileDialogService.ts @@ -283,10 +283,10 @@ export abstract class AbstractFileDialogService implements IFileDialogService { const filter: IFilter = { name: languageName, extensions: distinct(extensions).slice(0, 10).map(e => trim(e, '.')) }; - if (ext && extensions.indexOf(ext) >= 0) { + if (ext && extensions.indexOf(ext) >= 0 && !matchingFilter) { matchingFilter = filter; - return null; // matching filter will be added last to the top + return null; // first matching filter will be added to the top } return filter; From 2c937725db0aa39b2d6a00522b7092fade432a47 Mon Sep 17 00:00:00 2001 From: Damien Engels Date: Tue, 8 Dec 2020 07:58:33 +0100 Subject: [PATCH 0661/1837] Updates tsec This fixes the bug where tsec was not running a postinstall build, which caused it to keep running an old version. This new version comes with new violations and Trusted Types awareness. Also pins tsec to the latest commit so that the version fetched is always the same. --- package.json | 4 ++-- yarn.lock | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 13c521e2dec..2266c51e83c 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "source-map": "^0.4.4", "style-loader": "^1.0.0", "ts-loader": "^4.4.2", - "tsec": "googleinterns/tsec", + "tsec": "googleinterns/tsec#630b53fe2b23815c28dd219119cc98dbd59e29b2", "typescript": "^4.2.0-dev.20201119", "typescript-formatter": "7.1.0", "underscore": "^1.8.2", @@ -197,4 +197,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 8adc7c55ed3..88ce9fbe651 100644 --- a/yarn.lock +++ b/yarn.lock @@ -288,9 +288,9 @@ integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== "@types/node@^13.13.5": - version "13.13.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.28.tgz#b6d0628b0371d6c629d729c98322de314b640219" - integrity sha512-EM/qFeRH8ZCD+TlsaIPULyyFm9vOhFIvgskY2JmHbEsWsOPgN+rtjSXrcHGgJpob4Nu17VfO95FKewr0XY7iOQ== + version "13.13.34" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.34.tgz#c9300a1b6560d90817fb2bba650e250116a575f9" + integrity sha512-g8D1HF2dMDKYSDl5+79izRwRgNPsSynmWMbj50mj7GZ0b7Lv4p8EmZjbo3h0h+6iLr6YmVz9VnF6XVZ3O6V1Ug== "@types/semver@^5.4.0", "@types/semver@^5.5.0": version "5.5.0" @@ -9520,11 +9520,12 @@ ts-loader@^4.4.2: micromatch "^3.1.4" semver "^5.0.1" -tsec@googleinterns/tsec: +tsec@googleinterns/tsec#630b53fe2b23815c28dd219119cc98dbd59e29b2: version "0.0.1" - resolved "https://codeload.github.com/googleinterns/tsec/tar.gz/bec3c527789daa9151be2bc8471cfefa4f44d167" + resolved "https://codeload.github.com/googleinterns/tsec/tar.gz/630b53fe2b23815c28dd219119cc98dbd59e29b2" dependencies: "@types/node" "^13.13.5" + typescript "^3.9.2" tslib@^1.8.1, tslib@^1.9.0: version "1.9.3" @@ -9603,6 +9604,11 @@ typescript@^2.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q= +typescript@^3.9.2: + version "3.9.7" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" + integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== + typescript@^4.2.0-dev.20201119: version "4.2.0-dev.20201119" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201119.tgz#d4a43511cd9931adac05e1a47b6425f6b0e76cc3" From 5865aeaa7b93c907ffdc54063d2d614a7cd81665 Mon Sep 17 00:00:00 2001 From: Damien Engels Date: Tue, 8 Dec 2020 08:37:38 +0100 Subject: [PATCH 0662/1837] Rewrites Trusted Types sink assignements Moves the casts to the sink assignement expression so that tsec can recognize it. --- src/vs/base/browser/dom.ts | 2 +- src/vs/base/browser/markdownRenderer.ts | 10 +++------- src/vs/editor/browser/core/markdownRenderer.ts | 4 +--- .../editor/browser/view/domLineBreaksComputer.ts | 4 ++-- src/vs/editor/browser/view/viewLayer.ts | 14 +++++++------- src/vs/editor/browser/widget/diffEditorWidget.ts | 2 +- src/vs/editor/standalone/browser/colorizer.ts | 4 ++-- .../browser/view/renderers/cellRenderer.ts | 2 +- 8 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index b4740dadea0..17cab3a085a 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1385,7 +1385,7 @@ export function safeInnerHtml(node: HTMLElement, value: string): void { }, ['class', 'id', 'role', 'tabindex']); const html = _ttpSafeInnerHtml?.createHTML(value, options) ?? insane(value, options); - node.innerHTML = html as unknown as string; + node.innerHTML = html as string; } /** diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index a5cd4c5ec84..18bd5f2050a 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -239,7 +239,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende const renderedMarkdown = marked.parse(value, markedOptions); // sanitize with insane - element.innerHTML = sanitizeRenderedMarkdown(markdown, renderedMarkdown); + element.innerHTML = sanitizeRenderedMarkdown(markdown, renderedMarkdown) as string; // signal that async code blocks can be now be inserted signalInnerHTML!(); @@ -261,13 +261,9 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende function sanitizeRenderedMarkdown( options: { isTrusted?: boolean }, renderedMarkdown: string, -): string { +): string | TrustedHTML { const insaneOptions = getInsaneOptions(options); - if (_ttpInsane) { - return _ttpInsane.createHTML(renderedMarkdown, insaneOptions) as unknown as string; - } else { - return insane(renderedMarkdown, insaneOptions); - } + return _ttpInsane?.createHTML(renderedMarkdown, insaneOptions) ?? insane(renderedMarkdown, insaneOptions); } function getInsaneOptions(options: { readonly isTrusted?: boolean }): InsaneOptions { diff --git a/src/vs/editor/browser/core/markdownRenderer.ts b/src/vs/editor/browser/core/markdownRenderer.ts index e1eb76c8a87..c29335966ac 100644 --- a/src/vs/editor/browser/core/markdownRenderer.ts +++ b/src/vs/editor/browser/core/markdownRenderer.ts @@ -88,9 +88,7 @@ export class MarkdownRenderer { const element = document.createElement('span'); - element.innerHTML = MarkdownRenderer._ttpTokenizer - ? MarkdownRenderer._ttpTokenizer.createHTML(value, tokenization) as unknown as string - : tokenizeToString(value, tokenization); + element.innerHTML = (MarkdownRenderer._ttpTokenizer?.createHTML(value, tokenization) ?? tokenizeToString(value, tokenization)) as string; // use "good" font let fontFamily = this._options.codeBlockFontFamily; diff --git a/src/vs/editor/browser/view/domLineBreaksComputer.ts b/src/vs/editor/browser/view/domLineBreaksComputer.ts index 87c6461d54a..cd486fc270a 100644 --- a/src/vs/editor/browser/view/domLineBreaksComputer.ts +++ b/src/vs/editor/browser/view/domLineBreaksComputer.ts @@ -111,8 +111,8 @@ function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: numbe allVisibleColumns[i] = tmp[1]; } const html = sb.build(); - const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html; - containerDomNode.innerHTML = trustedhtml as unknown as string; + const trustedhtml = ttPolicy?.createHTML(html) ?? html; + containerDomNode.innerHTML = trustedhtml as string; containerDomNode.style.position = 'absolute'; containerDomNode.style.top = '10000'; diff --git a/src/vs/editor/browser/view/viewLayer.ts b/src/vs/editor/browser/view/viewLayer.ts index 89de8468f21..0a1a7ddc0c2 100644 --- a/src/vs/editor/browser/view/viewLayer.ts +++ b/src/vs/editor/browser/view/viewLayer.ts @@ -506,15 +506,15 @@ class ViewLayerRenderer { ctx.lines.splice(removeIndex, removeCount); } - private _finishRenderingNewLines(ctx: IRendererContext, domNodeIsEmpty: boolean, newLinesHTML: string, wasNew: boolean[]): void { + private _finishRenderingNewLines(ctx: IRendererContext, domNodeIsEmpty: boolean, newLinesHTML: string | TrustedHTML, wasNew: boolean[]): void { if (ViewLayerRenderer._ttPolicy) { - newLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(newLinesHTML) as unknown as string; // explains the ugly casts -> https://github.com/microsoft/vscode/issues/106396#issuecomment-692625393 + newLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(newLinesHTML as string); } const lastChild = this.domNode.lastChild; if (domNodeIsEmpty || !lastChild) { - this.domNode.innerHTML = newLinesHTML; + this.domNode.innerHTML = newLinesHTML as string; // explains the ugly casts -> https://github.com/microsoft/vscode/issues/106396#issuecomment-692625393; } else { - lastChild.insertAdjacentHTML('afterend', newLinesHTML); + lastChild.insertAdjacentHTML('afterend', newLinesHTML as string); } let currChild = this.domNode.lastChild; @@ -527,13 +527,13 @@ class ViewLayerRenderer { } } - private _finishRenderingInvalidLines(ctx: IRendererContext, invalidLinesHTML: string, wasInvalid: boolean[]): void { + private _finishRenderingInvalidLines(ctx: IRendererContext, invalidLinesHTML: string | TrustedHTML, wasInvalid: boolean[]): void { const hugeDomNode = document.createElement('div'); if (ViewLayerRenderer._ttPolicy) { - invalidLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(invalidLinesHTML) as unknown as string; + invalidLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(invalidLinesHTML as string); } - hugeDomNode.innerHTML = invalidLinesHTML; + hugeDomNode.innerHTML = invalidLinesHTML as string; for (let i = 0; i < ctx.linesLength; i++) { const line = ctx.lines[i]; diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 0730e4f00ec..200d237c9de 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -2370,7 +2370,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { const html = sb.build(); const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html; - domNode.innerHTML = trustedhtml as unknown as string; + domNode.innerHTML = trustedhtml as string; viewZone.minWidthInPx = (maxCharsPerLine * typicalHalfwidthCharacterWidth); if (viewLineCounts) { diff --git a/src/vs/editor/standalone/browser/colorizer.ts b/src/vs/editor/standalone/browser/colorizer.ts index 22bad13e9ef..aa83e5bafc5 100644 --- a/src/vs/editor/standalone/browser/colorizer.ts +++ b/src/vs/editor/standalone/browser/colorizer.ts @@ -42,8 +42,8 @@ export class Colorizer { let text = domNode.firstChild ? domNode.firstChild.nodeValue : ''; domNode.className += ' ' + theme; let render = (str: string) => { - const trustedhtml = ttPolicy ? ttPolicy.createHTML(str) : str; - domNode.innerHTML = trustedhtml as unknown as string; + const trustedhtml = ttPolicy?.createHTML(str) ?? str; + domNode.innerHTML = trustedhtml as string; }; return this.colorize(modeService, text || '', mimeType, options).then(render, (err) => console.error(err)); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 2fccd56c7b9..ac81b9a601e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -594,7 +594,7 @@ class EditorTextRenderer { const element = DOM.$('div', { style }); const linesHtml = this.getRichTextLinesAsHtml(model, modelRange, colorMap); - element.innerHTML = linesHtml as unknown as string; + element.innerHTML = linesHtml as string; return element; } From 6f5448afac57db6b850be930bee3d5e991557166 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Tue, 8 Dec 2020 09:01:59 +0100 Subject: [PATCH 0663/1837] Include candidate pull requests --- .vscode/notebooks/endgame.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 6f09e38c443..a3c81e4cc6e 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -104,7 +104,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:open label:candidate", + "value": "$REPOS $MILESTONE is:open label:candidate", "editable": true } ] \ No newline at end of file From a6946159d4e880b630604db186ad9c6dc53e9e95 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 09:29:16 +0100 Subject: [PATCH 0664/1837] :lipstick: layers checker --- build/lib/layersChecker.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/lib/layersChecker.ts b/build/lib/layersChecker.ts index 1c7579206af..c0d67db6017 100644 --- a/build/lib/layersChecker.ts +++ b/build/lib/layersChecker.ts @@ -25,8 +25,6 @@ import { match } from 'minimatch'; // Feel free to add more core types as you see needed if present in node.js and browsers const CORE_TYPES = [ 'require', // from our AMD loader - // 'atob', - // 'btoa', 'setTimeout', 'clearTimeout', 'setInterval', From 3212ddbc76fa2ceaa75724245729eaa22022c1cd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 09:40:42 +0100 Subject: [PATCH 0665/1837] multibyteAwareBtoa - add commented out failing test for #112013 --- src/vs/base/test/browser/dom.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/base/test/browser/dom.test.ts b/src/vs/base/test/browser/dom.test.ts index 99b4f1b90fc..c7f92e59ab1 100644 --- a/src/vs/base/test/browser/dom.test.ts +++ b/src/vs/base/test/browser/dom.test.ts @@ -73,8 +73,9 @@ suite('dom', () => { }); test('multibyteAwareBtoa', () => { - assert.equal(dom.multibyteAwareBtoa('hello world'), dom.multibyteAwareBtoa('hello world')); - assert.ok(dom.multibyteAwareBtoa('平仮名')); + assert.ok(dom.multibyteAwareBtoa('hello world').length > 0); + assert.ok(dom.multibyteAwareBtoa('平仮名').length > 0); + //assert.ok(dom.multibyteAwareBtoa(new Array(100000).fill('vs').join('')).length > 0); // https://github.com/microsoft/vscode/issues/112013 }); suite('$', () => { From 0e885aaf70ccffd3f2f6ad66c558cfd95e415719 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 8 Dec 2020 09:59:21 +0100 Subject: [PATCH 0666/1837] retry all cosmosdb ops --- build/azure-pipelines/common/createAsset.ts | 21 +-------------- build/azure-pipelines/common/createBuild.ts | 3 ++- build/azure-pipelines/common/releaseBuild.ts | 3 ++- build/azure-pipelines/common/retry.ts | 26 +++++++++++++++++++ build/azure-pipelines/common/sync-mooncake.ts | 5 ++-- 5 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 build/azure-pipelines/common/retry.ts diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts index f422d358b50..daf60d710ee 100644 --- a/build/azure-pipelines/common/createAsset.ts +++ b/build/azure-pipelines/common/createAsset.ts @@ -11,6 +11,7 @@ import * as crypto from 'crypto'; import * as azure from 'azure-storage'; import * as mime from 'mime'; import { CosmosClient } from '@azure/cosmos'; +import { retry } from './retry'; interface Asset { platform: string; @@ -66,26 +67,6 @@ function getEnv(name: string): string { return result; } -async function retry(fn: () => Promise): Promise { - for (let run = 1; run <= 10; run++) { - try { - return await fn(); - } catch (err) { - if (!/ECONNRESET/.test(err.message)) { - throw err; - } - - const millis = (Math.random() * 200) + (50 * Math.pow(1.5, run)); - console.log(`Creating build asset failed with ECONNRESET, retrying in ${millis}ms...`); - - // maximum delay is 10th retry: ~3 seconds - await new Promise(c => setTimeout(c, millis)); - } - } - - throw new Error('Retried too many times'); -} - async function main(): Promise { const [, , platform, type, fileName, filePath] = process.argv; const quality = getEnv('VSCODE_QUALITY'); diff --git a/build/azure-pipelines/common/createBuild.ts b/build/azure-pipelines/common/createBuild.ts index c8fd66b791d..e314d7c0988 100644 --- a/build/azure-pipelines/common/createBuild.ts +++ b/build/azure-pipelines/common/createBuild.ts @@ -6,6 +6,7 @@ 'use strict'; import { CosmosClient } from '@azure/cosmos'; +import { retry } from './retry'; if (process.argv.length !== 3) { console.error('Usage: node createBuild.js VERSION'); @@ -48,7 +49,7 @@ async function main(): Promise { const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); const scripts = client.database('builds').container(quality).scripts; - await scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]); + await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }])); } main().then(() => { diff --git a/build/azure-pipelines/common/releaseBuild.ts b/build/azure-pipelines/common/releaseBuild.ts index ac49e7b0042..d42b3f1a078 100644 --- a/build/azure-pipelines/common/releaseBuild.ts +++ b/build/azure-pipelines/common/releaseBuild.ts @@ -6,6 +6,7 @@ 'use strict'; import { CosmosClient } from '@azure/cosmos'; +import { retry } from './retry'; function getEnv(name: string): string { const result = process.env[name]; @@ -58,7 +59,7 @@ async function main(): Promise { console.log(`Releasing build ${commit}...`); const scripts = client.database('builds').container(quality).scripts; - await scripts.storedProcedure('releaseBuild').execute('', [commit]); + await retry(() => scripts.storedProcedure('releaseBuild').execute('', [commit])); } main().then(() => { diff --git a/build/azure-pipelines/common/retry.ts b/build/azure-pipelines/common/retry.ts new file mode 100644 index 00000000000..1737676590d --- /dev/null +++ b/build/azure-pipelines/common/retry.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +export async function retry(fn: () => Promise): Promise { + for (let run = 1; run <= 10; run++) { + try { + return await fn(); + } catch (err) { + if (!/ECONNRESET/.test(err.message)) { + throw err; + } + + const millis = (Math.random() * 200) + (50 * Math.pow(1.5, run)); + console.log(`Failed with ECONNRESET, retrying in ${millis}ms...`); + + // maximum delay is 10th retry: ~3 seconds + await new Promise(c => setTimeout(c, millis)); + } + } + + throw new Error('Retried too many times'); +} diff --git a/build/azure-pipelines/common/sync-mooncake.ts b/build/azure-pipelines/common/sync-mooncake.ts index 76f12185e12..4ffe7a8f15b 100644 --- a/build/azure-pipelines/common/sync-mooncake.ts +++ b/build/azure-pipelines/common/sync-mooncake.ts @@ -9,6 +9,7 @@ import * as url from 'url'; import * as azure from 'azure-storage'; import * as mime from 'mime'; import { CosmosClient } from '@azure/cosmos'; +import { retry } from './retry'; function log(...args: any[]) { console.log(...[`[${new Date().toISOString()}]`, ...args]); @@ -99,8 +100,8 @@ async function sync(commit: string, quality: string): Promise { log(` Updating build in DB...`); const mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`; - await container.scripts.storedProcedure('setAssetMooncakeUrl') - .execute('', [commit, asset.platform, asset.type, mooncakeUrl]); + await retry(() => container.scripts.storedProcedure('setAssetMooncakeUrl') + .execute('', [commit, asset.platform, asset.type, mooncakeUrl])); log(` Done ✔️`); } catch (err) { From 861e7bcc1b28ee3a79111c1cbadd4b3d95269ef4 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Dec 2020 10:02:34 +0100 Subject: [PATCH 0667/1837] Wait for the remote configuration before creating remote terminal processes --- .../contrib/terminal/common/remoteTerminalChannel.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index cc4de710a0a..d25b3982fcc 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event'; import { withNullAsUndefined } from 'vs/base/common/types'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -191,7 +191,7 @@ export class RemoteTerminalChannelClient { constructor( private readonly _remoteAuthority: string, private readonly _channel: IChannel, - @IConfigurationService private readonly _configurationService: IConfigurationService, + @IWorkbenchConfigurationService private readonly _configurationService: IWorkbenchConfigurationService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IConfigurationResolverService private readonly _resolverService: IConfigurationResolverService, @IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService, @@ -211,6 +211,9 @@ export class RemoteTerminalChannelClient { } public async createTerminalProcess(shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: URI | undefined, shouldPersistTerminal: boolean, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise { + // Be sure to first wait for the remote configuration + await this._configurationService.whenRemoteConfigurationLoaded(); + const terminalConfig = this._configurationService.getValue(TERMINAL_CONFIG_SECTION); const configuration: ICompleteTerminalConfiguration = { 'terminal.integrated.automationShell.windows': this._readSingleTerminalConfiguration('terminal.integrated.automationShell.windows'), From 08e29d24b4b840155bbf7aed00ef590c96d11865 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 10:20:14 +0100 Subject: [PATCH 0668/1837] Remove duplicate (case sensitive) recent workspace/folder names on the welcome screen (fix #111954) --- .../workspacesHistoryMainService.ts | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index 91d62d0ff95..f174547116c 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; -import * as arrays from 'vs/base/common/arrays'; +import { localize } from 'vs/nls'; +import { coalesce } from 'vs/base/common/arrays'; import { IStateService } from 'vs/platform/state/node/state'; import { app, JumpListCategory } from 'electron'; import { ILogService } from 'vs/platform/log/common/log'; @@ -14,7 +14,7 @@ import { isWindows, isMacintosh } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile, toStoreData, restoreRecentlyOpened, RecentlyOpenedStorageData, WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { ThrottledDelayer } from 'vs/base/common/async'; -import { isEqual, dirname, originalFSPath, basename, extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; +import { dirname, originalFSPath, basename, extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; @@ -57,10 +57,10 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa declare readonly _serviceBrand: undefined; - private readonly _onRecentlyOpenedChange = new Emitter(); + private readonly _onRecentlyOpenedChange = this._register(new Emitter()); readonly onRecentlyOpenedChange: CommonEvent = this._onRecentlyOpenedChange.event; - private macOSRecentDocumentsUpdater = this._register(new ThrottledDelayer(800)); + private readonly macOSRecentDocumentsUpdater = this._register(new ThrottledDelayer(800)); constructor( @IStateService private readonly stateService: IStateService, @@ -89,40 +89,40 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa } this.updateWindowsJumpList(); - this.onRecentlyOpenedChange(() => this.updateWindowsJumpList()); + this._register(this.onRecentlyOpenedChange(() => this.updateWindowsJumpList())); } - addRecentlyOpened(newlyAdded: IRecent[]): void { + addRecentlyOpened(recentToAdd: IRecent[]): void { const workspaces: Array = []; const files: IRecentFile[] = []; - for (let curr of newlyAdded) { + for (let recent of recentToAdd) { // Workspace - if (isRecentWorkspace(curr)) { - if (!this.workspacesMainService.isUntitledWorkspace(curr.workspace) && indexOfWorkspace(workspaces, curr.workspace) === -1) { - workspaces.push(curr); + if (isRecentWorkspace(recent)) { + if (!this.workspacesMainService.isUntitledWorkspace(recent.workspace) && indexOfWorkspace(workspaces, recent.workspace) === -1) { + workspaces.push(recent); } } // Folder - else if (isRecentFolder(curr)) { - if (indexOfFolder(workspaces, curr.folderUri) === -1) { - workspaces.push(curr); + else if (isRecentFolder(recent)) { + if (indexOfFolder(workspaces, recent.folderUri) === -1) { + workspaces.push(recent); } } // File else { - const alreadyExistsInHistory = indexOfFile(files, curr.fileUri) >= 0; - const shouldBeFiltered = curr.fileUri.scheme === Schemas.file && WorkspacesHistoryMainService.COMMON_FILES_FILTER.indexOf(basename(curr.fileUri)) >= 0; + const alreadyExistsInHistory = indexOfFile(files, recent.fileUri) >= 0; + const shouldBeFiltered = recent.fileUri.scheme === Schemas.file && WorkspacesHistoryMainService.COMMON_FILES_FILTER.indexOf(basename(recent.fileUri)) >= 0; if (!alreadyExistsInHistory && !shouldBeFiltered) { - files.push(curr); + files.push(recent); // Add to recent documents (Windows only, macOS later) - if (isWindows && curr.fileUri.scheme === Schemas.file) { - app.addRecentDocument(curr.fileUri.fsPath); + if (isWindows && recent.fileUri.scheme === Schemas.file) { + app.addRecentDocument(recent.fileUri.fsPath); } } } @@ -147,14 +147,15 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa } } - removeRecentlyOpened(toRemove: URI[]): void { + removeRecentlyOpened(recentToRemove: URI[]): void { const keep = (recent: IRecent) => { const uri = location(recent); - for (const resource of toRemove) { - if (isEqual(resource, uri)) { + for (const resourceToRemove of recentToRemove) { + if (extUriBiasedIgnorePathCase.isEqual(resourceToRemove, uri)) { return false; } } + return true; }; @@ -319,8 +320,8 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa items: [ { type: 'task', - title: nls.localize('newWindow', "New Window"), - description: nls.localize('newWindowDesc', "Opens a new window"), + title: localize('newWindow', "New Window"), + description: localize('newWindowDesc', "Opens a new window"), program: process.execPath, args: '-n', // force new window iconPath: process.execPath, @@ -351,18 +352,18 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa // Add entries jumpList.push({ type: 'custom', - name: nls.localize('recentFolders', "Recent Workspaces"), - items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { + name: localize('recentFolders', "Recent Workspaces"), + items: coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); let description; let args; if (isSingleFolderWorkspaceIdentifier(workspace)) { - description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); + description = localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService)); args = `--folder-uri "${workspace.toString()}"`; } else { - description = nls.localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); + description = localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService)); args = `--file-uri "${workspace.configPath.toString()}"`; } @@ -398,7 +399,7 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa // Workspace: Untitled if (extUriBiasedIgnorePathCase.isEqualOrParent(workspace.configPath, workspaceHome)) { - return nls.localize('untitledWorkspace', "Untitled (Workspace)"); + return localize('untitledWorkspace', "Untitled (Workspace)"); } let filename = basename(workspace.configPath); @@ -406,7 +407,7 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa filename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1); } - return nls.localize('workspaceName', "{0} (Workspace)", filename); + return localize('workspaceName', "{0} (Workspace)", filename); } } @@ -427,9 +428,9 @@ function indexOfWorkspace(arr: IRecent[], candidate: IWorkspaceIdentifier): numb } function indexOfFolder(arr: IRecent[], candidate: ISingleFolderWorkspaceIdentifier): number { - return arr.findIndex(folder => isRecentFolder(folder) && isEqual(folder.folderUri, candidate)); + return arr.findIndex(folder => isRecentFolder(folder) && extUriBiasedIgnorePathCase.isEqual(folder.folderUri, candidate)); } function indexOfFile(arr: IRecentFile[], candidate: URI): number { - return arr.findIndex(file => isEqual(file.fileUri, candidate)); + return arr.findIndex(file => extUriBiasedIgnorePathCase.isEqual(file.fileUri, candidate)); } From 66f5e9294e3af365bc62260839fe51806eb83ac5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 10:44:22 +0100 Subject: [PATCH 0669/1837] path lib usage :lipstick: --- src/vs/platform/files/common/fileService.ts | 30 +++++++++---------- .../node/watcher/nsfw/nsfwWatcherService.ts | 24 +++++++-------- .../watcher/unix/chokidarWatcherService.ts | 9 +++--- .../electron-main/workspacesMainService.ts | 11 ++++--- .../terminalValidatedLocalLinkProvider.ts | 7 +++-- .../services/editor/browser/editorService.ts | 5 ++-- .../abstractWorkspaceEditingService.ts | 1 + 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index 23001b2a20f..81ee5fe2580 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -725,16 +725,16 @@ export class FileService extends Disposable implements IFileService { // Check if source is equal or parent to target (requires providers to be the same) if (sourceProvider === targetProvider) { - const { extUri, isPathCaseSensitive } = this.getExtUri(sourceProvider); + const { providerExtUri, isPathCaseSensitive } = this.getExtUri(sourceProvider); if (!isPathCaseSensitive) { - isSameResourceWithDifferentPathCase = extUri.isEqual(source, target); + isSameResourceWithDifferentPathCase = providerExtUri.isEqual(source, target); } if (isSameResourceWithDifferentPathCase && mode === 'copy') { throw new Error(localize('unableToMoveCopyError1', "Unable to copy when source '{0}' is same as target '{1}' with different path case on a case insensitive file system", this.resourceForError(source), this.resourceForError(target))); } - if (!isSameResourceWithDifferentPathCase && extUri.isEqualOrParent(target, source)) { + if (!isSameResourceWithDifferentPathCase && providerExtUri.isEqualOrParent(target, source)) { throw new Error(localize('unableToMoveCopyError2', "Unable to move/copy when source '{0}' is parent of target '{1}'.", this.resourceForError(source), this.resourceForError(target))); } } @@ -751,8 +751,8 @@ export class FileService extends Disposable implements IFileService { // Special case: if the target is a parent of the source, we cannot delete // it as it would delete the source as well. In this case we have to throw if (sourceProvider === targetProvider) { - const { extUri } = this.getExtUri(sourceProvider); - if (extUri.isEqualOrParent(source, target)) { + const { providerExtUri } = this.getExtUri(sourceProvider); + if (providerExtUri.isEqualOrParent(source, target)) { throw new Error(localize('unableToMoveCopyError4', "Unable to move/copy '{0}' into '{1}' since a file would replace the folder it is contained in.", this.resourceForError(source), this.resourceForError(target))); } } @@ -761,11 +761,11 @@ export class FileService extends Disposable implements IFileService { return { exists, isSameResourceWithDifferentPathCase }; } - private getExtUri(provider: IFileSystemProvider): { extUri: IExtUri, isPathCaseSensitive: boolean } { + private getExtUri(provider: IFileSystemProvider): { providerExtUri: IExtUri, isPathCaseSensitive: boolean } { const isPathCaseSensitive = this.isPathCaseSensitive(provider); return { - extUri: isPathCaseSensitive ? extUri : extUriIgnorePathCase, + providerExtUri: isPathCaseSensitive ? extUri : extUriIgnorePathCase, isPathCaseSensitive }; } @@ -791,8 +791,8 @@ export class FileService extends Disposable implements IFileService { const directoriesToCreate: string[] = []; // mkdir until we reach root - const { extUri } = this.getExtUri(provider); - while (!extUri.isEqual(directory, dirname(directory))) { + const { providerExtUri } = this.getExtUri(provider); + while (!providerExtUri.isEqual(directory, dirname(directory))) { try { const stat = await provider.stat(directory); if ((stat.type & FileType.Directory) === 0) { @@ -940,12 +940,12 @@ export class FileService extends Disposable implements IFileService { } private toWatchKey(provider: IFileSystemProvider, resource: URI, options: IWatchOptions): string { - const { extUri } = this.getExtUri(provider); + const { providerExtUri } = this.getExtUri(provider); return [ - extUri.getComparisonKey(resource), // lowercase path if the provider is case insensitive - String(options.recursive), // use recursive: true | false as part of the key - options.excludes.join() // use excludes as part of the key + providerExtUri.getComparisonKey(resource), // lowercase path if the provider is case insensitive + String(options.recursive), // use recursive: true | false as part of the key + options.excludes.join() // use excludes as part of the key ].join(); } @@ -963,8 +963,8 @@ export class FileService extends Disposable implements IFileService { private readonly writeQueues: Map> = new Map(); private ensureWriteQueue(provider: IFileSystemProvider, resource: URI): Queue { - const { extUri } = this.getExtUri(provider); - const queueKey = extUri.getComparisonKey(resource); + const { providerExtUri } = this.getExtUri(provider); + const queueKey = providerExtUri.getComparisonKey(resource); // ensure to never write to the same resource without finishing // the one write. this ensures a write finishes consistently diff --git a/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts b/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts index 51a4b1a6510..70c4cfd6193 100644 --- a/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts +++ b/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as glob from 'vs/base/common/glob'; -import * as extpath from 'vs/base/common/extpath'; -import * as path from 'vs/base/common/path'; -import * as platform from 'vs/base/common/platform'; -import { IDiskFileChange, normalizeFileChanges, ILogMessage } from 'vs/platform/files/node/watcher/watcher'; import * as nsfw from 'vscode-nsfw'; +import * as glob from 'vs/base/common/glob'; +import { join } from 'vs/base/common/path'; +import { isMacintosh } from 'vs/base/common/platform'; +import { isEqualOrParent } from 'vs/base/common/extpath'; +import { IDiskFileChange, normalizeFileChanges, ILogMessage } from 'vs/platform/files/node/watcher/watcher'; import { IWatcherService, IWatcherRequest } from 'vs/platform/files/node/watcher/nsfw/watcher'; import { ThrottledDelayer } from 'vs/base/common/async'; import { FileChangeType } from 'vs/platform/files/common/files'; @@ -111,7 +111,7 @@ export class NsfwWatcherService extends Disposable implements IWatcherService { // We have to detect this case and massage the events to correct this. let realBasePathDiffers = false; let realBasePathLength = request.path.length; - if (platform.isMacintosh) { + if (isMacintosh) { try { // First check for symbolic link @@ -141,7 +141,7 @@ export class NsfwWatcherService extends Disposable implements IWatcherService { for (const e of events) { // Logging if (this.verboseLogging) { - const logPath = e.action === nsfw.actions.RENAMED ? path.join(e.directory, e.oldFile || '') + ' -> ' + e.newFile : path.join(e.directory, e.file || ''); + const logPath = e.action === nsfw.actions.RENAMED ? join(e.directory, e.oldFile || '') + ' -> ' + e.newFile : join(e.directory, e.file || ''); this.log(`${e.action === nsfw.actions.CREATED ? '[CREATED]' : e.action === nsfw.actions.DELETED ? '[DELETED]' : e.action === nsfw.actions.MODIFIED ? '[CHANGED]' : '[RENAMED]'} ${logPath}`); } @@ -149,20 +149,20 @@ export class NsfwWatcherService extends Disposable implements IWatcherService { let absolutePath: string; if (e.action === nsfw.actions.RENAMED) { // Rename fires when a file's name changes within a single directory - absolutePath = path.join(e.directory, e.oldFile || ''); + absolutePath = join(e.directory, e.oldFile || ''); if (!this.isPathIgnored(absolutePath, this.pathWatchers[request.path].ignored)) { undeliveredFileEvents.push({ type: FileChangeType.DELETED, path: absolutePath }); } else if (this.verboseLogging) { this.log(` >> ignored ${absolutePath}`); } - absolutePath = path.join(e.newDirectory || e.directory, e.newFile || ''); + absolutePath = join(e.newDirectory || e.directory, e.newFile || ''); if (!this.isPathIgnored(absolutePath, this.pathWatchers[request.path].ignored)) { undeliveredFileEvents.push({ type: FileChangeType.ADDED, path: absolutePath }); } else if (this.verboseLogging) { this.log(` >> ignored ${absolutePath}`); } } else { - absolutePath = path.join(e.directory, e.file || ''); + absolutePath = join(e.directory, e.file || ''); if (!this.isPathIgnored(absolutePath, this.pathWatchers[request.path].ignored)) { undeliveredFileEvents.push({ type: nsfwActionToRawChangeType[e.action], @@ -179,7 +179,7 @@ export class NsfwWatcherService extends Disposable implements IWatcherService { const events = undeliveredFileEvents; undeliveredFileEvents = []; - if (platform.isMacintosh) { + if (isMacintosh) { events.forEach(e => { // Mac uses NFD unicode form on disk, but we want NFC @@ -230,7 +230,7 @@ export class NsfwWatcherService extends Disposable implements IWatcherService { // Normalizes a set of root paths by removing any root paths that are // sub-paths of other roots. return roots.filter(r => roots.every(other => { - return !(r.path.length > other.path.length && extpath.isEqualOrParent(r.path, other.path)); + return !(r.path.length > other.path.length && isEqualOrParent(r.path, other.path)); })); } diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index 895e5dfa959..25276aa2ac4 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -6,9 +6,8 @@ import * as chokidar from 'chokidar'; import * as fs from 'fs'; import * as gracefulFs from 'graceful-fs'; -gracefulFs.gracefulify(fs); -import * as extpath from 'vs/base/common/extpath'; import * as glob from 'vs/base/common/glob'; +import { isEqualOrParent } from 'vs/base/common/extpath'; import { FileChangeType } from 'vs/platform/files/common/files'; import { ThrottledDelayer } from 'vs/base/common/async'; import { normalizeNFC } from 'vs/base/common/normalization'; @@ -20,6 +19,8 @@ import { Emitter, Event } from 'vs/base/common/event'; import { equals } from 'vs/base/common/arrays'; import { Disposable } from 'vs/base/common/lifecycle'; +gracefulFs.gracefulify(fs); // enable gracefulFs + process.noAsar = true; // disable ASAR support in watcher process interface IWatcher { @@ -311,7 +312,7 @@ function isIgnored(path: string, requests: ExtendedWatcherRequest[]): boolean { return false; } - if (extpath.isEqualOrParent(path, request.path)) { + if (isEqualOrParent(path, request.path)) { if (!request.parsedPattern) { if (request.excludes && request.excludes.length > 0) { const pattern = `{${request.excludes.join(',')}}`; @@ -343,7 +344,7 @@ export function normalizeRoots(requests: IWatcherRequest[]): { [basePath: string for (const request of requests) { const basePath = request.path; const ignored = (request.excludes || []).sort(); - if (prevRequest && (extpath.isEqualOrParent(basePath, prevRequest.path))) { + if (prevRequest && (isEqualOrParent(basePath, prevRequest.path))) { if (!isEqualIgnore(ignored, prevRequest.excludes)) { result[prevRequest.path].push({ path: basePath, excludes: ignored }); } diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index d5ff4b46d4b..b097660f24a 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -12,7 +12,7 @@ import { isLinux } from 'vs/base/common/platform'; import { Event, Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; import { createHash } from 'crypto'; -import * as json from 'vs/base/common/json'; +import { parse } from 'vs/base/common/json'; import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; @@ -66,7 +66,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain declare readonly _serviceBrand: undefined; - private readonly untitledWorkspacesHome: URI; // local URI that contains all untitled workspaces + private readonly untitledWorkspacesHome = this.environmentService.untitledWorkspacesHome; // local URI that contains all untitled workspaces private readonly _onUntitledWorkspaceDeleted = this._register(new Emitter()); readonly onUntitledWorkspaceDeleted: Event = this._onUntitledWorkspaceDeleted.event; @@ -81,8 +81,6 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain @IDialogMainService private readonly dialogMainService: IDialogMainService ) { super(); - - this.untitledWorkspacesHome = environmentService.untitledWorkspacesHome; } resolveLocalWorkspaceSync(uri: URI): IResolvedWorkspace | null { @@ -127,7 +125,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain private doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace { // Parse workspace file - let storedWorkspace: IStoredWorkspace = json.parse(contents); // use fault tolerant parser + const storedWorkspace: IStoredWorkspace = parse(contents); // use fault tolerant parser // Filter out folders which do not have a path or uri set if (storedWorkspace && Array.isArray(storedWorkspace.folders)) { @@ -226,7 +224,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain } getUntitledWorkspacesSync(): IUntitledWorkspaceInfo[] { - let untitledWorkspaces: IUntitledWorkspaceInfo[] = []; + const untitledWorkspaces: IUntitledWorkspaceInfo[] = []; try { const untitledWorkspacePaths = readdirSync(this.untitledWorkspacesHome.fsPath).map(folder => joinPath(this.untitledWorkspacesHome, folder, UNTITLED_WORKSPACE_NAME)); for (const untitledWorkspacePath of untitledWorkspacePaths) { @@ -243,6 +241,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain this.logService.warn(`Unable to read folders in ${this.untitledWorkspacesHome} (${error}).`); } } + return untitledWorkspaces; } diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts index fb420ef52ae..c2910ec1192 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts @@ -9,7 +9,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { TerminalLink, OPEN_FILE_LABEL, FOLDER_IN_WORKSPACE_LABEL, FOLDER_NOT_IN_WORKSPACE_LABEL } from 'vs/workbench/contrib/terminal/browser/links/terminalLink'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { isEqualOrParent } from 'vs/base/common/resources'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IHostService } from 'vs/workbench/services/host/browser/host'; @@ -62,7 +62,8 @@ export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider @IInstantiationService private readonly _instantiationService: IInstantiationService, @ICommandService private readonly _commandService: ICommandService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, - @IHostService private readonly _hostService: IHostService + @IHostService private readonly _hostService: IHostService, + @IUriIdentityService private readonly _uriIdentityService: IUriIdentityService ) { super(); } @@ -183,7 +184,7 @@ export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider private _isDirectoryInsideWorkspace(uri: URI) { const folders = this._workspaceContextService.getWorkspace().folders; for (let i = 0; i < folders.length; i++) { - if (isEqualOrParent(uri, folders[i].uri)) { + if (this._uriIdentityService.extUri.isEqualOrParent(uri, folders[i].uri)) { return true; } } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 458e5e41119..bd176bffd4c 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -11,7 +11,7 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn import { Registry } from 'vs/platform/registry/common/platform'; import { ResourceMap } from 'vs/base/common/map'; import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; -import { IFileService, FileOperationEvent, FileOperation, FileChangesEvent, FileChangeType, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; +import { IFileService, FileOperationEvent, FileOperation, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; @@ -251,8 +251,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { if (this.uriIdentityService.extUri.isEqual(source, resource)) { targetResource = target; // file got moved } else { - const ignoreCase = !this.fileService.hasCapability(resource, FileSystemProviderCapabilities.PathCaseSensitive); - const index = indexOfPath(resource.path, source.path, ignoreCase); + const index = indexOfPath(resource.path, source.path, this.uriIdentityService.extUri.ignorePathCasing(resource)); targetResource = joinPath(target, resource.path.substr(index + source.path.length + 1)); // parent folder got moved } diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts index 8a6d94c1e5a..5bfe4a37b48 100644 --- a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts @@ -221,6 +221,7 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi } // Allow to save the workspace of the current window + // if we have an identical match on the path if (isEqual(workspaceIdentifier.configPath, path)) { return this.saveWorkspace(workspaceIdentifier); } From 208bfc9970c644b004fcfbe19eebd1867feddabe Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Dec 2020 11:06:31 +0100 Subject: [PATCH 0670/1837] fixes #112046 --- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 74467fa8078..93db72f1439 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -305,7 +305,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { if (this.styleElement) { const debugConsole = this.configurationService.getValue('debug').console; const fontSize = debugConsole.fontSize; - const fontFamily = debugConsole.fontFamily === 'default' ? 'var(--monaco-monospace-font)' : `'${debugConsole.fontFamily}'`; + const fontFamily = debugConsole.fontFamily === 'default' ? 'var(--monaco-monospace-font)' : `${debugConsole.fontFamily}`; const lineHeight = debugConsole.lineHeight ? `${debugConsole.lineHeight}px` : '1.4em'; const backgroundColor = this.themeService.getColorTheme().getColor(this.getBackgroundColor()); From 46ee31fce0f143910dc3ab89afb568ffcfd0a4ee Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Dec 2020 16:27:07 +0100 Subject: [PATCH 0671/1837] Try to fix markdown tooltip for Safari #111756 --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 44c56834ff0..50274475e84 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -191,6 +191,7 @@ export class IconLabel extends Disposable { } private setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, markdownTooltip: string | IIconLabelMarkdownString): void { + htmlElement.setAttribute('title', ''); htmlElement.removeAttribute('title'); let tooltip: () => Promise; if (isString(markdownTooltip)) { From 9edc69706f804c74f22c3c031721404ef0e16fdb Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Dec 2020 11:09:44 +0100 Subject: [PATCH 0672/1837] Just set textContent for custom hover Fixes #111643 --- .../services/hover/browser/hoverWidget.ts | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/hover/browser/hoverWidget.ts b/src/vs/workbench/services/hover/browser/hoverWidget.ts index f0009cb66aa..a7fba5f9a76 100644 --- a/src/vs/workbench/services/hover/browser/hoverWidget.ts +++ b/src/vs/workbench/services/hover/browser/hoverWidget.ts @@ -16,7 +16,6 @@ import { Widget } from 'vs/base/browser/ui/widget'; import { AnchorPosition } from 'vs/base/browser/ui/contextview/contextview'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { MarkdownString, MarkdownStringTextNewlineStyle } from 'vs/base/common/htmlContent'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer'; @@ -82,25 +81,28 @@ export class HoverWidget extends Widget { const rowElement = $('div.hover-row.markdown-hover'); const contentsElement = $('div.hover-contents'); - const markdown = typeof options.text === 'string' ? new MarkdownString().appendText(options.text, MarkdownStringTextNewlineStyle.Break) : options.text; + if (typeof options.text === 'string') { + contentsElement.textContent = options.text; + } else { + const markdown = options.text; + const mdRenderer = this._instantiationService.createInstance( + MarkdownRenderer, + { codeBlockFontFamily: this._configurationService.getValue('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily } + ); - const mdRenderer = this._instantiationService.createInstance( - MarkdownRenderer, - { codeBlockFontFamily: this._configurationService.getValue('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily } - ); - - const { element } = mdRenderer.render(markdown, { - actionHandler: { - callback: (content) => this._linkHandler(content), - disposeables: this._messageListeners - }, - asyncRenderCallback: () => { - contentsElement.classList.add('code-hover-contents'); - // This changes the dimensions of the hover so trigger a layout - this._onRequestLayout.fire(); - } - }); - contentsElement.appendChild(element); + const { element } = mdRenderer.render(markdown, { + actionHandler: { + callback: (content) => this._linkHandler(content), + disposeables: this._messageListeners + }, + asyncRenderCallback: () => { + contentsElement.classList.add('code-hover-contents'); + // This changes the dimensions of the hover so trigger a layout + this._onRequestLayout.fire(); + } + }); + contentsElement.appendChild(element); + } rowElement.appendChild(contentsElement); this._hover.contentsDomNode.appendChild(rowElement); From 92d6f00d6e2f01efedd26b657c7218baf8c9d5e9 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Dec 2020 15:38:48 +0100 Subject: [PATCH 0673/1837] debug console: color the debug group elements fixes #112050 --- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- .../contrib/debug/browser/replViewer.ts | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 93db72f1439..58e44a25ad6 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -559,7 +559,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { this.instantiationService.createInstance(ReplVariablesRenderer, linkDetector), this.instantiationService.createInstance(ReplSimpleElementsRenderer, linkDetector), new ReplEvaluationInputsRenderer(), - new ReplGroupRenderer(), + this.instantiationService.createInstance(ReplGroupRenderer, linkDetector), new ReplEvaluationResultsRenderer(linkDetector), new ReplRawObjectsRenderer(linkDetector), ], diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts index 0d432417fcf..01614150f9e 100644 --- a/src/vs/workbench/contrib/debug/browser/replViewer.ts +++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts @@ -34,7 +34,7 @@ interface IReplEvaluationInputTemplateData { } interface IReplGroupTemplateData { - label: HighlightedLabel; + label: HTMLElement; } interface IReplEvaluationResultTemplateData { @@ -87,22 +87,28 @@ export class ReplEvaluationInputsRenderer implements ITreeRenderer { static readonly ID = 'replGroup'; + constructor( + private readonly linkDetector: LinkDetector, + @IThemeService private readonly themeService: IThemeService + ) { } + get templateId(): string { return ReplGroupRenderer.ID; } - renderTemplate(container: HTMLElement): IReplEvaluationInputTemplateData { - const input = dom.append(container, $('.expression')); - const label = new HighlightedLabel(input, false); + renderTemplate(container: HTMLElement): IReplGroupTemplateData { + const label = dom.append(container, $('.expression')); return { label }; } renderElement(element: ITreeNode, _index: number, templateData: IReplGroupTemplateData): void { const replGroup = element.element; - templateData.label.set(replGroup.name, createMatches(element.filterData)); + dom.clearNode(templateData.label); + const result = handleANSIOutput(replGroup.name, this.linkDetector, this.themeService, undefined); + templateData.label.appendChild(result); } - disposeTemplate(_templateData: IReplEvaluationInputTemplateData): void { + disposeTemplate(_templateData: IReplGroupTemplateData): void { // noop } } From c8b592a57a31a5bd53d1e9fdf1847a850d61757e Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Dec 2020 16:08:06 +0100 Subject: [PATCH 0674/1837] debug editor decorations: always decorate top stack frame, and decorate focused stack frame if it is not the top stack frame fyi @hediet --- .../browser/callStackEditorContribution.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/callStackEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/callStackEditorContribution.ts index 9fd5d78b003..fa7901ea386 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackEditorContribution.ts @@ -127,17 +127,21 @@ export class CallStackEditorContribution implements IEditorContribution { const isSessionFocused = s === focusedStackFrame?.thread.session; s.getAllThreads().forEach(t => { if (t.stopped) { - let candidateStackFrame = t === focusedStackFrame?.thread ? focusedStackFrame : undefined; - if (!candidateStackFrame) { - const callStack = t.getCallStack(); - if (callStack.length) { - candidateStackFrame = callStack[0]; + const callStack = t.getCallStack(); + const stackFrames: IStackFrame[] = []; + if (callStack.length > 0) { + // Always decorate top stack frame, and decorate focused stack frame if it is not the top stack frame + if (focusedStackFrame && !focusedStackFrame.equals(callStack[0])) { + stackFrames.push(focusedStackFrame); } + stackFrames.push(callStack[0]); } - if (candidateStackFrame && this.uriIdentityService.extUri.isEqual(candidateStackFrame.source.uri, this.editor.getModel()?.uri)) { - decorations.push(...createDecorationsForStackFrame(candidateStackFrame, this.topStackFrameRange, isSessionFocused)); - } + stackFrames.forEach(candidateStackFrame => { + if (candidateStackFrame && this.uriIdentityService.extUri.isEqual(candidateStackFrame.source.uri, this.editor.getModel()?.uri)) { + decorations.push(...createDecorationsForStackFrame(candidateStackFrame, this.topStackFrameRange, isSessionFocused)); + } + }); } }); }); From 768bcf454221232b6d1f342fd801d67266926db9 Mon Sep 17 00:00:00 2001 From: Andre-Fonteles Date: Tue, 8 Dec 2020 10:16:49 -0500 Subject: [PATCH 0675/1837] Fixed tab switching too fast when wheeling/scrolling (#112034) * Fixed tab switching too fast when wheeling/scrolling * Feedback/Suggested changes adoption * some :lipstick: before merge Co-authored-by: Andre Fonteles Co-authored-by: Benjamin Pasero --- .../browser/parts/editor/tabsTitleControl.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index bcd835f4cc5..44e788c7886 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -73,6 +73,9 @@ export class TabsTitleControl extends TitleControl { private static readonly TAB_HEIGHT = 35; + private static readonly MOUSE_WHEEL_EVENT_THRESHOLD = 150; + private static readonly MOUSE_WHEEL_DISTANCE_THRESHOLD = 1.5; + private titleContainer: HTMLElement | undefined; private tabsAndActionsContainer: HTMLElement | undefined; private tabsContainer: HTMLElement | undefined; @@ -93,6 +96,8 @@ export class TabsTitleControl extends TitleControl { private path: IPath = isWindows ? win32 : posix; + private lastMouseWheelEventTime = 0; + constructor( parent: HTMLElement, accessor: IEditorGroupsAccessor, @@ -337,8 +342,27 @@ export class TabsTitleControl extends TitleControl { } } - // Figure out scrolling direction - const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + (e.deltaX < 0 || e.deltaY < 0 /* scrolling up */ ? -1 : 1)); + // Ignore event if the last one happened too recently (https://github.com/microsoft/vscode/issues/96409) + // The restriction is relaxed according to the absolute value of `deltaX` and `deltaY` + // to support discrete (mouse wheel) and contiguous scrolling (touchpad) equally well + const now = Date.now(); + if (now - this.lastMouseWheelEventTime < TabsTitleControl.MOUSE_WHEEL_EVENT_THRESHOLD - 2 * (Math.abs(e.deltaX) + Math.abs(e.deltaY))) { + return; + } + + this.lastMouseWheelEventTime = now; + + // Figure out scrolling direction but ignore it if too subtle + let tabSwitchDirection: number; + if (e.deltaX + e.deltaY < - TabsTitleControl.MOUSE_WHEEL_DISTANCE_THRESHOLD) { + tabSwitchDirection = -1; + } else if (e.deltaX + e.deltaY > TabsTitleControl.MOUSE_WHEEL_DISTANCE_THRESHOLD) { + tabSwitchDirection = 1; + } else { + return; + } + + const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + tabSwitchDirection); if (!nextEditor) { return; } From 5e5ae15b22c6617f22923edce6e359897cac0f83 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Dec 2020 16:17:36 +0100 Subject: [PATCH 0676/1837] debug: show the hover not so eagarly (do it twice as slow as editor hover) --- .../workbench/contrib/debug/browser/debugEditorContribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index dbd53aa5bba..f37f9dd71d0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -339,7 +339,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { if (this.hoverRange) { this.showHover(this.hoverRange, false); } - }, hoverOption.delay); + }, hoverOption.delay * 2); this.toDispose.push(scheduler); return scheduler; From b3a3dc9c0a5d7840a11fe17859e61b780fa5cb84 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Dec 2020 17:03:21 +0100 Subject: [PATCH 0677/1837] Debt: Test findPorts (#112092) Add a test for the port finding logic --- .../api/node/extHostTunnelService.ts | 173 ++++++------ .../node/api/extHostTunnelService.test.ts | 266 ++++++++++++++++++ 2 files changed, 353 insertions(+), 86 deletions(-) create mode 100644 src/vs/workbench/test/node/api/extHostTunnelService.test.ts diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 922451d1079..ae477f9eaad 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -34,6 +34,92 @@ class ExtensionTunnel implements vscode.Tunnel { } } +export function getSockets(stdout: string): { pid: number, socket: number }[] { + const lines = stdout.trim().split('\n'); + const mapped: { pid: number, socket: number }[] = []; + lines.forEach(line => { + const match = /\/proc\/(\d+)\/fd\/\d+ -> socket:\[(\d+)\]/.exec(line)!; + if (match && match.length >= 3) { + mapped.push({ + pid: parseInt(match[1], 10), + socket: parseInt(match[2], 10) + }); + } + }); + return mapped; +} + +export function loadListeningPorts(...stdouts: string[]): { socket: number, ip: string, port: number }[] { + const table = ([] as Record[]).concat(...stdouts.map(loadConnectionTable)); + return [ + ...new Map( + table.filter(row => row.st === '0A') + .map(row => { + const address = row.local_address.split(':'); + return { + socket: parseInt(row.inode, 10), + ip: parseIpAddress(address[0]), + port: parseInt(address[1], 16) + }; + }).map(port => [port.ip + ':' + port.port, port]) + ).values() + ]; +} + +export function parseIpAddress(hex: string): string { + let result = ''; + if (hex.length === 8) { + for (let i = hex.length - 2; i >= 0; i -= 2) { + result += parseInt(hex.substr(i, 2), 16); + if (i !== 0) { + result += '.'; + } + } + } else { + for (let i = hex.length - 4; i >= 0; i -= 4) { + result += parseInt(hex.substr(i, 4), 16).toString(16); + if (i !== 0) { + result += ':'; + } + } + } + return result; +} + +export function loadConnectionTable(stdout: string): Record[] { + const lines = stdout.trim().split('\n'); + const names = lines.shift()!.trim().split(/\s+/) + .filter(name => name !== 'rx_queue' && name !== 'tm->when'); + const table = lines.map(line => line.trim().split(/\s+/).reduce((obj, value, i) => { + obj[names[i] || i] = value; + return obj; + }, {} as Record)); + return table; +} + +export async function findPorts(tcp: string, tcp6: string, procSockets: string, processes: { pid: number, cwd: string, cmd: string }[]) { + const connections: { socket: number, ip: string, port: number }[] = loadListeningPorts(tcp, tcp6); + const sockets = getSockets(procSockets); + + const socketMap = sockets.reduce((m, socket) => { + m[socket.socket] = socket; + return m; + }, {} as Record); + const processMap = processes.reduce((m, process) => { + m[process.pid] = process; + return m; + }, {} as Record); + + const ports: { host: string, port: number, detail: string }[] = []; + connections.filter((connection => socketMap[connection.socket])).forEach(({ socket, ip, port }) => { + const command = processMap[socketMap[socket].pid].cmd; + if (!command.match(/.*\.vscode-server-[a-zA-Z]+\/bin.*/) && (command.indexOf('out/vs/server/main.js') === -1)) { + ports.push({ host: ip, port, detail: processMap[socketMap[socket].pid].cmd }); + } + }); + return ports; +} + export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService { readonly _serviceBrand: undefined; private readonly _proxy: MainThreadTunnelServiceShape; @@ -137,9 +223,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe return undefined; } - async findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]> { - const ports: { host: string, port: number, detail: string }[] = []; let tcp: string = ''; let tcp6: string = ''; try { @@ -170,89 +254,6 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe // } } - - const connections: { socket: number, ip: string, port: number }[] = this.loadListeningPorts(tcp, tcp6); - const sockets = this.getSockets(procSockets); - - const socketMap = sockets.reduce((m, socket) => { - m[socket.socket] = socket; - return m; - }, {} as Record); - const processMap = processes.reduce((m, process) => { - m[process.pid] = process; - return m; - }, {} as Record); - - connections.filter((connection => socketMap[connection.socket])).forEach(({ socket, ip, port }) => { - const command = processMap[socketMap[socket].pid].cmd; - if (!command.match(/.*\.vscode-server-[a-zA-Z]+\/bin.*/) && (command.indexOf('out/vs/server/main.js') === -1)) { - ports.push({ host: ip, port, detail: processMap[socketMap[socket].pid].cmd }); - } - }); - - return ports; - } - - private getSockets(stdout: string): { pid: number, socket: number }[] { - const lines = stdout.trim().split('\n'); - const mapped: { pid: number, socket: number }[] = []; - lines.forEach(line => { - const match = /\/proc\/(\d+)\/fd\/\d+ -> socket:\[(\d+)\]/.exec(line)!; - if (match && match.length >= 3) { - mapped.push({ - pid: parseInt(match[1], 10), - socket: parseInt(match[2], 10) - }); - } - }); - return mapped; - } - - private loadListeningPorts(...stdouts: string[]): { socket: number, ip: string, port: number }[] { - const table = ([] as Record[]).concat(...stdouts.map(this.loadConnectionTable)); - return [ - ...new Map( - table.filter(row => row.st === '0A') - .map(row => { - const address = row.local_address.split(':'); - return { - socket: parseInt(row.inode, 10), - ip: this.parseIpAddress(address[0]), - port: parseInt(address[1], 16) - }; - }).map(port => [port.ip + ':' + port.port, port]) - ).values() - ]; - } - - private parseIpAddress(hex: string): string { - let result = ''; - if (hex.length === 8) { - for (let i = hex.length - 2; i >= 0; i -= 2) { - result += parseInt(hex.substr(i, 2), 16); - if (i !== 0) { - result += '.'; - } - } - } else { - for (let i = hex.length - 4; i >= 0; i -= 4) { - result += parseInt(hex.substr(i, 4), 16).toString(16); - if (i !== 0) { - result += ':'; - } - } - } - return result; - } - - private loadConnectionTable(stdout: string): Record[] { - const lines = stdout.trim().split('\n'); - const names = lines.shift()!.trim().split(/\s+/) - .filter(name => name !== 'rx_queue' && name !== 'tm->when'); - const table = lines.map(line => line.trim().split(/\s+/).reduce((obj, value, i) => { - obj[names[i] || i] = value; - return obj; - }, {} as Record)); - return table; + return findPorts(tcp, tcp6, procSockets, processes); } } diff --git a/src/vs/workbench/test/node/api/extHostTunnelService.test.ts b/src/vs/workbench/test/node/api/extHostTunnelService.test.ts new file mode 100644 index 00000000000..d10b52100e0 --- /dev/null +++ b/src/vs/workbench/test/node/api/extHostTunnelService.test.ts @@ -0,0 +1,266 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as platform from 'vs/base/common/platform'; +import { findPorts, getSockets, loadConnectionTable, loadListeningPorts } from 'vs/workbench/api/node/extHostTunnelService'; + +const tcp = + ` sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 00000000:0BBA 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2335214 1 0000000010173312 100 0 0 10 0 + 1: 00000000:1AF3 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2334514 1 000000008815920b 100 0 0 10 0 + 2: 0100007F:A9EA 0100007F:1AF3 01 00000000:00000000 00:00000000 00000000 1000 0 2334521 1 00000000a37d44c6 21 4 0 10 -1 + 3: 0100007F:E8B4 0100007F:98EF 01 00000000:00000000 00:00000000 00000000 1000 0 2334532 1 0000000031b88f06 21 4 0 10 -1 + 4: 0100007F:866C 0100007F:8783 01 00000000:00000000 00:00000000 00000000 1000 0 2334510 1 00000000cbf670bb 21 4 30 10 -1 + 5: 0100007F:1AF3 0100007F:A9EA 01 00000000:00000000 00:00000000 00000000 1000 0 2338989 1 0000000000bace62 21 4 1 10 -1 +`; +const tcp6 = + ` sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 00000000000000000000000000000000:815B 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2321070 1 00000000c44f3f02 100 0 0 10 0 + 1: 00000000000000000000000000000000:8783 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2334509 1 000000003915e812 100 0 0 10 0 + 2: 00000000000000000000000000000000:9907 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2284465 1 00000000f13b9374 100 0 0 10 0 + 3: 00000000000000000000000000000000:98EF 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2334531 1 00000000184cae9c 100 0 0 10 0 + 4: 00000000000000000000000000000000:8BCF 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 2329890 1 00000000c05a3466 100 0 0 10 0 + 5: 0000000000000000FFFF00000100007F:8783 0000000000000000FFFF00000100007F:866C 01 00000000:00000000 00:00000000 00000000 1000 0 2334511 1 00000000bf547132 21 4 1 10 -1 + 6: 0000000000000000FFFF00000100007F:98EF 0000000000000000FFFF00000100007F:E8B4 01 00000000:00000000 00:00000000 00000000 1000 0 2334533 1 0000000039d0bcd2 21 4 1 10 -1 + 7: 0000000000000000FFFF0000DFD317AC:9907 0000000000000000FFFF000001D017AC:C123 01 0000005A:00000000 01:00000017 00000000 1000 0 2311039 3 0000000067b6c8db 23 5 25 10 52 + 8: 0000000000000000FFFF0000DFD317AC:9907 0000000000000000FFFF000001D017AC:C124 01 00000000:00000000 00:00000000 00000000 1000 0 2311040 1 00000000230bb017 25 4 30 10 28 + 9: 0000000000000000FFFF0000DFD317AC:9907 0000000000000000FFFF000001D017AC:C213 01 00000000:00000000 00:00000000 00000000 1000 0 2331501 1 00000000957fcb4a 26 4 30 10 57 + 10: 0000000000000000FFFF0000DFD317AC:9907 0000000000000000FFFF000001D017AC:C214 01 00000000:00000000 00:00000000 00000000 1000 0 2331500 1 00000000d7f87ceb 25 4 28 10 -1 +`; + +const procSockets = + `ls: cannot access '/proc/8289/fd/255': No such file or directory + ls: cannot access '/proc/8289/fd/3': No such file or directory + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/230/fd/3 -> socket:[21862] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/0 -> socket:[2311043] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/1 -> socket:[2311045] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/19 -> socket:[2311040] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/2 -> socket:[2311047] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/20 -> socket:[2314928] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/22 -> socket:[2307042] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/24 -> socket:[2307051] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/25 -> socket:[2307044] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/27 -> socket:[2307046] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/29 -> socket:[2307053] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/3 -> socket:[2311049] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/30 -> socket:[2307048] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/32 -> socket:[2307055] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/33 -> socket:[2307067] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/34 -> socket:[2307057] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/35 -> socket:[2321483] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/37 -> socket:[2321070] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/41 -> socket:[2321485] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/42 -> socket:[2321074] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/43 -> socket:[2321487] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/44 -> socket:[2329890] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/45 -> socket:[2321489] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2504/fd/46 -> socket:[2334509] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/47 -> socket:[2334510] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/48 -> socket:[2329894] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/49 -> socket:[2334511] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/50 -> socket:[2334515] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/51 -> socket:[2334519] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/52 -> socket:[2334518] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/53 -> socket:[2334521] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/54 -> socket:[2334531] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/55 -> socket:[2334532] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/2504/fd/56 -> socket:[2334533] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2515/fd/3 -> socket:[2311053] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2719/fd/0 -> socket:[2307043] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2719/fd/1 -> socket:[2307045] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2719/fd/2 -> socket:[2307047] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2719/fd/3 -> socket:[2307049] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2725/fd/0 -> socket:[2307052] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2725/fd/1 -> socket:[2307054] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2725/fd/2 -> socket:[2307056] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2725/fd/20 -> socket:[2290617] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2725/fd/3 -> socket:[2307058] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2739/fd/0 -> socket:[2307052] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2739/fd/1 -> socket:[2307054] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2739/fd/2 -> socket:[2307056] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2739/fd/3 -> socket:[2290618] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2795/fd/0 -> socket:[2321484] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2795/fd/1 -> socket:[2321486] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2795/fd/2 -> socket:[2321488] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/2795/fd/3 -> socket:[2321490] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/18 -> socket:[2284465] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/19 -> socket:[2311039] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/23 -> socket:[2331501] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/24 -> socket:[2311052] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/25 -> socket:[2311042] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/26 -> socket:[2331504] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/27 -> socket:[2311051] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/29 -> socket:[2311044] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/314/fd/30 -> socket:[2321909] + lrwx------ 1 alex alex 64 Dec 8 14:59 /proc/314/fd/31 -> socket:[2311046] + lrwx------ 1 alex alex 64 Dec 8 15:14 /proc/314/fd/33 -> socket:[2311048] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/314/fd/35 -> socket:[2329692] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/314/fd/37 -> socket:[2331506] + lrwx------ 1 alex alex 64 Dec 8 15:20 /proc/314/fd/40 -> socket:[2331508] + lrwx------ 1 alex alex 64 Dec 8 15:20 /proc/314/fd/42 -> socket:[2331510] + lrwx------ 1 alex alex 64 Dec 8 15:17 /proc/314/fd/68 -> socket:[2322083] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4412/fd/20 -> socket:[2335214] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/0 -> socket:[2331505] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/1 -> socket:[2331507] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/2 -> socket:[2331509] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/23 -> socket:[2334514] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/24 -> socket:[2338989] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/26 -> socket:[2338276] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/27 -> socket:[2331500] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/3 -> socket:[2331511] + lrwx------ 1 alex alex 64 Dec 8 15:22 /proc/4496/fd/31 -> socket:[2338285]`; + +const processes: { pid: number, cwd: string, cmd: string }[] = [ + { + pid: 230, + cwd: '/mnt/c/WINDOWS/system32', + cmd: 'dockerserve--addressunix:///home/alex/.docker/run/docker-cli-api.sock', + }, + { + pid: 2504, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/bootstrap-fork--type=extensionHost--uriTransformerPath=/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/vs/server/uriTransformer.js--useHostProxy=', + }, + { + pid: 2515, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/bootstrap-fork--type=watcherService' + }, + { + pid: 2526, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: '/bin/bash' + }, { + pid: 2719, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node--max-old-space-size=3072/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/node_modules/typescript/lib/tsserver.js--serverModepartialSemantic--useInferredProjectPerProjectRoot--disableAutomaticTypingAcquisition--cancellationPipeName/tmp/vscode-typescript1000/7cfa7171c0c00aacf1ee/tscancellation-602cd80b954818b6a2f7.tmp*--logVerbosityverbose--logFile/home/alex/.vscode-server-insiders/data/logs/20201208T145954/exthost2/vscode.typescript-language-features/tsserver-log-nxBt2m/tsserver.log--globalPluginstypescript-vscode-sh-plugin--pluginProbeLocations/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/typescript-language-features--localeen--noGetErrOnBackgroundUpdate--validateDefaultNpmLocation' + }, + { + pid: 2725, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node--max-old-space-size=3072/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/node_modules/typescript/lib/tsserver.js--useInferredProjectPerProjectRoot--enableTelemetry--cancellationPipeName/tmp/vscode-typescript1000/7cfa7171c0c00aacf1ee/tscancellation-04a0b92f880c2fd535ae.tmp*--logVerbosityverbose--logFile/home/alex/.vscode-server-insiders/data/logs/20201208T145954/exthost2/vscode.typescript-language-features/tsserver-log-fqyBrs/tsserver.log--globalPluginstypescript-vscode-sh-plugin--pluginProbeLocations/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/typescript-language-features--localeen--noGetErrOnBackgroundUpdate--validateDefaultNpmLocation' + }, + { + pid: 2739, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/node_modules/typescript/lib/typingsInstaller.js--globalTypingsCacheLocation/home/alex/.cache/typescript/4.1--enableTelemetry--logFile/home/alex/.vscode-server-insiders/data/logs/20201208T145954/exthost2/vscode.typescript-language-features/tsserver-log-fqyBrs/ti-2725.log--typesMapLocation/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/node_modules/typescript/lib/typesMap.json--validateDefaultNpmLocation' + }, + { + pid: 2795, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/json-language-features/server/dist/node/jsonServerMain--node-ipc--clientProcessId=2504' + }, + { + pid: 286, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: 'sh-c\"$VSCODE_WSL_EXT_LOCATION/ scripts / wslServer.sh\" bc13785d3dd99b4b0e9da9aed17bb79809a50804 insider .vscode-server-insiders 0 ' + }, + { + pid: 287, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: 'sh/mnt/c/Users/alros/.vscode-insiders/extensions/ms-vscode-remote.remote-wsl-0.52.0/scripts/wslServer.shbc13785d3dd99b4b0e9da9aed17bb79809a50804insider.vscode-server-insiders0' + }, + { + pid: 3058, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: 'npm' + }, + { + pid: 3070, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: 'sh-ctsc -watch -p ./' + }, + { + pid: 3071, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: 'node/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample/node_modules/.bin/tsc-watch-p./' + }, + { + pid: 312, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: 'sh/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/server.sh--port=0--use-host-proxy--enable-remote-auto-shutdown--print-ip-address' + }, + { + pid: 314, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/vs/server/main.js--port=0--use-host-proxy--enable-remote-auto-shutdown--print-ip-address' + }, + { + pid: 3172, + cwd: '/home/alex', + cmd: '/bin/bash' + }, + { + pid: 3610, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: '/bin/bash' + }, + { + pid: 4412, + cwd: '/home/alex/repos/Microsoft/vscode-extension-samples/helloworld-sample', + cmd: 'http-server' + }, + { + pid: 4496, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node--inspect-brk=0.0.0.0:6899/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/bootstrap-fork--type=extensionHost--uriTransformerPath=/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/out/vs/server/uriTransformer.js--useHostProxy=' + }, + { + pid: 4507, + cwd: '/mnt/c/Users/alros/AppData/Local/Programs/Microsoft VS Code Insiders', + cmd: '/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/node/home/alex/.vscode-server-insiders/bin/bc13785d3dd99b4b0e9da9aed17bb79809a50804/extensions/ms-vscode.js-debug/src/hash.bundle.js' + } +]; + +if (platform.isLinux) { + suite('ExtHostTunnelService', () => { + test('getSockets', function () { + const result = getSockets(procSockets); + assert.equal(result.length, 78); + // 4412 is the pid fo the http-server in the test data + assert.notEqual(result.find(value => value.pid === 4412), undefined); + }); + + test('loadConnectionTable', function () { + const result = loadConnectionTable(tcp); + assert.equal(result.length, 6); + assert.deepEqual(result[0], { + 10: '1', + 11: '0000000010173312', + 12: '100', + 13: '0', + 14: '0', + 15: '10', + 16: '0', + inode: '2335214', + local_address: '00000000:0BBA', + rem_address: '00000000:0000', + retrnsmt: '00000000', + sl: '0:', + st: '0A', + timeout: '0', + tr: '00:00000000', + tx_queue: '00000000:00000000', + uid: '1000' + }); + }); + + test('loadListeningPorts', function () { + const result = loadListeningPorts(tcp, tcp6); + // There should be 7 based on the input data. One of them should be 3002. + assert.equal(result.length, 7); + assert.notEqual(result.find(value => value.port === 3002), undefined); + }); + + test('findPorts', async function () { + const result = await findPorts(tcp, tcp6, procSockets, processes); + assert.equal(result.length, 1); + assert.equal(result[0].host, '0.0.0.0'); + assert.equal(result[0].port, 3002); + assert.equal(result[0].detail, 'http-server'); + }); + }); +} From affd21e65ac41360704b573a4ca3b90107fd9ee8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Dec 2020 17:20:17 +0100 Subject: [PATCH 0678/1837] tabs - partially take changes from PR 106448 to reduce diff --- src/vs/base/browser/dom.ts | 2 + src/vs/workbench/browser/part.ts | 2 +- .../browser/parts/editor/editorGroupView.ts | 14 ++--- .../parts/editor/noTabsTitleControl.ts | 6 ++- .../browser/parts/editor/tabsTitleControl.ts | 54 ++++++++++--------- .../browser/parts/editor/titleControl.ts | 16 +++++- 6 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index b4740dadea0..283b8c82130 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -451,6 +451,8 @@ export interface IDimension { export class Dimension implements IDimension { + static readonly None = new Dimension(0, 0); + constructor( public readonly width: number, public readonly height: number, diff --git a/src/vs/workbench/browser/part.ts b/src/vs/workbench/browser/part.ts index dfab3bc5cfc..8e78cbccc27 100644 --- a/src/vs/workbench/browser/part.ts +++ b/src/vs/workbench/browser/part.ts @@ -162,7 +162,7 @@ class PartLayout { if (this.options && this.options.hasTitle) { titleSize = new Dimension(width, Math.min(height, PartLayout.TITLE_HEIGHT)); } else { - titleSize = new Dimension(0, 0); + titleSize = Dimension.None; } let contentWidth = width; diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index a212456dd4f..ed48c489007 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -1704,13 +1704,15 @@ export class EditorGroupView extends Themable implements IEditorGroupView { layout(width: number, height: number): void { this.dimension = new Dimension(width, height); - // Ensure editor container gets height as CSS depending on the preferred height of the title control - const titleHeight = this.titleDimensions.height; - const editorHeight = Math.max(0, height - titleHeight); - this.editorContainer.style.height = `${editorHeight}px`; + // Layout the title area first to receive the size it occupies + const titleAreaSize = this.titleAreaControl.layout({ + container: this.dimension, + available: new Dimension(width, height - this.editorControl.minimumHeight) + }); - // Forward to controls - this.titleAreaControl.layout(new Dimension(width, titleHeight)); + // Pass the container width and remaining height to the editor layout + const editorHeight = Math.max(0, height - titleAreaSize.height); + this.editorContainer.style.height = `${editorHeight}px`; this.editorControl.layout(new Dimension(width, editorHeight)); } diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 66a7caec173..35f36592e4a 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/notabstitlecontrol'; import { EditorResourceAccessor, Verbosity, IEditorInput, IEditorPartOptions, SideBySideEditor } from 'vs/workbench/common/editor'; -import { TitleControl, IToolbarActions } from 'vs/workbench/browser/parts/editor/titleControl'; +import { TitleControl, IToolbarActions, ITitleControlDimensions } from 'vs/workbench/browser/parts/editor/titleControl'; import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels'; import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; @@ -333,9 +333,11 @@ export class NoTabsTitleControl extends TitleControl { }; } - layout(dimension: Dimension): void { + layout(dimensions: ITitleControlDimensions): Dimension { if (this.breadcrumbsControl) { this.breadcrumbsControl.layout(undefined); } + + return new Dimension(dimensions.container.width, this.getDimensions().height); } } diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 44e788c7886..556e4ffecbe 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -18,7 +18,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService } from 'vs/platform/actions/common/actions'; -import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; +import { ITitleControlDimensions, TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; @@ -90,7 +90,11 @@ export class TabsTitleControl extends TitleControl { private tabActionBars: ActionBar[] = []; private tabDisposables: IDisposable[] = []; - private dimension: Dimension | undefined; + private dimensions: ITitleControlDimensions = { + container: Dimension.None, + available: Dimension.None + }; + private readonly layoutScheduled = this._register(new MutableDisposable()); private blockRevealActiveTab: boolean | undefined; @@ -380,7 +384,7 @@ export class TabsTitleControl extends TitleControl { // Changing the actions in the toolbar can have an impact on the size of the // tab container, so we need to layout the tabs to make sure the active is visible - this.layout(this.dimension); + this.layout(this.dimensions); } openEditor(editor: IEditorInput): void { @@ -463,7 +467,7 @@ export class TabsTitleControl extends TitleControl { }); // Moving an editor requires a layout to keep the active editor visible - this.layout(this.dimension); + this.layout(this.dimensions); } pinEditor(editor: IEditorInput): void { @@ -490,7 +494,7 @@ export class TabsTitleControl extends TitleControl { }); // A change to the sticky state requires a layout to keep the active editor visible - this.layout(this.dimension); + this.layout(this.dimensions); } setActive(isGroupActive: boolean): void { @@ -502,7 +506,7 @@ export class TabsTitleControl extends TitleControl { // Activity has an impact on the toolbar, so we need to update and layout this.updateEditorActionsToolbar(); - this.layout(this.dimension); + this.layout(this.dimensions); } private updateEditorLabelAggregator = this._register(new RunOnceScheduler(() => this.updateEditorLabels(), 0)); @@ -528,7 +532,7 @@ export class TabsTitleControl extends TitleControl { }); // A change to a label requires a layout to keep the active editor visible - this.layout(this.dimension); + this.layout(this.dimensions); } updateEditorDirty(editor: IEditorInput): void { @@ -1046,7 +1050,7 @@ export class TabsTitleControl extends TitleControl { this.updateEditorActionsToolbar(); // Ensure the active tab is always revealed - this.layout(this.dimension); + this.layout(this.dimensions); } private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar): void { @@ -1260,7 +1264,7 @@ export class TabsTitleControl extends TitleControl { getDimensions(): IEditorGroupTitleDimensions { let height = TabsTitleControl.TAB_HEIGHT; if (this.breadcrumbsControl && !this.breadcrumbsControl.isHidden()) { - height += BreadcrumbsControl.HEIGHT; + height += BreadcrumbsControl.HEIGHT; // Account for breadcrumbs if visible } return { @@ -1269,12 +1273,14 @@ export class TabsTitleControl extends TitleControl { }; } - layout(dimension: Dimension | undefined): void { - this.dimension = dimension; + layout(dimensions: ITitleControlDimensions): Dimension { + this.dimensions = dimensions; + // We need an opened editor and dimensions to layout the title + // Otherwise quickly return from the layout algorithm const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; - if (!activeTabAndIndex || !this.dimension) { - return; + if (!activeTabAndIndex || dimensions.container === Dimension.None || dimensions.available === Dimension.None) { + return Dimension.None; } // The layout of tabs can be an expensive operation because we access DOM properties @@ -1282,34 +1288,32 @@ export class TabsTitleControl extends TitleControl { // this a little bit we try at least to schedule this work on the next animation frame. if (!this.layoutScheduled.value) { this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { - const dimension = assertIsDefined(this.dimension); - this.doLayout(dimension); + this.doLayout(this.dimensions); this.layoutScheduled.clear(); }); } + + return new Dimension(dimensions.container.width, this.getDimensions().height); } - private doLayout(dimension: Dimension): void { + private doLayout(dimensions: ITitleControlDimensions): void { const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; if (!activeTabAndIndex) { return; // nothing to do if not editor opened } // Breadcrumbs - this.doLayoutBreadcrumbs(dimension); + this.doLayoutBreadcrumbs(dimensions); // Tabs const [activeTab, activeIndex] = activeTabAndIndex; this.doLayoutTabs(activeTab, activeIndex); } - private doLayoutBreadcrumbs(dimension: Dimension): void { + private doLayoutBreadcrumbs(dimensions: ITitleControlDimensions): void { if (this.breadcrumbsControl && !this.breadcrumbsControl.isHidden()) { - const tabsScrollbar = assertIsDefined(this.tabsScrollbar); - - this.breadcrumbsControl.layout(new Dimension(dimension.width, BreadcrumbsControl.HEIGHT)); - tabsScrollbar.getDomNode().style.height = `${dimension.height - BreadcrumbsControl.HEIGHT}px`; + this.breadcrumbsControl.layout(new Dimension(dimensions.container.width, BreadcrumbsControl.HEIGHT)); } } @@ -1452,8 +1456,10 @@ export class TabsTitleControl extends TitleControl { const editorIndex = this.group.getIndexOfEditor(editor); if (editorIndex >= 0) { const tabsContainer = assertIsDefined(this.tabsContainer); - - return [tabsContainer.children[editorIndex] as HTMLElement, editorIndex]; + const tab = tabsContainer.children[editorIndex]; + if (tab) { + return [tab as HTMLElement, editorIndex]; + } } return undefined; diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 8358dfcbaac..0eaa213ab76 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -46,6 +46,20 @@ export interface IToolbarActions { secondary: IAction[]; } +export interface ITitleControlDimensions { + + /** + * The size of the parent container the title control is layed out in. + */ + container: Dimension; + + /** + * The maximum size the title control is allowed to consume based on + * other controls that are positioned inside the container. + */ + available: Dimension; +} + export abstract class TitleControl extends Themable { protected readonly groupTransfer = LocalSelectionTransfer.getInstance(); @@ -407,7 +421,7 @@ export abstract class TitleControl extends Themable { abstract updateStyles(): void; - abstract layout(dimension: Dimension): void; + abstract layout(dimensions: ITitleControlDimensions): Dimension; abstract getDimensions(): IEditorGroupTitleDimensions; From b2eedd8ee0905b7aa970541c5e5a9c317c51014d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Dec 2020 17:24:59 +0100 Subject: [PATCH 0679/1837] Add `wss:` / `ws:` to the CSP --- .../extensions/worker/httpWebWorkerExtensionHostIframe.html | 2 +- .../extensions/worker/httpsWebWorkerExtensionHostIframe.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html index 392b4b4aeaa..67560d96e6d 100644 --- a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html +++ b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html @@ -1,7 +1,7 @@ - + `; return { @@ -153,8 +153,8 @@ class RichRenderer implements IOutputTransformContribution { }; } - renderHTML(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { - const data = output.data['text/html']; + renderHTML(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { + const data = output.model.data['text/html']; const str = (isArray(data) ? data.join('') : data) as string; return { type: RenderOutputType.Html, @@ -164,8 +164,8 @@ class RichRenderer implements IOutputTransformContribution { }; } - renderSVG(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { - const data = output.data['image/svg+xml']; + renderSVG(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { + const data = output.model.data['image/svg+xml']; const str = (isArray(data) ? data.join('') : data) as string; return { type: RenderOutputType.Html, @@ -175,8 +175,8 @@ class RichRenderer implements IOutputTransformContribution { }; } - renderMarkdown(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { - const data = output.data['text/markdown']; + renderMarkdown(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { + const data = output.model.data['text/markdown']; const str = (isArray(data) ? data.join('') : data) as string; const mdOutput = document.createElement('div'); const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) }); @@ -186,9 +186,9 @@ class RichRenderer implements IOutputTransformContribution { return { type: RenderOutputType.None, hasDynamicHeight: true }; } - renderPNG(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { + renderPNG(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { const image = document.createElement('img'); - image.src = `data:image/png;base64,${output.data['image/png']}`; + image.src = `data:image/png;base64,${output.model.data['image/png']}`; const display = document.createElement('div'); display.classList.add('display'); display.appendChild(image); @@ -196,9 +196,9 @@ class RichRenderer implements IOutputTransformContribution { return { type: RenderOutputType.None, hasDynamicHeight: true }; } - renderJPEG(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { + renderJPEG(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { const image = document.createElement('img'); - image.src = `data:image/jpeg;base64,${output.data['image/jpeg']}`; + image.src = `data:image/jpeg;base64,${output.model.data['image/jpeg']}`; const display = document.createElement('div'); display.classList.add('display'); display.appendChild(image); @@ -206,8 +206,8 @@ class RichRenderer implements IOutputTransformContribution { return { type: RenderOutputType.None, hasDynamicHeight: true }; } - renderPlainText(output: ITransformedDisplayOutputDto, notebookUri: URI, container: HTMLElement): IRenderOutput { - const data = output.data['text/plain']; + renderPlainText(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput { + const data = output.model.data['text/plain']; const contentNode = DOM.$('.output-plaintext'); truncatedArrayOfString(contentNode, isArray(data) ? data : [data], this.openerService, this.textFileService, this.themeService, true); container.appendChild(contentNode); diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts index b05a25d3b33..446c169057b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as DOM from 'vs/base/browser/dom'; -import { IRenderOutput, CellOutputKind, IStreamOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookRegistry } from 'vs/workbench/contrib/notebook/browser/notebookRegistry'; -import { INotebookEditor, IOutputTransformContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, IOutputTransformContribution, IRenderOutput, IStreamOutputViewModel, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { truncatedArrayOfString } from 'vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -21,7 +21,8 @@ class StreamRenderer implements IOutputTransformContribution { ) { } - render(output: IStreamOutput, container: HTMLElement): IRenderOutput { + render(viewModel: IStreamOutputViewModel, container: HTMLElement): IRenderOutput { + const output = viewModel.model; const contentNode = DOM.$('.output-stream'); truncatedArrayOfString(contentNode, [output.text], this.openerService, this.textFileService, this.themeService, false); container.appendChild(contentNode); 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 31fc6590e1f..7f81379160c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -11,13 +11,12 @@ import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { CellOutputKind, IDisplayOutput, IInsetRenderOutput, INotebookRendererInfo, IProcessedOutput, ITransformedDisplayOutputDto, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { dirname, joinPath } from 'vs/base/common/resources'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; @@ -26,6 +25,7 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -220,9 +220,9 @@ let version = 0; export class BackLayerWebView extends Disposable { element: HTMLElement; webview: WebviewElement | undefined = undefined; - insetMapping: Map = new Map(); - hiddenInsetMapping: Set = new Set(); - reversedInsetMapping: Map = new Map(); + insetMapping: Map = new Map(); + hiddenInsetMapping: Set = new Set(); + reversedInsetMapping: Map = new Map(); localResourceRootsCache: URI[] | undefined = undefined; rendererRootsCache: URI[] = []; kernelRootsCache: URI[] = []; @@ -336,7 +336,7 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cell: CodeCellViewModel, output: IProcessedOutput } | undefined { + private resolveOutputId(id: string): { cell: CodeCellViewModel, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; @@ -461,7 +461,7 @@ var requirejs = (function() { const info = this.resolveOutputId(data.id); if (info) { const { cell, output } = info; - const outputIndex = cell.outputs.indexOf(output); + const outputIndex = cell.outputsViewModels.indexOf(output); cell.updateOutputHeight(outputIndex, outputHeight); this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); } @@ -585,7 +585,7 @@ var requirejs = (function() { return webview; } - shouldUpdateInset(cell: CodeCellViewModel, output: IProcessedOutput, cellTop: number) { + shouldUpdateInset(cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { if (this._disposed) { return; } @@ -595,7 +595,7 @@ var requirejs = (function() { } const outputCache = this.insetMapping.get(output)!; - const outputIndex = cell.outputs.indexOf(output); + const outputIndex = cell.outputsViewModels.indexOf(output); const outputOffset = cellTop + cell.getOutputOffset(outputIndex); if (this.hiddenInsetMapping.has(output)) { @@ -609,7 +609,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: CodeCellViewModel, output: IProcessedOutput, cellTop: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { if (this._disposed) { return; } @@ -617,7 +617,7 @@ var requirejs = (function() { const widgets: IContentWidgetTopRequest[] = items.map(item => { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; - const outputIndex = item.cell.outputs.indexOf(item.output); + const outputIndex = item.cell.outputsViewModels.indexOf(item.output); const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); outputCache.cachedCreation.top = outputOffset; @@ -672,7 +672,7 @@ var requirejs = (function() { let message: ICreationRequestMessage; let renderer: INotebookRendererInfo | undefined; if (content.type === RenderOutputType.Extension) { - const output = content.source as ITransformedDisplayOutputDto; + const output = content.source.model; renderer = content.renderer; message = { ...messageBase, @@ -706,7 +706,7 @@ var requirejs = (function() { this.reversedInsetMapping.set(message.outputId, content.source); } - removeInset(output: IProcessedOutput) { + removeInset(output: IDisplayOutputViewModel) { if (this._disposed) { return; } @@ -729,7 +729,7 @@ var requirejs = (function() { this.reversedInsetMapping.delete(id); } - hideInset(output: IProcessedOutput) { + hideInset(output: IDisplayOutputViewModel) { if (this._disposed) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index ecd819b2beb..8c6a4129bc0 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -10,10 +10,10 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { CodeCellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CodeCellRenderTemplate, ICellOutputViewModel, IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { IRenderOutput, BUILTIN_RENDERER_ID, RenderOutputType, outputHasDynamicHeight, CellUri, CellOutputKind, NotebookCellOutputsSplice, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { BUILTIN_RENDERER_ID, CellUri, CellOutputKind, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; @@ -23,7 +23,6 @@ import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { CellOutputViewModel, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; const OUTPUT_COUNT_LIMIT = 500; @@ -42,7 +41,7 @@ export class OutputElement extends Disposable { private quickInputService: IQuickInputService, private viewCell: CodeCellViewModel, private outputContainer: HTMLElement, - readonly output: CellOutputViewModel + readonly output: ICellOutputViewModel ) { super(); } @@ -68,7 +67,7 @@ export class OutputElement extends Disposable { if (e.leftButton) { e.preventDefault(); e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(this.output as CellOutputViewModel & IDisplayOutputViewModel); + await this.pickActiveMimeTypeRenderer(this.output as IDisplayOutputViewModel); } })); @@ -77,7 +76,7 @@ export class OutputElement extends Disposable { if ((event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) { e.preventDefault(); e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(this.output as CellOutputViewModel & IDisplayOutputViewModel); + await this.pickActiveMimeTypeRenderer(this.output as IDisplayOutputViewModel); } }))); } @@ -90,10 +89,10 @@ export class OutputElement extends Disposable { if (pickedMimeTypeRenderer.rendererId !== BUILTIN_RENDERER_ID) { const renderer = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId); result = renderer - ? { type: RenderOutputType.Extension, renderer, source: this.output.model, mimeType: pickedMimeTypeRenderer.mimeType } - : this.notebookEditor.getOutputRenderer().render(this.output.model, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); + ? { type: RenderOutputType.Extension, renderer, source: this.output, mimeType: pickedMimeTypeRenderer.mimeType } + : this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); } else { - result = this.notebookEditor.getOutputRenderer().render(this.output.model, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),); } this.output.pickedMimeType = pick; @@ -102,7 +101,7 @@ export class OutputElement extends Disposable { const innerContainer = DOM.$('.output-inner-container'); DOM.append(outputItemDiv, innerContainer); - result = this.notebookEditor.getOutputRenderer().render(this.output.model, innerContainer, undefined, this.getNotebookUri(),); + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.getNotebookUri(),); } this.domNode = outputItemDiv; @@ -164,8 +163,7 @@ export class OutputElement extends Disposable { } } - async pickActiveMimeTypeRenderer(viewModel: CellOutputViewModel & IDisplayOutputViewModel) { - const output = viewModel.model; + async pickActiveMimeTypeRenderer(viewModel: IDisplayOutputViewModel) { const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(this.notebookEditor.textModel!); const items = mimeTypes.filter(mimeType => mimeType.isTrusted).map((mimeType, index): IMimeTypeRenderer => ({ @@ -204,7 +202,7 @@ export class OutputElement extends Disposable { const element = this.domNode; if (element) { element.parentElement?.removeChild(element); - this.notebookEditor.removeInset(output); + this.notebookEditor.removeInset(viewModel); } viewModel.pickedMimeType = pick; @@ -238,7 +236,7 @@ export class OutputElement extends Disposable { } export class OutputContainer extends Disposable { - private outputEntries = new Map(); + private outputEntries = new Map(); constructor( private notebookEditor: INotebookEditor, @@ -336,7 +334,7 @@ export class OutputContainer extends Disposable { viewUpdateHideOuputs(): void { for (const e of this.outputEntries.keys()) { - this.notebookEditor.hideInset(e.model); + this.notebookEditor.hideInset(e as IDisplayOutputViewModel); } } @@ -349,7 +347,7 @@ export class OutputContainer extends Disposable { }); } - private _calcuateOutputsToRender(): CellOutputViewModel[] { + private _calcuateOutputsToRender(): ICellOutputViewModel[] { const outputs = this.viewCell.outputsViewModels.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputsViewModels.length)); if (!this.notebookEditor.viewModel!.metadata.trusted) { // not trusted @@ -405,7 +403,7 @@ export class OutputContainer extends Disposable { this.viewCell.spliceOutputHeights(splice[0], splice[1], splice[2].map(_ => 0)); }); - const removedKeys: CellOutputViewModel[] = []; + const removedKeys: ICellOutputViewModel[] = []; this.outputEntries.forEach((value, key) => { if (this.viewCell.outputsViewModels.indexOf(key) < 0) { @@ -413,7 +411,9 @@ export class OutputContainer extends Disposable { removedKeys.push(key); // remove element from DOM this.templateData?.outputContainer?.removeChild(value.domNode); - this.notebookEditor.removeInset(key.model); + if (key.isDisplayOutput()) { + this.notebookEditor.removeInset(key); + } } }); @@ -456,7 +456,7 @@ export class OutputContainer extends Disposable { } } - private _renderOutput(currOutput: CellOutputViewModel, index: number, beforeElement?: HTMLElement) { + private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this.outputEntries.has(currOutput)) { this.outputEntries.set(currOutput, new OutputElement(this.notebookEditor, this.notebookService, this.quickInputService, this.viewCell, this.templateData.outputContainer, currOutput)); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 0de4cdaa717..4ef35e2bdad 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -5,8 +5,8 @@ import type { Event } from 'vs/base/common/event'; import type { IDisposable } from 'vs/base/common/lifecycle'; +import { RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { ToWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; -import { RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; // !! IMPORTANT !! everything must be in-line within the webviewPreloads // function. Imports are not allowed. This is stringifies and injected into diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel.ts index 2a2ec98c543..6f3b8bdd43b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel.ts @@ -4,16 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; +import { ICellOutputViewModel, IDisplayOutputViewModel, IErrorOutputViewModel, IStreamOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellOutputKind, IOrderedMimeType, IProcessedOutput, ITransformedDisplayOutputDto, RENDERER_NOT_AVAILABLE } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; -export interface IDisplayOutputViewModel { - model: ITransformedDisplayOutputDto; - resolveMimeTypes(textModel: NotebookTextModel): [readonly IOrderedMimeType[], number]; -} - -export class CellOutputViewModel extends Disposable { +export class CellOutputViewModel extends Disposable implements ICellOutputViewModel { get model() { return this._outputData; } @@ -33,6 +29,13 @@ export class CellOutputViewModel extends Disposable { ) { super(); } + isStreamOutput(): this is IStreamOutputViewModel { + return this._outputData.outputKind === CellOutputKind.Text; + } + + isErrorOutput(): this is IErrorOutputViewModel { + return this._outputData.outputKind === CellOutputKind.Error; + } isDisplayOutput(): this is IDisplayOutputViewModel { return this._outputData.outputKind === CellOutputKind.Rich; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index bca4635e68e..0d104847236 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -10,7 +10,7 @@ import * as model from 'vs/editor/common/model'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; @@ -67,7 +67,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod return this._layoutInfo; } - private _outputViewModels: CellOutputViewModel[]; + private _outputViewModels: ICellOutputViewModel[]; get outputsViewModels() { return this._outputViewModels; diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 941f4a479c4..d59dd7a95a3 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -271,36 +271,6 @@ export interface INotebookTextModel { onWillDispose(listener: () => void): IDisposable; } -export const enum RenderOutputType { - None, - Html, - Extension -} - -export interface IRenderNoOutput { - type: RenderOutputType.None; - hasDynamicHeight: boolean; -} - -export interface IRenderPlainHtmlOutput { - type: RenderOutputType.Html; - source: ITransformedDisplayOutputDto; - htmlContent: string; - hasDynamicHeight: boolean; -} - -export interface IRenderOutputViaExtension { - type: RenderOutputType.Extension; - source: ITransformedDisplayOutputDto; - mimeType: string; - renderer: INotebookRendererInfo; -} - -export type IInsetRenderOutput = IRenderPlainHtmlOutput | IRenderOutputViaExtension; -export type IRenderOutput = IRenderNoOutput | IInsetRenderOutput; - -export const outputHasDynamicHeight = (o: IRenderOutput) => o.type !== RenderOutputType.Extension && o.hasDynamicHeight; - export type NotebookCellTextModelSplice = [ number /* start */, number, diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 855ffe9fc61..ea7c4180a81 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -12,13 +12,13 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { Range } from 'vs/editor/common/core/range'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { EditorModel } from 'vs/workbench/common/editor'; -import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { CellKind, CellUri, INotebookEditorModel, IProcessedOutput, NotebookCellMetadata, IInsetRenderOutput, ICellRange, INotebookKernelInfo2, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellUri, INotebookEditorModel, IProcessedOutput, NotebookCellMetadata, ICellRange, INotebookKernelInfo2, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { ICompositeCodeEditor, IEditor } from 'vs/editor/common/editorCommon'; import { NotImplementedError } from 'vs/base/common/errors'; @@ -84,7 +84,7 @@ export class TestNotebookEditor implements INotebookEditor { throw new Error('Method not implemented.'); } - hideInset(output: IProcessedOutput): void { + hideInset(output: ICellOutputViewModel): void { throw new Error('Method not implemented.'); } @@ -282,7 +282,7 @@ export class TestNotebookEditor implements INotebookEditor { createInset(cell: CellViewModel, output: IInsetRenderOutput, offset: number): Promise { return Promise.resolve(); } - removeInset(output: IProcessedOutput): void { + removeInset(output: ICellOutputViewModel): void { // throw new Error('Method not implemented.'); } triggerScroll(event: IMouseWheelEvent): void { From 29bc5baadc95a797cc0df8cc8e66cea3cd289e34 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Thu, 10 Dec 2020 18:58:30 -0500 Subject: [PATCH 0777/1837] Only prompt if input (#112113) only show the terminal config prompt if the terminal instance that's active has had keyboard input. Does not address the case of typing and deleting all that you typed to simplify the code. --- .../terminal/browser/terminalInstance.ts | 26 ++++++++++++++----- .../contrib/terminal/common/terminal.ts | 4 ++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 08dfc59ed0b..9303f7bdb70 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -25,7 +25,7 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, SHOW_TERMINAL_CONFIG_PROMPT } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, TERMINAL_CREATION_COMMANDS } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; @@ -115,6 +115,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _timeoutDimension: dom.Dimension | undefined; + private hasHadInput: boolean; + public disableLayout: boolean; public get id(): number { return this._id; } public get cols(): number { @@ -208,6 +210,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._isDisposed = false; this._id = TerminalInstance._idCounter++; + this.hasHadInput = false; + this._titleReadyPromise = new Promise(c => { this._titleReadyComplete = c; }); @@ -544,15 +548,25 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return false; } + const SHOW_TERMINAL_CONFIG_PROMPT = 'terminal.integrated.showTerminalConfigPrompt'; + const EXCLUDED_KEYS = ['RightArrow', 'LeftArrow', 'UpArrow', 'DownArrow', 'Space', 'Meta', 'Control', 'Shift', 'Alt', '', 'Delete', 'Backspace', 'Tab']; + + // only keep track of input if prompt hasn't already been shown + if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT, StorageScope.GLOBAL, true) && + !EXCLUDED_KEYS.includes(event.key) && + !event.ctrlKey && + !event.shiftKey && + !event.altKey) { + this.hasHadInput = true; + } + // for keyboard events that resolve to commands described // within commandsToSkipShell, either alert or skip processing by xterm.js - if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) { + if (resolveResult && resolveResult.commandId && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) { // don't alert when terminal is opened or closed if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT, StorageScope.GLOBAL, true) && - resolveResult.commandId !== 'workbench.action.terminal.toggleTerminal' && - resolveResult.commandId !== 'workbench.action.terminal.new' && - resolveResult.commandId !== 'workbench.action.togglePanel' && - resolveResult.commandId !== 'workbench.action.terminal.focus') { + this.hasHadInput && + !TERMINAL_CREATION_COMMANDS.includes(resolveResult.commandId)) { this._notificationService.prompt( Severity.Info, nls.localize('configure terminal settings', "Some keybindings are dispatched to the workbench by default."), diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index ef7ff2e50bd..c852d4e7306 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -50,7 +50,9 @@ export const KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED = new RawContextKey Date: Thu, 10 Dec 2020 16:03:45 -0800 Subject: [PATCH 0778/1837] :lipstick: --- .../contrib/notebook/browser/viewModel/codeCellViewModel.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 0d104847236..74f6cf9385a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -33,9 +33,6 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private _outputsTop: PrefixSumComputer | null = null; - get outputs() { - return this.model.outputs; - } protected readonly _onDidChangeLayout = new Emitter(); readonly onDidChangeLayout = this._onDidChangeLayout.event; From 618bf22ca5ea100cc9a714a148e74a4e9664ac7b Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 10 Dec 2020 16:11:42 -0800 Subject: [PATCH 0779/1837] remove !. --- .../browser/view/renderers/cellOutput.ts | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index 8c6a4129bc0..6f17a156f95 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -23,6 +23,7 @@ import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; const OUTPUT_COUNT_LIMIT = 500; @@ -51,11 +52,17 @@ export class OutputElement extends Disposable { return; } + if (!this.notebookEditor.hasModel()) { + return; + } + + const notebookTextModel = this.notebookEditor.viewModel.notebookDocument; + const outputItemDiv = document.createElement('div'); let result: IRenderOutput | undefined = undefined; if (this.output.isDisplayOutput()) { - const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookEditor.textModel!); + const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel); if (mimeTypes.length > 1) { outputItemDiv.style.position = 'relative'; const mimeTypePicker = DOM.$('.multi-mimetype-output'); @@ -67,7 +74,7 @@ export class OutputElement extends Disposable { if (e.leftButton) { e.preventDefault(); e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(this.output as IDisplayOutputViewModel); + await this.pickActiveMimeTypeRenderer(notebookTextModel, this.output as IDisplayOutputViewModel); } })); @@ -76,7 +83,7 @@ export class OutputElement extends Disposable { if ((event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) { e.preventDefault(); e.stopPropagation(); - await this.pickActiveMimeTypeRenderer(this.output as IDisplayOutputViewModel); + await this.pickActiveMimeTypeRenderer(notebookTextModel, this.output as IDisplayOutputViewModel); } }))); } @@ -135,7 +142,7 @@ export class OutputElement extends Disposable { height: clientHeight }; const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { - if (this.outputContainer && document.body.contains(this.outputContainer!)) { + if (this.outputContainer && document.body.contains(this.outputContainer)) { const height = Math.ceil(elementSizeObserver.getHeight()); if (clientHeight === height) { @@ -163,8 +170,8 @@ export class OutputElement extends Disposable { } } - async pickActiveMimeTypeRenderer(viewModel: IDisplayOutputViewModel) { - const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(this.notebookEditor.textModel!); + private async pickActiveMimeTypeRenderer(notebookTextModel: NotebookTextModel, viewModel: IDisplayOutputViewModel) { + const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel); const items = mimeTypes.filter(mimeType => mimeType.isTrusted).map((mimeType, index): IMimeTypeRenderer => ({ label: mimeType.mimeType, @@ -215,7 +222,7 @@ export class OutputElement extends Disposable { return CellUri.parse(this.viewCell.uri)?.notebook; } - generateRendererInfo(renderId: string | undefined): string { + private generateRendererInfo(renderId: string | undefined): string { if (renderId === undefined || renderId === BUILTIN_RENDERER_ID) { return nls.localize('builtinRenderInfo', "built-in"); } @@ -230,7 +237,7 @@ export class OutputElement extends Disposable { return nls.localize('builtinRenderInfo', "built-in"); } - relayoutCell() { + private relayoutCell() { this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); } } From 0370a6ebf5fb6e6f33ca7631469b55d0cde1adb6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Dec 2020 17:18:29 -0800 Subject: [PATCH 0780/1837] add explicit jsdoc types --- src/vs/workbench/contrib/webview/browser/pre/host.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/webview/browser/pre/host.js b/src/vs/workbench/contrib/webview/browser/pre/host.js index b752d8f82f3..fabbc97ea02 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/host.js +++ b/src/vs/workbench/contrib/webview/browser/pre/host.js @@ -9,7 +9,9 @@ const hostMessaging = new class HostMessaging { constructor() { + /** @type {Map void>} */ this.handlers = new Map(); + window.addEventListener('message', (e) => { if (e.data && (e.data.command === 'onmessage' || e.data.command === 'do-update-state')) { // Came from inner iframe @@ -41,6 +43,7 @@ hostMessaging.postMessage('fatal-error', { message }); } + /** @type {Promise} */ const workerReady = new Promise(async (resolveWorkerReady) => { if (onElectron) { return resolveWorkerReady(); From 08e6047a050c8a646fff10669a4c11ea66af9eb6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Dec 2020 17:32:43 -0800 Subject: [PATCH 0781/1837] Remove extra lines --- src/vs/workbench/contrib/webview/browser/pre/main.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 726eff39c66..cba3d2c6614 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -585,8 +585,6 @@ newFrame.contentWindow.focus(); } - - contentWindow.addEventListener('scroll', handleInnerScroll); contentWindow.addEventListener('wheel', handleWheel); From 4d4f3a305c2a89ce8b2e257389749ad81f498e0c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Dec 2020 17:36:12 -0800 Subject: [PATCH 0782/1837] Observe the confirmBeforeClose setting for webviews --- .../webview/browser/baseWebviewElement.ts | 1 + .../contrib/webview/browser/pre/host.js | 92 ++++++++++++++----- .../contrib/webview/browser/webviewElement.ts | 28 +++++- 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts b/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts index 6b84fbcb776..403c586c9bb 100644 --- a/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts @@ -26,6 +26,7 @@ export const enum WebviewMessageChannels { didLoad = 'did-load', doUpdateState = 'do-update-state', doReload = 'do-reload', + setConfirmBeforeClose = 'set-confirm-before-close', loadResource = 'load-resource', loadLocalhost = 'load-localhost', webviewReady = 'webview-ready', diff --git a/src/vs/workbench/contrib/webview/browser/pre/host.js b/src/vs/workbench/contrib/webview/browser/pre/host.js index fabbc97ea02..f313b0d1f2f 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/host.js +++ b/src/vs/workbench/contrib/webview/browser/pre/host.js @@ -9,7 +9,7 @@ const hostMessaging = new class HostMessaging { constructor() { - /** @type {Map void>} */ + /** @type {Map void>>} */ this.handlers = new Map(); window.addEventListener('message', (e) => { @@ -20,21 +20,36 @@ } const channel = e.data.channel; - const handler = this.handlers.get(channel); - if (handler) { - handler(e, e.data.args); + const handlers = this.handlers.get(channel); + if (handlers) { + for (const handler of handlers) { + handler(e, e.data.args); + } } else { console.log('no handler for ', e); } }); } + /** + * @param {string} channel + * @param {any} data + */ postMessage(channel, data) { window.parent.postMessage({ target: id, channel, data }, '*'); } + /** + * @param {string} channel + * @param {(event: MessageEvent, data: any) => void} handler + */ onMessage(channel, handler) { - this.handlers.set(channel, handler); + let handlers = this.handlers.get(channel); + if (!handlers) { + handlers = []; + this.handlers.set(channel, handlers); + } + handlers.push(handler); } }(); @@ -108,30 +123,59 @@ } } - /** @type {undefined | ((iframe: HTMLIFrameElement) => void)} */ - let onIframeLoaded; + const unloadMonitor = new class { - if (!onElectron) { - let isModifierDown = false; + constructor() { + this.confirmBeforeClose = 'keyboardOnly'; + this.isModifierKeyDown = false; - onIframeLoaded = (frame) => { + hostMessaging.onMessage('set-confirm-before-close', (_e, /** @type {string} */ data) => { + this.confirmBeforeClose = data; + }); + + hostMessaging.onMessage('content', (_e, /** @type {any} */ data) => { + this.confirmBeforeClose = data.confirmBeforeClose; + }); + + window.addEventListener('beforeunload', (event) => { + if (onElectron) { + return; + } + + switch (this.confirmBeforeClose) { + case 'always': + { + event.preventDefault(); + event.returnValue = ''; + return ''; + } + case 'never': + { + break; + } + case 'keyboardOnly': + default: { + if (this.isModifierKeyDown) { + event.preventDefault(); + event.returnValue = ''; + return ''; + } + break; + } + } + }); + } + + onIframeLoaded(/** @type {HTMLIFrameElement} */frame) { frame.contentWindow.addEventListener('keydown', e => { - isModifierDown = e.metaKey || e.ctrlKey || e.altKey; + this.isModifierKeyDown = e.metaKey || e.ctrlKey || e.altKey; }); frame.contentWindow.addEventListener('keyup', () => { - isModifierDown = false; + this.isModifierKeyDown = false; }); - }; - - window.addEventListener('beforeunload', (event) => { - if (isModifierDown) { - event.preventDefault(); - event.returnValue = ''; - return ''; - } - }); - } + } + }; /** @type {import('./main').WebviewHost} */ const host = { @@ -140,7 +184,9 @@ ready: workerReady, fakeLoad: !onElectron, onElectron: onElectron, - onIframeLoaded, + onIframeLoaded: (/** @type {HTMLIFrameElement} */ frame) => { + unloadMonitor.onIframeLoaded(frame); + }, rewriteCSP: onElectron ? (csp) => { return csp.replace(/vscode-resource:(?=(\s|;|$))/g, 'vscode-webview-resource:'); diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index f142c2c2172..21c66f82cd3 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -8,6 +8,7 @@ import { streamToBuffer } from 'vs/base/common/buffer'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -24,6 +25,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ export class IFrameWebview extends BaseWebview implements Webview { private readonly _portMappingManager: WebviewPortMappingManager; + private _confirmBeforeClose: string; constructor( id: string, @@ -37,6 +39,7 @@ export class IFrameWebview extends BaseWebview implements Web @IRequestService private readonly requestService: IRequestService, @ITelemetryService telemetryService: ITelemetryService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IConfigurationService private readonly _configurationService: IConfigurationService, @IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, @ILogService logService: ILogService, ) { @@ -59,6 +62,15 @@ export class IFrameWebview extends BaseWebview implements Web this.localLocalhost(entry.origin); })); + this._confirmBeforeClose = this._configurationService.getValue('window.confirmBeforeClose'); + + this._register(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('window.confirmBeforeClose')) { + this._confirmBeforeClose = this._configurationService.getValue('window.confirmBeforeClose'); + this._send(WebviewMessageChannels.setConfirmBeforeClose, this._confirmBeforeClose); + } + })); + this.initElement(extension, options); } @@ -75,8 +87,19 @@ export class IFrameWebview extends BaseWebview implements Web } protected initElement(extension: WebviewExtensionDescription | undefined, options: WebviewOptions) { - // The extensionId and purpose in the URL are used for filtering in js-debug: - this.element!.setAttribute('src', `${this.externalEndpoint}/index.html?id=${this.id}&extensionId=${extension?.id.value ?? ''}&purpose=${options.purpose}`); + const params = { + id: this.id, + + // The extensionId and purpose in the URL are used for filtering in js-debug: + extensionId: extension?.id.value ?? '', + purpose: options.purpose, + } as const; + + const queryString = (Object.keys(params) as Array) + .map((key) => `${key}=${params[key]}`) + .join('&'); + + this.element!.setAttribute('src', `${this.externalEndpoint}/index.html?${queryString}`); } private get externalEndpoint(): string { @@ -116,6 +139,7 @@ export class IFrameWebview extends BaseWebview implements Web protected get extraContentOptions(): any { return { endpoint: this.externalEndpoint, + confirmBeforeClose: this._confirmBeforeClose, }; } From 39f78228fa6ae915c98d0d91696f6ec311dbe4ca Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Dec 2020 17:51:25 -0800 Subject: [PATCH 0783/1837] Add missing file to commit --- .../contrib/webview/electron-sandbox/iframeWebviewElement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/webview/electron-sandbox/iframeWebviewElement.ts b/src/vs/workbench/contrib/webview/electron-sandbox/iframeWebviewElement.ts index 8c010272b0d..d6c80d16fe2 100644 --- a/src/vs/workbench/contrib/webview/electron-sandbox/iframeWebviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-sandbox/iframeWebviewElement.ts @@ -58,7 +58,7 @@ export class ElectronIframeWebview extends IFrameWebview { @INativeHostService nativeHostService: INativeHostService, ) { super(id, options, contentOptions, extension, webviewThemeDataProvider, - noficationService, tunnelService, fileService, requestService, telemetryService, environmentService, _remoteAuthorityResolverService, logService); + noficationService, tunnelService, fileService, requestService, telemetryService, environmentService, configurationService, _remoteAuthorityResolverService, logService); this._resourceRequestManager = this._register(instantiationService.createInstance(WebviewResourceRequestManager, id, extension, this.content.options)); From 83f43bee1d553dff9fd80858b113e2cb225dfe8d Mon Sep 17 00:00:00 2001 From: Jason Williams <936006+jasonwilliams@users.noreply.github.com> Date: Fri, 11 Dec 2020 05:54:21 +0000 Subject: [PATCH 0784/1837] Changing autofetch to a string config which has "current", "all" and (#111090) --- extensions/git/package.json | 12 +++++++++++- extensions/git/package.nls.json | 2 +- extensions/git/src/autofetch.ts | 25 ++++++++++++++++++++----- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index bea5f96a67d..ba28f10b18c 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1644,7 +1644,17 @@ "default": true }, "git.autofetch": { - "type": "boolean", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string", + "enum": [ + "all" + ] + } + ], "scope": "resource", "description": "%config.autofetch%", "default": false, diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 6158a7e0cd5..7d7576f4419 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -97,7 +97,7 @@ "config.autoRepositoryDetection.subFolders": "Scan for subfolders of the currently opened folder.", "config.autoRepositoryDetection.openEditors": "Scan for parent folders of open files.", "config.autorefresh": "Whether auto refreshing is enabled.", - "config.autofetch": "When enabled, commits will automatically be fetched from the default remote of the current Git repository.", + "config.autofetch": "When set to true, commits will automatically be fetched from the default remote of the current Git repository. Setting to `all` will fetch from all remotes", "config.autofetchPeriod": "Duration in seconds between each automatic git fetch, when `git.autofetch` is enabled.", "config.confirmSync": "Confirm before synchronizing git repositories.", "config.countBadge": "Controls the Git count badge.", diff --git a/extensions/git/src/autofetch.ts b/extensions/git/src/autofetch.ts index d9e436b9f5c..d4ff1ef1e49 100644 --- a/extensions/git/src/autofetch.ts +++ b/extensions/git/src/autofetch.ts @@ -23,6 +23,7 @@ export class AutoFetcher { private onDidChange = this._onDidChange.event; private _enabled: boolean = false; + private _fetchAll: boolean = false; get enabled(): boolean { return this._enabled; } set enabled(enabled: boolean) { this._enabled = enabled; this._onDidChange.fire(enabled); } @@ -70,10 +71,20 @@ export class AutoFetcher { private onConfiguration(): void { const gitConfig = workspace.getConfiguration('git', Uri.file(this.repository.root)); - if (gitConfig.get('autofetch') === false) { - this.disable(); - } else { - this.enable(); + switch (gitConfig.get('autofetch')) { + case true: + this._fetchAll = false; + this.enable(); + break; + case 'all': + this._fetchAll = true; + this.enable(); + break; + case false: + default: + this._fetchAll = false; + this.disable(); + break; } } @@ -99,7 +110,11 @@ export class AutoFetcher { } try { - await this.repository.fetchDefault({ silent: true }); + if (this._fetchAll) { + await this.repository.fetchAll(); + } else { + await this.repository.fetchDefault({ silent: true }); + } } catch (err) { if (err.gitErrorCode === GitErrorCodes.AuthenticationFailed) { this.disable(); From 38a89809051659ec8723b3a772bb79ca67fc065f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 11 Dec 2020 01:06:10 -0500 Subject: [PATCH 0785/1837] Avoids triggering autofetch unless setting changes --- extensions/git/src/autofetch.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/extensions/git/src/autofetch.ts b/extensions/git/src/autofetch.ts index d4ff1ef1e49..5a45a522d19 100644 --- a/extensions/git/src/autofetch.ts +++ b/extensions/git/src/autofetch.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget, Uri } from 'vscode'; +import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget, Uri, ConfigurationChangeEvent } from 'vscode'; import { Repository, Operation } from './repository'; import { eventToPromise, filterEvent, onceEvent } from './util'; import * as nls from 'vscode-nls'; @@ -68,9 +68,12 @@ export class AutoFetcher { this.globalState.update(AutoFetcher.DidInformUser, true); } - private onConfiguration(): void { - const gitConfig = workspace.getConfiguration('git', Uri.file(this.repository.root)); + private onConfiguration(e?: ConfigurationChangeEvent): void { + if (e !== undefined && !e.affectsConfiguration('git.autofetch')) { + return; + } + const gitConfig = workspace.getConfiguration('git', Uri.file(this.repository.root)); switch (gitConfig.get('autofetch')) { case true: this._fetchAll = false; From 86deb14fd3ced5a77452b2c069c43766e9083334 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 09:31:50 +0100 Subject: [PATCH 0786/1837] make slow timeout event slower, fixes https://github.com/microsoft/vscode/issues/112262 --- .../test/browser/api/extHostDocumentSaveParticipant.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts index c1509ad3c89..8220fcf97aa 100644 --- a/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/browser/api/extHostDocumentSaveParticipant.test.ts @@ -226,11 +226,12 @@ suite('ExtHostDocumentSaveParticipant', () => { }); }); - test('event delivery, waitUntil will timeout', () => { + test('event delivery, waitUntil will timeout', function () { + const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, mainThreadBulkEdits, { timeout: 5, errors: 3 }); let sub = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { - event.waitUntil(timeout(15)); + event.waitUntil(timeout(100)); }); return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(values => { From fdbd7bf6bbc479f405d89de73b7c51d560a4cd0c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 11 Dec 2020 09:38:17 +0100 Subject: [PATCH 0787/1837] web - tweak dispose dialog --- src/vs/workbench/browser/window.ts | 13 +++++++------ .../services/lifecycle/browser/lifecycleService.ts | 4 +++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts index d61eb9d4d24..c6fa4c1f5e5 100644 --- a/src/vs/workbench/browser/window.ts +++ b/src/vs/workbench/browser/window.ts @@ -10,7 +10,6 @@ import Severity from 'vs/base/common/severity'; import { localize } from 'vs/nls'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; -import { IProductService } from 'vs/platform/product/common/productService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { BrowserLifecycleService } from 'vs/workbench/services/lifecycle/browser/lifecycleService'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; @@ -21,8 +20,7 @@ export class BrowserWindow extends Disposable { @IOpenerService private readonly openerService: IOpenerService, @ILifecycleService private readonly lifecycleService: BrowserLifecycleService, @IDialogService private readonly dialogService: IDialogService, - @IHostService private readonly hostService: IHostService, - @IProductService private readonly productService: IProductService + @IHostService private readonly hostService: IHostService ) { super(); @@ -44,10 +42,13 @@ export class BrowserWindow extends Disposable { // state. const res = await this.dialogService.show( Severity.Error, - localize('shutdownError', "{0} got disposed. Please close or reload this page.", this.productService.nameShort), + localize('shutdownError', "An unexpected error occurred that requires a reload of this page."), [ - localize('reload', "Reload"), - ] + localize('reload', "Reload") + ], + { + detail: localize('shutdownErrorDetail', "The workbench was unexpectedly disposed while running.") + } ); if (res.choice === 0) { diff --git a/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts b/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts index 609563ad05e..77c97f2fd5d 100644 --- a/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts @@ -37,12 +37,14 @@ export class BrowserLifecycleService extends AbstractLifecycleService { this.logService.info('[lifecycle] onBeforeUnload expected, ignoring once'); this.expectedUnload = false; + return; // ignore expected unload only once } this.logService.info('[lifecycle] onBeforeUnload triggered'); this.doShutdown(() => { + // Veto handling event.preventDefault(); event.returnValue = localize('lifecycleVeto', "Changes that you made may not be saved. Please check press 'Cancel' and try again."); @@ -61,7 +63,7 @@ export class BrowserLifecycleService extends AbstractLifecycleService { shutdown(): void { this.logService.info('[lifecycle] shutdown triggered'); - // Remove beforeunload listener that would prevent shutdown + // Remove `beforeunload` listener that would prevent shutdown this.beforeUnloadDisposable?.dispose(); // Handle shutdown without veto support From bb68097d15f4e010bd74e48252c157b2137f57a6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 09:48:15 +0100 Subject: [PATCH 0788/1837] add extra check to understand https://github.com/microsoft/vscode/issues/112263 --- .../src/singlefolder-tests/workspace.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index 82681ca0327..bbfbe17b1fd 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -132,7 +132,10 @@ suite('vscode API - workspace', () => { let d0 = vscode.workspace.onDidCloseTextDocument(e => closed = e); return vscode.window.showTextDocument(doc).then(() => { - return doc.save().then(() => { + return doc.save().then((didSave: boolean) => { + + assert.equal(didSave, true, `FAILED to save${doc.uri.toString()}`); + assert.ok(closed === doc); assert.ok(!doc.isDirty); assert.ok(fs.existsSync(path)); From 32cc71c4a73efda2fe70079225ba523ff64c710c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 11 Dec 2020 09:48:30 +0100 Subject: [PATCH 0789/1837] web - do not ask for clipboard access in ext tests (fix #112264) --- src/vs/workbench/browser/web.main.ts | 14 +++++++++----- .../services/clipboard/browser/clipboardService.ts | 8 +++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 088c5561594..564721dc09b 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -267,8 +267,9 @@ class BrowserMain extends Disposable { try { indexedDBLogProvider = await indexedDB.createFileSystemProvider(logsPath.scheme, INDEXEDDB_LOGS_OBJECT_STORE); } catch (error) { - console.error(error); + onUnexpectedError(error); } + if (indexedDBLogProvider) { fileService.registerProvider(logsPath.scheme, indexedDBLogProvider); } else { @@ -285,6 +286,7 @@ class BrowserMain extends Disposable { const connection = remoteAgentService.getConnection(); if (connection) { + // Remote file system const remoteFileSystemProvider = this._register(new RemoteFileSystemProvider(remoteAgentService)); fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider); @@ -295,8 +297,9 @@ class BrowserMain extends Disposable { try { indexedDBUserDataProvider = await indexedDB.createFileSystemProvider(Schemas.userData, INDEXEDDB_USERDATA_OBJECT_STORE); } catch (error) { - console.error(error); + onUnexpectedError(error); } + fileService.registerProvider(Schemas.userData, indexedDBUserDataProvider || new InMemoryFileSystemProvider()); if (indexedDBUserDataProvider) { registerAction2(class ResetUserDataAction extends Action2 { @@ -310,21 +313,22 @@ class BrowserMain extends Disposable { } }); } + async run(accessor: ServicesAccessor): Promise { const dialogService = accessor.get(IDialogService); const hostService = accessor.get(IHostService); const result = await dialogService.confirm({ message: localize('reset user data message', "Would you like to reset your data (settings, keybindings, extensions, snippets and UI State) and reload?") }); + if (result.confirmed) { - await indexedDBUserDataProvider!.reset(); + await indexedDBUserDataProvider?.reset(); } + hostService.reload(); } }); } - - fileService.registerProvider(Schemas.userData, indexedDBUserDataProvider || new InMemoryFileSystemProvider()); } private async createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IWorkbenchEnvironmentService, fileService: IFileService, logService: ILogService): Promise { diff --git a/src/vs/workbench/services/clipboard/browser/clipboardService.ts b/src/vs/workbench/services/clipboard/browser/clipboardService.ts index 89c532dec2e..7475c744b7b 100644 --- a/src/vs/workbench/services/clipboard/browser/clipboardService.ts +++ b/src/vs/workbench/services/clipboard/browser/clipboardService.ts @@ -11,12 +11,14 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { once } from 'vs/base/common/functional'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; export class BrowserClipboardService extends BaseBrowserClipboardService { constructor( @INotificationService private readonly notificationService: INotificationService, - @IOpenerService private readonly openerService: IOpenerService + @IOpenerService private readonly openerService: IOpenerService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService ) { super(); } @@ -29,6 +31,10 @@ export class BrowserClipboardService extends BaseBrowserClipboardService { try { return await navigator.clipboard.readText(); } catch (error) { + if (!!this.environmentService.extensionTestsLocationURI) { + return ''; // do not ask for input in tests (https://github.com/microsoft/vscode/issues/112264) + } + return new Promise(resolve => { // Inform user about permissions problem (https://github.com/microsoft/vscode/issues/112089) From 3b34ea9f163a727554b925a18bbc3316c95fd593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=89=BE=E6=96=AF=E7=89=B9=E6=B4=9B?= Date: Fri, 11 Dec 2020 16:57:34 +0800 Subject: [PATCH 0790/1837] Update commands.ts (#112222) --- extensions/git/src/commands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 2c24d9095b4..bb6c0215c2f 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -500,12 +500,12 @@ export class CommandCenter { @command('git.clone') async clone(url?: string, parentPath?: string): Promise { - this.cloneRepository(url, parentPath); + await this.cloneRepository(url, parentPath); } @command('git.cloneRecursive') async cloneRecursive(url?: string, parentPath?: string): Promise { - this.cloneRepository(url, parentPath, { recursive: true }); + await this.cloneRepository(url, parentPath, { recursive: true }); } @command('git.init') From 124b4bd151d09cd30951eeb1d484ca4b5eb18688 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Dec 2020 10:47:54 +0100 Subject: [PATCH 0791/1837] Try newer `actions/checkout@v2` --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08775eab933..f0c4fdf2316 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,7 +123,7 @@ jobs: CHILD_CONCURRENCY: "1" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - run: | sudo apt-get update From 019b5ab4c99686cc60b8d260f5b06582f77100ca Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Dec 2020 10:59:15 +0100 Subject: [PATCH 0792/1837] Remove yarn `CHILD_CONCURRENCY` limit --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0c4fdf2316..f16327f7242 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,7 +120,6 @@ jobs: monaco: runs-on: ubuntu-latest env: - CHILD_CONCURRENCY: "1" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 From f201645d8f7b6a9ffd5d74e9d8e77f6fdfe589ab Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Dec 2020 11:09:00 +0100 Subject: [PATCH 0793/1837] Do not configure `xvfb` --- .github/workflows/ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f16327f7242..0d3932bc08e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,11 +126,7 @@ jobs: # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - run: | sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev name: Setup Build Environment - uses: actions/setup-node@v1 with: From 1d5611c9d8f62cc78233f8344cf300eed42e10e5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Dec 2020 11:36:53 +0100 Subject: [PATCH 0794/1837] No need to install anything --- .github/workflows/ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d3932bc08e..b2806658197 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,11 +123,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev - name: Setup Build Environment - uses: actions/setup-node@v1 with: node-version: 10 From 61af2b26daa38848f0821d60ebad0adda8b35102 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Fri, 11 Dec 2020 19:06:26 +0800 Subject: [PATCH 0795/1837] feat: support Report Issue capability for built-in module --- .../electron-browser/reportExtensionIssueAction.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts index faf606a75e0..a41917474f4 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts @@ -14,6 +14,8 @@ import { ExtensionType, IExtensionDescription } from 'vs/platform/extensions/com import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; +const builtinExtensionIssueUrl = 'https://github.com/microsoft/vscode.git'; + export class ReportExtensionIssueAction extends Action { private static readonly _id = 'workbench.extensions.action.reportExtensionIssue'; @@ -34,7 +36,8 @@ export class ReportExtensionIssueAction extends Action { @INativeHostService private readonly nativeHostService: INativeHostService ) { super(ReportExtensionIssueAction._id, ReportExtensionIssueAction._label, 'extension-action report-issue'); - this.enabled = !!extension.description.repository && !!extension.description.repository.url; + + this.enabled = extension.description.isBuiltin || (!!extension.description.repository && !!extension.description.repository.url); } async run(): Promise { @@ -51,6 +54,9 @@ export class ReportExtensionIssueAction extends Action { unresponsiveProfile?: IExtensionHostProfile }): Promise { let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined; + if (extension.description.isBuiltin) { + baseUrl = builtinExtensionIssueUrl; + } if (!!baseUrl) { baseUrl = `${baseUrl.indexOf('.git') !== -1 ? baseUrl.substr(0, baseUrl.length - 4) : baseUrl}/issues/new/`; } else { From 0a2cb7630f3b95baf3f686d250c55a8effa4825c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 12:08:46 +0100 Subject: [PATCH 0796/1837] apply workspace edit from onWill-handler from within renderer, https://github.com/microsoft/vscode/issues/111878 --- .../api/browser/mainThreadBulkEdits.ts | 26 ++---------- .../api/browser/mainThreadEditors.ts | 2 +- .../mainThreadFileSystemEventService.ts | 12 ++++-- .../workbench/api/common/extHost.protocol.ts | 2 +- .../common/extHostFileSystemEventService.ts | 41 +++++++++---------- 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts index 70fb045d7aa..948f085f2ad 100644 --- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts @@ -3,29 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IBulkEditService, ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; -import { IExtHostContext, IWorkspaceEditDto, WorkspaceEditType, MainThreadBulkEditsShape, MainContext } from 'vs/workbench/api/common/extHost.protocol'; -import { revive } from 'vs/base/common/marshalling'; -import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; -import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; - -function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] { - if (!data?.edits) { - return []; - } - - const result: ResourceEdit[] = []; - for (let edit of revive(data).edits) { - if (edit._type === WorkspaceEditType.File) { - result.push(new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata)); - } else if (edit._type === WorkspaceEditType.Text) { - result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata)); - } else if (edit._type === WorkspaceEditType.Cell) { - result.push(new ResourceNotebookCellEdit(edit.resource, edit.edit, edit.notebookVersionId, edit.metadata)); - } - } - return result; -} +import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; +import { IExtHostContext, IWorkspaceEditDto, MainThreadBulkEditsShape, MainContext } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; +import { reviveWorkspaceEditDto2 } from 'vs/workbench/api/browser/mainThreadEditors'; @extHostNamedCustomer(MainContext.MainThreadBulkEdits) export class MainThreadBulkEdits implements MainThreadBulkEditsShape { diff --git a/src/vs/workbench/api/browser/mainThreadEditors.ts b/src/vs/workbench/api/browser/mainThreadEditors.ts index 1723f632866..0f52d9af149 100644 --- a/src/vs/workbench/api/browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadEditors.ts @@ -27,7 +27,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo import { revive } from 'vs/base/common/marshalling'; import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; -function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] { +export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] { if (!data?.edits) { return []; } diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index 81905c6b1d0..88f3f33f3aa 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -11,6 +11,8 @@ import { localize } from 'vs/nls'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { reviveWorkspaceEditDto2 } from 'vs/workbench/api/browser/mainThreadEditors'; +import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; @extHostCustomer export class MainThreadFileSystemEventService { @@ -20,7 +22,8 @@ export class MainThreadFileSystemEventService { constructor( extHostContext: IExtHostContext, @IFileService fileService: IFileService, - @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService + @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, + @IBulkEditService bulkEditService: IBulkEditService ) { const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService); @@ -56,9 +59,12 @@ export class MainThreadFileSystemEventService { // BEFORE file operation this._listener.add(workingCopyFileService.addFileOperationParticipant({ participate: async (files, operation, undoRedoGroupId, isUndoing, _progress, timeout, token) => { - if (!isUndoing) { - return proxy.$onWillRunFileOperation(operation, files, undoRedoGroupId, timeout, token); + if (isUndoing) { + return; } + const data = await proxy.$onWillRunFileOperation(operation, files, timeout, token); + const edit = reviveWorkspaceEditDto2(data); + await bulkEditService.apply(edit, { undoRedoGroupId }); } })); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index b97a962f6ed..a2ff7b55eed 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1147,7 +1147,7 @@ export interface SourceTargetPair { export interface ExtHostFileSystemEventServiceShape { $onFileEvent(events: FileSystemEvents): void; - $onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise; + $onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise; $onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void; } diff --git a/src/vs/workbench/api/common/extHostFileSystemEventService.ts b/src/vs/workbench/api/common/extHostFileSystemEventService.ts index 0503a131b93..585056c21b6 100644 --- a/src/vs/workbench/api/common/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/common/extHostFileSystemEventService.ts @@ -8,7 +8,7 @@ import { IRelativePattern, parse } from 'vs/base/common/glob'; import { URI } from 'vs/base/common/uri'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import type * as vscode from 'vscode'; -import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, SourceTargetPair, IWorkspaceEditDto, MainThreadBulkEditsShape } from './extHost.protocol'; +import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, SourceTargetPair, IWorkspaceEditDto } from './extHost.protocol'; import * as typeConverter from './extHostTypeConverters'; import { Disposable, WorkspaceEdit } from './extHostTypes'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; @@ -122,8 +122,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ constructor( mainContext: IMainContext, private readonly _logService: ILogService, - private readonly _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors, - private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape = mainContext.getProxy(MainContext.MainThreadBulkEdits) + private readonly _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors ) { // } @@ -178,23 +177,19 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ }; } - async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise { + async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise { switch (operation) { case FileOperation.MOVE: - await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, undoRedoGroupId, timeout, token); - break; + return await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token); case FileOperation.DELETE: - await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token); - break; + return await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token); case FileOperation.CREATE: - await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token); - break; - default: - //ignore, dont send + return await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token); } + return undefined; } - private async _fireWillEvent(emitter: AsyncEmitter, data: Omit, undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise { + private async _fireWillEvent(emitter: AsyncEmitter, data: Omit, timeout: number, token: CancellationToken): Promise { const edits: WorkspaceEdit[] = []; @@ -212,17 +207,19 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ }); if (token.isCancellationRequested) { - return; + return undefined; } - if (edits.length > 0) { - // concat all WorkspaceEdits collected via waitUntil-call and apply them in one go. - const dto: IWorkspaceEditDto = { edits: [] }; - for (let edit of edits) { - let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors); - dto.edits = dto.edits.concat(edits); - } - return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto, undoRedoGroupId); + if (edits.length === 0) { + return undefined; } + + // concat all WorkspaceEdits collected via waitUntil-call and send them over to the renderer + const dto: IWorkspaceEditDto = { edits: [] }; + for (let edit of edits) { + let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors); + dto.edits = dto.edits.concat(edits); + } + return dto; } } From a029dda2fe73994e5ff6e64e51b9ce66544560bc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 12:12:57 +0100 Subject: [PATCH 0797/1837] move suppress logic, https://github.com/microsoft/vscode/issues/111878 --- src/vs/workbench/api/browser/mainThreadBulkEdits.ts | 8 +------- .../api/browser/mainThreadFileSystemEventService.ts | 7 ++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts index 948f085f2ad..8583555b871 100644 --- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts @@ -19,12 +19,6 @@ export class MainThreadBulkEdits implements MainThreadBulkEditsShape { $tryApplyWorkspaceEdit(dto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise { const edits = reviveWorkspaceEditDto2(dto); - return this._bulkEditService.apply(edits, { - // having a undoRedoGroupId means that this is a nested workspace edit, - // e.g one from a onWill-handler and for now we need to forcefully suppress - // refactor previewing, see: https://github.com/microsoft/vscode/issues/111873#issuecomment-738739852 - undoRedoGroupId, - suppressPreview: typeof undoRedoGroupId === 'number' ? true : undefined - }).then(() => true, _err => false); + return this._bulkEditService.apply(edits, { undoRedoGroupId }).then(() => true, _err => false); } } diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index 88f3f33f3aa..b875404549b 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -64,7 +64,12 @@ export class MainThreadFileSystemEventService { } const data = await proxy.$onWillRunFileOperation(operation, files, timeout, token); const edit = reviveWorkspaceEditDto2(data); - await bulkEditService.apply(edit, { undoRedoGroupId }); + await bulkEditService.apply(edit, { + undoRedoGroupId, + // this is a nested workspace edit, e.g one from a onWill-handler and for now we need to forcefully suppress + // refactor previewing, see: https://github.com/microsoft/vscode/issues/111873#issuecomment-738739852 + suppressPreview: true + }); } })); From 84e5cdec2936f3d4b947a609d5cd1a3695222577 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 12:54:07 +0100 Subject: [PATCH 0798/1837] #92038 Use menu registry --- .../userDataSync/browser/userDataSync.ts | 50 +++++++++++++++--- .../userDataSync/browser/userDataSyncViews.ts | 52 ++----------------- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 8a1aa13b2d8..29c63183c85 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -20,7 +20,7 @@ import { localize } from 'vs/nls'; import { MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -50,8 +50,10 @@ import { IAuthenticationService } from 'vs/workbench/services/authentication/bro import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewContainerLocation, IViewContainersRegistry, Extensions, ViewContainer } from 'vs/workbench/common/views'; -import { UserDataSyncViewPaneContainer, UserDataSyncDataViews } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncViews'; +import { UserDataSyncDataViews } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncViews'; import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE, SYNC_VIEW_ICON } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { Codicon } from 'vs/base/common/codicons'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; const CONTEXT_CONFLICTS_SOURCES = new RawContextKey('conflictsSources', ''); @@ -732,6 +734,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo this.registerConfigureSyncAction(); this.registerShowSettingsAction(); this.registerShowLogAction(); + this.registerResetSyncDataAction(); } private registerTurnOnSyncAction(): void { @@ -1064,10 +1067,17 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo super({ id: configureSyncCommand.id, title: configureSyncCommand.title, - menu: { + icon: Codicon.settingsGear, + tooltip: localize('configure', "Configure..."), + menu: [{ id: MenuId.CommandPalette, when - } + }, { + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainer', SYNC_VIEW_CONTAINER_ID), + group: 'navigation', + order: 2 + }] }); } run(): any { return that.configureSyncOptions(); } @@ -1081,10 +1091,17 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo super({ id: SHOW_SYNC_LOG_COMMAND_ID, title: localize('show sync log title', "{0}: Show Log", SYNC_TITLE), - menu: { + tooltip: localize('show sync log toolrip', "Show Log"), + icon: Codicon.output, + menu: [{ id: MenuId.CommandPalette, when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized)), - }, + }, { + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainer', SYNC_VIEW_CONTAINER_ID), + group: 'navigation', + order: 1 + }], }); } run(): any { return that.showSyncActivity(); } @@ -1120,14 +1137,31 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo id: SYNC_VIEW_CONTAINER_ID, name: SYNC_TITLE, ctorDescriptor: new SyncDescriptor( - UserDataSyncViewPaneContainer, - [SYNC_VIEW_CONTAINER_ID] + ViewPaneContainer, + [SYNC_VIEW_CONTAINER_ID, { mergeViewWithContainerWhenSingleView: true }] ), icon: SYNC_VIEW_ICON, hideIfEmpty: true, }, ViewContainerLocation.Sidebar); } + private registerResetSyncDataAction(): void { + const that = this; + this._register(registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.actions.syncData.reset', + title: localize('workbench.actions.syncData.reset', "Clear Data in Cloud..."), + menu: [{ + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainer', SYNC_VIEW_CONTAINER_ID) + }], + }); + } + run(): any { return that.userDataSyncWorkbenchService.resetSyncedData(); } + })); + } + private registerDataViews(container: ViewContainer): void { this._register(this.instantiationService.createInstance(UserDataSyncDataViews, container)); } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts index d26d9dd1aa0..86c71c405da 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Registry } from 'vs/platform/registry/common/platform'; -import { IViewsRegistry, Extensions, ITreeViewDescriptor, ITreeViewDataProvider, ITreeItem, TreeItemCollapsibleState, TreeViewItemHandleArg, ViewContainer, IViewDescriptorService } from 'vs/workbench/common/views'; +import { IViewsRegistry, Extensions, ITreeViewDescriptor, ITreeViewDataProvider, ITreeItem, TreeItemCollapsibleState, TreeViewItemHandleArg, ViewContainer } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { TreeView, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView'; @@ -14,23 +14,14 @@ import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/act import { ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { URI } from 'vs/base/common/uri'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { FolderThemeIcon, IThemeService } from 'vs/platform/theme/common/themeService'; +import { FolderThemeIcon } from 'vs/platform/theme/common/themeService'; import { fromNow } from 'vs/base/common/date'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { Event } from 'vs/base/common/event'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Codicon } from 'vs/base/common/codicons'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IAction, Action } from 'vs/base/common/actions'; -import { IUserDataSyncWorkbenchService, CONTEXT_SYNC_STATE, getSyncAreaLabel, CONTEXT_ACCOUNT_STATE, AccountStatus, CONTEXT_ENABLE_ACTIVITY_VIEWS, SHOW_SYNC_LOG_COMMAND_ID, CONFIGURE_SYNC_COMMAND_ID, SYNC_MERGES_VIEW_ID, CONTEXT_ENABLE_SYNC_MERGES_VIEW, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { Action } from 'vs/base/common/actions'; +import { IUserDataSyncWorkbenchService, CONTEXT_SYNC_STATE, getSyncAreaLabel, CONTEXT_ACCOUNT_STATE, AccountStatus, CONTEXT_ENABLE_ACTIVITY_VIEWS, SYNC_MERGES_VIEW_ID, CONTEXT_ENABLE_SYNC_MERGES_VIEW, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync'; import { IUserDataSyncMachinesService, IUserDataSyncMachine } from 'vs/platform/userDataSync/common/userDataSyncMachines'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -38,41 +29,6 @@ import { flatten } from 'vs/base/common/arrays'; import { UserDataSyncMergesViewPane } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView'; import { basename } from 'vs/base/common/resources'; -export class UserDataSyncViewPaneContainer extends ViewPaneContainer { - - constructor( - containerId: string, - @IUserDataSyncWorkbenchService private readonly userDataSyncWorkbenchService: IUserDataSyncWorkbenchService, - @ICommandService private readonly commandService: ICommandService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @ITelemetryService telemetryService: ITelemetryService, - @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IConfigurationService configurationService: IConfigurationService, - @IStorageService storageService: IStorageService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @IContextMenuService contextMenuService: IContextMenuService, - @IExtensionService extensionService: IExtensionService, - @IViewDescriptorService viewDescriptorService: IViewDescriptorService, - ) { - super(containerId, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); - } - - getActions(): IAction[] { - return [ - new Action(SHOW_SYNC_LOG_COMMAND_ID, localize('showLog', "Show Log"), Codicon.output.classNames, true, async () => this.commandService.executeCommand(SHOW_SYNC_LOG_COMMAND_ID)), - new Action(CONFIGURE_SYNC_COMMAND_ID, localize('configure', "Configure..."), Codicon.settingsGear.classNames, true, async () => this.commandService.executeCommand(CONFIGURE_SYNC_COMMAND_ID)), - ]; - } - - getSecondaryActions(): IAction[] { - return [ - new Action('workbench.actions.syncData.reset', localize('workbench.actions.syncData.reset', "Clear Data in Cloud..."), undefined, true, () => this.userDataSyncWorkbenchService.resetSyncedData()), - ]; - } - -} - export class UserDataSyncDataViews extends Disposable { constructor( From d94ba9141341e43d234434d288681fdc0f1e6bf1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 13:04:09 +0100 Subject: [PATCH 0799/1837] #92038 dispose actions on change --- src/vs/workbench/browser/parts/views/viewMenuActions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts index fa97eb113f1..30f6dfac8dd 100644 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ b/src/vs/workbench/browser/parts/views/viewMenuActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IAction } from 'vs/base/common/actions'; -import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { combinedDisposable, Disposable, dispose, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; import { MenuId, IMenuService } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -30,6 +30,7 @@ export abstract class AbstractViewMenuActions extends Disposable { const menu = this._register(menuService.createMenu(menuId, contextKeyService)); const updateActions = () => { + dispose(combinedDisposable(...this.primaryActions, ...this.secondaryActions)); this.primaryActions = []; this.secondaryActions = []; this.titleActionsDisposable.value = createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, { primary: this.primaryActions, secondary: this.secondaryActions }); @@ -40,6 +41,7 @@ export abstract class AbstractViewMenuActions extends Disposable { const contextMenu = this._register(menuService.createMenu(contextMenuId, contextKeyService)); const updateContextMenuActions = () => { + dispose(combinedDisposable(...this.contextMenuActions)); this.contextMenuActions = []; this.titleActionsDisposable.value = createAndFillInActionBarActions(contextMenu, { shouldForwardArgs: true }, { primary: [], secondary: this.contextMenuActions }); }; From 136df0d897d9d7c05d307abf85a4089c50a1a4c2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 13:13:28 +0100 Subject: [PATCH 0800/1837] nuke getActions in outline pane, https://github.com/microsoft/vscode/issues/92038 --- .../contrib/outline/browser/outlinePane.ts | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 3062e937dce..af3eadc1a2e 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -23,10 +23,10 @@ import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureR import { OutlineElement, OutlineModel, TreeElement, IOutlineMarker } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { WorkbenchDataTree } from 'vs/platform/list/browser/listService'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; @@ -34,9 +34,8 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { OutlineConfigKeys, OutlineViewFocused, OutlineViewFiltered } from 'vs/editor/contrib/documentSymbols/outline'; +import { OutlineConfigKeys, OutlineViewFocused, OutlineViewFiltered, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; import { FuzzyScore } from 'vs/base/common/filters'; import { OutlineDataSource, OutlineItemComparator, OutlineSortOrder, OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItem, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineFilter, OutlineAccessibilityProvider } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IDataTreeViewState } from 'vs/base/browser/ui/tree/dataTree'; @@ -44,11 +43,12 @@ import { basename } from 'vs/base/common/resources'; import { IDataSource } from 'vs/base/browser/ui/tree/tree'; import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService'; import { MarkerSeverity } from 'vs/platform/markers/common/markers'; -import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { IView, IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Codicon } from 'vs/base/common/codicons'; +import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; class RequestState { @@ -397,10 +397,8 @@ export class OutlinePane extends ViewPane { this._tree.layout(height, width); } - getActions(): IAction[] { - return [ - new CollapseAction(() => this._tree, true, 'explorer-action ' + Codicon.collapseAll.classNames) - ]; + collapseAll(): void { + this._tree.collapseAll(); } getSecondaryActions(): IAction[] { @@ -637,3 +635,41 @@ export class OutlinePane extends ViewPane { this._tree.setSelection([item]); } } + +// --- commands + +abstract class ViewAction extends Action2 { + constructor(readonly desc: Readonly & { viewId: string }) { + super(desc); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const view = accessor.get(IViewsService).getActiveViewWithId(this.desc.viewId); + if (view) { + return this.runInView(accessor, view, ...args); + } + } + + abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; +} + +registerAction2(class Collapse extends ViewAction { + + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.collapse', + title: localize('collapse', "Collapse All"), + f1: false, + icon: Codicon.collapseAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.collapseAll(); + } +}); From 56e35cf038f2a5543f767cb53b80145f6acebcca Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 13:33:39 +0100 Subject: [PATCH 0801/1837] #92038 Create view and viewPaneContainer util actions --- .../browser/parts/views/viewPaneContainer.ts | 32 ++++++++++++++++++- .../contrib/outline/browser/outlinePane.ts | 21 ++---------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 410c6724491..97e62752246 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -23,7 +23,7 @@ import { PaneView, IPaneViewOptions, IPaneOptions, Pane, IPaneStyles } from 'vs/ import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon } from 'vs/workbench/common/views'; +import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon, IViewsService } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined } from 'vs/base/common/types'; @@ -1665,6 +1665,36 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } } +export abstract class ViewPaneContainerAction extends Action2 { + constructor(readonly desc: Readonly & { viewPaneContainerId: string }) { + super(desc); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(this.desc.viewPaneContainerId); + if (viewPaneContainer) { + return this.runInView(accessor, viewPaneContainer, ...args); + } + } + + abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; +} + +export abstract class ViewAction extends Action2 { + constructor(readonly desc: Readonly & { viewId: string }) { + super(desc); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const view = accessor.get(IViewsService).getActiveViewWithId(this.desc.viewId); + if (view) { + return this.runInView(accessor, view, ...args); + } + } + + abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; +} + class MoveViewPosition extends Action2 { constructor(desc: Readonly, private readonly offset: number) { super(desc); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index af3eadc1a2e..5ffb51b24b4 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -32,7 +32,7 @@ import { WorkbenchDataTree } from 'vs/platform/list/browser/listService'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewAction, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { OutlineConfigKeys, OutlineViewFocused, OutlineViewFiltered, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; @@ -43,12 +43,12 @@ import { basename } from 'vs/base/common/resources'; import { IDataSource } from 'vs/base/browser/ui/tree/tree'; import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService'; import { MarkerSeverity } from 'vs/platform/markers/common/markers'; -import { IView, IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; +import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Codicon } from 'vs/base/common/codicons'; -import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; +import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; class RequestState { @@ -638,21 +638,6 @@ export class OutlinePane extends ViewPane { // --- commands -abstract class ViewAction extends Action2 { - constructor(readonly desc: Readonly & { viewId: string }) { - super(desc); - } - - run(accessor: ServicesAccessor, ...args: any[]) { - const view = accessor.get(IViewsService).getActiveViewWithId(this.desc.viewId); - if (view) { - return this.runInView(accessor, view, ...args); - } - } - - abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; -} - registerAction2(class Collapse extends ViewAction { constructor() { From af74fd420bff63ebc720d44eb4896b3340c1f961 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 14:44:10 +0100 Subject: [PATCH 0802/1837] nuke getSecondaryActions from outline, https://github.com/microsoft/vscode/issues/92038 --- .../platform/contextkey/common/contextkey.ts | 4 +- .../contrib/outline/browser/outlinePane.ts | 199 +++++++++++++----- 2 files changed, 154 insertions(+), 49 deletions(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index ea7c83876ff..fde5606ea23 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -1278,11 +1278,11 @@ export class RawContextKey extends ContextKeyDefinedExpr { return ContextKeyExpr.not(this.key); } - public isEqualTo(value: string): ContextKeyExpression { + public isEqualTo(value: any): ContextKeyExpression { return ContextKeyExpr.equals(this.key, value); } - public notEqualsTo(value: string): ContextKeyExpression { + public notEqualsTo(value: any): ContextKeyExpression { return ContextKeyExpr.notEquals(this.key, value); } } diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 5ffb51b24b4..a8abcbbe804 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -6,11 +6,9 @@ import 'vs/css!./outlinePane'; import * as dom from 'vs/base/browser/dom'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; -import { Action, IAction, RadioGroup, Separator } from 'vs/base/common/actions'; import { createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; -import { defaultGenerator } from 'vs/base/common/idGenerator'; import { IDisposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { LRUCache } from 'vs/base/common/map'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; @@ -23,7 +21,7 @@ import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureR import { OutlineElement, OutlineModel, TreeElement, IOutlineMarker } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ContextKeyEqualsExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -144,25 +142,6 @@ class RequestOracle { } } -class SimpleToggleAction extends Action { - - private readonly _listener: IDisposable; - - constructor(state: OutlineViewState, label: string, isChecked: () => boolean, callback: (action: SimpleToggleAction) => any, className?: string) { - super(`simple` + defaultGenerator.nextId(), label, className, true, async () => { - this.checked = !this.checked; - callback(this); - }); - this.checked = isChecked(); - this._listener = state.onDidChange(() => this.checked = isChecked()); - } - - dispose(): void { - this._listener.dispose(); - super.dispose(); - } -} - class OutlineViewState { @@ -250,8 +229,11 @@ export class OutlinePane extends ViewPane { private _treeFilter!: OutlineFilter; private _treeStates = new LRUCache(10); - private readonly _contextKeyFocused: IContextKey; - private readonly _contextKeyFiltered: IContextKey; + private readonly _ctxFocused: IContextKey; + private readonly _ctxFiltered: IContextKey; + private readonly _ctxFollowsCursor: IContextKey; + private readonly _ctxFilterOnType: IContextKey; + private readonly _ctxSortMode: IContextKey; constructor( options: IViewletViewOptions, @@ -271,10 +253,22 @@ export class OutlinePane extends ViewPane { ) { super(options, keybindingService, contextMenuService, _configurationService, contextKeyService, viewDescriptorService, _instantiationService, openerService, themeService, telemetryService); this._outlineViewState.restore(this._storageService); - this._contextKeyFocused = OutlineViewFocused.bindTo(contextKeyService); - this._contextKeyFiltered = OutlineViewFiltered.bindTo(contextKeyService); - this._disposables.add(this.onDidFocus(_ => this._contextKeyFocused.set(true))); - this._disposables.add(this.onDidBlur(_ => this._contextKeyFocused.set(false))); + this._ctxFocused = OutlineViewFocused.bindTo(contextKeyService); + this._ctxFiltered = OutlineViewFiltered.bindTo(contextKeyService); + this._disposables.add(this.onDidFocus(_ => this._ctxFocused.set(true))); + this._disposables.add(this.onDidBlur(_ => this._ctxFocused.set(false))); + + + this._ctxFollowsCursor = _ctxFollowsCursor.bindTo(contextKeyService); + this._ctxFilterOnType = _ctxFilterOnType.bindTo(contextKeyService); + this._ctxSortMode = _ctxSortMode.bindTo(contextKeyService); + const viewStateToContext = () => { + this._ctxFollowsCursor.set(this._outlineViewState.followCursor); + this._ctxFilterOnType.set(this._outlineViewState.filterOnType); + this._ctxSortMode.set(this._outlineViewState.sortBy); + }; + viewStateToContext(); + this._outlineViewState.onDidChange(viewStateToContext, this); } dispose(): void { @@ -401,25 +395,27 @@ export class OutlinePane extends ViewPane { this._tree.collapseAll(); } - getSecondaryActions(): IAction[] { - const group = this._register(new RadioGroup([ - new SimpleToggleAction(this._outlineViewState, localize('sortByPosition', "Sort By: Position"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByPosition, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByPosition), - new SimpleToggleAction(this._outlineViewState, localize('sortByName', "Sort By: Name"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByName, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByName), - new SimpleToggleAction(this._outlineViewState, localize('sortByKind', "Sort By: Category"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByKind, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByKind), - ])); - const result = [ - new SimpleToggleAction(this._outlineViewState, localize('followCur', "Follow Cursor"), () => this._outlineViewState.followCursor, action => this._outlineViewState.followCursor = action.checked), - new SimpleToggleAction(this._outlineViewState, localize('filterOnType', "Filter on Type"), () => this._outlineViewState.filterOnType, action => this._outlineViewState.filterOnType = action.checked), - new Separator(), - ...group.actions, - ]; - for (const r of result) { - this._register(r); - } - - return result; + get outlineViewState() { + return this._outlineViewState; } + // getSecondaryActions(): IAction[] { + // const group = this._register(new RadioGroup([ + // new SimpleToggleAction(this._outlineViewState, localize('sortByPosition', "Sort By: Position"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByPosition, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByPosition), + // new SimpleToggleAction(this._outlineViewState, localize('sortByName', "Sort By: Name"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByName, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByName), + // new SimpleToggleAction(this._outlineViewState, localize('sortByKind', "Sort By: Category"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByKind, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByKind), + // ])); + // const result = [ + // new Separator(), + // ...group.actions, + // ]; + // for (const r of result) { + // this._register(r); + // } + + // return result; + // } + private _onDidChangeUserState(e: { followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }) { this._outlineViewState.persist(this._storageService); if (e.followCursor) { @@ -535,7 +531,7 @@ export class OutlinePane extends ViewPane { this._tree.setInput(newModel, state); } - this._editorDisposables.add(toDisposable(() => this._contextKeyFiltered.reset())); + this._editorDisposables.add(toDisposable(() => this._ctxFiltered.reset())); // feature: reveal outline selection in editor // on change -> reveal/select defining range @@ -636,10 +632,14 @@ export class OutlinePane extends ViewPane { } } + +const _ctxFollowsCursor = new RawContextKey('outlineFollowsCursor', false); +const _ctxFilterOnType = new RawContextKey('outlineFiltersOnType', false); +const _ctxSortMode = new RawContextKey('outlineSortMode', OutlineSortOrder.ByPosition); + // --- commands registerAction2(class Collapse extends ViewAction { - constructor() { super({ viewId: OutlineViewId, @@ -658,3 +658,108 @@ registerAction2(class Collapse extends ViewAction { view.collapseAll(); } }); + +registerAction2(class FollowCursor extends ViewAction { + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.followCursor', + title: localize('followCur', "Follow Cursor"), + f1: false, + toggled: _ctxFollowsCursor, + menu: { + id: MenuId.ViewTitle, + group: 'config', + order: 1, + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.outlineViewState.followCursor = !view.outlineViewState.followCursor; + } +}); + +registerAction2(class FilterOnType extends ViewAction { + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.filterOnType', + title: localize('filterOnType', "Filter on Type"), + f1: false, + toggled: _ctxFilterOnType, + menu: { + id: MenuId.ViewTitle, + group: 'config', + order: 2, + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.outlineViewState.filterOnType = !view.outlineViewState.filterOnType; + } +}); + +registerAction2(class SortByPosition extends ViewAction { + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.sortByPosition', + title: localize('sortByPosition', "Sort By: Position"), + f1: false, + toggled: _ctxSortMode.isEqualTo(OutlineSortOrder.ByPosition), + menu: { + id: MenuId.ViewTitle, + group: 'sort', + order: 1, + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.outlineViewState.sortBy = OutlineSortOrder.ByPosition; + } +}); + +registerAction2(class SortByName extends ViewAction { + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.sortByName', + title: localize('sortByName', "Sort By: Name"), + f1: false, + toggled: _ctxSortMode.isEqualTo(OutlineSortOrder.ByName), + menu: { + id: MenuId.ViewTitle, + group: 'sort', + order: 2, + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.outlineViewState.sortBy = OutlineSortOrder.ByName; + } +}); + +registerAction2(class SortByKind extends ViewAction { + constructor() { + super({ + viewId: OutlineViewId, + id: 'outline.sortByKind', + title: localize('sortByKind', "Sort By: Category"), + f1: false, + toggled: _ctxSortMode.isEqualTo(OutlineSortOrder.ByKind), + menu: { + id: MenuId.ViewTitle, + group: 'sort', + order: 3, + when: ContextKeyEqualsExpr.create('view', OutlineViewId) + } + }); + } + runInView(_accessor: ServicesAccessor, view: OutlinePane) { + view.outlineViewState.sortBy = OutlineSortOrder.ByKind; + } +}); From eea0681288d893456be53a058c0bb1c792604101 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Dec 2020 14:47:48 +0100 Subject: [PATCH 0803/1837] adopt `actions/setup-node@v2-beta` --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2806658197..a50a8b69097 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,9 +123,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2-beta with: - node-version: 10 + node-version: 12 - run: yarn --frozen-lockfile name: Install Dependencies - run: yarn monaco-compile-check From fff6f7414f0a18f70ad92fcdd683029182cb44ad Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 15:03:53 +0100 Subject: [PATCH 0804/1837] :lipstick: remove commented code --- .../contrib/outline/browser/outlinePane.ts | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index a8abcbbe804..1bc3e714c6f 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -399,28 +399,9 @@ export class OutlinePane extends ViewPane { return this._outlineViewState; } - // getSecondaryActions(): IAction[] { - // const group = this._register(new RadioGroup([ - // new SimpleToggleAction(this._outlineViewState, localize('sortByPosition', "Sort By: Position"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByPosition, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByPosition), - // new SimpleToggleAction(this._outlineViewState, localize('sortByName', "Sort By: Name"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByName, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByName), - // new SimpleToggleAction(this._outlineViewState, localize('sortByKind', "Sort By: Category"), () => this._outlineViewState.sortBy === OutlineSortOrder.ByKind, _ => this._outlineViewState.sortBy = OutlineSortOrder.ByKind), - // ])); - // const result = [ - // new Separator(), - // ...group.actions, - // ]; - // for (const r of result) { - // this._register(r); - // } - - // return result; - // } - private _onDidChangeUserState(e: { followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }) { this._outlineViewState.persist(this._storageService); - if (e.followCursor) { - // todo@jrieken update immediately - } + if (e.sortBy) { this._treeComparator.type = this._outlineViewState.sortBy; this._tree.resort(); From f211a2bbe9685e0468000bfe34e87390c7eced22 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 15:14:50 +0100 Subject: [PATCH 0805/1837] clarify docs, fixes https://github.com/microsoft/vscode/issues/111686 --- src/vs/vscode.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index e1c2dd30ccb..81b27da542b 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5173,9 +5173,9 @@ declare module 'vscode' { set(uri: Uri, diagnostics: ReadonlyArray | undefined): void; /** - * Replace all entries in this collection. + * Replace diagnostics for multiple resources in this collection. * - * Diagnostics of multiple tuples of the same uri will be merged, e.g + * _Note_ that multiple tuples of the same uri will be merged, e.g * `[[file1, [d1]], [file1, [d2]]]` is equivalent to `[[file1, [d1, d2]]]`. * If a diagnostics item is `undefined` as in `[file1, undefined]` * all previous but not subsequent diagnostics are removed. From c350d8b4238599bb07526b6a0cd5e7998769c7df Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 15:22:07 +0100 Subject: [PATCH 0806/1837] #92038 Move panel actions to use menu registry --- src/vs/workbench/browser/contextkeys.ts | 16 ++- src/vs/workbench/browser/panecomposite.ts | 4 +- .../workbench/browser/parts/compositePart.ts | 12 -- .../browser/parts/panel/panelActions.ts | 127 +++++++++--------- .../browser/parts/panel/panelPart.ts | 11 +- .../browser/parts/views/viewMenuActions.ts | 18 ++- src/vs/workbench/common/panel.ts | 2 + src/vs/workbench/common/views.ts | 9 +- .../contrib/markers/browser/markersView.ts | 2 +- 9 files changed, 101 insertions(+), 100 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 10e7b53ef34..833ec221536 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -17,7 +17,7 @@ import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/ import { SideBarVisibleContext } from 'vs/workbench/common/viewlet'; import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { PanelPositionContext } from 'vs/workbench/common/panel'; +import { PanelMaximizedContext, PanelPositionContext, PanelVisibleContext } from 'vs/workbench/common/panel'; import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { isNative } from 'vs/base/common/platform'; @@ -64,6 +64,8 @@ export class WorkbenchContextKeysHandler extends Disposable { private sideBarVisibleContext: IContextKey; private editorAreaVisibleContext: IContextKey; private panelPositionContext: IContextKey; + private panelVisibleContext: IContextKey; + private panelMaximizedContext: IContextKey; constructor( @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -146,9 +148,13 @@ export class WorkbenchContextKeysHandler extends Disposable { // Sidebar this.sideBarVisibleContext = SideBarVisibleContext.bindTo(this.contextKeyService); - // Panel Position + // Panel this.panelPositionContext = PanelPositionContext.bindTo(this.contextKeyService); this.panelPositionContext.set(positionToString(this.layoutService.getPanelPosition())); + this.panelVisibleContext = PanelVisibleContext.bindTo(this.contextKeyService); + this.panelVisibleContext.set(this.layoutService.isVisible(Parts.PANEL_PART)); + this.panelMaximizedContext = PanelMaximizedContext.bindTo(this.contextKeyService); + this.panelMaximizedContext.set(this.layoutService.isPanelMaximized()); this.registerListeners(); } @@ -182,7 +188,11 @@ export class WorkbenchContextKeysHandler extends Disposable { this._register(this.viewletService.onDidViewletClose(() => this.updateSideBarContextKeys())); this._register(this.viewletService.onDidViewletOpen(() => this.updateSideBarContextKeys())); - this._register(this.layoutService.onPartVisibilityChange(() => this.editorAreaVisibleContext.set(this.layoutService.isVisible(Parts.EDITOR_PART)))); + this._register(this.layoutService.onPartVisibilityChange(() => { + this.editorAreaVisibleContext.set(this.layoutService.isVisible(Parts.EDITOR_PART)); + this.panelVisibleContext.set(this.layoutService.isVisible(Parts.PANEL_PART)); + this.panelMaximizedContext.set(this.layoutService.isPanelMaximized()); + })); this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.dirtyWorkingCopiesContext.set(workingCopy.isDirty() || this.workingCopyService.hasDirty))); } diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts index f6d2e814c6b..b1e83500c44 100644 --- a/src/vs/workbench/browser/panecomposite.ts +++ b/src/vs/workbench/browser/panecomposite.ts @@ -37,7 +37,7 @@ export class PaneComposite extends Composite implements IPaneComposite { ) { super(id, telemetryService, themeService, storageService); - this.menuActions = this._register(this.instantiationService.createInstance(ViewContainerMenuActions, this.getId(), MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext)); + this.menuActions = this._register(this.instantiationService.createInstance(ViewContainerMenuActions, viewPaneContainer.viewContainer, MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext)); this._register(this.menuActions.onDidChangeTitle(() => this.updateTitleArea())); this._register(this.viewPaneContainer.onTitleAreaUpdate(() => this.updateTitleArea())); } @@ -85,8 +85,8 @@ export class PaneComposite extends Composite implements IPaneComposite { getActions(): ReadonlyArray { const result = []; - result.push(...this.menuActions.getPrimaryActions()); result.push(...this.viewPaneContainer.getActions()); + result.push(...this.menuActions.getPrimaryActions()); return result; } diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 1350ddfe51b..13fe045e552 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -327,10 +327,6 @@ export abstract class CompositePart extends Part { const primaryActions: IAction[] = composite?.getActions().slice(0) || []; const secondaryActions: IAction[] = composite?.getSecondaryActions().slice(0) || []; - // From Part - primaryActions.push(...this.getActions()); - secondaryActions.push(...this.getSecondaryActions()); - // Update context const toolBar = assertIsDefined(this.toolBar); toolBar.context = this.actionsContextProvider(); @@ -471,14 +467,6 @@ export abstract class CompositePart extends Part { return compositeItem ? compositeItem.progress : undefined; } - protected getActions(): ReadonlyArray { - return []; - } - - protected getSecondaryActions(): ReadonlyArray { - return []; - } - protected getTitleAreaDropDownAnchorAlignment(): AnchorAlignment { return AnchorAlignment.RIGHT; } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 74619ecec37..9fa815919e7 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -5,45 +5,26 @@ import 'vs/css!./media/panelpart'; import * as nls from 'vs/nls'; -import { DisposableStore } from 'vs/base/common/lifecycle'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Action } from 'vs/base/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; -import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { SyncActionDescriptor, MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions, CATEGORIES } from 'vs/workbench/common/actions'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; import { ActivityAction, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositeBarActions'; import { IActivity } from 'vs/workbench/common/activity'; -import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { ActivePanelContext, PanelPositionContext } from 'vs/workbench/common/panel'; -import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; +import { ActivePanelContext, PanelMaximizedContext, PanelPositionContext, PanelVisibleContext } from 'vs/workbench/common/panel'; +import { ContextKeyEqualsExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { ViewContainerLocation, ViewContainerLocationToString } from 'vs/workbench/common/views'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; const maximizeIcon = registerIcon('panel-maximize', Codicon.chevronUp, nls.localize('maximizeIcon', 'Icon to maximize a panel.')); const restoreIcon = registerIcon('panel-restore', Codicon.chevronDown, nls.localize('restoreIcon', 'Icon to restore a panel.')); const closeIcon = registerIcon('panel-close', Codicon.close, nls.localize('closeIcon', 'Icon to close a panel.')); -export class ClosePanelAction extends Action { - - static readonly ID = 'workbench.action.closePanel'; - static readonly LABEL = nls.localize('closePanel', "Close Panel"); - - constructor( - id: string, - name: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService - ) { - super(id, name, ThemeIcon.asClassName(closeIcon)); - } - - async run(): Promise { - this.layoutService.setPanelHidden(true); - } -} - export class TogglePanelAction extends Action { static readonly ID = 'workbench.action.togglePanel'; @@ -91,46 +72,6 @@ class FocusPanelAction extends Action { } } - -export class ToggleMaximizedPanelAction extends Action { - - static readonly ID = 'workbench.action.toggleMaximizedPanel'; - static readonly LABEL = nls.localize('toggleMaximizedPanel', "Toggle Maximized Panel"); - - private static readonly MAXIMIZE_LABEL = nls.localize('maximizePanel', "Maximize Panel Size"); - private static readonly RESTORE_LABEL = nls.localize('minimizePanel', "Restore Panel Size"); - - private readonly toDispose = this._register(new DisposableStore()); - - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IEditorGroupsService editorGroupsService: IEditorGroupsService - ) { - super(id, label, layoutService.isPanelMaximized() ? ThemeIcon.asClassName(restoreIcon) : ThemeIcon.asClassName(maximizeIcon)); - - this.toDispose.add(editorGroupsService.onDidLayout(() => { - const maximized = this.layoutService.isPanelMaximized(); - this.class = maximized ? ThemeIcon.asClassName(restoreIcon) : ThemeIcon.asClassName(maximizeIcon); - this.label = maximized ? ToggleMaximizedPanelAction.RESTORE_LABEL : ToggleMaximizedPanelAction.MAXIMIZE_LABEL; - })); - } - - async run(): Promise { - if (!this.layoutService.isVisible(Parts.PANEL_PART)) { - this.layoutService.setPanelHidden(false); - // If the panel is not already maximized, maximize it - if (!this.layoutService.isPanelMaximized()) { - this.layoutService.toggleMaximizedPanel(); - } - } - else { - this.layoutService.toggleMaximizedPanel(); - } - } -} - const PositionPanelActionId = { LEFT: 'workbench.action.positionPanelLeft', RIGHT: 'workbench.action.positionPanelRight', @@ -287,11 +228,65 @@ export class NextPanelViewAction extends SwitchPanelViewAction { const actionRegistry = Registry.as(WorkbenchExtensions.WorkbenchActions); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(TogglePanelAction, { primary: KeyMod.CtrlCmd | KeyCode.KEY_J }), 'View: Toggle Panel', CATEGORIES.View.value); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPanelAction), 'View: Focus into Panel', CATEGORIES.View.value); -actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleMaximizedPanelAction), 'View: Toggle Maximized Panel', CATEGORIES.View.value); -actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ClosePanelAction), 'View: Close Panel', CATEGORIES.View.value); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(PreviousPanelViewAction), 'View: Previous Panel View', CATEGORIES.View.value); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NextPanelViewAction), 'View: Next Panel View', CATEGORIES.View.value); +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.toggleMaximizedPanel', + title: { value: nls.localize('toggleMaximizedPanel', "Toggle Maximized Panel"), original: 'Toggle Maximized Panel' }, + tooltip: { value: nls.localize('maximizePanel', "Maximize Panel Size"), original: 'Maximize Panel Size' }, + category: CATEGORIES.View, + f1: true, + icon: maximizeIcon, + toggled: { condition: PanelMaximizedContext, icon: restoreIcon, tooltip: { value: nls.localize('minimizePanel', "Restore Panel Size"), original: 'Restore Panel Size' } }, + menu: [{ + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Panel)), + group: 'navigation', + order: 1 + }] + }); + } + run(accessor: ServicesAccessor) { + const layoutService = accessor.get(IWorkbenchLayoutService); + if (!layoutService.isVisible(Parts.PANEL_PART)) { + layoutService.setPanelHidden(false); + // If the panel is not already maximized, maximize it + if (!layoutService.isPanelMaximized()) { + layoutService.toggleMaximizedPanel(); + } + } + else { + layoutService.toggleMaximizedPanel(); + } + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.closePanel', + title: { value: nls.localize('closePanel', "Close Panel"), original: 'Close Panel' }, + category: CATEGORIES.View, + icon: closeIcon, + menu: [{ + id: MenuId.CommandPalette, + when: PanelVisibleContext, + }, { + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Panel)), + group: 'navigation', + order: 2 + }] + }); + } + run(accessor: ServicesAccessor) { + accessor.get(IWorkbenchLayoutService).setPanelHidden(true); + } +}); + MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { group: '2_workbench_layout', command: { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 89d515e6634..8a7c5c62f4a 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 { ClosePanelAction, PanelActivityAction, ToggleMaximizedPanelAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions'; +import { PanelActivityAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } 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'; @@ -195,7 +195,7 @@ export class PanelPart extends CompositePart implements IPanelService { viewMenuActions.dispose(); } - const viewContainerMenuActions = this.instantiationService.createInstance(ViewContainerMenuActions, container.id, MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext); + const viewContainerMenuActions = this.instantiationService.createInstance(ViewContainerMenuActions, container, MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext); result.push(...viewContainerMenuActions.getContextMenuActions()); viewContainerMenuActions.dispose(); } @@ -534,13 +534,6 @@ export class PanelPart extends CompositePart implements IPanelService { .sort((p1, p2) => pinnedCompositeIds.indexOf(p1.id) - pinnedCompositeIds.indexOf(p2.id)); } - protected getActions(): ReadonlyArray { - return [ - this.instantiationService.createInstance(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL), - this.instantiationService.createInstance(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL) - ]; - } - getActivePanel(): IPanel | undefined { return this.getActiveComposite(); } diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts index 30f6dfac8dd..3454853ee65 100644 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ b/src/vs/workbench/browser/parts/views/viewMenuActions.ts @@ -9,6 +9,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { MenuId, IMenuService } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IViewDescriptorService, ViewContainer, ViewContainerLocationToString } from 'vs/workbench/common/views'; export abstract class AbstractViewMenuActions extends Disposable { @@ -89,20 +90,25 @@ export class ViewMenuActions extends AbstractViewMenuActions { export class ViewContainerMenuActions extends AbstractViewMenuActions { constructor( - containerId: string, + viewContainer: ViewContainer, menuId: MenuId, contextMenuId: MenuId, @IContextKeyService contextKeyService: IContextKeyService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IMenuService menuService: IMenuService, ) { const scopedContextKeyService = contextKeyService.createScoped(); - scopedContextKeyService.createKey('viewContainer', containerId); + scopedContextKeyService.createKey('viewContainer', viewContainer.id); + const updateViewContainerLocationContext = () => { + const viewContainerLocation = viewDescriptorService.getViewContainerLocation(viewContainer); + if (viewContainerLocation !== null) { + scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewContainerLocation)); + } + }; + updateViewContainerLocationContext(); super(menuId, contextMenuId, scopedContextKeyService, menuService); this._register(scopedContextKeyService); - } - - getSecondaryActions(): IAction[] { - return super.getSecondaryActions(); + this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(updateViewContainerLocationContext)); } } diff --git a/src/vs/workbench/common/panel.ts b/src/vs/workbench/common/panel.ts index 7b836be9552..555e85dcf89 100644 --- a/src/vs/workbench/common/panel.ts +++ b/src/vs/workbench/common/panel.ts @@ -9,5 +9,7 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export const ActivePanelContext = new RawContextKey('activePanel', ''); export const PanelFocusContext = new RawContextKey('panelFocus', false); export const PanelPositionContext = new RawContextKey('panelPosition', 'bottom'); +export const PanelVisibleContext = new RawContextKey('panelVisible', false); +export const PanelMaximizedContext = new RawContextKey('panelMaximized', false); export interface IPanel extends IComposite { } diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 0744cecf620..5fa948c8f85 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -38,11 +38,18 @@ export namespace Extensions { export const ViewsRegistry = 'workbench.registry.view'; } -export enum ViewContainerLocation { +export const enum ViewContainerLocation { Sidebar, Panel } +export function ViewContainerLocationToString(viewContainerLocation: ViewContainerLocation) { + switch (viewContainerLocation) { + case ViewContainerLocation.Sidebar: return 'sidebar'; + case ViewContainerLocation.Panel: return 'panel'; + } +} + export interface IViewContainerDescriptor { readonly id: string; diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 8836c8371b2..8046070b68e 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -219,7 +219,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { id: MenuId.ViewTitle, when: ContextKeyEqualsExpr.create('view', that.id), group: 'navigation', - order: Number.MAX_SAFE_INTEGER, + order: 2, }, icon: Codicon.collapseAll }); From 684ceea0ed62eb436b1ca255ba32fb50951436b8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 11 Dec 2020 15:31:26 +0100 Subject: [PATCH 0807/1837] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef6f8dc26f1..18e620a5363 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "1aaf2adfd4fd7c35c133724c4d97e103f2fa331f", + "distro": "b1d4d66f8f5734c216ae6288c36660e81511706b", "author": { "name": "Microsoft Corporation" }, From 887bc5274397f00ca989bfa1f304cd226fd97fa3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 15:35:43 +0100 Subject: [PATCH 0808/1837] remove extra separator --- .../extensions/browser/extensionsViews.ts | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index 5eabd9d6a63..42ef838cce3 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -266,32 +266,27 @@ export class ExtensionsListView extends ViewPane { const runningExtensions = await this.extensionService.getExtensions(); const manageExtensionAction = this.instantiationService.createInstance(ManageExtensionAction); manageExtensionAction.extension = e.element; + let groups: IAction[][] = []; if (manageExtensionAction.enabled) { - const groups = await manageExtensionAction.getActionGroups(runningExtensions); - let actions: IAction[] = []; - for (const menuActions of groups) { - actions = [...actions, ...menuActions, new Separator()]; - } - this.contextMenuService.showContextMenu({ - getAnchor: () => e.anchor, - getActions: () => actions.slice(0, actions.length - 1) - }); + groups = await manageExtensionAction.getActionGroups(runningExtensions); + } else if (e.element) { - const groups = getContextMenuActions(e.element, false, this.instantiationService); + groups = getContextMenuActions(e.element, false, this.instantiationService); groups.forEach(group => group.forEach(extensionAction => { if (extensionAction instanceof ExtensionAction) { extensionAction.extension = e.element!; } })); - let actions: IAction[] = []; - for (const menuActions of groups) { - actions = [...actions, ...menuActions, new Separator()]; - } - this.contextMenuService.showContextMenu({ - getAnchor: () => e.anchor, - getActions: () => actions - }); } + let actions: IAction[] = []; + for (const menuActions of groups) { + actions = [...actions, ...menuActions, new Separator()]; + } + actions.pop(); + this.contextMenuService.showContextMenu({ + getAnchor: () => e.anchor, + getActions: () => actions + }); } } From b857599fb9b511bb81e3aeb2fa5ca259f4691286 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 15:35:58 +0100 Subject: [PATCH 0809/1837] Attempt to cache root node modules --- .github/workflows/ci.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a50a8b69097..eeb6158923a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,12 +123,33 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-node@v2-beta with: node-version: 12 + + - name: Compute yarn cache key + id: yarn-cache-key + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock') }}" + + - name: Cache root node modules + id: root-node-modules # use this to check for `cache-hit` (`steps.root-node-modules.outputs.cache-hit != 'true'`) + uses: actions/cache@v2 + env: + cache-name: root-node-modules + with: + path: ./node_modules + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - run: yarn --frozen-lockfile name: Install Dependencies + - run: yarn monaco-compile-check name: Run Monaco Editor Checks + - run: yarn gulp editor-esm-bundle name: Editor Distro & ESM Bundle From 8af387dddd74950f16fbb2171d6d096fb23d7ce3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 15:41:53 +0100 Subject: [PATCH 0810/1837] Fix #112287 --- .../browser/preferences.contribution.ts | 23 ++++++++++++++++++- .../contrib/preferences/common/preferences.ts | 1 + .../common/keybindingsEditorModel.ts | 4 ++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index 511b2c236fd..496c76c0f66 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -33,7 +33,7 @@ import { KeybindingsEditor } from 'vs/workbench/contrib/preferences/browser/keyb import { ConfigureLanguageBasedSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions'; import { PreferencesEditor } from 'vs/workbench/contrib/preferences/browser/preferencesEditor'; import { SettingsEditor2, SettingsFocusContext } from 'vs/workbench/contrib/preferences/browser/settingsEditor2'; -import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, KEYBINDINGS_EDITOR_COMMAND_ADD, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, KEYBINDINGS_EDITOR_COMMAND_ADD, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU } from 'vs/workbench/contrib/preferences/common/preferences'; import { PreferencesContribution } from 'vs/workbench/contrib/preferences/common/preferencesContribution'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -909,6 +909,27 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon } } }); + registerAction2(class extends Action2 { + constructor() { + super({ + id: KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS, + title: { value: nls.localize('showExtensionKeybindings', "Show Extension Keybindings"), original: 'Show Extension Keybindings' }, + menu: [ + { + id: MenuId.EditorTitle, + when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR), + group: '1_keyboard_preferences_actions' + } + ] + }); + } + run(accessor: ServicesAccessor) { + const editorPane = accessor.get(IEditorService).activeEditorPane; + if (editorPane instanceof KeybindingsEditor) { + editorPane.search('@source:extension'); + } + } + }); registerAction2(class extends Action2 { constructor() { super({ diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index 928106092b3..9d5ab0f1b77 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -67,6 +67,7 @@ export const KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR = 'keybindings.editor.showC export const KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS = 'keybindings.editor.focusKeybindings'; export const KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS = 'keybindings.editor.showDefaultKeybindings'; export const KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS = 'keybindings.editor.showUserKeybindings'; +export const KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS = 'keybindings.editor.showExtensionKeybindings'; export const MODIFIED_SETTING_TAG = 'modified'; export const EXTENSION_SETTING_TAG = 'ext:'; diff --git a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts index 7946b790377..304afc422af 100644 --- a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts +++ b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts @@ -99,9 +99,9 @@ export class KeybindingsEditorModel extends EditorModel { .map(keybindingItem => ({ id: KeybindingsEditorModel.getId(keybindingItem), keybindingItem, templateId: KEYBINDING_ENTRY_TEMPLATE_ID })); } - if (/@source:\s*(user|default)/i.test(searchValue)) { + if (/@source:\s*(user|default|extension)/i.test(searchValue)) { keybindingItems = this.filterBySource(keybindingItems, searchValue); - searchValue = searchValue.replace(/@source:\s*(user|default)/i, ''); + searchValue = searchValue.replace(/@source:\s*(user|default|extension)/i, ''); } else { const keybindingMatches = /@keybinding:\s*((\".+\")|(\S+))/i.exec(searchValue); if (keybindingMatches && (keybindingMatches[2] || keybindingMatches[3])) { From d9f2b49323c2990dcc6a864f971011fc21b44670 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 15:48:34 +0100 Subject: [PATCH 0811/1837] Attempt to cache all node_modules folders --- .github/workflows/ci.yml | 51 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eeb6158923a..7c7ae4c3eb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,13 +132,55 @@ jobs: id: yarn-cache-key run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock') }}" - - name: Cache root node modules - id: root-node-modules # use this to check for `cache-hit` (`steps.root-node-modules.outputs.cache-hit != 'true'`) + - name: Cache node modules + id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) uses: actions/cache@v2 env: - cache-name: root-node-modules + cache-name: node-modules-cache with: - path: ./node_modules + path: + - ./node_modules + - ./build/node_modules + - ./build/lib/watch/node_modules + - ./extensions/node_modules + - ./extensions/configuration-editing/node_modules + - ./extensions/css-language-features/node_modules + - ./extensions/css-language-features/server/node_modules + - ./extensions/debug-auto-launch/node_modules + - ./extensions/debug-server-ready/node_modules + - ./extensions/emmet/node_modules + - ./extensions/extension-editing/node_modules + - ./extensions/git/node_modules + - ./extensions/git-ui/node_modules + - ./extensions/github/node_modules + - ./extensions/github-authentication/node_modules + - ./extensions/grunt/node_modules + - ./extensions/gulp/node_modules + - ./extensions/html-language-features/node_modules + - ./extensions/html-language-features/server/node_modules + - ./extensions/image-preview/node_modules + - ./extensions/jake/node_modules + - ./extensions/json-language-features/node_modules + - ./extensions/json-language-features/server/node_modules + - ./extensions/markdown-language-features/node_modules + - ./extensions/merge-conflict/node_modules + - ./extensions/microsoft-authentication/node_modules + - ./extensions/npm/node_modules + - ./extensions/php-language-features/node_modules + - ./extensions/search-result/node_modules + - ./extensions/typescript-language-features/node_modules + - ./extensions/vscode-api-tests/node_modules + - ./extensions/vscode-colorize-tests/node_modules + - ./extensions/vscode-custom-editor-tests/node_modules + - ./extensions/vscode-notebook-tests/node_modules + - ./extensions/vscode-test-resolver/node_modules + - ./remote/node_modules + - ./remote/web/node_modules + - ./test/automation/node_modules + - ./test/integration/browser/node_modules + - ./test/smoke/node_modules + - ./test/ui/splitview/node_modules + - ./test/ui/tree/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- @@ -146,6 +188,7 @@ jobs: ${{ runner.os }}- - run: yarn --frozen-lockfile + if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} name: Install Dependencies - run: yarn monaco-compile-check From bfaaca632f398b08c8301ea3fc6a9aef6874a67a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 15:51:44 +0100 Subject: [PATCH 0812/1837] Fix array syntax --- .github/workflows/ci.yml | 86 ++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c7ae4c3eb6..8c837a5ca2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,49 +138,49 @@ jobs: env: cache-name: node-modules-cache with: - path: - - ./node_modules - - ./build/node_modules - - ./build/lib/watch/node_modules - - ./extensions/node_modules - - ./extensions/configuration-editing/node_modules - - ./extensions/css-language-features/node_modules - - ./extensions/css-language-features/server/node_modules - - ./extensions/debug-auto-launch/node_modules - - ./extensions/debug-server-ready/node_modules - - ./extensions/emmet/node_modules - - ./extensions/extension-editing/node_modules - - ./extensions/git/node_modules - - ./extensions/git-ui/node_modules - - ./extensions/github/node_modules - - ./extensions/github-authentication/node_modules - - ./extensions/grunt/node_modules - - ./extensions/gulp/node_modules - - ./extensions/html-language-features/node_modules - - ./extensions/html-language-features/server/node_modules - - ./extensions/image-preview/node_modules - - ./extensions/jake/node_modules - - ./extensions/json-language-features/node_modules - - ./extensions/json-language-features/server/node_modules - - ./extensions/markdown-language-features/node_modules - - ./extensions/merge-conflict/node_modules - - ./extensions/microsoft-authentication/node_modules - - ./extensions/npm/node_modules - - ./extensions/php-language-features/node_modules - - ./extensions/search-result/node_modules - - ./extensions/typescript-language-features/node_modules - - ./extensions/vscode-api-tests/node_modules - - ./extensions/vscode-colorize-tests/node_modules - - ./extensions/vscode-custom-editor-tests/node_modules - - ./extensions/vscode-notebook-tests/node_modules - - ./extensions/vscode-test-resolver/node_modules - - ./remote/node_modules - - ./remote/web/node_modules - - ./test/automation/node_modules - - ./test/integration/browser/node_modules - - ./test/smoke/node_modules - - ./test/ui/splitview/node_modules - - ./test/ui/tree/node_modules + path: | + ./node_modules + ./build/node_modules + ./build/lib/watch/node_modules + ./extensions/node_modules + ./extensions/configuration-editing/node_modules + ./extensions/css-language-features/node_modules + ./extensions/css-language-features/server/node_modules + ./extensions/debug-auto-launch/node_modules + ./extensions/debug-server-ready/node_modules + ./extensions/emmet/node_modules + ./extensions/extension-editing/node_modules + ./extensions/git/node_modules + ./extensions/git-ui/node_modules + ./extensions/github/node_modules + ./extensions/github-authentication/node_modules + ./extensions/grunt/node_modules + ./extensions/gulp/node_modules + ./extensions/html-language-features/node_modules + ./extensions/html-language-features/server/node_modules + ./extensions/image-preview/node_modules + ./extensions/jake/node_modules + ./extensions/json-language-features/node_modules + ./extensions/json-language-features/server/node_modules + ./extensions/markdown-language-features/node_modules + ./extensions/merge-conflict/node_modules + ./extensions/microsoft-authentication/node_modules + ./extensions/npm/node_modules + ./extensions/php-language-features/node_modules + ./extensions/search-result/node_modules + ./extensions/typescript-language-features/node_modules + ./extensions/vscode-api-tests/node_modules + ./extensions/vscode-colorize-tests/node_modules + ./extensions/vscode-custom-editor-tests/node_modules + ./extensions/vscode-notebook-tests/node_modules + ./extensions/vscode-test-resolver/node_modules + ./remote/node_modules + ./remote/web/node_modules + ./test/automation/node_modules + ./test/integration/browser/node_modules + ./test/smoke/node_modules + ./test/ui/splitview/node_modules + ./test/ui/tree/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- From 8f78f153fe084e367ab279cde2d89d2d2409c563 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Dec 2020 15:59:16 +0100 Subject: [PATCH 0813/1837] Fix #112221 --- .../contrib/extensions/browser/extensions.contribution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 02b7c98e80d..fab860c4bcb 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -1029,6 +1029,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi group: '1_copy' }, run: async (accessor: ServicesAccessor, extensionId: string) => { + const clipboardService = accessor.get(IClipboardService); let extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0] || (await this.extensionsWorkbenchService.queryGallery({ names: [extensionId], pageSize: 1 }, CancellationToken.None)).firstPage[0]; if (extension) { @@ -1039,7 +1040,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi const publisher = localize('extensionInfoPublisher', 'Publisher: {0}', extension.publisherDisplayName); const link = extension.url ? localize('extensionInfoVSMarketplaceLink', 'VS Marketplace Link: {0}', `${extension.url}`) : null; const clipboardStr = `${name}\n${id}\n${description}\n${verision}\n${publisher}${link ? '\n' + link : ''}`; - await accessor.get(IClipboardService).writeText(clipboardStr); + await clipboardService.writeText(clipboardStr); } } }); From 6d79a70a36217be38024490767caf65c2cd4b86c Mon Sep 17 00:00:00 2001 From: "stanislav.dombrovsky" Date: Fri, 11 Dec 2020 18:04:41 +0300 Subject: [PATCH 0814/1837] Add more frequently-used Ruby filenames to Ruby bundle (based on the actual TextMate bundle) --- extensions/ruby/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ruby/package.json b/extensions/ruby/package.json index 4572f2526d8..020b1d6daf6 100644 --- a/extensions/ruby/package.json +++ b/extensions/ruby/package.json @@ -13,7 +13,7 @@ "languages": [{ "id": "ruby", "extensions": [ ".rb", ".rbx", ".rjs", ".gemspec", ".rake", ".ru", ".erb", ".podspec", ".rbi" ], - "filenames": [ "rakefile", "gemfile", "guardfile", "podfile", "capfile" ], + "filenames": [ "rakefile", "gemfile", "guardfile", "podfile", "capfile", "cheffile", "hobofile", "vagrantfile", "appraisals", "rantfile", "berksfile", "berksfile.lock", "thorfile", "puppetfile", "dangerfile", "brewfile", "fastfile", "appfile", "deliverfile", "matchfile", "scanfile", "snapfile", "gymfile" ], "aliases": [ "Ruby", "rb" ], "firstLine": "^#!\\s*/.*\\bruby\\b", "configuration": "./language-configuration.json" From d39671e7cb1cd0316c9ee742bf28cc0617679feb Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:06:52 +0100 Subject: [PATCH 0815/1837] Convert to use `for ... of` --- src/vs/editor/browser/config/configuration.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 11e10a2cfd8..3e09144622a 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -138,8 +138,7 @@ class CSSBasedConfiguration extends Disposable { private _evictUntrustedReadings(): void { const values = this._cache.getValues(); let somethingRemoved = false; - for (let i = 0, len = values.length; i < len; i++) { - const item = values[i]; + for (const item of values) { if (!item.isTrusted) { somethingRemoved = true; this._cache.remove(item); @@ -158,8 +157,7 @@ class CSSBasedConfiguration extends Disposable { public restoreFontInfo(savedFontInfos: ISerializedFontInfo[]): void { // Take all the saved font info and insert them in the cache without the trusted flag. // The reason for this is that a font might have been installed on the OS in the meantime. - for (let i = 0, len = savedFontInfos.length; i < len; i++) { - const savedFontInfo = savedFontInfos[i]; + for (const savedFontInfo of savedFontInfos) { // compatibility with older versions of VS Code which did not store this... savedFontInfo.fontFeatureSettings = savedFontInfo.fontFeatureSettings || EditorFontLigatures.OFF; savedFontInfo.middotWidth = savedFontInfo.middotWidth || savedFontInfo.spaceWidth; From ed584f486eb6366afee7973172a552237f821378 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 11 Dec 2020 16:17:57 +0100 Subject: [PATCH 0816/1837] use tt policy for nested workers, https://github.com/microsoft/vscode/issues/108400 --- .../extensions/browser/webWorkerExtensionHost.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 237ef4e94c2..32a3d8ac92f 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -43,6 +43,15 @@ export interface IWebWorkerExtensionHostDataProvider { const ttPolicy = window.trustedTypes?.createPolicy('webWorkerExtensionHost', { createScriptURL: value => value }); +const ttPolicyNestedWorker = window.trustedTypes?.createPolicy('webNestedWorkerExtensionHost', { + createScriptURL(value) { + if (value.startsWith('blob:')) { + return value; + } + throw new Error(value + ' is NOT allowed'); + } +}); + export class WebWorkerExtensionHost extends Disposable implements IExtensionHost { public readonly kind = ExtensionHostKind.LocalWebWorker; @@ -245,7 +254,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost } else if (data?.type === '_newWorker') { // receiving a message to create a new nested/child worker - const worker = new Worker(data.url, data.options); + const worker = new Worker((ttPolicyNestedWorker?.createScriptURL(data.url) ?? data.url) as string, data.options); worker.postMessage(data.port, [data.port]); worker.onerror = console.error.bind(console); nestedWorker.set(data.id, worker); From b9b1b6156f9d471ba5394c097e33fdb9a4a33357 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:18:00 +0100 Subject: [PATCH 0817/1837] Run compile on the `/build/` folder if the node_modules cache is hit --- .github/workflows/ci.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c837a5ca2c..5c6d9071580 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,12 +187,19 @@ jobs: ${{ runner.os }}-build- ${{ runner.os }}- - - run: yarn --frozen-lockfile + - name: Install Dependencies if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} - name: Install Dependencies + run: yarn --frozen-lockfile - - run: yarn monaco-compile-check - name: Run Monaco Editor Checks + - name: Compile ./build/ folder + # this normally executes as a postinstall script, but if the cache is hit above, + # yarn will not execute at all. Therefore, we manually launch it if necessary + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + run: yarn run compile + working-directory: ./build - - run: yarn gulp editor-esm-bundle - name: Editor Distro & ESM Bundle + - name: Run Monaco Editor Checks + run: yarn monaco-compile-check + + - name: Editor Distro & ESM Bundle + run: yarn gulp editor-esm-bundle From 27dee6886740e6db0835d2bf9ebdb89627162fd9 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:36:40 +0100 Subject: [PATCH 0818/1837] Attempt to revive linux github action --- .github/workflows/ci.yml | 162 +++++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 42 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c6d9071580..9a83ff37fb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,46 +11,124 @@ on: - release/* jobs: - # linux: - # runs-on: ubuntu-latest - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - # - run: | - # sudo apt-get update - # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - # sudo chmod +x /etc/init.d/xvfb - # sudo update-rc.d xvfb defaults - # sudo service xvfb start - # name: Setup Build Environment - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # # TODO: cache node modules - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron x64 - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: DISPLAY=:10 yarn test-browser --browser chromium - # name: Run Unit Tests (Browser) - # - run: DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" - # name: Run Integration Tests (Electron) + linux: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - name: Setup Build Environment + - run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + name: Setup Build Environment + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Compute yarn cache key + id: yarn-cache-key + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}" + + - name: Cache node modules + id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) + uses: actions/cache@v2 + env: + cache-name: node-modules-cache + with: + path: | + ./node_modules + ./build/node_modules + ./build/lib/watch/node_modules + ./extensions/node_modules + ./extensions/configuration-editing/node_modules + ./extensions/css-language-features/node_modules + ./extensions/css-language-features/server/node_modules + ./extensions/debug-auto-launch/node_modules + ./extensions/debug-server-ready/node_modules + ./extensions/emmet/node_modules + ./extensions/extension-editing/node_modules + ./extensions/git/node_modules + ./extensions/git-ui/node_modules + ./extensions/github/node_modules + ./extensions/github-authentication/node_modules + ./extensions/grunt/node_modules + ./extensions/gulp/node_modules + ./extensions/html-language-features/node_modules + ./extensions/html-language-features/server/node_modules + ./extensions/image-preview/node_modules + ./extensions/jake/node_modules + ./extensions/json-language-features/node_modules + ./extensions/json-language-features/server/node_modules + ./extensions/markdown-language-features/node_modules + ./extensions/merge-conflict/node_modules + ./extensions/microsoft-authentication/node_modules + ./extensions/npm/node_modules + ./extensions/php-language-features/node_modules + ./extensions/search-result/node_modules + ./extensions/typescript-language-features/node_modules + ./extensions/vscode-api-tests/node_modules + ./extensions/vscode-colorize-tests/node_modules + ./extensions/vscode-custom-editor-tests/node_modules + ./extensions/vscode-notebook-tests/node_modules + ./extensions/vscode-test-resolver/node_modules + ./remote/node_modules + ./remote/web/node_modules + ./test/automation/node_modules + ./test/integration/browser/node_modules + ./test/smoke/node_modules + ./test/ui/splitview/node_modules + ./test/ui/tree/node_modules + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install Dependencies + if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile + + - name: Compile /build/ folder + # this normally executes as a postinstall script, but if the cache is hit above, + # yarn will not execute at all. Therefore, we manually launch it if necessary + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + run: yarn run compile + working-directory: ./build + + - name: Download Electron + run: yarn electron x64 + + - name: Run Hygiene Checks + run: yarn gulp hygiene + + - name: Run Monaco Editor Checks + run: yarn monaco-compile-check + + - name: Run Valid Layers Checks + run: yarn valid-layers-check + + - name: Compile Sources + run: yarn compile + + - name: Download Built-in Extensions + run: yarn download-builtin-extensions + + - name: Run Unit Tests (Electron) + run: DISPLAY=:10 ./scripts/test.sh + + - name: Run Unit Tests (Browser) + run: DISPLAY=:10 yarn test-browser --browser chromium + + - name: Run Integration Tests (Electron) + run: DISPLAY=:10 ./scripts/test-integration.sh # windows: # runs-on: windows-2016 @@ -130,7 +208,7 @@ jobs: - name: Compute yarn cache key id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock') }}" + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}" - name: Cache node modules id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) @@ -191,7 +269,7 @@ jobs: if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} run: yarn --frozen-lockfile - - name: Compile ./build/ folder + - name: Compile /build/ folder # this normally executes as a postinstall script, but if the cache is hit above, # yarn will not execute at all. Therefore, we manually launch it if necessary if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} From b95feff0398a9ea115b02397882a360dd1e16c8e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:39:18 +0100 Subject: [PATCH 0819/1837] Fix indentation --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a83ff37fb3..8529620d491 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,11 +97,11 @@ jobs: run: yarn --frozen-lockfile - name: Compile /build/ folder - # this normally executes as a postinstall script, but if the cache is hit above, - # yarn will not execute at all. Therefore, we manually launch it if necessary - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} - run: yarn run compile - working-directory: ./build + # this normally executes as a postinstall script, but if the cache is hit above, + # yarn will not execute at all. Therefore, we manually launch it if necessary + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + run: yarn run compile + working-directory: ./build - name: Download Electron run: yarn electron x64 From 00c3a0bc9dc45d97df36f1ea8f2935c3f2f050df Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:41:05 +0100 Subject: [PATCH 0820/1837] Gotta love yaml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8529620d491..0ad2fc575f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - name: Setup Build Environment - - run: | + run: | sudo apt-get update sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb From 824df4da78f93833e62f1135b52c77e4bfca5691 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 16:42:04 +0100 Subject: [PATCH 0821/1837] Fix duplicate name --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ad2fc575f2..a31e90f44f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,6 @@ jobs: sudo chmod +x /etc/init.d/xvfb sudo update-rc.d xvfb defaults sudo service xvfb start - name: Setup Build Environment - uses: actions/setup-node@v2-beta with: From 2fc36a7d386b4475b44c040670e0939141d4138c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 11 Dec 2020 16:47:29 +0100 Subject: [PATCH 0822/1837] enum all breakpoint icons, avoid css selectors with patterns --- .../browser/breakpointEditorContribution.ts | 16 +++---- .../contrib/debug/browser/breakpointsView.ts | 18 ++++---- .../contrib/debug/browser/debugIcons.ts | 44 ++++++++++++------- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 966dc83e5da..d2b337bfaa7 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -454,7 +454,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi // Candidate decoration has a breakpoint attached when a breakpoint is already at that location and we did not yet set a decoration there // In practice this happens for the first breakpoint that was set on a line // We could have also rendered this first decoration as part of desiredBreakpointDecorations however at that moment we have no location information - const icon = candidate.breakpoint ? getBreakpointMessageAndIcon(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).icon : icons.debugBreakpointDisabled; + const icon = candidate.breakpoint ? getBreakpointMessageAndIcon(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).icon : icons.breakpoint.disabled; const contextMenuActions = () => this.getContextMenuActions(candidate.breakpoint ? [candidate.breakpoint] : [], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn); const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, ThemeIcon.asClassName(icon), candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions); @@ -645,15 +645,11 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointColor = theme.getColor(debugIconBreakpointForeground); if (debugIconBreakpointColor) { collector.addRule(` - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}, - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointConditional)}, - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointLog)}, - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointFunction)}, - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointData)}, + ${icons.allBreakpoints.map(b => `.monaco-workbench ${ThemeIcon.asCSSSelector(b.regular)}`).join(',\n ')}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointUnsupported)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpointHint)}:not([class*='codicon-debug-breakpoint']):not([class*='codicon-debug-stackframe']), - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}${ThemeIcon.asCSSSelector(icons.debugStackframeFocused)}::after, - .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugBreakpoint)}${ThemeIcon.asCSSSelector(icons.debugStackframe)}::after { + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.breakpoint.regular)}${ThemeIcon.asCSSSelector(icons.debugStackframeFocused)}::after, + .monaco-workbench ${ThemeIcon.asCSSSelector(icons.breakpoint.regular)}${ThemeIcon.asCSSSelector(icons.debugStackframe)}::after { color: ${debugIconBreakpointColor} !important; } `); @@ -662,7 +658,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointDisabledColor = theme.getColor(debugIconBreakpointDisabledForeground); if (debugIconBreakpointDisabledColor) { collector.addRule(` - .monaco-workbench .codicon[class*='-disabled'] { + ${icons.allBreakpoints.map(b => `.monaco-workbench ${ThemeIcon.asCSSSelector(b.disabled)}`).join(',\n ')} { color: ${debugIconBreakpointDisabledColor} !important; } `); @@ -671,7 +667,7 @@ registerThemingParticipant((theme, collector) => { const debugIconBreakpointUnverifiedColor = theme.getColor(debugIconBreakpointUnverifiedForeground); if (debugIconBreakpointUnverifiedColor) { collector.addRule(` - .monaco-workbench .codicon[class*='-unverified'] { + ${icons.allBreakpoints.map(b => `.monaco-workbench ${ThemeIcon.asCSSSelector(b.unverified)}`).join(',\n ')} { color: ${debugIconBreakpointUnverifiedColor}; } `); diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 7fa72c43fc6..dbbddbd426d 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -814,9 +814,11 @@ export function openBreakpointSource(breakpoint: IBreakpoint, sideBySide: boolea export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: boolean, breakpoint: IBreakpoint | IFunctionBreakpoint | IDataBreakpoint, labelService?: ILabelService): { message?: string, icon: ThemeIcon } { const debugActive = state === State.Running || state === State.Stopped; + const breakpointIcon = breakpoint instanceof DataBreakpoint ? icons.dataBreakpoint : breakpoint instanceof FunctionBreakpoint ? icons.functionBreakpoint : breakpoint.logMessage ? icons.logBreakpoint : icons.breakpoint; + if (!breakpoint.enabled || !breakpointsActivated) { return { - icon: breakpoint instanceof DataBreakpoint ? icons.debugBreakpointDataDisabled : breakpoint instanceof FunctionBreakpoint ? icons.debugBreakpointFunctionDisabled : breakpoint.logMessage ? icons.debugBreakpointLogDisabled : icons.debugBreakpointDisabled, + icon: breakpointIcon.disabled, message: breakpoint.logMessage ? nls.localize('disabledLogpoint', "Disabled Logpoint") : nls.localize('disabledBreakpoint', "Disabled Breakpoint"), }; } @@ -826,7 +828,7 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: }; if (debugActive && !breakpoint.verified) { return { - icon: breakpoint instanceof DataBreakpoint ? icons.debugBreakpointDataUnverified : breakpoint instanceof FunctionBreakpoint ? icons.debugBreakpointFunctionUnverified : breakpoint.logMessage ? icons.debugBreakpointLogUnverified : icons.debugBreakpointUnverified, + icon: breakpointIcon.unverified, message: ('message' in breakpoint && breakpoint.message) ? breakpoint.message : (breakpoint.logMessage ? nls.localize('unverifiedLogpoint', "Unverified Logpoint") : nls.localize('unverifiedBreakopint', "Unverified Breakpoint")), }; } @@ -834,13 +836,13 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: if (breakpoint instanceof FunctionBreakpoint) { if (!breakpoint.supported) { return { - icon: icons.debugBreakpointFunctionUnverified, + icon: breakpointIcon.unverified, message: nls.localize('functionBreakpointUnsupported', "Function breakpoints not supported by this debug type"), }; } return { - icon: icons.debugBreakpointFunction, + icon: breakpointIcon.regular, message: breakpoint.message || nls.localize('functionBreakpoint', "Function Breakpoint") }; } @@ -848,13 +850,13 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: if (breakpoint instanceof DataBreakpoint) { if (!breakpoint.supported) { return { - icon: icons.debugBreakpointDataUnverified, + icon: breakpointIcon.unverified, message: nls.localize('dataBreakpointUnsupported', "Data breakpoints not supported by this debug type"), }; } return { - icon: icons.debugBreakpointData, + icon: breakpointIcon.regular, message: breakpoint.message || nls.localize('dataBreakpoint', "Data Breakpoint") }; } @@ -880,14 +882,14 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: } return { - icon: breakpoint.logMessage ? icons.debugBreakpointLog : icons.debugBreakpointConditional, + icon: breakpoint.logMessage ? icons.logBreakpoint.regular : icons.conditionalBreakpoint.regular, message: appendMessage(messages.join('\n')) }; } const message = ('message' in breakpoint && breakpoint.message) ? breakpoint.message : breakpoint instanceof Breakpoint && labelService ? labelService.getUriLabel(breakpoint.uri) : nls.localize('breakpoint', "Breakpoint"); return { - icon: icons.debugBreakpoint, + icon: breakpointIcon.regular, message }; } diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts index b2203e38102..b031cd582c3 100644 --- a/src/vs/workbench/contrib/debug/browser/debugIcons.ts +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -15,25 +15,37 @@ export const callStackViewIcon = registerIcon('callstack-view-icon', Codicon.deb export const breakpointsViewIcon = registerIcon('breakpoints-view-icon', Codicon.debugAlt, localize('breakpointsViewIcon', 'View icon of the breakpoints view.')); export const loadedScriptsViewIcon = registerIcon('loaded-scripts-view-icon', Codicon.debugAlt, localize('loadedScriptsViewIcon', 'View icon of the loaded scripts view.')); -export const debugBreakpoint = registerIcon('debug-breakpoint', Codicon.debugBreakpoint, localize('debugBreakpoint', 'Icon for breakpoints.')); -export const debugBreakpointDisabled = registerIcon('debug-breakpoint-disabled', Codicon.debugBreakpointDisabled, localize('debugBreakpointDisabled', 'Icon for disabled breakpoints.')); -export const debugBreakpointUnverified = registerIcon('debug-breakpoint-unverified', Codicon.debugBreakpointUnverified, localize('debugBreakpointUnverified', 'Icon for unverified breakpoints.')); -export const debugBreakpointHint = registerIcon('debug-hint', Codicon.debugHint, localize('debugBreakpointHint', 'Icon for breakpoint hints shown on hover in editor glyph margin.')); -export const debugBreakpointFunction = registerIcon('debug-breakpoint-function', Codicon.debugBreakpointFunction, localize('debugBreakpointFunction', 'Icon for function breakpoints.')); -export const debugBreakpointFunctionUnverified = registerIcon('debug-breakpoint-function-unverified', Codicon.debugBreakpointFunctionUnverified, localize('debugBreakpointFunctionUnverified', 'Icon for unverified function breakpoints.')); -export const debugBreakpointFunctionDisabled = registerIcon('debug-breakpoint-function-disabled', Codicon.debugBreakpointFunctionDisabled, localize('debugBreakpointFunctionDisabled', 'Icon for disabled function breakpoints.')); +export const breakpoint = { + regular: registerIcon('debug-breakpoint', Codicon.debugBreakpoint, localize('debugBreakpoint', 'Icon for breakpoints.')), + disabled: registerIcon('debug-breakpoint-disabled', Codicon.debugBreakpointDisabled, localize('debugBreakpointDisabled', 'Icon for disabled breakpoints.')), + unverified: registerIcon('debug-breakpoint-unverified', Codicon.debugBreakpointUnverified, localize('debugBreakpointUnverified', 'Icon for unverified breakpoints.')) +}; +export const functionBreakpoint = { + regular: registerIcon('debug-breakpoint-function', Codicon.debugBreakpointFunction, localize('debugBreakpointFunction', 'Icon for function breakpoints.')), + disabled: registerIcon('debug-breakpoint-function-disabled', Codicon.debugBreakpointFunctionDisabled, localize('debugBreakpointFunctionDisabled', 'Icon for disabled function breakpoints.')), + unverified: registerIcon('debug-breakpoint-function-unverified', Codicon.debugBreakpointFunctionUnverified, localize('debugBreakpointFunctionUnverified', 'Icon for unverified function breakpoints.')) +}; +export const conditionalBreakpoint = { + regular: registerIcon('debug-breakpoint-conditional', Codicon.debugBreakpointConditional, localize('debugBreakpointConditional', 'Icon for conditional breakpoints.')), + disabled: registerIcon('debug-breakpoint-conditional-disabled', Codicon.debugBreakpointConditionalDisabled, localize('debugBreakpointConditionalDisabled', 'Icon for disabled conditional breakpoints.')), + unverified: registerIcon('debug-breakpoint-conditional-unverified', Codicon.debugBreakpointConditionalUnverified, localize('debugBreakpointConditionalUnverified', 'Icon for unverified conditional breakpoints.')) +}; +export const dataBreakpoint = { + regular: registerIcon('debug-breakpoint-data', Codicon.debugBreakpointData, localize('debugBreakpointData', 'Icon for data breakpoints.')), + disabled: registerIcon('debug-breakpoint-data-disabled', Codicon.debugBreakpointDataDisabled, localize('debugBreakpointDataDisabled', 'Icon for disabled data breakpoints.')), + unverified: registerIcon('debug-breakpoint-data-unverified', Codicon.debugBreakpointDataUnverified, localize('debugBreakpointDataUnverified', 'Icon for unverified data breakpoints.')), +}; +export const logBreakpoint = { + regular: registerIcon('debug-breakpoint-log', Codicon.debugBreakpointLog, localize('debugBreakpointLog', 'Icon for log breakpoints.')), + disabled: registerIcon('debug-breakpoint-log-disabled', Codicon.debugBreakpointLogDisabled, localize('debugBreakpointLogDisabled', 'Icon for disabled log breakpoint.')), + unverified: registerIcon('debug-breakpoint-log-unverified', Codicon.debugBreakpointLogUnverified, localize('debugBreakpointLogUnverified', 'Icon for unverified log breakpoints.')), +}; +export const debugBreakpointHint = registerIcon('debug-hint', Codicon.debugHint, localize('debugBreakpointHint', 'Icon for breakpoint hints shown on hover in editor glyph margin.')); export const debugBreakpointUnsupported = registerIcon('debug-breakpoint-unsupported', Codicon.debugBreakpointUnsupported, localize('debugBreakpointUnsupported', 'Icon for unsupported breakpoints.')); -export const debugBreakpointConditionalUnverified = registerIcon('debug-breakpoint-conditional-unverified', Codicon.debugBreakpointConditionalUnverified, localize('debugBreakpointConditionalUnverified', 'Icon for unverified conditional breakpoints.')); -export const debugBreakpointConditional = registerIcon('debug-breakpoint-conditional', Codicon.debugBreakpointConditional, localize('debugBreakpointConditional', 'Icon for conditional breakpoints.')); -export const debugBreakpointConditionalDisabled = registerIcon('debug-breakpoint-conditional-disabled', Codicon.debugBreakpointConditionalDisabled, localize('debugBreakpointConditionalDisabled', 'Icon for disabled conditional breakpoints.')); -export const debugBreakpointDataUnverified = registerIcon('debug-breakpoint-data-unverified', Codicon.debugBreakpointDataUnverified, localize('debugBreakpointDataUnverified', 'Icon for unverified data breakpoints.')); -export const debugBreakpointData = registerIcon('debug-breakpoint-data', Codicon.debugBreakpointData, localize('debugBreakpointData', 'Icon for data breakpoints.')); -export const debugBreakpointDataDisabled = registerIcon('debug-breakpoint-data-disabled', Codicon.debugBreakpointDataDisabled, localize('debugBreakpointDataDisabled', 'Icon for disabled data breakpoints.')); -export const debugBreakpointLogUnverified = registerIcon('debug-breakpoint-log-unverified', Codicon.debugBreakpointLogUnverified, localize('debugBreakpointLogUnverified', 'Icon for unverified log breakpoints.')); -export const debugBreakpointLog = registerIcon('debug-breakpoint-log', Codicon.debugBreakpointLog, localize('debugBreakpointLog', 'Icon for log breakpoints.')); -export const debugBreakpointLogDisabled = registerIcon('debug-breakpoint-log-disabled', Codicon.debugBreakpointLogDisabled, localize('debugBreakpointLogDisabled', 'Icon for disabled log breakpoint.')); +export const allBreakpoints = [breakpoint, functionBreakpoint, conditionalBreakpoint, dataBreakpoint, logBreakpoint]; + export const debugStackframe = registerIcon('debug-stackframe', Codicon.debugStackframe, localize('debugStackframe', 'Icon for a stackframe shown in the editor glyph margin.')); export const debugStackframeFocused = registerIcon('debug-stackframe-focused', Codicon.debugStackframeFocused, localize('debugStackframeFocused', 'Icon for a focused stackframe shown in the editor glyph margin.')); From 50d0d5f0d253b4324d0d280e20e6ab687e87f384 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 11 Dec 2020 16:47:59 +0100 Subject: [PATCH 0823/1837] Theme icon modifiers should work everywhere. Fixes #112298 --- src/vs/base/browser/codicons.ts | 8 ++++---- src/vs/base/browser/markdownRenderer.ts | 2 +- .../ui/codicons/codicon/codicon-modifications.css | 8 -------- .../{codicon-animations.css => codicon-modifiers.css} | 10 +++++++++- src/vs/base/browser/ui/codicons/codiconStyles.ts | 3 +-- src/vs/base/browser/ui/dialog/dialog.ts | 6 ++++-- src/vs/base/test/browser/codicons.test.ts | 2 +- src/vs/platform/theme/common/themeService.ts | 2 +- 8 files changed, 21 insertions(+), 20 deletions(-) delete mode 100644 src/vs/base/browser/ui/codicons/codicon/codicon-modifications.css rename src/vs/base/browser/ui/codicons/codicon/{codicon-animations.css => codicon-modifiers.css} (81%) diff --git a/src/vs/base/browser/codicons.ts b/src/vs/base/browser/codicons.ts index cf55c1a9b92..5793a73b66c 100644 --- a/src/vs/base/browser/codicons.ts +++ b/src/vs/base/browser/codicons.ts @@ -17,8 +17,8 @@ export function renderCodicons(text: string): Array { elements.push(text.substring(textStart, textStop)); textStart = (match.index || 0) + match[0].length; - const [, escaped, codicon, name, animation] = match; - elements.push(escaped ? `$(${codicon})` : renderCodicon(name, animation)); + const [, escaped, codicon, name, modifier] = match; + elements.push(escaped ? `$(${codicon})` : renderCodicon(name, modifier)); } if (textStart < text.length) { @@ -27,6 +27,6 @@ export function renderCodicons(text: string): Array { return elements; } -export function renderCodicon(name: string, animation: string): HTMLSpanElement { - return dom.$(`span.codicon.codicon-${name}${animation ? `.codicon-animation-${animation}` : ''}`); +export function renderCodicon(name: string, modifier: string): HTMLSpanElement { + return dom.$(`span.codicon.codicon-${name}${modifier ? `.codicon-modifier-${modifier}` : ''}`); } diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 18bd5f2050a..71248b11b0e 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -303,7 +303,7 @@ function getInsaneOptions(options: { readonly isTrusted?: boolean }): InsaneOpti return !!token.attrs['style'].match(/^(color\:#[0-9a-fA-F]+;)?(background-color\:#[0-9a-fA-F]+;)?$/); } else if (token.attrs['class']) { // The class should match codicon rendering in src\vs\base\common\codicons.ts - return !!token.attrs['class'].match(/^codicon codicon-[a-z\-]+( codicon-animation-[a-z\-]+)?$/); + return !!token.attrs['class'].match(/^codicon codicon-[a-z\-]+( codicon-modifier-[a-z\-]+)?$/); } return false; } diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon-modifications.css b/src/vs/base/browser/ui/codicons/codicon/codicon-modifications.css deleted file mode 100644 index 950493dd6be..00000000000 --- a/src/vs/base/browser/ui/codicons/codicon/codicon-modifications.css +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.codicon-wrench-subaction { - opacity: 0.5; -} diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon-animations.css b/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css similarity index 81% rename from src/vs/base/browser/ui/codicons/codicon/codicon-animations.css rename to src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css index 667002f5b7c..6007a997eac 100644 --- a/src/vs/base/browser/ui/codicons/codicon/codicon-animations.css +++ b/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css @@ -3,13 +3,21 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +.codicon-wrench-subaction { + opacity: 0.5; +} + @keyframes codicon-spin { 100% { transform:rotate(360deg); } } -.codicon-animation-spin { +.codicon-modifier-spin { /* Use steps to throttle FPS to reduce CPU usage */ animation: codicon-spin 1.5s steps(30) infinite; } + +.codicon-modifier-disabled { + opacity: 0.4; +} diff --git a/src/vs/base/browser/ui/codicons/codiconStyles.ts b/src/vs/base/browser/ui/codicons/codiconStyles.ts index 44281196746..f2f58befbc9 100644 --- a/src/vs/base/browser/ui/codicons/codiconStyles.ts +++ b/src/vs/base/browser/ui/codicons/codiconStyles.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./codicon/codicon'; -import 'vs/css!./codicon/codicon-modifications'; -import 'vs/css!./codicon/codicon-animations'; +import 'vs/css!./codicon/codicon-modifiers'; import { Codicon } from 'vs/base/common/codicons'; diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index 4d8a075dfca..5a5908a165f 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -307,7 +307,9 @@ export class Dialog extends Disposable { } })); - this.iconElement.classList.remove(...dialogErrorIcon.classNamesArray, ...dialogWarningIcon.classNamesArray, ...dialogInfoIcon.classNamesArray, ...Codicon.loading.classNamesArray); + const spinModifierClassName = 'codicon-modifier-spin'; + + this.iconElement.classList.remove(...dialogErrorIcon.classNamesArray, ...dialogWarningIcon.classNamesArray, ...dialogInfoIcon.classNamesArray, ...Codicon.loading.classNamesArray, spinModifierClassName); switch (this.options.type) { case 'error': @@ -317,7 +319,7 @@ export class Dialog extends Disposable { this.iconElement.classList.add(...dialogWarningIcon.classNamesArray); break; case 'pending': - this.iconElement.classList.add(...Codicon.loading.classNamesArray, 'codicon-animation-spin'); + this.iconElement.classList.add(...Codicon.loading.classNamesArray, spinModifierClassName); break; case 'none': case 'info': diff --git a/src/vs/base/test/browser/codicons.test.ts b/src/vs/base/test/browser/codicons.test.ts index fd5b0332a51..bd9e432921d 100644 --- a/src/vs/base/test/browser/codicons.test.ts +++ b/src/vs/base/test/browser/codicons.test.ts @@ -41,7 +41,7 @@ suite('renderCodicons', () => { test('codicon with animation', () => { const result = renderCodicons('$(zip~anim)'); - assert.equal(elementsToString(result), ''); + assert.equal(elementsToString(result), ''); }); const elementsToString = (elements: Array): string => { diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index f82c45767e5..8ed0a1400b7 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -80,7 +80,7 @@ export namespace ThemeIcon { let [, , name, modifier] = match; let className = `codicon-${name}`; if (modifier) { - return ['codicon', className, modifier.substr(1)]; + return ['codicon', className, `codicon-modifier-${modifier.substr(1)}`]; } return ['codicon', className]; } From 5e6152dcb39176be13d83bcc3df08000d91eb2fc Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 17:00:42 +0100 Subject: [PATCH 0824/1837] Introduce a `linux-node-modules` job --- .github/workflows/ci.yml | 110 +++++++++++++++------------------------ 1 file changed, 42 insertions(+), 68 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a31e90f44f1..71e540a622b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,30 +11,20 @@ on: - release/* jobs: - linux: + linux-node-modules: runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - - uses: actions/setup-node@v2-beta with: node-version: 12 - name: Compute yarn cache key id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}" + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" - name: Cache node modules id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) @@ -43,6 +33,7 @@ jobs: cache-name: node-modules-cache with: path: | + ~/.cache/ms-playwright ./node_modules ./build/node_modules ./build/lib/watch/node_modules @@ -95,10 +86,44 @@ jobs: if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} run: yarn --frozen-lockfile + linux: + needs: linux-node-modules + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - name: Setup Build Environment + run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Compute yarn cache key + id: yarn-cache-key + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" + + - name: Cache node modules + id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) + uses: actions/cache@v2 + env: + cache-name: node-modules-cache + with: + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Compile /build/ folder - # this normally executes as a postinstall script, but if the cache is hit above, - # yarn will not execute at all. Therefore, we manually launch it if necessary - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} run: yarn run compile working-directory: ./build @@ -195,6 +220,7 @@ jobs: # name: Run Integration Tests (Electron) monaco: + needs: linux-node-modules runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -204,10 +230,9 @@ jobs: - uses: actions/setup-node@v2-beta with: node-version: 12 - - name: Compute yarn cache key id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}" + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" - name: Cache node modules id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) @@ -215,63 +240,12 @@ jobs: env: cache-name: node-modules-cache with: - path: | - ./node_modules - ./build/node_modules - ./build/lib/watch/node_modules - ./extensions/node_modules - ./extensions/configuration-editing/node_modules - ./extensions/css-language-features/node_modules - ./extensions/css-language-features/server/node_modules - ./extensions/debug-auto-launch/node_modules - ./extensions/debug-server-ready/node_modules - ./extensions/emmet/node_modules - ./extensions/extension-editing/node_modules - ./extensions/git/node_modules - ./extensions/git-ui/node_modules - ./extensions/github/node_modules - ./extensions/github-authentication/node_modules - ./extensions/grunt/node_modules - ./extensions/gulp/node_modules - ./extensions/html-language-features/node_modules - ./extensions/html-language-features/server/node_modules - ./extensions/image-preview/node_modules - ./extensions/jake/node_modules - ./extensions/json-language-features/node_modules - ./extensions/json-language-features/server/node_modules - ./extensions/markdown-language-features/node_modules - ./extensions/merge-conflict/node_modules - ./extensions/microsoft-authentication/node_modules - ./extensions/npm/node_modules - ./extensions/php-language-features/node_modules - ./extensions/search-result/node_modules - ./extensions/typescript-language-features/node_modules - ./extensions/vscode-api-tests/node_modules - ./extensions/vscode-colorize-tests/node_modules - ./extensions/vscode-custom-editor-tests/node_modules - ./extensions/vscode-notebook-tests/node_modules - ./extensions/vscode-test-resolver/node_modules - ./remote/node_modules - ./remote/web/node_modules - ./test/automation/node_modules - ./test/integration/browser/node_modules - ./test/smoke/node_modules - ./test/ui/splitview/node_modules - ./test/ui/tree/node_modules - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - name: Install Dependencies - if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} - run: yarn --frozen-lockfile - - name: Compile /build/ folder - # this normally executes as a postinstall script, but if the cache is hit above, - # yarn will not execute at all. Therefore, we manually launch it if necessary - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} run: yarn run compile working-directory: ./build From dc99b1ab774000568e39cbbaab2df09e33ca4bbd Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 17:08:01 +0100 Subject: [PATCH 0825/1837] Add the key property to the Cache node modules action --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71e540a622b..c3985bfb703 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,7 @@ jobs: env: cache-name: node-modules-cache with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- @@ -240,6 +241,7 @@ jobs: env: cache-name: node-modules-cache with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- From a0122361111dc0daec54e04d4fe38d4c296e8183 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 17:13:05 +0100 Subject: [PATCH 0826/1837] Define `path` for the Cache node modules step --- .github/workflows/ci.yml | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3985bfb703..189564fdb28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,50 @@ jobs: env: cache-name: node-modules-cache with: + path: | + ~/.cache/ms-playwright + ./node_modules + ./build/node_modules + ./build/lib/watch/node_modules + ./extensions/node_modules + ./extensions/configuration-editing/node_modules + ./extensions/css-language-features/node_modules + ./extensions/css-language-features/server/node_modules + ./extensions/debug-auto-launch/node_modules + ./extensions/debug-server-ready/node_modules + ./extensions/emmet/node_modules + ./extensions/extension-editing/node_modules + ./extensions/git/node_modules + ./extensions/git-ui/node_modules + ./extensions/github/node_modules + ./extensions/github-authentication/node_modules + ./extensions/grunt/node_modules + ./extensions/gulp/node_modules + ./extensions/html-language-features/node_modules + ./extensions/html-language-features/server/node_modules + ./extensions/image-preview/node_modules + ./extensions/jake/node_modules + ./extensions/json-language-features/node_modules + ./extensions/json-language-features/server/node_modules + ./extensions/markdown-language-features/node_modules + ./extensions/merge-conflict/node_modules + ./extensions/microsoft-authentication/node_modules + ./extensions/npm/node_modules + ./extensions/php-language-features/node_modules + ./extensions/search-result/node_modules + ./extensions/typescript-language-features/node_modules + ./extensions/vscode-api-tests/node_modules + ./extensions/vscode-colorize-tests/node_modules + ./extensions/vscode-custom-editor-tests/node_modules + ./extensions/vscode-notebook-tests/node_modules + ./extensions/vscode-test-resolver/node_modules + ./remote/node_modules + ./remote/web/node_modules + ./test/automation/node_modules + ./test/integration/browser/node_modules + ./test/smoke/node_modules + ./test/ui/splitview/node_modules + ./test/ui/tree/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- @@ -241,6 +285,50 @@ jobs: env: cache-name: node-modules-cache with: + path: | + ~/.cache/ms-playwright + ./node_modules + ./build/node_modules + ./build/lib/watch/node_modules + ./extensions/node_modules + ./extensions/configuration-editing/node_modules + ./extensions/css-language-features/node_modules + ./extensions/css-language-features/server/node_modules + ./extensions/debug-auto-launch/node_modules + ./extensions/debug-server-ready/node_modules + ./extensions/emmet/node_modules + ./extensions/extension-editing/node_modules + ./extensions/git/node_modules + ./extensions/git-ui/node_modules + ./extensions/github/node_modules + ./extensions/github-authentication/node_modules + ./extensions/grunt/node_modules + ./extensions/gulp/node_modules + ./extensions/html-language-features/node_modules + ./extensions/html-language-features/server/node_modules + ./extensions/image-preview/node_modules + ./extensions/jake/node_modules + ./extensions/json-language-features/node_modules + ./extensions/json-language-features/server/node_modules + ./extensions/markdown-language-features/node_modules + ./extensions/merge-conflict/node_modules + ./extensions/microsoft-authentication/node_modules + ./extensions/npm/node_modules + ./extensions/php-language-features/node_modules + ./extensions/search-result/node_modules + ./extensions/typescript-language-features/node_modules + ./extensions/vscode-api-tests/node_modules + ./extensions/vscode-colorize-tests/node_modules + ./extensions/vscode-custom-editor-tests/node_modules + ./extensions/vscode-notebook-tests/node_modules + ./extensions/vscode-test-resolver/node_modules + ./remote/node_modules + ./remote/web/node_modules + ./test/automation/node_modules + ./test/integration/browser/node_modules + ./test/smoke/node_modules + ./test/ui/splitview/node_modules + ./test/ui/tree/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- From 2554c8c14e042fabc163bcf797af0d52fc108cce Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 17:24:29 +0100 Subject: [PATCH 0827/1837] Remove the `linux-node-modules` job --- .github/workflows/ci.yml | 182 ++++----------------------------------- 1 file changed, 19 insertions(+), 163 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 189564fdb28..5b9bb0c87aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,83 +11,7 @@ on: - release/* jobs: - linux-node-modules: - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-node@v2-beta - with: - node-version: 12 - - - name: Compute yarn cache key - id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" - - - name: Cache node modules - id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) - uses: actions/cache@v2 - env: - cache-name: node-modules-cache - with: - path: | - ~/.cache/ms-playwright - ./node_modules - ./build/node_modules - ./build/lib/watch/node_modules - ./extensions/node_modules - ./extensions/configuration-editing/node_modules - ./extensions/css-language-features/node_modules - ./extensions/css-language-features/server/node_modules - ./extensions/debug-auto-launch/node_modules - ./extensions/debug-server-ready/node_modules - ./extensions/emmet/node_modules - ./extensions/extension-editing/node_modules - ./extensions/git/node_modules - ./extensions/git-ui/node_modules - ./extensions/github/node_modules - ./extensions/github-authentication/node_modules - ./extensions/grunt/node_modules - ./extensions/gulp/node_modules - ./extensions/html-language-features/node_modules - ./extensions/html-language-features/server/node_modules - ./extensions/image-preview/node_modules - ./extensions/jake/node_modules - ./extensions/json-language-features/node_modules - ./extensions/json-language-features/server/node_modules - ./extensions/markdown-language-features/node_modules - ./extensions/merge-conflict/node_modules - ./extensions/microsoft-authentication/node_modules - ./extensions/npm/node_modules - ./extensions/php-language-features/node_modules - ./extensions/search-result/node_modules - ./extensions/typescript-language-features/node_modules - ./extensions/vscode-api-tests/node_modules - ./extensions/vscode-colorize-tests/node_modules - ./extensions/vscode-custom-editor-tests/node_modules - ./extensions/vscode-notebook-tests/node_modules - ./extensions/vscode-test-resolver/node_modules - ./remote/node_modules - ./remote/web/node_modules - ./test/automation/node_modules - ./test/integration/browser/node_modules - ./test/smoke/node_modules - ./test/ui/splitview/node_modules - ./test/ui/tree/node_modules - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- - - - name: Install Dependencies - if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} - run: yarn --frozen-lockfile - linux: - needs: linux-node-modules runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -110,7 +34,7 @@ jobs: - name: Compute yarn cache key id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" + run: echo "::set-output name=value::${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}3" - name: Cache node modules id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) @@ -120,55 +44,21 @@ jobs: with: path: | ~/.cache/ms-playwright - ./node_modules - ./build/node_modules - ./build/lib/watch/node_modules - ./extensions/node_modules - ./extensions/configuration-editing/node_modules - ./extensions/css-language-features/node_modules - ./extensions/css-language-features/server/node_modules - ./extensions/debug-auto-launch/node_modules - ./extensions/debug-server-ready/node_modules - ./extensions/emmet/node_modules - ./extensions/extension-editing/node_modules - ./extensions/git/node_modules - ./extensions/git-ui/node_modules - ./extensions/github/node_modules - ./extensions/github-authentication/node_modules - ./extensions/grunt/node_modules - ./extensions/gulp/node_modules - ./extensions/html-language-features/node_modules - ./extensions/html-language-features/server/node_modules - ./extensions/image-preview/node_modules - ./extensions/jake/node_modules - ./extensions/json-language-features/node_modules - ./extensions/json-language-features/server/node_modules - ./extensions/markdown-language-features/node_modules - ./extensions/merge-conflict/node_modules - ./extensions/microsoft-authentication/node_modules - ./extensions/npm/node_modules - ./extensions/php-language-features/node_modules - ./extensions/search-result/node_modules - ./extensions/typescript-language-features/node_modules - ./extensions/vscode-api-tests/node_modules - ./extensions/vscode-colorize-tests/node_modules - ./extensions/vscode-custom-editor-tests/node_modules - ./extensions/vscode-notebook-tests/node_modules - ./extensions/vscode-test-resolver/node_modules - ./remote/node_modules - ./remote/web/node_modules - ./test/automation/node_modules - ./test/integration/browser/node_modules - ./test/smoke/node_modules - ./test/ui/splitview/node_modules - ./test/ui/tree/node_modules + **/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- + - name: Install Dependencies + if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile + - name: Compile /build/ folder + # this normally executes as a postinstall script, but if the cache is hit above, + # yarn will not execute at all. Therefore, we manually launch it if necessary + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} run: yarn run compile working-directory: ./build @@ -265,7 +155,6 @@ jobs: # name: Run Integration Tests (Electron) monaco: - needs: linux-node-modules runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -275,9 +164,10 @@ jobs: - uses: actions/setup-node@v2-beta with: node-version: 12 + - name: Compute yarn cache key id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock', '.yarnrc', 'remote/.yarnrc') }}2" + run: echo "::set-output name=value::${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}3" - name: Cache node modules id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) @@ -287,55 +177,21 @@ jobs: with: path: | ~/.cache/ms-playwright - ./node_modules - ./build/node_modules - ./build/lib/watch/node_modules - ./extensions/node_modules - ./extensions/configuration-editing/node_modules - ./extensions/css-language-features/node_modules - ./extensions/css-language-features/server/node_modules - ./extensions/debug-auto-launch/node_modules - ./extensions/debug-server-ready/node_modules - ./extensions/emmet/node_modules - ./extensions/extension-editing/node_modules - ./extensions/git/node_modules - ./extensions/git-ui/node_modules - ./extensions/github/node_modules - ./extensions/github-authentication/node_modules - ./extensions/grunt/node_modules - ./extensions/gulp/node_modules - ./extensions/html-language-features/node_modules - ./extensions/html-language-features/server/node_modules - ./extensions/image-preview/node_modules - ./extensions/jake/node_modules - ./extensions/json-language-features/node_modules - ./extensions/json-language-features/server/node_modules - ./extensions/markdown-language-features/node_modules - ./extensions/merge-conflict/node_modules - ./extensions/microsoft-authentication/node_modules - ./extensions/npm/node_modules - ./extensions/php-language-features/node_modules - ./extensions/search-result/node_modules - ./extensions/typescript-language-features/node_modules - ./extensions/vscode-api-tests/node_modules - ./extensions/vscode-colorize-tests/node_modules - ./extensions/vscode-custom-editor-tests/node_modules - ./extensions/vscode-notebook-tests/node_modules - ./extensions/vscode-test-resolver/node_modules - ./remote/node_modules - ./remote/web/node_modules - ./test/automation/node_modules - ./test/integration/browser/node_modules - ./test/smoke/node_modules - ./test/ui/splitview/node_modules - ./test/ui/tree/node_modules + **/node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- + - name: Install Dependencies + if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile + - name: Compile /build/ folder + # this normally executes as a postinstall script, but if the cache is hit above, + # yarn will not execute at all. Therefore, we manually launch it if necessary + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} run: yarn run compile working-directory: ./build From 76436a4d43566cd313629799e2ec51b4d00caa64 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 17:42:20 +0100 Subject: [PATCH 0828/1837] Cache the /build/ folder compilation --- .github/workflows/ci.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b9bb0c87aa..fdfaf69475e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,10 +55,16 @@ jobs: if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} run: yarn --frozen-lockfile - - name: Compile /build/ folder - # this normally executes as a postinstall script, but if the cache is hit above, - # yarn will not execute at all. Therefore, we manually launch it if necessary + - name: Cache compile /build/ folder + id: build-folder-compile-cache if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Compile /build/ folder + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} run: yarn run compile working-directory: ./build @@ -188,10 +194,16 @@ jobs: if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} run: yarn --frozen-lockfile - - name: Compile /build/ folder - # this normally executes as a postinstall script, but if the cache is hit above, - # yarn will not execute at all. Therefore, we manually launch it if necessary + - name: Cache compile /build/ folder + id: build-folder-compile-cache if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Compile /build/ folder + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} run: yarn run compile working-directory: ./build From c197be4ef7465a3b4ec0d14545ee415a28b6358a Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 11 Dec 2020 17:52:44 +0100 Subject: [PATCH 0829/1837] externalize remote icons --- .../contrib/remote/browser/remote.ts | 24 +++++++------------ .../contrib/remote/browser/remoteExplorer.ts | 4 ++-- .../contrib/remote/browser/remoteIcons.ts | 23 ++++++++++++++++++ .../contrib/remote/browser/tunnelView.ts | 24 +++++++++---------- .../themes/browser/themes.contribution.ts | 12 +++++++++- .../remote/common/remoteExplorerService.ts | 3 ++- 6 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 src/vs/workbench/contrib/remote/browser/remoteIcons.ts diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 29ab926a392..ebb45d33177 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -54,8 +54,8 @@ import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/e import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { RemoteStatusIndicator } from 'vs/workbench/contrib/remote/browser/remoteIndicator'; import { inQuickPickContextKeyValue } from 'vs/workbench/browser/quickaccess'; -import { Codicon } from 'vs/base/common/codicons'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import * as icons from 'vs/workbench/contrib/remote/browser/remoteIcons'; + export interface HelpInformation { extensionDescription: IExtensionDescription; @@ -149,14 +149,6 @@ class HelpDataSource implements IAsyncDataSource { return []; } } - -const getStartedIcon = registerIcon('remote-explorer-get-started', Codicon.star, nls.localize('getStartedIcon', 'Getting started icon in the remote explorer view.')); -const documentationIcon = registerIcon('remote-explorer-documentation', Codicon.book, nls.localize('documentationIcon', 'Documentation icon in the remote explorer view.')); -const feedbackIcon = registerIcon('remote-explorer-feedback', Codicon.twitter, nls.localize('feedbackIcon', 'Feedback icon in the remote explorer view.')); -const reviewIssuesIcon = registerIcon('remote-explorer-review-issues', Codicon.issues, nls.localize('reviewIssuesIcon', 'Review issue icon in the remote explorer view.')); -const reportIssuesIcon = registerIcon('remote-explorer-report-issues', Codicon.comment, nls.localize('reportIssuesIcon', 'Report issue icon in the remote explorer view.')); -const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); - interface IHelpItem { icon: ThemeIcon, iconClasses: string[]; @@ -180,7 +172,7 @@ class HelpModel { if (getStarted.length) { helpItems.push(new HelpItem( - getStartedIcon, + icons.getStartedIcon, nls.localize('remote.help.getStarted', "Get Started"), getStarted.map((info: HelpInformation) => (new HelpItemValue(commandService, info.extensionDescription, @@ -198,7 +190,7 @@ class HelpModel { if (documentation.length) { helpItems.push(new HelpItem( - documentationIcon, + icons.documentationIcon, nls.localize('remote.help.documentation', "Read Documentation"), documentation.map((info: HelpInformation) => (new HelpItemValue(commandService, info.extensionDescription, @@ -216,7 +208,7 @@ class HelpModel { if (feedback.length) { helpItems.push(new HelpItem( - feedbackIcon, + icons.feedbackIcon, nls.localize('remote.help.feedback', "Provide Feedback"), feedback.map((info: HelpInformation) => (new HelpItemValue(commandService, info.extensionDescription, @@ -234,7 +226,7 @@ class HelpModel { if (issues.length) { helpItems.push(new HelpItem( - reviewIssuesIcon, + icons.reviewIssuesIcon, nls.localize('remote.help.issues', "Review Issues"), issues.map((info: HelpInformation) => (new HelpItemValue(commandService, info.extensionDescription, @@ -250,7 +242,7 @@ class HelpModel { if (helpItems.length) { helpItems.push(new IssueReporterItem( - reportIssuesIcon, + icons.reportIssuesIcon, nls.localize('remote.help.report', "Report Issue"), viewModel.helpInformation.map(info => (new HelpItemValue(commandService, info.extensionDescription, @@ -585,7 +577,7 @@ Registry.as(Extensions.ViewContainersRegistry).register return; } }, - icon: remoteExplorerViewIcon, + icon: icons.remoteExplorerViewIcon, order: 4 }, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index aaabe66b02d..a57e54b14ad 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -22,12 +22,12 @@ import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { OperatingSystem } from 'vs/base/common/platform'; import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; -import { Codicon } from 'vs/base/common/codicons'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService'; import { optional } from 'vs/platform/instantiation/common/instantiation'; +import { portsViewIcon } from 'vs/workbench/contrib/remote/browser/remoteIcons'; export const VIEWLET_ID = 'workbench.view.remote'; @@ -68,7 +68,7 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu return Registry.as(Extensions.ViewContainersRegistry).registerViewContainer({ id: TunnelPanel.ID, name: nls.localize('ports', "Ports"), - icon: Codicon.plug, + icon: portsViewIcon, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TunnelPanel.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: TunnelPanel.ID, hideIfEmpty: true, diff --git a/src/vs/workbench/contrib/remote/browser/remoteIcons.ts b/src/vs/workbench/contrib/remote/browser/remoteIcons.ts new file mode 100644 index 00000000000..76b854c1550 --- /dev/null +++ b/src/vs/workbench/contrib/remote/browser/remoteIcons.ts @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; + +import { Codicon } from 'vs/base/common/codicons'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + +export const getStartedIcon = registerIcon('remote-explorer-get-started', Codicon.star, nls.localize('getStartedIcon', 'Getting started icon in the remote explorer view.')); +export const documentationIcon = registerIcon('remote-explorer-documentation', Codicon.book, nls.localize('documentationIcon', 'Documentation icon in the remote explorer view.')); +export const feedbackIcon = registerIcon('remote-explorer-feedback', Codicon.twitter, nls.localize('feedbackIcon', 'Feedback icon in the remote explorer view.')); +export const reviewIssuesIcon = registerIcon('remote-explorer-review-issues', Codicon.issues, nls.localize('reviewIssuesIcon', 'Review issue icon in the remote explorer view.')); +export const reportIssuesIcon = registerIcon('remote-explorer-report-issues', Codicon.comment, nls.localize('reportIssuesIcon', 'Report issue icon in the remote explorer view.')); +export const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); + +export const portsViewIcon = registerIcon('ports-view-icon', Codicon.plug, nls.localize('portsViewIcon', 'View icon of the remote ports view.')); +export const portIcon = registerIcon('ports-view-icon', Codicon.plug, nls.localize('portIcon', 'Icon representing a remote port.')); + +export const forwardPortIcon = registerIcon('ports-forward-icon', Codicon.plus, nls.localize('forwardPortIcon', 'Icon for the forward action.')); +export const stopForwardIcon = registerIcon('ports-stop-forward-icon', Codicon.x, nls.localize('stopForwardIcon', 'Icon for the stop forwarding action.')); +export const openBrowserIcon = registerIcon('ports-open-browser-icon', Codicon.globe, nls.localize('openBrowserIcon', 'Icon for the open browser action.')); diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 7ed9fa790e0..0888c56179e 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -33,7 +33,7 @@ import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { once } from 'vs/base/common/functional'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { URI } from 'vs/base/common/uri'; @@ -42,7 +42,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; -import { Codicon } from 'vs/base/common/codicons'; +import { forwardPortIcon, openBrowserIcon, portIcon, portsViewIcon, stopForwardIcon } from 'vs/workbench/contrib/remote/browser/remoteIcons'; export const forwardedPortsViewEnabled = new RawContextKey('forwardedPortsViewEnabled', false); export const PORT_AUTO_FORWARD_SETTING = 'remote.autoForwardPorts'; @@ -88,7 +88,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel { remoteHost: 'localhost', remotePort: 0, description: '', - iconClasses: undefined + icon: undefined }; } @@ -285,8 +285,8 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer { + async run(): Promise { + await this.progressService.withProgress({ location: ProgressLocation.Dialog }, async (r) => { + r.report({ message: 'ssdf', total: 30 }); + return new Promise((s, e) => { + setTimeout(() => s(), 5000); + }); + }); + + let theme = this.themeService.getColorTheme(); let colors = Registry.as(ColorRegistryExtensions.ColorContribution).getColors(); let colorIds = colors.map(c => c.id).sort(); diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index ec449745fd2..fbf76ceda2e 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -14,6 +14,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { TunnelInformation, TunnelDescription, IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const IRemoteExplorerService = createDecorator('remoteExplorerService'); export const REMOTE_EXPLORER_TYPE_KEY: string = 'remote.explorerType'; @@ -36,7 +37,7 @@ export interface ITunnelItem { name?: string; closeable?: boolean; description?: string; - readonly iconClasses?: string; + readonly icon?: ThemeIcon; readonly label: string; } From fd45ba86b05a88a0a3b7d333c51be9b38db69f97 Mon Sep 17 00:00:00 2001 From: "condichen@tencent.com" <178854407@qq.com> Date: Sat, 12 Dec 2020 01:29:47 +0800 Subject: [PATCH 0830/1837] chore: remove git suffix --- .../extensions/electron-browser/reportExtensionIssueAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts index a41917474f4..99283e660b2 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts @@ -14,7 +14,7 @@ import { ExtensionType, IExtensionDescription } from 'vs/platform/extensions/com import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; -const builtinExtensionIssueUrl = 'https://github.com/microsoft/vscode.git'; +const builtinExtensionIssueUrl = 'https://github.com/microsoft/vscode'; export class ReportExtensionIssueAction extends Action { From baacaaca3e1de91e27e7d812afa26d70ad162e44 Mon Sep 17 00:00:00 2001 From: "condichen@tencent.com" <178854407@qq.com> Date: Sat, 12 Dec 2020 01:30:17 +0800 Subject: [PATCH 0831/1837] feat: use baseUrl first --- .../extensions/electron-browser/reportExtensionIssueAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts index 99283e660b2..762b07c457f 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/reportExtensionIssueAction.ts @@ -54,7 +54,7 @@ export class ReportExtensionIssueAction extends Action { unresponsiveProfile?: IExtensionHostProfile }): Promise { let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined; - if (extension.description.isBuiltin) { + if (!baseUrl && extension.description.isBuiltin) { baseUrl = builtinExtensionIssueUrl; } if (!!baseUrl) { From e1bc069d6ab197c6e6bbe4ca4792adeb3e4cca0b Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Fri, 11 Dec 2020 19:15:02 +0100 Subject: [PATCH 0832/1837] Push workflow stub file --- .github/workflows/pr.yml | 150 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 .github/workflows/pr.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 00000000000..7306c14035f --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,150 @@ +name: PR + +on: + push: + branches: + - lszomoru/pipeline-improvements + +jobs: + # linux: + # runs-on: ubuntu-latest + # env: + # CHILD_CONCURRENCY: "1" + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v1 + # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + # - run: | + # sudo apt-get update + # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + # sudo chmod +x /etc/init.d/xvfb + # sudo update-rc.d xvfb defaults + # sudo service xvfb start + # name: Setup Build Environment + # - uses: actions/setup-node@v1 + # with: + # node-version: 10 + # # TODO: cache node modules + # - run: yarn --frozen-lockfile + # name: Install Dependencies + # - run: yarn electron x64 + # name: Download Electron + # - run: yarn gulp hygiene + # name: Run Hygiene Checks + # - run: yarn monaco-compile-check + # name: Run Monaco Editor Checks + # - run: yarn valid-layers-check + # name: Run Valid Layers Checks + # - run: yarn compile + # name: Compile Sources + # - run: yarn download-builtin-extensions + # name: Download Built-in Extensions + # - run: DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" + # name: Run Unit Tests (Electron) + # - run: DISPLAY=:10 yarn test-browser --browser chromium + # name: Run Unit Tests (Browser) + # - run: DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" + # name: Run Integration Tests (Electron) + + # windows: + # runs-on: windows-2016 + # env: + # CHILD_CONCURRENCY: "1" + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v1 + # - uses: actions/setup-node@v1 + # with: + # node-version: 10 + # - uses: actions/setup-python@v1 + # with: + # python-version: '2.x' + # - run: yarn --frozen-lockfile + # name: Install Dependencies + # - run: yarn electron + # name: Download Electron + # - run: yarn gulp hygiene + # name: Run Hygiene Checks + # - run: yarn monaco-compile-check + # name: Run Monaco Editor Checks + # - run: yarn valid-layers-check + # name: Run Valid Layers Checks + # - run: yarn compile + # name: Compile Sources + # - run: yarn download-builtin-extensions + # name: Download Built-in Extensions + # - run: .\scripts\test.bat --tfs "Unit Tests" + # name: Run Unit Tests (Electron) + # - run: yarn test-browser --browser chromium + # name: Run Unit Tests (Browser) + # - run: .\scripts\test-integration.bat --tfs "Integration Tests" + # name: Run Integration Tests (Electron) + + # darwin: + # runs-on: macos-latest + # env: + # CHILD_CONCURRENCY: "1" + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v1 + # - uses: actions/setup-node@v1 + # with: + # node-version: 10 + # - run: yarn --frozen-lockfile + # name: Install Dependencies + # - run: yarn electron x64 + # name: Download Electron + # - run: yarn gulp hygiene + # name: Run Hygiene Checks + # - run: yarn monaco-compile-check + # name: Run Monaco Editor Checks + # - run: yarn valid-layers-check + # name: Run Valid Layers Checks + # - run: yarn compile + # name: Compile Sources + # - run: yarn download-builtin-extensions + # name: Download Built-in Extensions + # - run: ./scripts/test.sh --tfs "Unit Tests" + # name: Run Unit Tests (Electron) + # - run: yarn test-browser --browser chromium --browser webkit + # name: Run Unit Tests (Browser) + # - run: ./scripts/test-integration.sh --tfs "Integration Tests" + # name: Run Integration Tests (Electron) + + monaco: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Compute yarn cache key + id: yarn-cache-key + run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock') }}" + + - name: Cache root node modules + id: root-node-modules # use this to check for `cache-hit` (`steps.root-node-modules.outputs.cache-hit != 'true'`) + uses: actions/cache@v2 + env: + cache-name: root-node-modules + with: + path: ./node_modules + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - run: yarn --frozen-lockfile + name: Install Dependencies + + - run: yarn monaco-compile-check + name: Run Monaco Editor Checks + + - run: yarn gulp editor-esm-bundle + name: Editor Distro & ESM Bundle From b2444f539bc5e3bbc099ea6ee453e0dd7b3f4385 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Fri, 11 Dec 2020 10:31:46 -0800 Subject: [PATCH 0833/1837] Open Search Editor Action Bar item should clone search view's config Closes #112209 --- .../contrib/search/browser/searchView.ts | 2 +- .../browser/searchEditorActions.ts | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 5a42e7b884b..30dc713f0fb 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -397,7 +397,7 @@ export class SearchView extends ViewPane { return this.inputPatternIncludes; } - get searchExcludePattern(): PatternInputWidget { + get searchExcludePattern(): ExcludePatternInputWidget { return this.inputPatternExcludes; } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index f1d1426f4b1..a935fe640ab 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -29,6 +29,8 @@ import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/ import { EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IViewsService } from 'vs/workbench/common/views'; +import { getSearchView } from 'vs/workbench/contrib/search/browser/searchActions'; export const toggleSearchEditorCaseSensitiveCommand = (accessor: ServicesAccessor) => { const editorService = accessor.get(IEditorService); @@ -85,6 +87,7 @@ export class OpenSearchEditorAction extends Action { constructor(id: string, label: string, @IInstantiationService private readonly instantiationService: IInstantiationService, + @IViewsService private readonly viewsService: IViewsService, ) { super(id, label, ThemeIcon.asClassName(searchNewEditorIcon)); } @@ -98,7 +101,20 @@ export class OpenSearchEditorAction extends Action { } async run() { - await this.instantiationService.invokeFunction(openNewSearchEditor); + const searchView = getSearchView(this.viewsService); + if (searchView) { + await this.instantiationService.invokeFunction(openNewSearchEditor, { + filesToInclude: searchView.searchIncludePattern.getValue(), + filesToExclude: searchView.searchExcludePattern.getValue(), + isRegexp: searchView.searchAndReplaceWidget.searchInput.getRegex(), + isCaseSensitive: searchView.searchAndReplaceWidget.searchInput.getCaseSensitive(), + matchWholeWord: searchView.searchAndReplaceWidget.searchInput.getWholeWords(), + useExcludeSettingsAndIgnoreFiles: searchView.searchExcludePattern.useExcludesAndIgnoreFiles(), + showIncludesExcludes: !!(searchView.searchIncludePattern.getValue() || searchView.searchExcludePattern.getValue() || !searchView.searchExcludePattern.useExcludesAndIgnoreFiles()) + }); + } else { + await this.instantiationService.invokeFunction(openNewSearchEditor); + } } } From c7fa4ef02189685e0b79f343ea543498b4c1d587 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 20:13:45 +0100 Subject: [PATCH 0834/1837] Troubleshoot expression --- .github/workflows/ci.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdfaf69475e..5f812e3fc53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,9 +74,6 @@ jobs: - name: Run Hygiene Checks run: yarn gulp hygiene - - name: Run Monaco Editor Checks - run: yarn monaco-compile-check - - name: Run Valid Layers Checks run: yarn valid-layers-check @@ -202,6 +199,18 @@ jobs: path: build/**/*.js key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: dbg1 + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + run: echo dbg1 + + - name: dbg2 + if: ${{ steps.build-folder-compile-cache.cache-hit != 'true' }} + run: echo dbg2 + + - name: dbg3 + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} + run: echo dbg3 + - name: Compile /build/ folder if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} run: yarn run compile From d819caf1d27650eb1171657339ffe68726c7a5af Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 20:19:57 +0100 Subject: [PATCH 0835/1837] Fix if condition --- .github/workflows/ci.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f812e3fc53..c0f8513cb6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Compile /build/ folder - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.outputs.cache-hit != 'true' }} run: yarn run compile working-directory: ./build @@ -199,20 +199,8 @@ jobs: path: build/**/*.js key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: dbg1 - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} - run: echo dbg1 - - - name: dbg2 - if: ${{ steps.build-folder-compile-cache.cache-hit != 'true' }} - run: echo dbg2 - - - name: dbg3 - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} - run: echo dbg3 - - name: Compile /build/ folder - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.cache-hit != 'true' }} + if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.outputs.cache-hit != 'true' }} run: yarn run compile working-directory: ./build From 0ec1755aa9bcc564aa126c3ccff5eb80b7fab2cc Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 20:33:02 +0100 Subject: [PATCH 0836/1837] Simplify caching strategy --- .github/workflows/ci.yml | 81 ++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0f8513cb6e..04a76a54d73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,41 +32,31 @@ jobs: with: node-version: 12 - - name: Compute yarn cache key - id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}3" - - name: Cache node modules - id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) + id: cacheNodeModules uses: actions/cache@v2 - env: - cache-name: node-modules-cache with: - path: | - ~/.cache/ms-playwright - **/node_modules - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Install Dependencies - if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} - run: yarn --frozen-lockfile - - - name: Cache compile /build/ folder - id: build-folder-compile-cache - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + - name: Cache /build/ scripts + id: cacheBuildScripts uses: actions/cache@v2 with: path: build/**/*.js - key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Compile /build/ folder - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.outputs.cache-hit != 'true' }} - run: yarn run compile - working-directory: ./build + - name: Cache playwright + id: cachePlaywright + uses: actions/cache@v2 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-cachePlaywright-${{ hashFiles('yarn.lock') }} + + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' || steps.cachePlaywright.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile - name: Download Electron run: yarn electron x64 @@ -168,41 +158,24 @@ jobs: with: node-version: 12 - - name: Compute yarn cache key - id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}3" - - name: Cache node modules - id: node-modules-cache # use this to check for `cache-hit` (`steps.node-modules-cache.outputs.cache-hit != 'true'`) + id: cacheNodeModules uses: actions/cache@v2 - env: - cache-name: node-modules-cache with: - path: | - ~/.cache/ms-playwright - **/node_modules - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Install Dependencies - if: ${{ steps.node-modules-cache.outputs.cache-hit != 'true' }} - run: yarn --frozen-lockfile - - - name: Cache compile /build/ folder - id: build-folder-compile-cache - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' }} + - name: Cache /build/ scripts + id: cacheBuildScripts uses: actions/cache@v2 with: path: build/**/*.js - key: ${{ runner.os }}-compileBuildFolder-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Compile /build/ folder - if: ${{ steps.node-modules-cache.outputs.cache-hit == 'true' && steps.build-folder-compile-cache.outputs.cache-hit != 'true' }} - run: yarn run compile - working-directory: ./build + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile - name: Run Monaco Editor Checks run: yarn monaco-compile-check From 641abd4170dbafe6ccfaad35a476f54235ddc664 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:01:50 +0100 Subject: [PATCH 0837/1837] Extract the hygiene check to its own job --- .github/workflows/ci.yml | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04a76a54d73..52bb6356c80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,40 @@ on: - release/* jobs: + hygiene: + name: Hygiene check + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' || steps.cachePlaywright.outputs.cache-hit != 'true' }} + run: yarn --frozen-lockfile + + - name: Run Hygiene Checks + run: yarn gulp hygiene + linux: runs-on: ubuntu-latest env: @@ -61,9 +95,6 @@ jobs: - name: Download Electron run: yarn electron x64 - - name: Run Hygiene Checks - run: yarn gulp hygiene - - name: Run Valid Layers Checks run: yarn valid-layers-check @@ -148,6 +179,7 @@ jobs: # name: Run Integration Tests (Electron) monaco: + name: Monaco Editor checks runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4942f2420509298c07c6ac3d40b425dca232714b Mon Sep 17 00:00:00 2001 From: Brian Clark Date: Fri, 11 Dec 2020 15:06:22 -0500 Subject: [PATCH 0838/1837] quick fix for setting description typo (#112327) --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 49035d583c3..79397349a65 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3278,7 +3278,7 @@ class EditorSuggest extends BaseEditorOption Date: Fri, 11 Dec 2020 21:11:48 +0100 Subject: [PATCH 0839/1837] Move valid layers check together with the hygiene check --- .github/workflows/ci.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52bb6356c80..3fcddd94734 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: jobs: hygiene: - name: Hygiene check + name: Hygiene and Layers check runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -39,13 +39,22 @@ jobs: key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' || steps.cachePlaywright.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - name: Run Hygiene Checks run: yarn gulp hygiene + - name: Download Playwright + run: node ./node_modules/playwright/install.js + + - name: Run Valid Layers Checks + run: yarn valid-layers-check + linux: + name: Linux runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -95,9 +104,6 @@ jobs: - name: Download Electron run: yarn electron x64 - - name: Run Valid Layers Checks - run: yarn valid-layers-check - - name: Compile Sources run: yarn compile @@ -207,6 +213,8 @@ jobs: - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - name: Run Monaco Editor Checks From 92723a8a2c88041d59bdefade50cbff8254d486e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Dec 2020 12:14:04 -0800 Subject: [PATCH 0840/1837] Bump markdown-it and highlight versions --- .../markdown-language-features/package.json | 6 +- .../markdown-language-features/yarn.lock | 63 +++++++++---------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 72b952e82f2..cd44088b6f5 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -324,14 +324,14 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "dependencies": { - "highlight.js": "10.1.2", - "markdown-it": "^10.0.0", + "highlight.js": "^10.4.1", + "markdown-it": "^12.0.3", "markdown-it-front-matter": "^0.2.1", "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/highlight.js": "9.12.3", + "@types/highlight.js": "10.1.0", "@types/lodash.throttle": "^4.1.3", "@types/markdown-it": "0.0.2", "@types/node": "^12.11.7", diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 065943fa43a..38f3912f9a9 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -2,10 +2,12 @@ # yarn lockfile v1 -"@types/highlight.js@9.12.3": - version "9.12.3" - resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca" - integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ== +"@types/highlight.js@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-10.1.0.tgz#89bb0c202997d7a90a07bd2ec1f7d00c56bb90b4" + integrity sha512-77hF2dGBsOgnvZll1vymYiNUtqJ8cJfXPD6GG/2M0aLRc29PkvB7Au6sIDjIEFcSICBhCh2+Pyq6WSRS7LUm6A== + dependencies: + highlight.js "*" "@types/lodash.throttle@^4.1.3": version "4.1.3" @@ -330,12 +332,10 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" - integrity sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY= - dependencies: - sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== arr-diff@^1.0.1: version "1.1.0" @@ -1321,10 +1321,10 @@ enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" -entities@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -2131,10 +2131,10 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -highlight.js@10.1.2: - version "10.1.2" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.1.2.tgz#c20db951ba1c22c055010648dfffd7b2a968e00c" - integrity sha512-Q39v/Mn5mfBlMff9r+zzA+gWxRsCRKwEMvYTiisLr/XUiFI/4puWt0Ojdko3R3JCNWGdOWaA5g/Yxqa23kC5AA== +highlight.js@*, 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== hmac-drbg@^1.0.0: version "1.0.1" @@ -2630,10 +2630,10 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -linkify-it@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" - integrity sha1-2UpGSPmxwXnWT6lykSaL22zpQ08= +linkify-it@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" + integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== dependencies: uc.micro "^1.0.1" @@ -2831,14 +2831,14 @@ markdown-it-front-matter@^0.2.1: resolved "https://registry.yarnpkg.com/markdown-it-front-matter/-/markdown-it-front-matter-0.2.1.tgz#dca49a827bb3cebb0528452c1d87dff276eb28dc" integrity sha512-ydUIqlKfDscRpRUTRcA3maeeUKn3Cl5EaKZSA+I/f0KOGCBurW7e+bbz59sxqkC3FA9Q2S2+t4mpkH9T0BCM6A== -markdown-it@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" - integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== +markdown-it@^12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.3.tgz#8d1e47daf1d716d63610495eb93f6665573e4abe" + integrity sha512-M57RsMv+QQmJHz1yCu0gTJRMx/LlxRPtrrw+2kb/CpDVK/graCmWO0qfNnz/SE1FCNdyq3pkMMZ+itTnyT/YGA== dependencies: - argparse "^1.0.7" - entities "~2.0.0" - linkify-it "^2.0.0" + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" mdurl "^1.0.1" uc.micro "^1.0.5" @@ -4143,11 +4143,6 @@ split@0.3: dependencies: through "2" -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - sshpk@^1.7.0: version "1.13.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" From eb5c4388c749bbab371377f6b13a3b7db9d81fba Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Dec 2020 12:14:58 -0800 Subject: [PATCH 0841/1837] Revert "Pick up offical TS build for web server" This reverts commit f29a3cabc4744d6b39a25056672e65679702589c. --- .../extension-browser.webpack.config.js | 4 ++-- extensions/typescript-language-features/package.json | 2 +- extensions/typescript-language-features/yarn.lock | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/extensions/typescript-language-features/extension-browser.webpack.config.js b/extensions/typescript-language-features/extension-browser.webpack.config.js index 531a5d29c19..fd8e5877c3a 100644 --- a/extensions/typescript-language-features/extension-browser.webpack.config.js +++ b/extensions/typescript-language-features/extension-browser.webpack.config.js @@ -22,7 +22,7 @@ module.exports = withBrowserDefaults({ new CopyPlugin({ patterns: [ { - from: 'node_modules/typescript-web/lib/*.d.ts', + from: 'node_modules/typescript-web-server/*.d.ts', to: 'typescript-web/', flatten: true }, @@ -32,7 +32,7 @@ module.exports = withBrowserDefaults({ new CopyPlugin({ patterns: [ { - from: 'node_modules/typescript-web/lib/tsserver.js', + from: 'node_modules/typescript-web-server/tsserver.js', to: 'typescript-web/tsserver.web.js', transform: (content) => { return Terser.minify(content.toString()).code; diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 169cda3056a..2ea05450a0d 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -29,7 +29,7 @@ "@types/semver": "^5.5.0", "copy-webpack-plugin": "^6.0.3", "terser": "^4.8.0", - "typescript-web": "npm:typescript@^4.2.0-dev.20201209", + "typescript-web-server": "git://github.com/mjbvz/ts-server-web-build", "vscode": "^1.1.36" }, "scripts": { diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index f51857a320b..4ef8f032788 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -876,10 +876,9 @@ typescript-vscode-sh-plugin@^0.6.14: resolved "https://registry.yarnpkg.com/typescript-vscode-sh-plugin/-/typescript-vscode-sh-plugin-0.6.14.tgz#a81031b502f6346a26ea49ce082438c3e353bb38" integrity sha512-AkNlRBbI6K7gk29O92qthNSvc6jjmNQ6isVXoYxkFwPa8D04tIv2SOPd+sd+mNpso4tNdL2gy7nVtrd5yFqvlA== -"typescript-web@npm:typescript@^4.2.0-dev.20201209": - version "4.2.0-dev.20201209" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201209.tgz#fab33fdb1aa7beb857271e0626bca6b200c61351" - integrity sha512-rXJtE/naraN9n3bPBDA5Sa/2nrx1di5se/kVkmAjhUSpBzGmx3zeNHZF59U8XhYQdQ1QsMiDDnjmtjFUGC9LEQ== +"typescript-web-server@git://github.com/mjbvz/ts-server-web-build": + version "0.0.0" + resolved "git://github.com/mjbvz/ts-server-web-build#2a70d88432760118a6aab21da7b819a57e7d4e5e" unique-filename@^1.1.1: version "1.1.1" From 01ea0ecc098e41812d38ad15ca172a6036c6c50e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:17:46 +0100 Subject: [PATCH 0842/1837] Remove playwright caching --- .github/workflows/ci.yml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fcddd94734..e388c7525ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,9 +47,6 @@ jobs: - name: Run Hygiene Checks run: yarn gulp hygiene - - name: Download Playwright - run: node ./node_modules/playwright/install.js - - name: Run Valid Layers Checks run: yarn valid-layers-check @@ -90,20 +87,16 @@ jobs: path: build/**/*.js key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Cache playwright - id: cachePlaywright - uses: actions/cache@v2 - with: - path: ~/.cache/ms-playwright - key: ${{ runner.os }}-cachePlaywright-${{ hashFiles('yarn.lock') }} - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' || steps.cachePlaywright.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} run: yarn --frozen-lockfile - name: Download Electron run: yarn electron x64 + - name: Download Playwright + run: node ./node_modules/playwright/install.js + - name: Compile Sources run: yarn compile From 623440c55c14acd8bbfe7a18af14efa00fd1ac5b Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:27:08 +0100 Subject: [PATCH 0843/1837] Extract cached yarn logic to a separate file --- .github/workflows/ci.yml | 22 ++-------------------- .github/workflows/ci/cached-yarn.yml | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/ci/cached-yarn.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e388c7525ec..b3e0853e190 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,26 +189,8 @@ jobs: with: node-version: 12 - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- - - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + - name: Cached yarn + uses: ./ci/cached-yarn - name: Run Monaco Editor Checks run: yarn monaco-compile-check diff --git a/.github/workflows/ci/cached-yarn.yml b/.github/workflows/ci/cached-yarn.yml new file mode 100644 index 00000000000..29963cea03d --- /dev/null +++ b/.github/workflows/ci/cached-yarn.yml @@ -0,0 +1,24 @@ +name: Cached yarn +runs: + using: composite + steps: + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile From 7e7c1de569765ee654f72bf6017c8cea9115d615 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:33:46 +0100 Subject: [PATCH 0844/1837] Follow the expected naming scheme --- .../{ci/cached-yarn.yml => ci-cached-yarn/action.yaml} | 0 .github/workflows/ci.yml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{ci/cached-yarn.yml => ci-cached-yarn/action.yaml} (100%) diff --git a/.github/workflows/ci/cached-yarn.yml b/.github/workflows/ci-cached-yarn/action.yaml similarity index 100% rename from .github/workflows/ci/cached-yarn.yml rename to .github/workflows/ci-cached-yarn/action.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3e0853e190..1d10c2cc881 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,7 +190,7 @@ jobs: node-version: 12 - name: Cached yarn - uses: ./ci/cached-yarn + uses: ./ci-cached-yarn - name: Run Monaco Editor Checks run: yarn monaco-compile-check From d1d4143971acdad31fba287394ff9c0cad1b4e41 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:36:30 +0100 Subject: [PATCH 0845/1837] Attempt using absolute path --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d10c2cc881..d118d583d2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,7 +190,7 @@ jobs: node-version: 12 - name: Cached yarn - uses: ./ci-cached-yarn + uses: ./.github/workflows/ci-cached-yarn - name: Run Monaco Editor Checks run: yarn monaco-compile-check From e3e3f8802ffc309056df3c7fcfa8e3282cc547fc Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 21:40:29 +0100 Subject: [PATCH 0846/1837] Abandon composite actions since they cannot actually compose on other actions --- .github/workflows/ci-cached-yarn/action.yaml | 24 ------------------ .github/workflows/ci.yml | 26 +++++++++++++++----- 2 files changed, 20 insertions(+), 30 deletions(-) delete mode 100644 .github/workflows/ci-cached-yarn/action.yaml diff --git a/.github/workflows/ci-cached-yarn/action.yaml b/.github/workflows/ci-cached-yarn/action.yaml deleted file mode 100644 index 29963cea03d..00000000000 --- a/.github/workflows/ci-cached-yarn/action.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: Cached yarn -runs: - using: composite - steps: - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- - - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d118d583d2c..c89f0372fc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,14 +30,12 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts id: cacheBuildScripts uses: actions/cache@v2 with: path: build/**/*.js key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} env: @@ -79,16 +77,16 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts id: cacheBuildScripts uses: actions/cache@v2 with: path: build/**/*.js key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - name: Download Electron @@ -189,8 +187,24 @@ jobs: with: node-version: 12 - - name: Cached yarn - uses: ./.github/workflows/ci-cached-yarn + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile - name: Run Monaco Editor Checks run: yarn monaco-compile-check From f79e3aea635919515f13d8bfead13adbb2e01d5f Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Dec 2020 12:55:43 -0800 Subject: [PATCH 0847/1837] Fix notebook status bar icon colors (fixes #112323) --- .../contrib/notebook/browser/notebookEditorWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index cc2d889c3e6..9b650c94323 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -2191,12 +2191,12 @@ registerThemingParticipant((theme, collector) => { const cellStatusSuccessIcon = theme.getColor(cellStatusIconSuccess); if (cellStatusSuccessIcon) { - collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-check { color: ${cellStatusSuccessIcon} }`); + collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-notebook-state-success { color: ${cellStatusSuccessIcon} }`); } const cellStatusErrorIcon = theme.getColor(cellStatusIconError); if (cellStatusErrorIcon) { - collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-error { color: ${cellStatusErrorIcon} }`); + collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-notebook-state-error { color: ${cellStatusErrorIcon} }`); } const cellStatusRunningIcon = theme.getColor(cellStatusIconRunning); From e2e23aeb7771bbfd8cccd61dd7c604b15349d153 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:15:05 +0100 Subject: [PATCH 0848/1837] Add a compile and a linux build step --- .github/workflows/ci.yml | 116 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c89f0372fc7..182841c7c1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,122 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check + compile: + name: Compile + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Cache compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ GITHUB_SHA }} + + - name: Compile Core + run: yarn gulp compile-build + + - name: Compile Extensions + run: yarn gulp compile-extensions-build + + - name: Minify VS Code + run: yarn gulp minify-vscode + + linux-build: + name: Linux Build + needs: compile + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - name: Setup Build Environment + run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Restore cached node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + + - name: Restore cached /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ GITHUB_SHA }} + + - name: Build VS Code + run: yarn gulp vscode-linux-x64-min-ci + + - name: Download Electron + run: yarn electron x64 + + - name: Run Unit Tests (Electron) + run: DISPLAY=:10 ./scripts/test.sh --build + + - name: Download Playwright + run: node ./node_modules/playwright/install.js + + - name: Run Unit Tests (Browser) + run: DISPLAY=:10 yarn test-browser --build --browser chromium + + - name: Run Integration Tests (Electron) + run: DISPLAY=:10 ./scripts/test-integration.sh --build + linux: name: Linux runs-on: ubuntu-latest From 0dd9cdbb45f39977cbea48debf1993935d86de84 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:17:46 +0100 Subject: [PATCH 0849/1837] Fix env variable usages --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 182841c7c1b..d9320dcdb0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,7 +87,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ GITHUB_SHA }} + key: cacheCompiledCode-${{ env.GITHUB_SHA }} - name: Compile Core run: yarn gulp compile-build @@ -144,7 +144,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ GITHUB_SHA }} + key: cacheCompiledCode-${{ env.GITHUB_SHA }} - name: Build VS Code run: yarn gulp vscode-linux-x64-min-ci From 3bad41ff3c3b84675bd536a71d7dd97e4e95f865 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:36:44 +0100 Subject: [PATCH 0850/1837] Attempt to run things in parallel --- .github/workflows/ci.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9320dcdb0e..bd62f9fd12c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -205,17 +205,13 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Download Electron - run: yarn electron x64 - - - name: Download Playwright - run: node ./node_modules/playwright/install.js - - - name: Compile Sources - run: yarn compile - - - name: Download Built-in Extensions - run: yarn download-builtin-extensions + - name: Compile & Download + run: | + yarn compile & + yarn electron x64 & + node ./node_modules/playwright/install.js & + yarn download-builtin-extensions + wait - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh From 771068e997889ef76168b5c214a0f14434de1e01 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Dec 2020 12:24:53 -0800 Subject: [PATCH 0851/1837] Remove unused function --- .../webview/electron-browser/pre/electron-index.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js b/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js index 3dfdad8b2b3..91458588028 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js +++ b/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js @@ -6,16 +6,6 @@ (function () { 'use strict'; - const registerVscodeResourceScheme = (function () { - let hasRegistered = false; - return () => { - if (hasRegistered) { - return; - } - hasRegistered = true; - }; - }()); - const ipcRenderer = require('electron').ipcRenderer; let isInDevelopmentMode = false; @@ -73,8 +63,6 @@ }); document.addEventListener('DOMContentLoaded', () => { - registerVscodeResourceScheme(); - // Forward messages from the embedded iframe window.onmessage = (message) => { ipcRenderer.sendToHost(message.data.command, message.data.data); From 5b8a6ee21b4709dd853814be30deafb540151822 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Dec 2020 12:40:30 -0800 Subject: [PATCH 0852/1837] Add more logging to resource loading for webviews --- src/vs/platform/webview/common/resourceLoader.ts | 13 +++++++++++++ .../webview/electron-main/webviewMainService.ts | 4 +++- .../electron-main/webviewProtocolProvider.ts | 6 ++++-- .../contrib/webview/browser/webviewElement.ts | 4 ++-- .../webview/electron-sandbox/resourceLoading.ts | 9 +++++++-- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/vs/platform/webview/common/resourceLoader.ts b/src/vs/platform/webview/common/resourceLoader.ts index ee64c8ef4ff..ac2931d3fe8 100644 --- a/src/vs/platform/webview/common/resourceLoader.ts +++ b/src/vs/platform/webview/common/resourceLoader.ts @@ -9,6 +9,7 @@ import { isUNC } from 'vs/base/common/extpath'; import { Schemas } from 'vs/base/common/network'; import { sep } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; +import { ILogService } from 'vs/platform/log/common/log'; import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IRequestService } from 'vs/platform/request/common/request'; import { getWebviewContentMimeType } from 'vs/platform/webview/common/mimeTypes'; @@ -48,8 +49,14 @@ export async function loadLocalResource( }, fileReader: FileReader, requestService: IRequestService, + logService: ILogService, ): Promise { + logService.debug(`loadLocalResource - being. requestUri=${requestUri}`); + let resourceToLoad = getResourceToLoad(requestUri, options.roots); + + logService.debug(`loadLocalResource - found resource to load. requestUri=${requestUri}, resourceToLoad=${resourceToLoad}`); + if (!resourceToLoad) { return WebviewResourceResponse.AccessDenied; } @@ -63,6 +70,8 @@ export async function loadLocalResource( if (resourceToLoad.scheme === Schemas.http || resourceToLoad.scheme === Schemas.https) { const response = await requestService.request({ url: resourceToLoad.toString(true) }, CancellationToken.None); + logService.debug(`loadLocalResource - Loaded over http(s). requestUri=${requestUri}, response=${response.res.statusCode}`); + if (response.res.statusCode === 200) { return new WebviewResourceResponse.StreamSuccess(response.stream, mime); } @@ -71,9 +80,13 @@ export async function loadLocalResource( try { const contents = await fileReader.readFileStream(resourceToLoad); + logService.debug(`loadLocalResource - Loaded using fileReader. requestUri=${requestUri}`); + return new WebviewResourceResponse.StreamSuccess(contents, mime); } catch (err) { + logService.debug(`loadLocalResource - Error using fileReader. requestUri=${requestUri}`); console.log(err); + return WebviewResourceResponse.Failed; } } diff --git a/src/vs/platform/webview/electron-main/webviewMainService.ts b/src/vs/platform/webview/electron-main/webviewMainService.ts index 03a6e306cac..92bd47e2d55 100644 --- a/src/vs/platform/webview/electron-main/webviewMainService.ts +++ b/src/vs/platform/webview/electron-main/webviewMainService.ts @@ -8,6 +8,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; +import { ILogService } from 'vs/platform/log/common/log'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { IRequestService } from 'vs/platform/request/common/request'; import { IWebviewManagerService, RegisterWebviewMetadata, WebviewWebContentsId, WebviewWindowId } from 'vs/platform/webview/common/webviewManagerService'; @@ -24,12 +25,13 @@ export class WebviewMainService extends Disposable implements IWebviewManagerSer constructor( @IFileService fileService: IFileService, + @ILogService logService: ILogService, @IRequestService requestService: IRequestService, @ITunnelService tunnelService: ITunnelService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService, ) { super(); - this.protocolProvider = this._register(new WebviewProtocolProvider(fileService, requestService, windowsMainService)); + this.protocolProvider = this._register(new WebviewProtocolProvider(fileService, logService, requestService, windowsMainService)); this.portMappingProvider = this._register(new WebviewPortMappingProvider(tunnelService)); } diff --git a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts index ce6233924b0..ea3a6dee8a9 100644 --- a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts +++ b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts @@ -10,6 +10,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { FileAccess, Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; +import { ILogService } from 'vs/platform/log/common/log'; import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IRequestService } from 'vs/platform/request/common/request'; import { loadLocalResource, webviewPartitionId, WebviewResourceResponse } from 'vs/platform/webview/common/resourceLoader'; @@ -38,8 +39,9 @@ export class WebviewProtocolProvider extends Disposable { constructor( @IFileService private readonly fileService: IFileService, + @ILogService private readonly logService: ILogService, @IRequestService private readonly requestService: IRequestService, - @IWindowsMainService readonly windowsMainService: IWindowsMainService, + @IWindowsMainService private readonly windowsMainService: IWindowsMainService, ) { super(); @@ -208,7 +210,7 @@ export class WebviewProtocolProvider extends Disposable { roots: metadata.localResourceRoots, remoteConnectionData: metadata.remoteConnectionData, rewriteUri, - }, fileService, this.requestService); + }, fileService, this.requestService, this.logService); if (result.type === WebviewResourceResponse.Type.Success) { return callback({ diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 21c66f82cd3..5dc06842d37 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -41,7 +41,7 @@ export class IFrameWebview extends BaseWebview implements Web @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IConfigurationService private readonly _configurationService: IConfigurationService, @IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, - @ILogService logService: ILogService, + @ILogService private readonly logService: ILogService, ) { super(id, options, contentOptions, extension, webviewThemeDataProvider, notificationService, logService, telemetryService, environmentService); @@ -192,7 +192,7 @@ export class IFrameWebview extends BaseWebview implements Web rewriteUri, }, { readFileStream: (resource) => this.fileService.readFileStream(resource).then(x => x.value), - }, this.requestService); + }, this.requestService, this.logService); if (result.type === WebviewResourceResponse.Type.Success) { const { buffer } = await streamToBuffer(result.stream); diff --git a/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts b/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts index b4236def69f..62e5d11d330 100644 --- a/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts +++ b/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts @@ -79,6 +79,7 @@ export class WebviewResourceRequestManager extends Disposable { const remoteConnectionData = remoteAuthority ? remoteAuthorityResolverService.getConnectionData(remoteAuthority) : null; this._logService.debug(`WebviewResourceRequestManager(${this.id}): did-start-loading`); + this._ready = this._webviewManagerService.registerWebview(this.id, nativeHostService.windowId, { extensionLocation: this.extension?.location.toJSON(), localResourceRoots: this._localResourceRoots.map(x => x.toJSON()), @@ -101,14 +102,18 @@ export class WebviewResourceRequestManager extends Disposable { const loadResourceChannel = `vscode:loadWebviewResource-${id}`; const loadResourceListener = async (_event: any, requestId: number, resource: UriComponents) => { + const uri = URI.revive(resource); try { - const response = await loadLocalResource(URI.revive(resource), { + this._logService.debug(`WebviewResourceRequestManager(${this.id}): starting resource load. uri: ${uri}`); + + const response = await loadLocalResource(uri, { extensionLocation: this.extension?.location, roots: this._localResourceRoots, remoteConnectionData: remoteConnectionData, }, { readFileStream: (resource) => fileService.readFileStream(resource).then(x => x.value), - }, requestService); + }, requestService, this._logService); + this._logService.debug(`WebviewResourceRequestManager(${this.id}): finished resource load. uri: ${uri}, type=${response.type}`); if (response.type === WebviewResourceResponse.Type.Success) { const buffer = await streamToBuffer(response.stream); From 072d922c450cf080da48b5cb9b1ddff86253d309 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Dec 2020 13:39:03 -0800 Subject: [PATCH 0853/1837] Revert "Revert "Pick up offical TS build for web server"" This reverts commit eb5c4388c749bbab371377f6b13a3b7db9d81fba. --- .../extension-browser.webpack.config.js | 4 ++-- extensions/typescript-language-features/package.json | 2 +- extensions/typescript-language-features/yarn.lock | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/extensions/typescript-language-features/extension-browser.webpack.config.js b/extensions/typescript-language-features/extension-browser.webpack.config.js index fd8e5877c3a..531a5d29c19 100644 --- a/extensions/typescript-language-features/extension-browser.webpack.config.js +++ b/extensions/typescript-language-features/extension-browser.webpack.config.js @@ -22,7 +22,7 @@ module.exports = withBrowserDefaults({ new CopyPlugin({ patterns: [ { - from: 'node_modules/typescript-web-server/*.d.ts', + from: 'node_modules/typescript-web/lib/*.d.ts', to: 'typescript-web/', flatten: true }, @@ -32,7 +32,7 @@ module.exports = withBrowserDefaults({ new CopyPlugin({ patterns: [ { - from: 'node_modules/typescript-web-server/tsserver.js', + from: 'node_modules/typescript-web/lib/tsserver.js', to: 'typescript-web/tsserver.web.js', transform: (content) => { return Terser.minify(content.toString()).code; diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 2ea05450a0d..169cda3056a 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -29,7 +29,7 @@ "@types/semver": "^5.5.0", "copy-webpack-plugin": "^6.0.3", "terser": "^4.8.0", - "typescript-web-server": "git://github.com/mjbvz/ts-server-web-build", + "typescript-web": "npm:typescript@^4.2.0-dev.20201209", "vscode": "^1.1.36" }, "scripts": { diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 4ef8f032788..f51857a320b 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -876,9 +876,10 @@ typescript-vscode-sh-plugin@^0.6.14: resolved "https://registry.yarnpkg.com/typescript-vscode-sh-plugin/-/typescript-vscode-sh-plugin-0.6.14.tgz#a81031b502f6346a26ea49ce082438c3e353bb38" integrity sha512-AkNlRBbI6K7gk29O92qthNSvc6jjmNQ6isVXoYxkFwPa8D04tIv2SOPd+sd+mNpso4tNdL2gy7nVtrd5yFqvlA== -"typescript-web-server@git://github.com/mjbvz/ts-server-web-build": - version "0.0.0" - resolved "git://github.com/mjbvz/ts-server-web-build#2a70d88432760118a6aab21da7b819a57e7d4e5e" +"typescript-web@npm:typescript@^4.2.0-dev.20201209": + version "4.2.0-dev.20201209" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201209.tgz#fab33fdb1aa7beb857271e0626bca6b200c61351" + integrity sha512-rXJtE/naraN9n3bPBDA5Sa/2nrx1di5se/kVkmAjhUSpBzGmx3zeNHZF59U8XhYQdQ1QsMiDDnjmtjFUGC9LEQ== unique-filename@^1.1.1: version "1.1.1" From 0059c4cbfe09458d89d5da75d6e5c2f524b86773 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:42:23 +0100 Subject: [PATCH 0854/1837] Tweak combined step --- .github/workflows/ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd62f9fd12c..26248e18415 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -206,12 +206,7 @@ jobs: run: yarn --frozen-lockfile - name: Compile & Download - run: | - yarn compile & - yarn electron x64 & - node ./node_modules/playwright/install.js & - yarn download-builtin-extensions - wait + run: yarn compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo Compile & Download finished. - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh From 44b918b624839e180301ab9fb5c6499a5da9826d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:46:14 +0100 Subject: [PATCH 0855/1837] Avoid "&" --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26248e18415..387aacf7be0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -205,8 +205,8 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Compile & Download - run: yarn compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo Compile & Download finished. + - name: Compile and Download + run: yarn compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo "Compile and Download finished". - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh From ba16f865b22ae102914867b619952fffb2c05565 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:46:37 +0100 Subject: [PATCH 0856/1837] Remove compile and linux build for now --- .github/workflows/ci.yml | 194 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 387aacf7be0..78cfcd4210d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,121 +48,121 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check - compile: - name: Compile - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # compile: + # name: Compile + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + # - name: Cache node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules- + # - name: Cache /build/ scripts + # id: cacheBuildScripts + # uses: actions/cache@v2 + # with: + # path: build/**/*.js + # key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + # - name: Execute yarn + # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + # env: + # PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + # run: yarn --frozen-lockfile - - name: Cache compiled code - id: cacheCompiledCode - uses: actions/cache@v2 - with: - path: | - .build - out-build - out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + # - name: Cache compiled code + # id: cacheCompiledCode + # uses: actions/cache@v2 + # with: + # path: | + # .build + # out-build + # out-vscode-min + # key: cacheCompiledCode-${{ env.GITHUB_SHA }} - - name: Compile Core - run: yarn gulp compile-build + # - name: Compile Core + # run: yarn gulp compile-build - - name: Compile Extensions - run: yarn gulp compile-extensions-build + # - name: Compile Extensions + # run: yarn gulp compile-extensions-build - - name: Minify VS Code - run: yarn gulp minify-vscode + # - name: Minify VS Code + # run: yarn gulp minify-vscode - linux-build: - name: Linux Build - needs: compile - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # linux-build: + # name: Linux Build + # needs: compile + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start + # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + # - name: Setup Build Environment + # run: | + # sudo apt-get update + # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + # sudo chmod +x /etc/init.d/xvfb + # sudo update-rc.d xvfb defaults + # sudo service xvfb start - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Restore cached /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + # - name: Restore cached /build/ scripts + # id: cacheBuildScripts + # uses: actions/cache@v2 + # with: + # path: build/**/*.js + # key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Restore cached compiled code - id: cacheCompiledCode - uses: actions/cache@v2 - with: - path: | - .build - out-build - out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + # - name: Restore cached compiled code + # id: cacheCompiledCode + # uses: actions/cache@v2 + # with: + # path: | + # .build + # out-build + # out-vscode-min + # key: cacheCompiledCode-${{ env.GITHUB_SHA }} - - name: Build VS Code - run: yarn gulp vscode-linux-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-linux-x64-min-ci - - name: Download Electron - run: yarn electron x64 + # - name: Download Electron + # run: yarn electron x64 - - name: Run Unit Tests (Electron) - run: DISPLAY=:10 ./scripts/test.sh --build + # - name: Run Unit Tests (Electron) + # run: DISPLAY=:10 ./scripts/test.sh --build - - name: Download Playwright - run: node ./node_modules/playwright/install.js + # - name: Download Playwright + # run: node ./node_modules/playwright/install.js - - name: Run Unit Tests (Browser) - run: DISPLAY=:10 yarn test-browser --build --browser chromium + # - name: Run Unit Tests (Browser) + # run: DISPLAY=:10 yarn test-browser --build --browser chromium - - name: Run Integration Tests (Electron) - run: DISPLAY=:10 ./scripts/test-integration.sh --build + # - name: Run Integration Tests (Electron) + # run: DISPLAY=:10 ./scripts/test-integration.sh --build linux: name: Linux From 73c050511b5dd62ac96b00534d1e9915e2490dff Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:51:33 +0100 Subject: [PATCH 0857/1837] Avoid respawning --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78cfcd4210d..bf41e5b5bb5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -206,7 +206,7 @@ jobs: run: yarn --frozen-lockfile - name: Compile and Download - run: yarn compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo "Compile and Download finished". + run: node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo "Compile and Download finished". - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh From 58e88100755465c28531bfd0baa321d61eec9602 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 22:58:29 +0100 Subject: [PATCH 0858/1837] Try `yarn concurrently` --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf41e5b5bb5..309bb4996e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -206,7 +206,7 @@ jobs: run: yarn --frozen-lockfile - name: Compile and Download - run: node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile & yarn electron x64 & node ./node_modules/playwright/install.js & yarn download-builtin-extensions; echo "Compile and Download finished". + run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh From 374e7487bd22ac8b8684c833b9aff1d98848dbf3 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 23:08:10 +0100 Subject: [PATCH 0859/1837] Run unit tests concurrently --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 309bb4996e6..74d7db8f376 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,14 +208,8 @@ jobs: - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - - name: Run Unit Tests (Electron) - run: DISPLAY=:10 ./scripts/test.sh - - - name: Run Unit Tests (Browser) - run: DISPLAY=:10 yarn test-browser --browser chromium - - - name: Run Integration Tests (Electron) - run: DISPLAY=:10 ./scripts/test-integration.sh + - name: Run Unit Tests + run: DISPLAY=:10 yarn concurrently --names "unit-tests-electron,unit-tests-browser,integration-tests-electron" "./scripts/test.sh" "yarn test-browser --browser chromium" "./scripts/test-integration.sh" # windows: # runs-on: windows-2016 From 70355b6676546736a8bb3a0bcc4e24eca5bc3d67 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 23:17:17 +0100 Subject: [PATCH 0860/1837] Add macOS --- .github/workflows/ci.yml | 72 ++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74d7db8f376..ed377dc6f9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: jobs: hygiene: - name: Hygiene and Layers check + name: Hygiene and Layering runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -208,7 +208,7 @@ jobs: - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - - name: Run Unit Tests + - name: Run Unit and Integration Tests run: DISPLAY=:10 yarn concurrently --names "unit-tests-electron,unit-tests-browser,integration-tests-electron" "./scripts/test.sh" "yarn test-browser --browser chromium" "./scripts/test-integration.sh" # windows: @@ -245,39 +245,45 @@ jobs: # - run: .\scripts\test-integration.bat --tfs "Integration Tests" # name: Run Integration Tests (Electron) - # darwin: - # runs-on: macos-latest - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron x64 - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: ./scripts/test.sh --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: yarn test-browser --browser chromium --browser webkit - # name: Run Unit Tests (Browser) - # - run: ./scripts/test-integration.sh --tfs "Integration Tests" - # name: Run Integration Tests (Electron) + darwin: + name: macOS + runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Compile and Download + run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + + - name: Run Unit and Integration Tests + run: DISPLAY=:10 yarn concurrently --names "unit-tests-electron,unit-tests-browser,integration-tests-electron" "./scripts/test.sh" "yarn test-browser --browser chromium" "./scripts/test-integration.sh" monaco: - name: Monaco Editor checks + name: Monaco Editor runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 7ae944e4b043e5c84a687c401654b3e06b86182d Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 11 Dec 2020 14:19:23 -0800 Subject: [PATCH 0861/1837] load static renderers --- .../notebook/browser/diff/cellComponents.ts | 94 ++++++++-- .../notebook/browser/diff/cellOutputs.ts | 165 ++++++++++++++++++ .../contrib/notebook/browser/diff/common.ts | 2 + .../notebook/browser/diff/notebookDiff.css | 69 +++++++- .../browser/diff/notebookTextDiffEditor.ts | 23 ++- .../notebook/browser/notebookBrowser.ts | 1 - 6 files changed, 333 insertions(+), 21 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index a6c71a531c6..eebd011d88a 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -32,6 +32,9 @@ import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/noteb import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { renderCodicons } from 'vs/base/browser/codicons'; +import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/cellOutputs'; + +const RENDER_RICH_OUTPUT = true; const fixedEditorOptions: IEditorOptions = { padding: { @@ -82,7 +85,7 @@ class PropertyHeader extends Disposable { constructor( readonly cell: CellDiffViewModel, - readonly metadataHeaderContainer: HTMLElement, + readonly propertyHeaderContainer: HTMLElement, readonly notebookEditor: INotebookTextDiffEditor, readonly accessor: { updateInfoRendering: () => void; @@ -105,21 +108,21 @@ class PropertyHeader extends Disposable { buildHeader(): void { let metadataChanged = this.accessor.checkIfModified(this.cell); - this._foldingIndicator = DOM.append(this.metadataHeaderContainer, DOM.$('.property-folding-indicator')); + this._foldingIndicator = DOM.append(this.propertyHeaderContainer, DOM.$('.property-folding-indicator')); this._foldingIndicator.classList.add(this.accessor.prefix); this._updateFoldingIcon(); - const metadataStatus = DOM.append(this.metadataHeaderContainer, DOM.$('div.property-status')); + const metadataStatus = DOM.append(this.propertyHeaderContainer, DOM.$('div.property-status')); this._statusSpan = DOM.append(metadataStatus, DOM.$('span')); if (metadataChanged) { this._statusSpan.textContent = this.accessor.changedLabel; this._statusSpan.style.fontWeight = 'bold'; - this.metadataHeaderContainer.classList.add('modified'); + this.propertyHeaderContainer.classList.add('modified'); } else { this._statusSpan.textContent = this.accessor.unChangedLabel; } - const cellToolbarContainer = DOM.append(this.metadataHeaderContainer, DOM.$('div.property-toolbar')); + const cellToolbarContainer = DOM.append(this.propertyHeaderContainer, DOM.$('div.property-toolbar')); this._toolbar = new ToolBar(cellToolbarContainer, this.contextMenuService, { actionViewItemProvider: action => { if (action instanceof MenuItemAction) { @@ -190,7 +193,7 @@ class PropertyHeader extends Disposable { if (metadataChanged) { this._statusSpan.textContent = this.accessor.changedLabel; this._statusSpan.style.fontWeight = 'bold'; - this.metadataHeaderContainer.classList.add('modified'); + this.propertyHeaderContainer.classList.add('modified'); const actions: IAction[] = []; createAndFillInActionBarActions(this._menu, undefined, actions); this._toolbar.setActions(actions); @@ -222,6 +225,11 @@ abstract class AbstractCellRenderer extends Disposable { protected _outputHeader!: PropertyHeader; protected _outputInfoContainer!: HTMLElement; protected _outputEditorContainer?: HTMLElement; + protected _outputViewContainer?: HTMLElement; + protected _outputLeftContainer?: HTMLElement; + protected _outputRightContainer?: HTMLElement; + protected _outputLeftView?: OutputContainer; + protected _outputRightView?: OutputContainer; protected _outputEditorDisposeStore!: DisposableStore; protected _outputEditor?: CodeEditorWidget | DiffEditorWidget; @@ -300,15 +308,26 @@ abstract class AbstractCellRenderer extends Disposable { updateOutputRendering() { if (this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - this._outputInfoContainer.style.display = 'block'; + if (RENDER_RICH_OUTPUT) { + this._outputInfoContainer.style.display = 'block'; - if (!this._outputEditorContainer || !this._outputEditor) { - // create editor - this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); - this._buildOutputEditor(); + if (!this._outputViewContainer) { + this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); + this._buildOutputContainer(); + } else { + this.layout({ outputView: true }); + } } else { - this._layoutInfo.outputHeight = this._outputEditor.getContentHeight(); - this.layout({ outputEditor: true }); + this._outputInfoContainer.style.display = 'block'; + + if (!this._outputEditorContainer || !this._outputEditor) { + // create editor + this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); + this._buildOutputEditor(); + } else { + this._layoutInfo.outputHeight = this._outputEditor.getContentHeight(); + this.layout({ outputEditor: true }); + } } } else { this._outputInfoContainer.style.display = 'none'; @@ -318,6 +337,8 @@ abstract class AbstractCellRenderer extends Disposable { } } + abstract _buildOutputContainer(): void; + protected _getFormatedMetadataJSON(metadata: NotebookCellMetadata, language?: string) { let filteredMetadata: { [key: string]: any } = {}; @@ -638,7 +659,7 @@ abstract class AbstractCellRenderer extends Disposable { abstract styleContainer(container: HTMLElement): void; abstract updateSourceEditor(): void; abstract onDidLayoutChange(event: CellDiffViewModelLayoutChangeEvent): void; - abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }): void; + abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }): void; } abstract class SingleSideCell extends AbstractCellRenderer { @@ -779,7 +800,6 @@ abstract class SingleSideCell extends AbstractCellRenderer { this._register(this._outputHeader); this._outputHeader.buildHeader(); } - } export class DeletedCell extends SingleSideCell { private _editor!: CodeEditorWidget; @@ -872,6 +892,12 @@ export class DeletedCell extends SingleSideCell { this.layoutNotebookCell(); }); } + + _buildOutputContainer() { + // this._outputView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputViewContainer!); + // this._outputView.render(); + // this.layout({ outputView: true }); + } } export class InsertCell extends SingleSideCell { @@ -939,7 +965,13 @@ export class InsertCell extends SingleSideCell { } } - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }) { + _buildOutputContainer() { + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputViewContainer!); + this._outputLeftView.render(); + this.layout({ outputView: true }); + } + + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { this._editor.layout({ @@ -962,7 +994,15 @@ export class InsertCell extends SingleSideCell { }); } + if (state.outputView) { + this._layoutInfo.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; + } + this.layoutNotebookCell(); + + if (this._diagonalFill) { + this._diagonalFill.style.height = `${this._layoutInfo.editorHeight + this._layoutInfo.editorMargin + this._layoutInfo.metadataStatusHeight + this._layoutInfo.metadataHeight + this._layoutInfo.outputHeight + this._layoutInfo.outputStatusHeight}px`; + } }); } } @@ -1068,6 +1108,10 @@ export class ModifiedCell extends AbstractCellRenderer { return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); }; + if (checkIfOutputsModified(this.cell)) { + this._outputInfoContainer.classList.add('modified'); + } + if (checkIfOutputsModified(this.cell)) { this.cell.outputFoldingState = PropertyFoldingState.Expanded; } @@ -1098,6 +1142,17 @@ export class ModifiedCell extends AbstractCellRenderer { this._outputHeader.buildHeader(); } + _buildOutputContainer() { + this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left')); + this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right')); + // We should use the original text model here + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.original!, this._outputLeftContainer!); + this._outputLeftView.render(); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputRightContainer!); + this._outputRightView.render(); + + this.layout({ outputView: true }); + } updateSourceEditor(): void { const modifiedCell = this.cell.modified!; @@ -1202,7 +1257,7 @@ export class ModifiedCell extends AbstractCellRenderer { } } - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }) { + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight) { this._editorContainer.style.height = `${this._layoutInfo.editorHeight}px`; @@ -1231,6 +1286,11 @@ export class ModifiedCell extends AbstractCellRenderer { } } + if (state.outputView) { + this._layoutInfo.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); + } + + this.layoutNotebookCell(); }); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts new file mode 100644 index 00000000000..6ba1e204d3a --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts @@ -0,0 +1,165 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as DOM from 'vs/base/browser/dom'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { BUILTIN_RENDERER_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; + +export class OutputElement extends Disposable { + readonly resizeListener = new DisposableStore(); + domNode!: HTMLElement; + renderResult?: IRenderOutput; + + constructor( + private notebookEditor: INotebookTextDiffEditor, + private notebookTextModel: NotebookTextModel, + private notebookService: INotebookService, + // private viewCell: CodeCellViewModel, + private outputContainer: HTMLElement, + readonly output: ICellOutputViewModel + ) { + super(); + } + + render(beforeElement?: HTMLElement) { + const outputItemDiv = document.createElement('div'); + let result: IRenderOutput | undefined = undefined; + + if (this.output.isDisplayOutput()) { + const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookTextModel); + const pickedMimeTypeRenderer = mimeTypes[pick]; + const innerContainer = DOM.$('.output-inner-container'); + DOM.append(outputItemDiv, innerContainer); + + + if (pickedMimeTypeRenderer.rendererId !== BUILTIN_RENDERER_ID) { + const renderer = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId); + result = renderer + ? { type: RenderOutputType.Extension, renderer, source: this.output, mimeType: pickedMimeTypeRenderer.mimeType } + : this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.notebookTextModel.uri,); + } else { + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.notebookTextModel.uri); + } + + this.output.pickedMimeType = pick; + } else { + // for text and error, there is no mimetype + const innerContainer = DOM.$('.output-inner-container'); + DOM.append(outputItemDiv, innerContainer); + + result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.notebookTextModel.uri); + } + + this.domNode = outputItemDiv; + this.renderResult = result; + + if (!result) { + // this.viewCell.updateOutputHeight(index, 0); + return; + } + + if (beforeElement) { + this.outputContainer.insertBefore(outputItemDiv, beforeElement); + } else { + this.outputContainer.appendChild(outputItemDiv); + } + + if (result.type !== RenderOutputType.None) { + // this.viewCell.selfSizeMonitoring = true; + // this.notebookEditor.createInset(this.viewCell, result as any, this.viewCell.getOutputOffset(index)); + } else { + outputItemDiv.classList.add('foreground', 'output-element'); + outputItemDiv.style.position = 'absolute'; + } + + if (outputHasDynamicHeight(result)) { + // this.viewCell.selfSizeMonitoring = true; + + // const clientHeight = outputItemDiv.clientHeight; + // const dimension = { + // width: this.viewCell.layoutInfo.editorWidth, + // height: clientHeight + // }; + // const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { + // if (this.outputContainer && document.body.contains(this.outputContainer)) { + // const height = Math.ceil(elementSizeObserver.getHeight()); + + // if (clientHeight === height) { + // return; + // } + + // const currIndex = this.viewCell.outputsViewModels.indexOf(this.output); + // if (currIndex < 0) { + // return; + // } + + // this.viewCell.updateOutputHeight(currIndex, height); + // this.relayoutCell(); + // } + // }); + // elementSizeObserver.startObserving(); + // this.resizeListener.add(elementSizeObserver); + // this.viewCell.updateOutputHeight(index, clientHeight); + } else if (result.type === RenderOutputType.None) { // no-op if it's a webview + // const clientHeight = Math.ceil(outputItemDiv.clientHeight); + // this.viewCell.updateOutputHeight(index, clientHeight); + + // const top = this.viewCell.getOutputOffsetInContainer(index); + // outputItemDiv.style.top = `${top}px`; + } + } + +} + +export class OutputContainer extends Disposable { + private _outputViewModels: ICellOutputViewModel[]; + private outputEntries = new Map(); + constructor( + private _editor: INotebookTextDiffEditor, + private notebookTextModel: NotebookTextModel, + cell: NotebookCellTextModel, + private outputContainer: HTMLElement, + @INotebookService private notebookService: INotebookService, + // @IQuickInputService private readonly quickInputService: IQuickInputService, + @IOpenerService readonly openerService: IOpenerService, + @ITextFileService readonly textFileService: ITextFileService, + + ) { + super(); + this._outputViewModels = cell.outputs.map(output => new CellOutputViewModel(output, notebookService)); + + // TODO, onDidChangeOutputs + + // viewCell.onDidChangeLayout + // say the height of the cell editor changes + } + + render() { + // TODO, outputs to render (should have a limit) + for (let index = 0; index < this._outputViewModels.length; index++) { + const currOutput = this._outputViewModels[index]; + + // always add to the end + this._renderOutput(currOutput, index, undefined); + } + } + + private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { + if (!this.outputEntries.has(currOutput)) { + this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.outputContainer, currOutput)); + } + + this.outputEntries.get(currOutput)!.render(beforeElement); + + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 8fa33af9dbe..115173f8bac 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -12,6 +12,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; +import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -19,6 +20,7 @@ export interface INotebookTextDiffEditor { getOverflowContainerDomNode(): HTMLElement; getLayoutInfo(): NotebookLayoutInfo; layoutNotebookCell(cell: CellDiffViewModel, height: number): void; + getOutputRenderer(): OutputRenderer; } export interface CellDiffSingleSideRenderTemplate { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index 950cbce2f43..5866ea2c558 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -32,7 +32,8 @@ .notebook-text-diff-editor .cell-body .cell-diff-editor-container { width: 100%; - overflow: hidden; + /* why we overflow hidden at the beginning?*/ + /* overflow: hidden; */ } .notebook-text-diff-editor .cell-body .cell-diff-editor-container .metadata-editor-container.diff, @@ -106,6 +107,10 @@ overflow: hidden; } +.monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row { + overflow: visible !important; +} + .monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row, .monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover, .monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused { @@ -118,3 +123,65 @@ top: 16px; margin: 4px 2px; } + + + +.monaco-workbench .notebook-text-diff-editor .cell-body .output-view-container .output-inner-container { + /* overflow-x: scroll; */ + white-space: initial; +} + +.monaco-workbench .notebook-text-diff-editor .cell-body.left .output-view-container .output-inner-container, +.monaco-workbench .notebook-text-diff-editor .cell-body.right .output-view-container .output-inner-container { + width: calc(50% - 16px); + padding: 4px 8px; + box-sizing: border-box; +} +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-view-container .output-inner-container { + width: calc(100% - 16px); + padding: 4px 8px; + box-sizing: border-box; +} + +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-left, +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-right { + width: 50%; + display: inline-block; +} + +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-left, +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-right { + width: 50%; + position: relative; +} + +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-left div.foreground, +.monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-right div.foreground { + width: 100%; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container > div.foreground { + width: 100%; + min-height: 24px; + box-sizing: border-box; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container .error_message { + color: red; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container .error > div { + white-space: normal; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container .error pre.traceback { + margin: 8px 0; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container .error .traceback > span { + display: block; +} + +.monaco-workbench .notebook-text-diff-editor .output-view-container .display img { + max-width: 100%; +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 5c715b6d923..473e3cea78d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -24,7 +24,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; -import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -37,6 +37,7 @@ import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { IDiffChange } from 'vs/base/common/diff/diff'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; export const IN_NOTEBOOK_TEXT_DIFF_EDITOR = new RawContextKey('isInNotebookTextDiffEditor', false); @@ -55,6 +56,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD protected _scopeContextKeyService!: IContextKeyService; private _model: INotebookDiffEditorModel | null = null; private _modifiedResourceDisposableStore = new DisposableStore(); + private _outputRenderer: OutputRenderer; get textModel() { return this._model?.modified.notebook; @@ -79,6 +81,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._revealFirst = true; this._register(this._modifiedResourceDisposableStore); + // TODO + this._outputRenderer = new OutputRenderer(this as unknown as INotebookEditor, this.instantiationService); } protected createEditor(parent: HTMLElement): void { @@ -381,6 +385,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._list?.splice(0, this._list?.length || 0); } + getOutputRenderer(): OutputRenderer { + return this._outputRenderer; + } + getLayoutInfo(): NotebookLayoutInfo { if (!this._list) { throw new Error('Editor is not initalized successfully'); @@ -430,6 +438,11 @@ registerThemingParticipant((theme, collector) => { const added = theme.getColor(diffInserted); if (added) { + collector.addRule( + ` + .monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-right div.foreground { background-color: ${added}; } + ` + ); collector.addRule(` .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .source-container { background-color: ${added}; } .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .source-container .monaco-editor .margin, @@ -448,6 +461,7 @@ registerThemingParticipant((theme, collector) => { ); collector.addRule(` .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .output-editor-container { background-color: ${added}; } + .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .output-inner-container { background-color: ${added}; } .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .output-editor-container .monaco-editor .margin, .notebook-text-diff-editor .cell-body .cell-diff-editor-container.inserted .output-editor-container .monaco-editor .monaco-editor-background { background-color: ${added}; @@ -461,7 +475,12 @@ registerThemingParticipant((theme, collector) => { ); } const removed = theme.getColor(diffRemoved); - if (added) { + if (removed) { + collector.addRule( + ` + .monaco-workbench .notebook-text-diff-editor .cell-body.full .output-info-container.modified .output-view-container .output-view-container-left div.foreground { background-color: ${removed}; } + ` + ); collector.addRule(` .notebook-text-diff-editor .cell-body .cell-diff-editor-container.removed .source-container { background-color: ${removed}; } .notebook-text-diff-editor .cell-body .cell-diff-editor-container.removed .source-container .monaco-editor .margin, diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 60c9cf0f345..5c8a46f1063 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -164,7 +164,6 @@ export interface IDisplayOutputViewModel extends ICellOutputViewModel { model: ITransformedDisplayOutputDto; resolveMimeTypes(textModel: NotebookTextModel): [readonly IOrderedMimeType[], number]; pickedMimeType: number; - resolveMimeTypes(textModel: NotebookTextModel): [readonly IOrderedMimeType[], number]; } export interface IErrorOutputViewModel extends ICellOutputViewModel { From c5c6c8241134c319bb280cf025ed0e191979251a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Dec 2020 23:42:14 +0100 Subject: [PATCH 0862/1837] Add Windows --- .github/workflows/ci.yml | 100 ++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed377dc6f9b..fcca313b3dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,42 +208,62 @@ jobs: - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - - name: Run Unit and Integration Tests - run: DISPLAY=:10 yarn concurrently --names "unit-tests-electron,unit-tests-browser,integration-tests-electron" "./scripts/test.sh" "yarn test-browser --browser chromium" "./scripts/test-integration.sh" + - name: Run Unit Tests (Electron) + run: DISPLAY=:10 ./scripts/test.sh - # windows: - # runs-on: windows-2016 - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # - uses: actions/setup-python@v1 - # with: - # python-version: '2.x' - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: .\scripts\test.bat --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: yarn test-browser --browser chromium - # name: Run Unit Tests (Browser) - # - run: .\scripts\test-integration.bat --tfs "Integration Tests" - # name: Run Integration Tests (Electron) + - name: Run Unit Tests (Browser) + run: DISPLAY=:10 yarn test-browser --browser chromium + + - name: Run Integration Tests (Electron) + run: DISPLAY=:10 ./scripts/test-integration.sh + + windows: + name: Windows + runs-on: windows-latest + env: + CHILD_CONCURRENCY: "1" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - uses: actions/setup-python@v2 + with: + python-version: '2.x' + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Compile and Download + run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + + - name: Run Unit Tests (Electron) + run: .\scripts\test.bat + + - name: Run Unit Tests (Browser) + run: yarn test-browser --browser chromium + + - name: Run Integration Tests (Electron) + run: .\scripts\test-integration.bat darwin: name: macOS @@ -279,8 +299,14 @@ jobs: - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - - name: Run Unit and Integration Tests - run: DISPLAY=:10 yarn concurrently --names "unit-tests-electron,unit-tests-browser,integration-tests-electron" "./scripts/test.sh" "yarn test-browser --browser chromium" "./scripts/test-integration.sh" + - name: Run Unit Tests (Electron) + run: DISPLAY=:10 ./scripts/test.sh + + - name: Run Unit Tests (Browser) + run: DISPLAY=:10 yarn test-browser --browser chromium + + - name: Run Integration Tests (Electron) + run: DISPLAY=:10 ./scripts/test-integration.sh monaco: name: Monaco Editor From 70a67a1b8447e18a6d7d0ebc7e20dadbf363533a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Sat, 12 Dec 2020 00:08:35 +0100 Subject: [PATCH 0863/1837] Convert to use `for ... of` --- src/vs/editor/browser/view/viewImpl.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index b656a3f8ec6..bbd67d6a99e 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -330,8 +330,8 @@ export class View extends ViewEventHandler { this._viewLines.dispose(); // Destroy view parts - for (let i = 0, len = this._viewParts.length; i < len; i++) { - this._viewParts[i].dispose(); + for (const viewPart of this._viewParts) { + viewPart.dispose(); } super.dispose(); @@ -354,8 +354,7 @@ export class View extends ViewEventHandler { private _getViewPartsToRender(): ViewPart[] { let result: ViewPart[] = [], resultLen = 0; - for (let i = 0, len = this._viewParts.length; i < len; i++) { - const viewPart = this._viewParts[i]; + for (const viewPart of this._viewParts) { if (viewPart.shouldRender()) { result[resultLen++] = viewPart; } @@ -401,13 +400,11 @@ export class View extends ViewEventHandler { const renderingContext = new RenderingContext(this._context.viewLayout, viewportData, this._viewLines); // Render the rest of the parts - for (let i = 0, len = viewPartsToRender.length; i < len; i++) { - const viewPart = viewPartsToRender[i]; + for (const viewPart of viewPartsToRender) { viewPart.prepareRender(renderingContext); } - for (let i = 0, len = viewPartsToRender.length; i < len; i++) { - const viewPart = viewPartsToRender[i]; + for (const viewPart of viewPartsToRender) { viewPart.render(renderingContext); viewPart.onDidRender(); } @@ -462,8 +459,7 @@ export class View extends ViewEventHandler { if (everything) { // Force everything to render... this._viewLines.forceShouldRender(); - for (let i = 0, len = this._viewParts.length; i < len; i++) { - const viewPart = this._viewParts[i]; + for (const viewPart of this._viewParts) { viewPart.forceShouldRender(); } } From f30948328de20391d7703937ecc02e6780d06924 Mon Sep 17 00:00:00 2001 From: Chris Dias Date: Fri, 11 Dec 2020 15:08:57 -0800 Subject: [PATCH 0864/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18e620a5363..7d9da490d1f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "b1d4d66f8f5734c216ae6288c36660e81511706b", + "distro": "25d6e2bec6a5bf41f26c0f1c164b8e75f441a057", "author": { "name": "Microsoft Corporation" }, From a9bf16e00192e5da6b1067667a0b55a4593bcc5f Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Dec 2020 15:15:25 -0800 Subject: [PATCH 0865/1837] testing: base test explorer --- src/vs/vscode.proposed.d.ts | 12 +- .../api/browser/mainThreadTesting.ts | 4 + src/vs/workbench/api/common/extHostTesting.ts | 35 +- .../api/common/extHostTypeConverters.ts | 4 +- src/vs/workbench/api/common/extHostTypes.ts | 11 +- .../contrib/testing/browser/icons.ts | 16 + .../contrib/testing/browser/media/testing.css | 42 ++ .../testing/browser/testExplorerActions.ts | 87 ++++ .../testing/browser/testing.contribution.ts | 54 +++ .../browser/testingCollectionService.ts | 276 ++++++++++++ .../testing/browser/testingExplorerView.ts | 394 ++++++++++++++++++ .../browser/testingViewPaneContainer.ts | 49 +++ .../contrib/testing/common/testCollection.ts | 8 +- .../contrib/testing/common/testService.ts | 3 + .../contrib/testing/common/testServiceImpl.ts | 36 +- .../contrib/testing/common/testViews.ts | 6 + .../testing/common/testingContextKeys.ts | 10 + 17 files changed, 1020 insertions(+), 27 deletions(-) create mode 100644 src/vs/workbench/contrib/testing/browser/icons.ts create mode 100644 src/vs/workbench/contrib/testing/browser/media/testing.css create mode 100644 src/vs/workbench/contrib/testing/browser/testExplorerActions.ts create mode 100644 src/vs/workbench/contrib/testing/browser/testingCollectionService.ts create mode 100644 src/vs/workbench/contrib/testing/browser/testingExplorerView.ts create mode 100644 src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.ts create mode 100644 src/vs/workbench/contrib/testing/common/testViews.ts create mode 100644 src/vs/workbench/contrib/testing/common/testingContextKeys.ts diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 19e8d8f1032..50649100004 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2211,16 +2211,18 @@ declare module 'vscode' { export enum TestRunState { // Initial state Unset = 0, + // Test will be run, but is not currently running. + Queued = 1, // Test is currently running - Running = 1, + Running = 2, // Test run has passed - Passed = 2, + Passed = 3, // Test run has failed (on an assertion) - Failed = 3, + Failed = 4, // Test run has been skipped - Skipped = 4, + Skipped = 5, // Test run failed for some other reason (compilation error, timeout, etc) - Errored = 5 + Errored = 6 } /** diff --git a/src/vs/workbench/api/browser/mainThreadTesting.ts b/src/vs/workbench/api/browser/mainThreadTesting.ts index 52185f8dd91..825c4f7b818 100644 --- a/src/vs/workbench/api/browser/mainThreadTesting.ts +++ b/src/vs/workbench/api/browser/mainThreadTesting.ts @@ -23,6 +23,10 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostTesting); this._register(this.testService.onShouldSubscribe(args => this.proxy.$subscribeToTests(args.resource, args.uri))); this._register(this.testService.onShouldUnsubscribe(args => this.proxy.$unsubscribeFromTests(args.resource, args.uri))); + + for (const { resource, uri } of this.testService.subscriptions) { + this.proxy.$subscribeToTests(resource, uri); + } } /** diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index 02fc32cbffb..8b8cf915b28 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -28,7 +28,11 @@ export class ExtHostTesting implements ExtHostTestingShape { private readonly providers = new Map(); private readonly proxy: MainThreadTestingShape; private readonly ownedTests = new OwnedTestCollection(); - private readonly testSubscriptions = new Map(); + private readonly testSubscriptions = new Map void; + }>(); private workspaceObservers: WorkspaceFolderTestObserverFactory; private textDocumentObservers: TextDocumentTestObserverFactory; @@ -47,6 +51,14 @@ export class ExtHostTesting implements ExtHostTestingShape { this.providers.set(providerId, provider); this.proxy.$registerTestProvider(providerId); + // give the ext a moment to register things rather than synchronously invoking within activate() + const toSubscribe = [...this.testSubscriptions.keys()]; + setTimeout(() => { + for (const subscription of toSubscribe) { + this.testSubscriptions.get(subscription)?.subscribeFn(providerId, provider); + } + }, 0); + return new Disposable(() => { this.providers.delete(providerId); this.proxy.$unregisterTestProvider(providerId); @@ -89,7 +101,7 @@ export class ExtHostTesting implements ExtHostTestingShape { * Handles a request to read tests for a file, or workspace. * @override */ - public $subscribeToTests(resource: ExtHostTestingResource, uriComponents: UriComponents) { + public async $subscribeToTests(resource: ExtHostTestingResource, uriComponents: UriComponents) { const uri = URI.revive(uriComponents); const subscriptionKey = getTestSubscriptionKey(resource, uri); if (this.testSubscriptions.has(subscriptionKey)) { @@ -103,7 +115,7 @@ export class ExtHostTesting implements ExtHostTestingShape { method = p => p.createDocumentTestHierarchy?.(document.document); } } else { - const folder = this.workspace.getWorkspaceFolder(uri, false); + const folder = await this.workspace.getWorkspaceFolder2(uri, false); if (folder) { method = p => p.createWorkspaceTestHierarchy?.(folder); } @@ -113,13 +125,11 @@ export class ExtHostTesting implements ExtHostTestingShape { return; } - const disposable = new DisposableStore(); - const collection = disposable.add(this.ownedTests.createForHierarchy(diff => this.proxy.$publishDiff(resource, uriComponents, diff))); - for (const [id, provider] of this.providers) { + const subscribeFn = (id: string, provider: vscode.TestProvider) => { try { - const hierarchy = method(provider); + const hierarchy = method!(provider); if (!hierarchy) { - continue; + return; } disposable.add(hierarchy); @@ -128,9 +138,15 @@ export class ExtHostTesting implements ExtHostTestingShape { } catch (e) { console.error(e); } + }; + + const disposable = new DisposableStore(); + const collection = disposable.add(this.ownedTests.createForHierarchy(diff => this.proxy.$publishDiff(resource, uriComponents, diff))); + for (const [id, provider] of this.providers) { + subscribeFn(id, provider); } - this.testSubscriptions.set(subscriptionKey, { store: disposable, collection }); + this.testSubscriptions.set(subscriptionKey, { store: disposable, collection, subscribeFn }); } /** @@ -296,7 +312,6 @@ export class SingleUseTestCollection implements IDisposable { this.testIdToInternal.delete(item.id); } - this.testIdToInternal.clear(); this.diff = []; this.disposed = true; } diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index d80dfae4b0c..ee4a7197a3c 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1393,9 +1393,9 @@ export namespace TestItem { return { label: item.label, location: item.location ? location.from(item.location) : undefined, - debuggable: item.debuggable, + debuggable: item.debuggable ?? false, description: item.description, - runnable: item.runnable, + runnable: item.runnable ?? true, state: TestState.from(item.state), }; } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 069c565836e..e01c9270d39 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2924,11 +2924,12 @@ export class LinkedEditingRanges { //#region Testing export enum TestRunState { Unset = 0, - Running = 1, - Passed = 2, - Failed = 3, - Skipped = 4, - Errored = 5 + Queued = 1, + Running = 2, + Passed = 3, + Failed = 4, + Skipped = 5, + Errored = 6 } export enum TestMessageSeverity { diff --git a/src/vs/workbench/contrib/testing/browser/icons.ts b/src/vs/workbench/contrib/testing/browser/icons.ts new file mode 100644 index 00000000000..4ba154715eb --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/icons.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + + +export const testingViewIcon = registerIcon('testing-view-icon', Codicon.beaker, localize('testingViewIcon', 'View icon of the testing view.')); +export const testingRunIcon = registerIcon('testing-run-icon', Codicon.debugStart, localize('testingRunIcon', 'Icon of the "run test" action.')); +export const testingDebugIcon = registerIcon('testing-debug-icon', Codicon.debugAlt, localize('testingDebugIcon', 'Icon of the "debug test" action.')); + +export const testingShowAsList = registerIcon('testing-show-as-list-icon', Codicon.listTree, localize('testingShowAsList', 'Icon shown when the test explorer is disabled as a tree.')); +export const testingShowAsTree = registerIcon('testing-show-as-list-icon', Codicon.listFlat, localize('testingShowAsTree', 'Icon shown when the test explorer is disabled as a list.')); diff --git a/src/vs/workbench/contrib/testing/browser/media/testing.css b/src/vs/workbench/contrib/testing/browser/media/testing.css new file mode 100644 index 00000000000..74623396875 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/media/testing.css @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.test-explorer .test-item { + display: flex; +} + +.test-explorer .monaco-list-row .monaco-action-bar { + display: none; + flex-shrink: 0; + margin-right: 1px; +} + +.test-explorer .monaco-list-row:hover .monaco-action-bar { + display: initial; +} + +.test-explorer .name { + overflow: hidden; + text-overflow: ellipsis; + flex-grow: 1; + height: 22px; + align-items: center; +} + +.test-explore .codicon { + line-height: 22px; + margin-right: 2px; +} + +.monaco-workbench + .test-explorer + .monaco-action-bar + .action-item + > .action-label { + width: 16px; + height: 100%; + line-height: 22px; + margin-right: 8px; +} diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts new file mode 100644 index 00000000000..2e8fecb180a --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { Action } from 'vs/base/common/actions'; +import { Event } from 'vs/base/common/event'; +import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import * as icons from 'vs/workbench/contrib/testing/browser/icons'; +import { ITestSubscriptionItem } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; + +export class DebugAction extends Action { + constructor( + private readonly test: ITestSubscriptionItem, + @ITestService private readonly testService: ITestService + ) { + super( + 'action.run', + localize('debug test', 'Debug Test'), + 'test-action ' + ThemeIcon.asClassName(icons.testingDebugIcon), + /* enabled= */ test.item.state.runState !== TestRunState.Running + ); + } + + public run(): Promise { + return this.testService.runTests({ + tests: [{ testId: this.test.id, providerId: this.test.providerId }], + debug: false, + }); + } +} + +export class RunAction extends Action { + constructor( + private readonly test: ITestSubscriptionItem, + @ITestService private readonly testService: ITestService + ) { + super( + 'action.run', + localize('run test', 'Run Test'), + 'test-action ' + ThemeIcon.asClassName(icons.testingRunIcon), + /* enabled= */ test.item.state.runState !== TestRunState.Running, + ); + } + + public run(): Promise { + return this.testService.runTests({ + tests: [{ testId: this.test.id, providerId: this.test.providerId }], + debug: false, + }); + } +} + +export const enum ViewMode { + List, + Tree +} + + +export class ToggleViewModeAction extends Action { + static readonly ID = 'workbench.testing.action.toggleViewMode'; + static readonly LABEL = localize('toggleViewMode', "Toggle View Mode"); + + constructor(private readonly viewModel: { viewMode: ViewMode, onViewModeChange: Event }) { + super( + 'workbench.testing.action.toggleViewMode', + localize('toggleViewMode', "Toggle View Mode"), + ); + this._register(viewModel.onViewModeChange(this.onDidChangeMode, this)); + this.onDidChangeMode(this.viewModel.viewMode); + } + + async run(): Promise { + this.viewModel.viewMode = this.viewModel.viewMode === ViewMode.List + ? ViewMode.Tree + : ViewMode.List; + } + + private onDidChangeMode(mode: ViewMode): void { + const iconClass = ThemeIcon.asClassName(mode === ViewMode.List ? icons.testingShowAsList : icons.testingShowAsTree); + this.class = iconClass; + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts index 4e541bc83e8..8cc6f3b959f 100644 --- a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -3,8 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as ViewContainerExtensions, IViewContainersRegistry, IViewsRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; +import { testingViewIcon } from 'vs/workbench/contrib/testing/browser/icons'; +import { ITestingCollectionService, TestingCollectionService } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { TestingExplorerView, TESTING_EXPLORER_VIEW_ID } from 'vs/workbench/contrib/testing/browser/testingExplorerView'; +import { TestingViewPaneContainer } from 'vs/workbench/contrib/testing/browser/testingViewPaneContainer'; +import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; import { TestService } from 'vs/workbench/contrib/testing/common/testServiceImpl'; +import { TESTING_VIEWLET_ID } from 'vs/workbench/contrib/testing/common/testViews'; registerSingleton(ITestService, TestService); +registerSingleton(ITestingCollectionService, TestingCollectionService); + +const viewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ + id: TESTING_VIEWLET_ID, + name: localize('testing', "Testing"), + ctorDescriptor: new SyncDescriptor(TestingViewPaneContainer), + icon: testingViewIcon, + alwaysUseContainerInfo: true, + order: 5, + hideIfEmpty: true, +}, ViewContainerLocation.Sidebar); + + +const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); + +viewsRegistry.registerViewWelcomeContent(TESTING_EXPLORER_VIEW_ID, { + content: localize('noTestProvidersRegistered', "No test providers are registered for this workspace."), +}); + +viewsRegistry.registerViewWelcomeContent(TESTING_EXPLORER_VIEW_ID, { + content: localize( + { + key: 'searchMarketplaceForTestExtensions', + comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'], + }, + "[Search Marketplace](command:{0})", + `workbench.extensions.search?${encodeURIComponent(JSON.stringify(['@tag:testing']))}` + ), +}); + +viewsRegistry.registerViews([{ + id: TESTING_EXPLORER_VIEW_ID, + name: localize('testExplorer', "Test Explorer"), + ctorDescriptor: new SyncDescriptor(TestingExplorerView), + canToggleVisibility: true, + workspace: true, + canMoveView: true, + weight: 80, + order: -999, + containerIcon: testingViewIcon, + // temporary until release, at which point we can show the welcome view: + when: ContextKeyExpr.greater(TestingContextKeys.providerCount.serialize(), 0), +}], viewContainer); diff --git a/src/vs/workbench/contrib/testing/browser/testingCollectionService.ts b/src/vs/workbench/contrib/testing/browser/testingCollectionService.ts new file mode 100644 index 00000000000..338256bda13 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testingCollectionService.ts @@ -0,0 +1,276 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { debounce } from 'vs/base/common/decorators'; +import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; +import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; + +export const isTestItem = (v: ITestSubscriptionItem | ITestSubscriptionFolder): v is ITestSubscriptionItem => v.depth > 0; + +export interface ITestSubscriptionFolder { + depth: 0; + folder: IWorkspaceFolder; + childCount: number; + getChildren(): Iterable; +} + +export interface ITestSubscriptionItem extends IncrementalTestCollectionItem { + depth: number; + getChildren(): Iterable; + childCount: number; + root: ITestSubscriptionFolder; + parentItem: ITestSubscriptionItem | ITestSubscriptionFolder; +} + +export interface ITestSubscription { + add(node: ITestSubscriptionItem | ITestSubscriptionFolder): void; + update(node: ITestSubscriptionItem | ITestSubscriptionFolder): void; + remove(node: ITestSubscriptionItem | ITestSubscriptionFolder): void; +} + +/** + * Maintains an observable set of tests in the core. + */ +export interface ITestingCollectionService { + readonly _serviceBrand: undefined; + + /** + * Gets the current tests. Will only be non-zero if there's at least one + * active subscriber/ + */ + readonly count: number; + + /** + * Gets all workspace folders we're listening to. + */ + workspaceFolders(): ReadonlyArray; + + /** + * Adds a listener that receives updates about tests. + */ + subscribeToWorkspaceTests(collector: ITestSubscription): IDisposable; +} + +export const ITestingCollectionService = createDecorator('ITestingViewService'); + +export class TestingCollectionService implements ITestingCollectionService { + declare _serviceBrand: undefined; + + private subscription?: TestSubscription; + + public workspaceFolders() { + return this.subscription?.workspaceFolders || []; + } + + constructor(@IInstantiationService protected instantiationService: IInstantiationService) { } + + /** + * @inheritdoc + */ + public get count() { + return this.subscription?.testCount || 0; + } + + /** + * @inheritdoc + */ + public subscribeToWorkspaceTests(listener: ITestSubscription): IDisposable { + if (!this.subscription) { + this.subscription = this.instantiationService.createInstance(TestSubscription); + } + + this.subscription.addListener(listener); + return toDisposable(() => { + if (!this.subscription) { + return; + } + + this.subscription.removeListener(listener); + if (this.subscription.listenerCount === 0) { + this.debounceDispose(); + } + }); + } + + @debounce(10_0000) + private debounceDispose() { + if (this.subscription && this.subscription.listenerCount === 0) { + this.subscription.dispose(); + this.subscription = undefined; + } + } +} + + +class TestSubscription extends Disposable { + private listeners = new Set(); + private readonly collectionsForWorkspaces = new Map(); + public testCount = 0; + + public get listenerCount() { + return this.listeners.size; + } + + public get workspaceFolders() { + return [...this.collectionsForWorkspaces.values()].map(v => v.folder); + } + + constructor( + @IWorkspaceContextService workspaceContext: IWorkspaceContextService, + @ITestService private readonly testService: ITestService, + ) { + super(); + + this._register(toDisposable(() => { + for (const { listener } of this.collectionsForWorkspaces.values()) { + listener.dispose(); + } + })); + + this._register(workspaceContext.onDidChangeWorkspaceFolders(evt => { + for (const folder of evt.added) { + this.subscribeToWorkspace(folder); + } + + for (const folder of evt.removed) { + const existing = this.collectionsForWorkspaces.get(folder.uri.toString()); + if (existing) { + this.collectionsForWorkspaces.delete(folder.uri.toString()); + existing.listener.dispose(); + for (const listener of this.listeners) { + listener.remove(existing.folder); + } + } + } + })); + + for (const folder of workspaceContext.getWorkspace().folders) { + this.subscribeToWorkspace(folder); + } + } + + public addListener(listener: ITestSubscription) { + this.listeners.add(listener); + for (const { collection, folder } of this.collectionsForWorkspaces.values()) { + listener.add(folder); + + const queue = [collection.rootNodes]; + while (queue.length) { + for (const node of queue.pop()!) { + listener.add(collection.getNodeById(node)!); + } + } + } + } + + public removeListener(listener: ITestSubscription) { + this.listeners.delete(listener); + } + + private subscribeToWorkspace(folder: IWorkspaceFolder) { + const folderNode: ITestSubscriptionFolder = { + folder, + depth: 0, + get childCount() { + return collection.rootNodes.size; + }, + getChildren: function* () { + for (const rootId of collection.rootNodes) { + const node = collection.getNodeById(rootId); + if (node) { + yield node; + } + } + }, + }; + + const collection = new TestCollection(folderNode, { + add: node => { + this.testCount++; + for (const listener of this.listeners) { + listener.add(node); + } + }, + remove: (node, isNested) => { + this.testCount--; + if (!isNested) { + for (const listener of this.listeners) { + listener.remove(node); + } + } + }, + update: node => { + for (const listener of this.listeners) { + listener.update(node); + } + }, + complete: () => { + // no-op + }, + }); + + for (const listener of this.listeners) { + listener.add(folderNode); + } + + const listener = this.testService.subscribeToDiffs( + ExtHostTestingResource.Workspace, + folder.uri, + diff => collection.apply(diff), + ); + + this.collectionsForWorkspaces.set(folder.uri.toString(), { listener, collection, folder: folderNode }); + } +} + +class TestCollection extends AbstractIncrementalTestCollection { + constructor(private readonly workspace: ITestSubscriptionFolder, private readonly collector: IncrementalChangeCollector) { + super(); + } + + public get rootNodes() { + return this.roots; + } + + public getNodeById(id: string) { + return this.items.get(id); + } + + protected createChangeCollector() { + return this.collector; + } + + protected createItem(internal: InternalTestItem, parentItem?: ITestSubscriptionItem): ITestSubscriptionItem { + const children = new Set(); + const items = this.items; + const actualParent = parentItem || this.workspace; + return { + ...internal, + depth: actualParent.depth + 1, + parentItem: actualParent, + root: this.workspace, + get childCount() { + return children.size; + }, + getChildren: function* () { + for (const childId of children) { + const node = items.get(childId); + if (node) { + yield node; + } + } + }, + children: children, + }; + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts new file mode 100644 index 00000000000..5e9a0f28166 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -0,0 +1,394 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as dom from 'vs/base/browser/dom'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; +import { ICompressedTreeElement, ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { ICompressibleKeyboardNavigationLabelProvider, ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; +import { ITreeFilter, ITreeNode, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; +import { Emitter } from 'vs/base/common/event'; +import { createMatches, FuzzyScore } from 'vs/base/common/filters'; +import { Iterable } from 'vs/base/common/iterator'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import 'vs/css!./media/testing'; +import { localize } from 'vs/nls'; +import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { MenuItemAction } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { FileKind } from 'vs/platform/files/common/files'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { WorkbenchCompressibleObjectTree } from 'vs/platform/list/browser/listService'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IResourceLabel, IResourceLabelOptions, IResourceLabelProps, ResourceLabels } from 'vs/workbench/browser/labels'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; +import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { isTestItem, ITestingCollectionService, ITestSubscriptionFolder, ITestSubscriptionItem } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { DebugAction, RunAction, ToggleViewModeAction, ViewMode } from './testExplorerActions'; + +export const TESTING_EXPLORER_VIEW_ID = 'workbench.view.testing'; + +export class TestingExplorerView extends ViewPane { + private listContainer!: HTMLElement; + private tree!: WorkbenchCompressibleObjectTree; + private filter!: TestsFilter; + private toggleViewModeAction!: ToggleViewModeAction; + private currentSubscription?: IDisposable; + private _viewMode = Number(this.storageService.get('testing.viewMode', StorageScope.WORKSPACE, String(ViewMode.Tree))) as ViewMode; + private viewModeChangeEmitter = new Emitter(); + + /** + * Fires when the tree view mode changes. + */ + public readonly onViewModeChange = this.viewModeChangeEmitter.event; + + public get viewMode() { + return this._viewMode; + } + + public set viewMode(newMode: ViewMode) { + if (newMode === this._viewMode) { + return; + } + + this._viewMode = newMode; + for (const folder of this.testCollection.workspaceFolders()) { + if (newMode === ViewMode.Tree) { + this.renderTreeChildren(folder); + } else { + this.renderListChildren(folder); + } + } + + this.storageService.store('testing.viewMode', newMode, StorageScope.WORKSPACE, StorageTarget.USER); + this.viewModeChangeEmitter.fire(newMode); + } + + constructor( + options: IViewletViewOptions, + @ITestingCollectionService private readonly testCollection: ITestingCollectionService, + @ITestService private readonly testService: ITestService, + @IEditorService private readonly _editorService: IEditorService, + @IStorageService private readonly storageService: IStorageService, + @IContextMenuService contextMenuService: IContextMenuService, + @IKeybindingService keybindingService: IKeybindingService, + @IConfigurationService configurationService: IConfigurationService, + @IInstantiationService instantiationService: IInstantiationService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, + @IOpenerService openerService: IOpenerService, + @IThemeService themeService: IThemeService, + @ITelemetryService telemetryService: ITelemetryService, + ) { + super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); + this._register(testService.onDidChangeProviders(() => this._onDidChangeViewWelcomeState.fire())); + this.toggleViewModeAction = this._register(new ToggleViewModeAction(this)); + } + + /** + * @override + */ + public shouldShowWelcome() { + return this.testService.providers === 0; + } + + /** + * @override + */ + protected renderBody(container: HTMLElement): void { + super.renderBody(container); + + const labels = this._register(this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility })); + + this.filter = new TestsFilter(); + this.listContainer = dom.append(container, dom.$('.test-explorer')); + this.tree = this.instantiationService.createInstance( + WorkbenchCompressibleObjectTree, + 'Test Explorer List', + this.listContainer, + new ListDelegate(), + [ + this.instantiationService.createInstance(TestsRenderer, labels, this) + ], + { + identityProvider: this.instantiationService.createInstance(IdentityProvider), + hideTwistiesOfChildlessElements: true, + sorter: this.instantiationService.createInstance(TreeSorter), + keyboardNavigationLabelProvider: this.instantiationService.createInstance(TreeKeyboardNavigationLabelProvider), + accessibilityProvider: this.instantiationService.createInstance(ListAccessibilityProvider), + filter: this.filter, + }) as WorkbenchCompressibleObjectTree; + + this._register(this.tree); + + this._register(this.tree.onDidChangeSelection(evt => { + const [first] = evt.elements; + if (!first || !isTestItem(first) || !first.item.location) { + return; + } + + this._editorService.openEditor({ + resource: URI.revive(first.item.location.uri), + options: { selection: first.item.location.range, preserveFocus: true } + }); + })); + + + this._register(this.onDidChangeBodyVisibility(visible => { + if (!visible && this.currentSubscription) { + this.currentSubscription.dispose(); + this.currentSubscription = undefined; + } else if (visible && !this.currentSubscription) { + this.currentSubscription = this.createSubscription(); + } + })); + } + + /** + * @override + */ + public getActions() { + return [this.toggleViewModeAction, ...super.getActions()]; + } + + /** + * @override + */ + protected layoutBody(height: number, width: number): void { + super.layoutBody(height, width); + this.tree.layout(height, width); + } + + /** + * Renders children of the node as a tree. + */ + private renderTreeChildren(node: TreeElement) { + this.tree.setChildren(node, Iterable.map(node.getChildren(), renderElement)); + } + + /** + * Renders the tests in a folder as a list. Effectively, this filters + * non-runnable nodes from the test tree, and shows the runnable leaf nodes + * in the list. + */ + private renderListChildren(node: ITestSubscriptionFolder) { + const leafNodes: ICompressedTreeElement[] = []; + + // returns true if the current node is a runnable leaf, or one of its children is + const traverse = (node: ITestSubscriptionItem): boolean => { + let hadRunnableLeaf = false; + for (const child of node.getChildren()) { + if (traverse(child)) { + hadRunnableLeaf = true; + } + } + + if (hadRunnableLeaf) { + return true; + } + + if (node.item.runnable || node.item.debuggable) { + leafNodes.push({ element: node }); + return true; + } + + return false; + }; + + for (const child of node.getChildren()) { + traverse(child); + } + + this.tree.setChildren(node, leafNodes); + } + + private createSubscription() { + const updateParent = (node: TreeElement) => { + if (!isTestItem(node)) { + this.tree.setChildren(null, Iterable.map(this.testCollection.workspaceFolders(), renderElement)); + } else if (this.viewMode === ViewMode.Tree) { + this.renderTreeChildren(node.parentItem); + } else { + this.renderListChildren(node.root); + } + }; + + return this.testCollection.subscribeToWorkspaceTests({ + add: updateParent, + remove: updateParent, + update: node => this.tree.rerender(node) + }); + } +} + +const renderElement = (item: TreeElement): ICompressedTreeElement => { + return { + element: item, + children: Iterable.map(item.getChildren(), renderElement), + incompressible: item.depth > 2, // compress workspace folders (0) and provider roots (1) + }; +}; + +const getLabel = (item: TreeElement) => isTestItem(item) ? item.item.label : item.folder.name; + +class TestsFilter implements ITreeFilter { + private filterText: string | undefined; + + public setFilter(filterText: string) { + this.filterText = filterText; + } + + public filter(element: TreeElement): TreeFilterResult { + if (!this.filterText) { + return TreeVisibility.Visible; + } + + if (getLabel(element).includes(this.filterText)) { + return TreeVisibility.Visible; + } + + return element.childCount ? TreeVisibility.Recurse : TreeVisibility.Hidden; + } +} + +type TreeElement = ITestSubscriptionFolder | ITestSubscriptionItem; + +class TreeSorter implements ITreeSorter { + public compare(a: TreeElement, b: TreeElement): number { + return getLabel(a).localeCompare(getLabel(b)); + } +} + +class ListAccessibilityProvider implements IListAccessibilityProvider { + getWidgetAriaLabel(): string { + return localize('testExplorer', "Test Explorer"); + } + + getAriaLabel(element: TreeElement): string { + return getLabel(element); + } +} + +class TreeKeyboardNavigationLabelProvider implements ICompressibleKeyboardNavigationLabelProvider { + getKeyboardNavigationLabel(element: TreeElement) { + return getLabel(element); + } + + getCompressedNodeKeyboardNavigationLabel(elements: TreeElement[]) { + return elements.map(getLabel).join('/'); + } +} + +class ListDelegate implements IListVirtualDelegate { + getHeight(_element: TreeElement) { + return 22; + } + + getTemplateId(_element: TreeElement) { + return TestsRenderer.ID; + } +} + +class IdentityProvider implements IIdentityProvider { + public getId(element: TreeElement) { + return isTestItem(element) ? `test:${element.id}` : `folder:${element.folder.index}`; + } +} + +interface TestTemplateData { + label: IResourceLabel; + actionBar: ActionBar; +} + +class TestsRenderer implements ICompressibleTreeRenderer { + public static readonly ID = 'testExplorer'; + + constructor( + private labels: ResourceLabels, + private readonly view: TestingExplorerView, + @IInstantiationService private readonly instantiationService: IInstantiationService + ) { } + + get templateId(): string { + return TestsRenderer.ID; + } + + public renderTemplate(container: HTMLElement): TestTemplateData { + const wrapper = dom.append(container, dom.$('.test-item')); + + const name = dom.append(wrapper, dom.$('.name')); + const label = this.labels.create(name, { supportHighlights: true }); + + const actionBar = new ActionBar(wrapper, { + actionViewItemProvider: action => + action instanceof MenuItemAction + ? this.instantiationService.createInstance(MenuEntryActionViewItem, action) + : undefined + }); + + return { label, actionBar }; + } + + public renderElement(node: ITreeNode, index: number, data: TestTemplateData): void { + const element = node.element; + this.render(element, getLabel(element), data, node.filterData); + } + + public renderCompressedElements(node: ITreeNode, FuzzyScore>, index: number, data: TestTemplateData): void { + const element = node.element.elements[node.element.elements.length - 1]; + this.render(element, getLabel(element), data, node.filterData); + } + + private render(element: TreeElement, labels: string | string[], data: TestTemplateData, filterData: FuzzyScore | undefined) { + const label: IResourceLabelProps = { + name: labels, + }; + const options: IResourceLabelOptions = {}; + data.actionBar.clear(); + + if (isTestItem(element)) { + if (element.item.location) { + label.resource = URI.revive(element.item.location.uri); + } + + options.title = 'hover title'; + options.fileKind = FileKind.FILE; + + if (element.item.runnable) { + data.actionBar.push(this.instantiationService.createInstance(RunAction, element), { icon: true, label: false }); + } + + if (element.item.debuggable) { + data.actionBar.push(this.instantiationService.createInstance(DebugAction, element), { icon: true, label: false }); + } + + if (this.view.viewMode === ViewMode.List && element.depth > 1) { + label.description = getLabel(element.parentItem); + } + } else { + options.fileKind = FileKind.ROOT_FOLDER; + } + + + options.matches = createMatches(filterData); + data.label.setResource(label, options); + } + + disposeTemplate(templateData: TestTemplateData): void { + templateData.label.dispose(); + templateData.actionBar.dispose(); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.ts b/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.ts new file mode 100644 index 00000000000..2712086cc8f --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { TESTING_VIEWLET_ID } from 'vs/workbench/contrib/testing/common/testViews'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; + +export class TestingViewPaneContainer extends ViewPaneContainer { + + constructor( + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @ITelemetryService telemetryService: ITelemetryService, + @IInstantiationService instantiationService: IInstantiationService, + @IContextMenuService contextMenuService: IContextMenuService, + @IThemeService themeService: IThemeService, + @IStorageService storageService: IStorageService, + @IConfigurationService configurationService: IConfigurationService, + @IExtensionService extensionService: IExtensionService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + ) { + super(TESTING_VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); + } + + create(parent: HTMLElement): void { + super.create(parent); + parent.classList.add('testing-view-pane'); + } + + getOptimalWidth(): number { + return 400; + } + + getTitle(): string { + return localize('testing', "Testing"); + } +} diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index ab76dab7311..e2c3c57c865 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -61,8 +61,8 @@ export interface ITestItem { children?: never; location: ModeLocation | undefined; description: string | undefined; - runnable: boolean | undefined; - debuggable: boolean | undefined; + runnable: boolean; + debuggable: boolean; state: ITestState; } @@ -127,7 +127,7 @@ export class IncrementalChangeCollector { /** * A node was removed. */ - public remove(node: T): void { } + public remove(node: T, isNestedOperation: boolean): void { } /** * Called when the diff has been applied. @@ -204,7 +204,7 @@ export abstract class AbstractIncrementalTestCollection; readonly onShouldUnsubscribe: Event<{ resource: ExtHostTestingResource, uri: URI }>; + readonly onDidChangeProviders: Event<{ delta: number }>; + readonly providers: number; + readonly subscriptions: ReadonlyArray<{ resource: ExtHostTestingResource, uri: URI }>; registerTestController(id: string, controller: MainTestController): void; unregisterTestController(id: string): void; runTests(req: RunTestsRequest): Promise; diff --git a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts index 845534dd816..7aeb2c890ad 100644 --- a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts +++ b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts @@ -8,8 +8,10 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { isDefined } from 'vs/base/common/types'; import { URI, UriComponents } from 'vs/base/common/uri'; +import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; import { AbstractIncrementalTestCollection, collectTestResults, getTestSubscriptionKey, IncrementalTestCollectionItem, InternalTestItem, RunTestsRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestService, MainTestController, TestDiffListener } from 'vs/workbench/contrib/testing/common/testService'; export class TestService extends Disposable implements ITestService { @@ -17,11 +19,27 @@ export class TestService extends Disposable implements ITestService { private testControllers = new Map(); private readonly testSubscriptions = new Map; listeners: number; }>(); + private readonly subscribeEmitter = new Emitter<{ resource: ExtHostTestingResource, uri: URI }>(); private readonly unsubscribeEmitter = new Emitter<{ resource: ExtHostTestingResource, uri: URI }>(); + private readonly changeProvidersEmitter = new Emitter<{ delta: number }>(); + private readonly providerCount: IContextKey; + + constructor(@IContextKeyService contextKeyService: IContextKeyService) { + super(); + this.providerCount = TestingContextKeys.providerCount.bindTo(contextKeyService); + } + + /** + * Gets the current provider count. + */ + public get providers() { + return this.providerCount.get() || 0; + } /** * Fired when extension hosts should pull events from their test factories. @@ -33,6 +51,18 @@ export class TestService extends Disposable implements ITestService { */ public readonly onShouldUnsubscribe = this.unsubscribeEmitter.event; + /** + * Fired when the number of providers change. + */ + public readonly onDidChangeProviders = this.changeProvidersEmitter.event; + + /** + * @inheritdoc + */ + public get subscriptions() { + return [...this.testSubscriptions].map(([, s]) => s.ident); + } + /** * @inheritdoc */ @@ -54,7 +84,7 @@ export class TestService extends Disposable implements ITestService { const subscriptionKey = getTestSubscriptionKey(resource, uri); let subscription = this.testSubscriptions.get(subscriptionKey); if (!subscription) { - subscription = { collection: new MainThreadTestCollection(), listeners: 0, onDiff: new Emitter() }; + subscription = { ident: { resource, uri }, collection: new MainThreadTestCollection(), listeners: 0, onDiff: new Emitter() }; this.subscribeEmitter.fire({ resource, uri }); this.testSubscriptions.set(subscriptionKey, subscription); } @@ -93,6 +123,8 @@ export class TestService extends Disposable implements ITestService { */ public registerTestController(id: string, controller: MainTestController): void { this.testControllers.set(id, controller); + this.providerCount.set(this.testControllers.size); + this.changeProvidersEmitter.fire({ delta: 1 }); } /** @@ -100,6 +132,8 @@ export class TestService extends Disposable implements ITestService { */ public unregisterTestController(id: string): void { this.testControllers.delete(id); + this.providerCount.set(this.testControllers.size); + this.changeProvidersEmitter.fire({ delta: -1 }); } } diff --git a/src/vs/workbench/contrib/testing/common/testViews.ts b/src/vs/workbench/contrib/testing/common/testViews.ts new file mode 100644 index 00000000000..1143dae15f3 --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/testViews.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const TESTING_VIEWLET_ID = 'workbench.view.testing'; diff --git a/src/vs/workbench/contrib/testing/common/testingContextKeys.ts b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts new file mode 100644 index 00000000000..7345cb0181d --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; + +export namespace TestingContextKeys { + export const providerCount = new RawContextKey('testingProviderCount', 0); +} From 75dd72eeff5aad66989973cfbf352ebb699c5d0c Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 11 Dec 2020 15:17:15 -0800 Subject: [PATCH 0866/1837] move layout info into diff cell view model. --- .../notebook/browser/diff/cellComponents.ts | 160 +++++------------- .../browser/diff/celllDiffViewModel.ts | 86 +++++++++- .../contrib/notebook/browser/diff/common.ts | 6 +- 3 files changed, 134 insertions(+), 118 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index eebd011d88a..0fa9531f4a5 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -8,7 +8,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffViewModel, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; -import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -236,15 +236,6 @@ abstract class AbstractCellRenderer extends Disposable { protected _diffEditorContainer!: HTMLElement; protected _diagonalFill?: HTMLElement; - protected _layoutInfo!: { - editorHeight: number; - editorMargin: number; - metadataStatusHeight: number; - metadataHeight: number; - outputStatusHeight: number; - outputHeight: number; - bodyMargin: number; - }; protected _isDisposed: boolean; constructor( @@ -266,20 +257,11 @@ abstract class AbstractCellRenderer extends Disposable { super(); // init this._isDisposed = false; - this._layoutInfo = { - editorHeight: 0, - editorMargin: 0, - metadataHeight: 0, - metadataStatusHeight: 25, - outputHeight: 0, - outputStatusHeight: 25, - bodyMargin: 32 - }; this._metadataEditorDisposeStore = new DisposableStore(); this._outputEditorDisposeStore = new DisposableStore(); this._register(this._metadataEditorDisposeStore); + this._register(cell.onDidLayoutChange(e => this.layout(e))); this.buildBody(); - this._register(cell.onDidLayoutChange(e => this.onDidLayoutChange(e))); } abstract buildBody(): void; @@ -294,15 +276,13 @@ abstract class AbstractCellRenderer extends Disposable { this._metadataEditorContainer = DOM.append(this._metadataInfoContainer, DOM.$('.metadata-editor-container')); this._buildMetadataEditor(); } else { - this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight(); - this.layout({ metadataEditor: true }); + this.cell.metadataHeight = this._metadataEditor.getContentHeight(); } } else { // we should collapse the metadata editor this._metadataInfoContainer.style.display = 'none'; this._metadataEditorDisposeStore.clear(); - this._layoutInfo.metadataHeight = 0; - this.layout({}); + this.cell.metadataHeight = 0; } } @@ -315,6 +295,7 @@ abstract class AbstractCellRenderer extends Disposable { this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); this._buildOutputContainer(); } else { + // TODO, should we check its height? this.layout({ outputView: true }); } } else { @@ -325,15 +306,13 @@ abstract class AbstractCellRenderer extends Disposable { this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); this._buildOutputEditor(); } else { - this._layoutInfo.outputHeight = this._outputEditor.getContentHeight(); - this.layout({ outputEditor: true }); + this.cell.outputHeight = this._outputEditor.getContentHeight(); } } } else { this._outputInfoContainer.style.display = 'none'; this._outputEditorDisposeStore.clear(); - this._layoutInfo.outputHeight = 0; - this.layout({}); + this.cell.outputHeight = 0; } } @@ -479,13 +458,11 @@ abstract class AbstractCellRenderer extends Disposable { this._register(originalMetadataModel); this._register(modifiedMetadataModel); - this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight(); - this.layout({ metadataEditor: true }); + this.cell.metadataHeight = this._metadataEditor.getContentHeight(); this._register(this._metadataEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.metadataFoldingState === PropertyFoldingState.Expanded) { - this._layoutInfo.metadataHeight = e.contentHeight; - this.layout({ metadataEditor: true }); + this.cell.metadataHeight = e.contentHeight; } })); @@ -539,13 +516,11 @@ abstract class AbstractCellRenderer extends Disposable { this._metadataEditor.setModel(metadataModel); this._register(metadataModel); - this._layoutInfo.metadataHeight = this._metadataEditor.getContentHeight(); - this.layout({ metadataEditor: true }); + this.cell.metadataHeight = this._metadataEditor.getContentHeight(); this._register(this._metadataEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.metadataFoldingState === PropertyFoldingState.Expanded) { - this._layoutInfo.metadataHeight = e.contentHeight; - this.layout({ metadataEditor: true }); + this.cell.metadataHeight = e.contentHeight; } })); } @@ -587,13 +562,11 @@ abstract class AbstractCellRenderer extends Disposable { modified: modifiedModel }); - this._layoutInfo.outputHeight = this._outputEditor.getContentHeight(); - this.layout({ outputEditor: true }); + this.cell.outputHeight = this._outputEditor.getContentHeight(); this._register(this._outputEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - this._layoutInfo.outputHeight = e.contentHeight; - this.layout({ outputEditor: true }); + this.cell.outputHeight = e.contentHeight; } })); @@ -627,13 +600,11 @@ abstract class AbstractCellRenderer extends Disposable { const outputModel = this.modelService.createModel(originaloutputSource, mode, undefined, true); this._outputEditor.setModel(outputModel); - this._layoutInfo.outputHeight = this._outputEditor.getContentHeight(); - this.layout({ outputEditor: true }); + this.cell.outputHeight = this._outputEditor.getContentHeight(); this._register(this._outputEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - this._layoutInfo.outputHeight = e.contentHeight; - this.layout({ outputEditor: true }); + this.cell.outputHeight = e.contentHeight; } })); } @@ -641,13 +612,7 @@ abstract class AbstractCellRenderer extends Disposable { protected layoutNotebookCell() { this.notebookEditor.layoutNotebookCell( this.cell, - this._layoutInfo.editorHeight - + this._layoutInfo.editorMargin - + this._layoutInfo.metadataHeight - + this._layoutInfo.metadataStatusHeight - + this._layoutInfo.outputHeight - + this._layoutInfo.outputStatusHeight - + this._layoutInfo.bodyMargin + this.cell.totalHeight ); } @@ -658,7 +623,6 @@ abstract class AbstractCellRenderer extends Disposable { abstract styleContainer(container: HTMLElement): void; abstract updateSourceEditor(): void; - abstract onDidLayoutChange(event: CellDiffViewModelLayoutChangeEvent): void; abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }): void; } @@ -753,9 +717,8 @@ abstract class SingleSideCell extends AbstractCellRenderer { this._metadataHeader.buildHeader(); if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { - this._layoutInfo.outputHeight = 0; - this._layoutInfo.outputStatusHeight = 0; - this.layout({}); + this.cell.outputHeight = 0; + this.cell.outputStatusHeight = 0; this.templateData.outputHeaderContainer.style.display = 'none'; this.templateData.outputInfoContainer.style.display = 'none'; return; @@ -837,12 +800,11 @@ export class DeletedCell extends SingleSideCell { height: editorHeight }); - this._layoutInfo.editorHeight = editorHeight; + this.cell.editorHeight = editorHeight; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this._layoutInfo.editorHeight !== e.contentHeight) { - this._layoutInfo.editorHeight = e.contentHeight; - this.layout({ editorHeight: true }); + if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + this.cell.editorHeight = e.contentHeight; } })); @@ -855,37 +817,30 @@ export class DeletedCell extends SingleSideCell { const textModel = ref.object.textEditorModel; this._editor.setModel(textModel); - this._layoutInfo.editorHeight = this._editor.getContentHeight(); - this.layout({ editorHeight: true }); + this.cell.editorHeight = this._editor.getContentHeight(); }); - } - onDidLayoutChange(e: CellDiffViewModelLayoutChangeEvent) { - if (e.outerWidth !== undefined) { - this.layout({ outerWidth: true }); - } - } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { this._editor.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this._layoutInfo.editorHeight + height: this.cell.editorHeight }); } if (state.metadataEditor || state.outerWidth) { this._metadataEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this._layoutInfo.metadataHeight + height: this.cell.metadataHeight }); } if (state.outputEditor || state.outerWidth) { this._outputEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this._layoutInfo.outputHeight + height: this.cell.outputHeight }); } @@ -936,12 +891,11 @@ export class InsertCell extends SingleSideCell { } ); this._editor.updateOptions({ readOnly: false }); - this._layoutInfo.editorHeight = editorHeight; + this.cell.editorHeight = editorHeight; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this._layoutInfo.editorHeight !== e.contentHeight) { - this._layoutInfo.editorHeight = e.contentHeight; - this.layout({ editorHeight: true }); + if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + this.cell.editorHeight = e.contentHeight; } })); @@ -954,21 +908,14 @@ export class InsertCell extends SingleSideCell { const textModel = ref.object.textEditorModel; this._editor.setModel(textModel); - this._layoutInfo.editorHeight = this._editor.getContentHeight(); - this.layout({ editorHeight: true }); + this.cell.editorHeight = this._editor.getContentHeight(); }); } - onDidLayoutChange(e: CellDiffViewModelLayoutChangeEvent) { - if (e.outerWidth !== undefined) { - this.layout({ outerWidth: true }); - } - } - _buildOutputContainer() { this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputViewContainer!); this._outputLeftView.render(); - this.layout({ outputView: true }); + this.cell.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { @@ -976,32 +923,29 @@ export class InsertCell extends SingleSideCell { if (state.editorHeight || state.outerWidth) { this._editor.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this._layoutInfo.editorHeight + height: this.cell.editorHeight }); } if (state.metadataEditor || state.outerWidth) { this._metadataEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), - height: this._layoutInfo.metadataHeight + height: this.cell.metadataHeight }); } if (state.outputEditor || state.outerWidth) { this._outputEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), - height: this._layoutInfo.outputHeight + height: this.cell.outputHeight }); } - if (state.outputView) { - this._layoutInfo.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; - } this.layoutNotebookCell(); if (this._diagonalFill) { - this._diagonalFill.style.height = `${this._layoutInfo.editorHeight + this._layoutInfo.editorMargin + this._layoutInfo.metadataStatusHeight + this._layoutInfo.metadataHeight + this._layoutInfo.outputHeight + this._layoutInfo.outputStatusHeight}px`; + this._diagonalFill.style.height = `${this.cell.editorHeight + this.cell.editorMargin + this.cell.metadataStatusHeight + this.cell.metadataHeight + this.cell.outputHeight + this.cell.outputStatusHeight}px`; } }); } @@ -1091,9 +1035,8 @@ export class ModifiedCell extends AbstractCellRenderer { this._metadataHeader.buildHeader(); if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { - this._layoutInfo.outputHeight = 0; - this._layoutInfo.outputStatusHeight = 0; - this.layout({}); + this.cell.outputHeight = 0; + this.cell.outputStatusHeight = 0; this.templateData.outputHeaderContainer.style.display = 'none'; this.templateData.outputInfoContainer.style.display = 'none'; return; @@ -1151,7 +1094,7 @@ export class ModifiedCell extends AbstractCellRenderer { this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputRightContainer!); this._outputRightView.render(); - this.layout({ outputView: true }); + this.cell.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); } updateSourceEditor(): void { @@ -1172,9 +1115,8 @@ export class ModifiedCell extends AbstractCellRenderer { this._editorContainer.style.height = `${editorHeight}px`; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this._layoutInfo.editorHeight !== e.contentHeight) { - this._layoutInfo.editorHeight = e.contentHeight; - this.layout({ editorHeight: true }); + if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + this.cell.editorHeight = e.contentHeight; } })); @@ -1246,50 +1188,38 @@ export class ModifiedCell extends AbstractCellRenderer { }); const contentHeight = this._editor!.getContentHeight(); - this._layoutInfo.editorHeight = contentHeight; - this.layout({ editorHeight: true }); - - } - - onDidLayoutChange(e: CellDiffViewModelLayoutChangeEvent) { - if (e.outerWidth !== undefined) { - this.layout({ outerWidth: true }); - } + this.cell.editorHeight = contentHeight; } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight) { - this._editorContainer.style.height = `${this._layoutInfo.editorHeight}px`; + this._editorContainer.style.height = `${this.cell.editorHeight}px`; this._editor!.layout({ width: this._editor!.getViewWidth(), - height: this._layoutInfo.editorHeight + height: this.cell.editorHeight }); } if (state.outerWidth) { - this._editorContainer.style.height = `${this._layoutInfo.editorHeight}px`; + this._editorContainer.style.height = `${this.cell.editorHeight}px`; this._editor!.layout(); } if (state.metadataEditor || state.outerWidth) { if (this._metadataEditorContainer) { - this._metadataEditorContainer.style.height = `${this._layoutInfo.metadataHeight}px`; + this._metadataEditorContainer.style.height = `${this.cell.metadataHeight}px`; this._metadataEditor?.layout(); } } if (state.outputEditor || state.outerWidth) { if (this._outputEditorContainer) { - this._outputEditorContainer.style.height = `${this._layoutInfo.outputHeight}px`; + this._outputEditorContainer.style.height = `${this.cell.outputHeight}px`; this._outputEditor?.layout(); } } - if (state.outputView) { - this._layoutInfo.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); - } - this.layoutNotebookCell(); }); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index 55e25cee313..bda3804f7df 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -20,9 +20,77 @@ export class CellDiffViewModel extends Disposable { public metadataFoldingState: PropertyFoldingState; public outputFoldingState: PropertyFoldingState; private _layoutInfoEmitter = new Emitter(); - onDidLayoutChange = this._layoutInfoEmitter.event; + protected _layoutInfo!: { + editorHeight: number; + editorMargin: number; + metadataStatusHeight: number; + metadataHeight: number; + outputStatusHeight: number; + outputHeight: number; + bodyMargin: number; + }; + + set outputHeight(height: number) { + this._layoutInfo.outputHeight = height; + this._fireLayoutChangeEvent({ outputEditor: true, outputView: true }); + } + + get outputHeight() { + return this._layoutInfo.outputHeight; + } + + set outputStatusHeight(height: number) { + this._layoutInfo.outputStatusHeight = height; + this._fireLayoutChangeEvent({}); + } + + get outputStatusHeight() { + return this._layoutInfo.outputStatusHeight; + } + + set editorHeight(height: number) { + this._layoutInfo.editorHeight = height; + this._fireLayoutChangeEvent({ editorHeight: true }); + } + + get editorHeight() { + return this._layoutInfo.editorHeight; + } + + set editorMargin(height: number) { + this._layoutInfo.editorMargin = height; + this._fireLayoutChangeEvent({}); + } + + get editorMargin() { + return this._layoutInfo.editorMargin; + } + + get metadataStatusHeight() { + return this._layoutInfo.metadataStatusHeight; + } + + set metadataHeight(height: number) { + this._layoutInfo.metadataHeight = height; + this._fireLayoutChangeEvent({ metadataEditor: true }); + } + + get metadataHeight() { + return this._layoutInfo.metadataHeight; + } + + get totalHeight() { + return this._layoutInfo.editorHeight + + this._layoutInfo.editorMargin + + this._layoutInfo.metadataHeight + + this._layoutInfo.metadataStatusHeight + + this._layoutInfo.outputHeight + + this._layoutInfo.outputStatusHeight + + this._layoutInfo.bodyMargin; + } + constructor( readonly original: NotebookCellTextModel | undefined, readonly modified: NotebookCellTextModel | undefined, @@ -30,14 +98,28 @@ export class CellDiffViewModel extends Disposable { readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { super(); + this._layoutInfo = { + editorHeight: 0, + editorMargin: 0, + metadataHeight: 0, + metadataStatusHeight: 25, + outputHeight: 0, + outputStatusHeight: 25, + bodyMargin: 32 + }; + this.metadataFoldingState = PropertyFoldingState.Collapsed; this.outputFoldingState = PropertyFoldingState.Collapsed; this._register(this.editorEventDispatcher.onDidChangeLayout(e => { - this._layoutInfoEmitter.fire({ outerWidth: e.value.width }); + this._layoutInfoEmitter.fire({ outerWidth: true }); })); } + private _fireLayoutChangeEvent(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { + this._layoutInfoEmitter.fire(state); + } + getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { return layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0) - 2; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 115173f8bac..a08dce346a1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -54,7 +54,11 @@ export interface CellDiffSideBySideRenderTemplate { export interface CellDiffViewModelLayoutChangeEvent { font?: BareFontInfo; - outerWidth?: number; + outerWidth?: boolean; + editorHeight?: boolean; + metadataEditor?: boolean; + outputEditor?: boolean; + outputView?: boolean; } export const DIFF_CELL_MARGIN = 16; From 91bb3857ac94109cf923788f7011c61cbdbbda20 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Fri, 11 Dec 2020 15:28:03 -0800 Subject: [PATCH 0867/1837] Use tree widget in the process explorer, fixes #104013 --- .../processExplorer/media/processExplorer.css | 38 +- .../processExplorer/processExplorer.html | 2 +- .../processExplorer/processExplorerMain.ts | 478 ++++++++++-------- src/vs/platform/issue/common/issue.ts | 1 - .../issue/electron-sandbox/issueService.ts | 5 +- 5 files changed, 266 insertions(+), 258 deletions(-) diff --git a/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css b/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css index add9cdae262..54a37380feb 100644 --- a/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css +++ b/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css @@ -49,28 +49,12 @@ body { width: 90px; } -.process-item { - line-height: 22px; +.monaco-list-row:first-of-type { + border-bottom: 1px solid; } -table { - border-collapse: collapse; - width: 100%; - table-layout: fixed; -} - -th[scope='col'] { - vertical-align: bottom; - border-bottom: 1px solid #cccccc; - padding: .5rem; - border-top: 1px solid #cccccc; - cursor: default; -} - -td { - padding: .25rem; - vertical-align: top; - cursor: default; +.row { + display: flex; } .centered { @@ -79,6 +63,8 @@ td { .nameLabel{ text-align: left; + flex-grow: 1; + overflow: hidden; } .data { @@ -93,15 +79,3 @@ td { padding-left: 20px; white-space: nowrap; } - -tbody > tr:hover { - background-color: #2A2D2E; -} - -.hidden { - display: none; -} - -.header { - display: flex; -} diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorer.html b/src/vs/code/electron-sandbox/processExplorer/processExplorer.html index 517805abdb7..73d89eac31d 100644 --- a/src/vs/code/electron-sandbox/processExplorer/processExplorer.html +++ b/src/vs/code/electron-sandbox/processExplorer/processExplorer.html @@ -6,7 +6,7 @@ -
+
diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts index ef93a1c528d..02e05f17573 100644 --- a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts @@ -14,36 +14,224 @@ import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu'; import { ProcessItem } from 'vs/base/common/processes'; -import { addDisposableListener, $ } from 'vs/base/browser/dom'; +import * as dom from 'vs/base/browser/dom'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; import { ByteSize } from 'vs/platform/files/common/files'; +import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IDataSource, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; +import { DataTree } from 'vs/base/browser/ui/tree/dataTree'; const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/; const DEBUG_PORT_PATTERN = /\s--(inspect|debug)-port=(\d+)/; -interface FormattedProcessItem { - cpu: number; - memory: number; - pid: string; +class ProcessListDelegate implements IListVirtualDelegate { + getHeight(element: MachineProcessInformation | ProcessItem | IRemoteDiagnosticError) { + return 22; + } + + getTemplateId(element: ProcessInformation | MachineProcessInformation | ProcessItem | IRemoteDiagnosticError) { + if (isProcessItem(element)) { + return 'process'; + } + + if (isMachineProcessInformation(element)) { + return 'machine'; + } + + if (isRemoteDiagnosticError(element)) { + return 'error'; + } + + if (isProcessInformation(element)) { + return 'header'; + } + + return ''; + } +} + +interface IProcessItemTemplateData extends IProcessRowTemplateData { + CPU: HTMLElement; + memory: HTMLElement; + PID: HTMLElement; +} + +interface IProcessRowTemplateData { + name: HTMLElement; +} + +class ProcessTreeDataSource implements IDataSource { + hasChildren(element: ProcessTree | ProcessInformation | MachineProcessInformation | ProcessItem | IRemoteDiagnosticError): boolean { + if (isRemoteDiagnosticError(element)) { + return false; + } + + if (isProcessItem(element)) { + return !!element.children?.length; + } else { + return true; + } + } + + getChildren(element: ProcessTree | ProcessInformation | MachineProcessInformation | ProcessItem | IRemoteDiagnosticError) { + if (isProcessItem(element)) { + return element.children ? element.children : []; + } + + if (isRemoteDiagnosticError(element)) { + return []; + } + + if (isProcessInformation(element)) { + // If there are multiple process roots, return these, otherwise go directly to the root process + if (element.processRoots.length > 1) { + return element.processRoots; + } else { + return [element.processRoots[0].rootProcess]; + } + } + + if (isMachineProcessInformation(element)) { + return [element.rootProcess]; + } + + return [element.processes]; + } +} + +class ProcessHeaderTreeRenderer implements ITreeRenderer { + templateId: string = 'header'; + renderTemplate(container: HTMLElement): IProcessItemTemplateData { + const data = Object.create(null); + const row = dom.append(container, dom.$('.row')); + data.name = dom.append(row, dom.$('.nameLabel')); + data.CPU = dom.append(row, dom.$('.cpu')); + data.memory = dom.append(row, dom.$('.memory')); + data.PID = dom.append(row, dom.$('.pid')); + return data; + } + renderElement(node: ITreeNode, index: number, templateData: IProcessItemTemplateData, height: number | undefined): void { + templateData.name.textContent = localize('name', "Process Name"); + templateData.CPU.textContent = localize('cpu', "CPU %"); + templateData.PID.textContent = localize('pid', "PID"); + templateData.memory.textContent = localize('memory', "Memory (MB)"); + + } + disposeTemplate(templateData: any): void { + // Nothing to do + } +} + +class MachineRenderer implements ITreeRenderer { + templateId: string = 'machine'; + renderTemplate(container: HTMLElement): IProcessRowTemplateData { + const data = Object.create(null); + const row = dom.append(container, dom.$('.row')); + data.name = dom.append(row, dom.$('.nameLabel')); + return data; + } + renderElement(node: ITreeNode, index: number, templateData: IProcessRowTemplateData, height: number | undefined): void { + templateData.name.textContent = node.element.name; + } + disposeTemplate(templateData: IProcessRowTemplateData): void { + // Nothing to do + } +} + +class ErrorRenderer implements ITreeRenderer { + templateId: string = 'error'; + renderTemplate(container: HTMLElement): IProcessRowTemplateData { + const data = Object.create(null); + const row = dom.append(container, dom.$('.row')); + data.name = dom.append(row, dom.$('.nameLabel')); + return data; + } + renderElement(node: ITreeNode, index: number, templateData: IProcessRowTemplateData, height: number | undefined): void { + templateData.name.textContent = node.element.errorMessage; + } + disposeTemplate(templateData: IProcessRowTemplateData): void { + // Nothing to do + } +} + + +class ProcessRenderer implements ITreeRenderer { + constructor(private platform: string, private totalMem: number, private mapPidToWindowTitle: Map) { } + + templateId: string = 'process'; + renderTemplate(container: HTMLElement): IProcessItemTemplateData { + const data = Object.create(null); + const row = dom.append(container, dom.$('.row')); + + data.name = dom.append(row, dom.$('.nameLabel')); + data.CPU = dom.append(row, dom.$('.cpu')); + data.memory = dom.append(row, dom.$('.memory')); + data.PID = dom.append(row, dom.$('.pid')); + + return data; + } + renderElement(node: ITreeNode, index: number, templateData: IProcessItemTemplateData, height: number | undefined): void { + const { element } = node; + + let name = element.name; + if (name === 'window') { + const windowTitle = this.mapPidToWindowTitle.get(element.pid); + name = windowTitle !== undefined ? `${name} (${this.mapPidToWindowTitle.get(element.pid)})` : name; + } + + templateData.name.textContent = name; + templateData.name.title = element.cmd; + + templateData.CPU.textContent = element.load.toString(); + templateData.PID.textContent = element.pid.toString(); + + const memory = this.platform === 'win32' ? element.mem : (this.totalMem * (element.mem / 100)); + templateData.memory.textContent = Math.round((memory / ByteSize.MB)).toString(); + } + + disposeTemplate(templateData: IProcessItemTemplateData): void { + // Nothing to do + } +} + +interface MachineProcessInformation { name: string; - formattedName: string; - cmd: string; + rootProcess: ProcessItem | IRemoteDiagnosticError +} + +interface ProcessInformation { + processRoots: MachineProcessInformation[]; +} + +interface ProcessTree { + processes: ProcessInformation; +} + +function isMachineProcessInformation(item: any): item is MachineProcessInformation { + return !!item.name && !!item.rootProcess; +} + +function isProcessInformation(item: any): item is ProcessInformation { + return !!item.processRoots; +} + +function isProcessItem(item: any): item is ProcessItem { + return !!item.pid; } class ProcessExplorer { private lastRequestTime: number; - private collapsedStateCache: Map = new Map(); - private mapPidToWindowTitle = new Map(); private listeners = new DisposableStore(); private nativeHostService: INativeHostService; + private tree: DataTree | undefined; + constructor(windowId: number, private data: ProcessExplorerData) { const mainProcessService = new MainProcessService(windowId); this.nativeHostService = new NativeHostService(windowId, mainProcessService) as INativeHostService; @@ -56,8 +244,19 @@ class ProcessExplorer { windows.forEach(window => this.mapPidToWindowTitle.set(window.pid, window.title)); }); - ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => { - this.updateProcessInfo(processRoots); + ipcRenderer.on('vscode:listProcessesResponse', async (event: unknown, processRoots: MachineProcessInformation[]) => { + processRoots.forEach((info, index) => { + if (isProcessItem(info.rootProcess)) { + info.rootProcess.name = index === 0 ? `${this.data.applicationName} main` : 'remote agent'; + } + }); + + if (!this.tree) { + await this.createProcessTree(processRoots); + } else { + this.tree.setInput({ processes: { processRoots } }); + } + this.requestProcessList(0); }); @@ -66,54 +265,58 @@ class ProcessExplorer { ipcRenderer.send('vscode:listProcesses'); } - private getProcessList(rootProcess: ProcessItem, isLocal: boolean, totalMem: number): FormattedProcessItem[] { - const processes: FormattedProcessItem[] = []; - const handledProcesses = new Set(); - - if (rootProcess) { - this.getProcessItem(processes, rootProcess, 0, isLocal, totalMem, handledProcesses); + private async createProcessTree(processRoots: MachineProcessInformation[]): Promise { + const container = document.getElementById('process-list'); + if (!container) { + return; } - return processes; - } + const { totalmem } = await this.nativeHostService.getOSStatistics(); - private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean, totalMem: number, handledProcesses: Set): void { - const isRoot = (indent === 0); + const renderers = [ + new ProcessRenderer(this.data.platform, totalmem, this.mapPidToWindowTitle), + new ProcessHeaderTreeRenderer(), + new MachineRenderer(), + new ErrorRenderer() + ]; - handledProcesses.add(item.pid); + this.tree = new DataTree('processExplorer', + container, + new ProcessListDelegate(), + renderers, + new ProcessTreeDataSource(), + { + identityProvider: + { + getId: (element: ProcessTree | ProcessItem | MachineProcessInformation | ProcessInformation | IRemoteDiagnosticError) => { + if (isProcessItem(element)) { + return element.pid.toString(); + } - let name = item.name; - if (isRoot) { - name = isLocal ? `${this.data.applicationName} main` : 'remote agent'; - } + if (isRemoteDiagnosticError(element)) { + return element.hostName; + } - if (name === 'window') { - const windowTitle = this.mapPidToWindowTitle.get(item.pid); - name = windowTitle !== undefined ? `${name} (${this.mapPidToWindowTitle.get(item.pid)})` : name; - } + if (isProcessInformation(element)) { + return 'processes'; + } - // Format name with indent - const formattedName = isRoot ? name : `${' '.repeat(indent)} ${name}`; - const memory = this.data.platform === 'win32' ? item.mem : (totalMem * (item.mem / 100)); - processes.push({ - cpu: item.load, - memory: (memory / ByteSize.MB), - pid: item.pid.toFixed(0), - name, - formattedName, - cmd: item.cmd - }); + if (isMachineProcessInformation(element)) { + return element.name; + } - // Recurse into children if any - if (Array.isArray(item.children)) { - item.children.forEach(child => { - if (!child || handledProcesses.has(child.pid)) { - return; // prevent loops + return 'header'; + } } - - this.getProcessItem(processes, child, indent + 1, isLocal, totalMem, handledProcesses); }); - } + + this.tree.setInput({ processes: { processRoots } }); + this.tree.layout(window.innerHeight, window.innerWidth); + this.tree.onContextMenu(e => { + if (isProcessItem(e.element)) { + this.showContextMenu(e.element, true); + } + }); } private isDebuggable(cmd: string): boolean { @@ -121,7 +324,7 @@ class ProcessExplorer { return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0; } - private attachTo(item: FormattedProcessItem) { + private attachTo(item: ProcessItem) { const config: any = { type: 'node', request: 'attach', @@ -150,179 +353,16 @@ class ProcessExplorer { ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] }); } - private getProcessIdWithHighestProperty(processList: any[], propertyName: string) { - let max = 0; - let maxProcessId; - processList.forEach(process => { - if (process[propertyName] > max) { - max = process[propertyName]; - maxProcessId = process.pid; - } - }); - - return maxProcessId; - } - - private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: CodiconLabel, sectionName: string) { - if (shouldExpand) { - body.classList.remove('hidden'); - this.collapsedStateCache.set(sectionName, false); - twistie.text = '$(chevron-down)'; - } else { - body.classList.add('hidden'); - this.collapsedStateCache.set(sectionName, true); - twistie.text = '$(chevron-right)'; - } - } - - private renderProcessFetchError(sectionName: string, errorMessage: string) { - const container = document.getElementById('process-list'); - if (!container) { - return; - } - - const body = document.createElement('tbody'); - - this.renderProcessGroupHeader(sectionName, body, container); - - const errorRow = document.createElement('tr'); - const data = document.createElement('td'); - data.textContent = errorMessage; - data.className = 'error'; - data.colSpan = 4; - errorRow.appendChild(data); - - body.appendChild(errorRow); - container.appendChild(body); - } - - private renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) { - const headerRow = document.createElement('tr'); - - const headerData = document.createElement('td'); - headerData.colSpan = 4; - headerRow.appendChild(headerData); - - const headerContainer = document.createElement('div'); - headerContainer.className = 'header'; - headerData.appendChild(headerContainer); - - const twistieContainer = document.createElement('div'); - const twistieCodicon = new CodiconLabel(twistieContainer); - this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistieCodicon, sectionName); - headerContainer.appendChild(twistieContainer); - - const headerLabel = document.createElement('span'); - headerLabel.textContent = sectionName; - headerContainer.appendChild(headerLabel); - - this.listeners.add(addDisposableListener(headerData, 'click', (e) => { - const isHidden = body.classList.contains('hidden'); - this.updateSectionCollapsedState(isHidden, body, twistieCodicon, sectionName); - })); - - container.appendChild(headerRow); - } - - private renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void { - const container = document.getElementById('process-list'); - if (!container) { - return; - } - - const highestCPUProcess = this.getProcessIdWithHighestProperty(processList, 'cpu'); - const highestMemoryProcess = this.getProcessIdWithHighestProperty(processList, 'memory'); - - const body = document.createElement('tbody'); - - if (renderManySections) { - this.renderProcessGroupHeader(sectionName, body, container); - } - - processList.forEach(p => { - const row = document.createElement('tr'); - row.id = p.pid.toString(); - - const cpu = document.createElement('td'); - p.pid === highestCPUProcess - ? cpu.classList.add('centered', 'highest') - : cpu.classList.add('centered'); - cpu.textContent = p.cpu.toFixed(0); - - const memory = document.createElement('td'); - p.pid === highestMemoryProcess - ? memory.classList.add('centered', 'highest') - : memory.classList.add('centered'); - memory.textContent = p.memory.toFixed(0); - - const pid = document.createElement('td'); - pid.classList.add('centered'); - pid.textContent = p.pid; - - const name = document.createElement('th'); - name.scope = 'row'; - name.classList.add('data'); - name.title = p.cmd; - name.textContent = p.formattedName; - - row.append(cpu, memory, pid, name); - - this.listeners.add(addDisposableListener(row, 'contextmenu', (e) => { - this.showContextMenu(e, p, sectionIsLocal); - })); - - body.appendChild(row); - }); - - container.appendChild(body); - } - - private async updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): Promise { - const container = document.getElementById('process-list'); - if (!container) { - return; - } - - container.innerText = ''; - this.listeners.clear(); - - const tableHead = $('thead', undefined); - const row = $('tr'); - tableHead.append(row); - - row.append($('th.cpu', { scope: 'col' }, localize('cpu', "CPU %"))); - row.append($('th.memory', { scope: 'col' }, localize('memory', "Memory (MB)"))); - row.append($('th.pid', { scope: 'col' }, localize('pid', "PID"))); - row.append($('th.nameLabel', { scope: 'col' }, localize('name', "Name"))); - - container.append(tableHead); - - const hasMultipleMachines = Object.keys(processLists).length > 1; - const { totalmem } = await this.nativeHostService.getOSStatistics(); - processLists.forEach((remote, i) => { - const isLocal = i === 0; - if (isRemoteDiagnosticError(remote.rootProcess)) { - this.renderProcessFetchError(remote.name, remote.rootProcess.errorMessage); - } else { - this.renderTableSection(remote.name, this.getProcessList(remote.rootProcess, isLocal, totalmem), hasMultipleMachines, isLocal); - } - }); - } - private applyStyles(styles: ProcessExplorerStyles): void { const styleTag = document.createElement('style'); const content: string[] = []; if (styles.hoverBackground) { - content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`); + content.push(`.monaco-list-row:hover { background-color: ${styles.hoverBackground}; }`); } if (styles.hoverForeground) { - content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`); - } - - if (styles.highlightForeground) { - content.push(`.highest { color: ${styles.highlightForeground}; }`); + content.push(`.monaco-list-row:hover { color: ${styles.hoverForeground}; }`); } styleTag.textContent = content.join('\n'); @@ -334,9 +374,7 @@ class ProcessExplorer { } } - private showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) { - e.preventDefault(); - + private showContextMenu(item: ProcessItem, isLocal: boolean) { const items: IContextMenuItem[] = []; const pid = Number(item.pid); @@ -417,8 +455,6 @@ class ProcessExplorer { } } - - export function startup(windowId: number, data: ProcessExplorerData): void { const platformClass = data.platform === 'win32' ? 'windows' : data.platform === 'linux' ? 'linux' : 'mac'; document.body.classList.add(platformClass); // used by our fonts diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts index e981a34d5f5..ba0bae45c5a 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -72,7 +72,6 @@ export interface IssueReporterFeatures { export interface ProcessExplorerStyles extends WindowStyles { hoverBackground?: string; hoverForeground?: string; - highlightForeground?: string; } export interface ProcessExplorerData extends WindowData { diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts index f7beaf0f504..47f72a58ba7 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts @@ -6,7 +6,7 @@ import { IssueReporterStyles, IssueReporterData, ProcessExplorerData, IssueReporterExtensionData } from 'vs/platform/issue/common/issue'; import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue'; import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground, textLinkActiveForeground, inputValidationErrorBackground, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; +import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, textLinkActiveForeground, inputValidationErrorBackground, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -71,8 +71,7 @@ export class WorkbenchIssueService implements IWorkbenchIssueService { backgroundColor: getColor(theme, editorBackground), color: getColor(theme, editorForeground), hoverBackground: getColor(theme, listHoverBackground), - hoverForeground: getColor(theme, listHoverForeground), - highlightForeground: getColor(theme, listHighlightForeground), + hoverForeground: getColor(theme, listHoverForeground) }, platform: process.platform, applicationName: this.productService.applicationName From fe4f9a9e6fb543eac50bd1f8725df3a5bc838a61 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Dec 2020 15:28:56 -0800 Subject: [PATCH 0868/1837] testing: add to i18n --- build/lib/i18n.resources.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index e2fa142c9d3..89b1aa5968b 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -182,6 +182,10 @@ "name": "vs/workbench/contrib/tasks", "project": "vscode-workbench" }, + { + "name": "vs/workbench/contrib/testing", + "project": "vscode-workbench" + }, { "name": "vs/workbench/contrib/terminal", "project": "vscode-workbench" From fd44d15c2236e95dd0bd93a6c75f7902b5e90783 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 11 Dec 2020 15:49:08 -0800 Subject: [PATCH 0869/1837] fix #112337. --- .../notebook/browser/view/output/transforms/textHelper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts index 1a4fbe7bfcc..08e8abf93ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts @@ -90,7 +90,6 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[] const lineCount = buffer.getLineCount(); const fullRange = new Range(1, 1, lineCount, Math.max(1, buffer.getLineLastNonWhitespaceColumn(lineCount))); - container.innerText = buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined); if (renderANSI) { container.appendChild(handleANSIOutput(buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined), themeService)); } else { From ced21a0abcc77cd1c54c84bebd11cf8c70e84a78 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 11 Dec 2020 16:06:48 -0800 Subject: [PATCH 0870/1837] :lipstick: --- .../notebook/browser/diff/cellComponents.ts | 99 +++++-------------- .../browser/diff/celllDiffViewModel.ts | 50 ++++++++++ .../browser/diff/notebookTextDiffEditor.ts | 6 ++ .../view/output/transforms/textHelper.ts | 1 - 4 files changed, 82 insertions(+), 74 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 0fa9531f4a5..6a5be0bdd4d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellDiffViewModel, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModel, getFormatedMetadataJSON, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; @@ -17,7 +17,6 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { CellEditType, CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { hash } from 'vs/base/common/hash'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; @@ -295,8 +294,7 @@ abstract class AbstractCellRenderer extends Disposable { this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); this._buildOutputContainer(); } else { - // TODO, should we check its height? - this.layout({ outputView: true }); + this._updateOutputContainerHeight(); } } else { this._outputInfoContainer.style.display = 'block'; @@ -317,34 +315,7 @@ abstract class AbstractCellRenderer extends Disposable { } abstract _buildOutputContainer(): void; - - protected _getFormatedMetadataJSON(metadata: NotebookCellMetadata, language?: string) { - let filteredMetadata: { [key: string]: any } = {}; - - if (this.notebookEditor.textModel) { - const transientMetadata = this.notebookEditor.textModel!.transientOptions.transientMetadata; - - const keys = new Set([...Object.keys(metadata)]); - for (let key of keys) { - if (!(transientMetadata[key as keyof NotebookCellMetadata]) - ) { - filteredMetadata[key] = metadata[key as keyof NotebookCellMetadata]; - } - } - } else { - filteredMetadata = metadata; - } - - const content = JSON.stringify({ - language, - ...filteredMetadata - }); - - const edits = format(content, undefined, {}); - const metadataSource = applyEdits(content, edits); - - return metadataSource; - } + abstract _updateOutputContainerHeight(): void; private _applySanitizedMetadataChanges(currentMetadata: NotebookCellMetadata, newMetadata: any) { let result: { [key: string]: any } = {}; @@ -429,8 +400,8 @@ abstract class AbstractCellRenderer extends Disposable { private _buildMetadataEditor() { if (this.cell.type === 'modified' || this.cell.type === 'unchanged') { - const originalMetadataSource = this._getFormatedMetadataJSON(this.cell.original?.metadata || {}, this.cell.original?.language); - const modifiedMetadataSource = this._getFormatedMetadataJSON(this.cell.modified?.metadata || {}, this.cell.modified?.language); + const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.original?.metadata || {}, this.cell.original?.language); + const modifiedMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.modified?.metadata || {}, this.cell.modified?.language); this._metadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._metadataEditorContainer!, { ...fixedDiffEditorOptions, overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), @@ -481,7 +452,7 @@ abstract class AbstractCellRenderer extends Disposable { return; } - const modifiedMetadataSource = this._getFormatedMetadataJSON(this.cell.modified?.metadata || {}, this.cell.modified?.language); + const modifiedMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.modified?.metadata || {}, this.cell.modified?.language); modifiedMetadataModel.setValue(modifiedMetadataSource); })); @@ -500,7 +471,7 @@ abstract class AbstractCellRenderer extends Disposable { this._register(this._metadataEditor); const mode = this.modeService.create('jsonc'); - const originalMetadataSource = this._getFormatedMetadataJSON( + const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.type === 'insert' ? this.cell.modified!.metadata || {} : this.cell.original!.metadata || {}); @@ -683,14 +654,6 @@ abstract class SingleSideCell extends AbstractCellRenderer { this._metadataHeaderContainer.innerText = ''; this._metadataInfoContainer.innerText = ''; - const checkIfModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && hash(this._getFormatedMetadataJSON(cell.original?.metadata || {}, cell.original?.language)) !== hash(this._getFormatedMetadataJSON(cell.modified?.metadata ?? {}, cell.modified?.language)); - }; - - if (checkIfModified(this.cell)) { - this.cell.metadataFoldingState = PropertyFoldingState.Expanded; - } - this._metadataHeader = this.instantiationService.createInstance( PropertyHeader, this.cell, @@ -699,7 +662,7 @@ abstract class SingleSideCell extends AbstractCellRenderer { { updateInfoRendering: this.updateMetadataRendering.bind(this), checkIfModified: (cell) => { - return checkIfModified(cell); + return cell.checkMetadataIfModified(); }, getFoldingState: (cell) => { return cell.metadataFoldingState; @@ -730,14 +693,6 @@ abstract class SingleSideCell extends AbstractCellRenderer { this._outputHeaderContainer.innerText = ''; this._outputInfoContainer.innerText = ''; - const checkIfOutputsModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); - }; - - if (checkIfOutputsModified(this.cell)) { - this.cell.outputFoldingState = PropertyFoldingState.Expanded; - } - this._outputHeader = this.instantiationService.createInstance( PropertyHeader, this.cell, @@ -746,7 +701,7 @@ abstract class SingleSideCell extends AbstractCellRenderer { { updateInfoRendering: this.updateOutputRendering.bind(this), checkIfModified: (cell) => { - return checkIfOutputsModified(cell); + return cell.checkIfOutputsModified(); }, getFoldingState: (cell) => { return cell.outputFoldingState; @@ -853,6 +808,10 @@ export class DeletedCell extends SingleSideCell { // this._outputView.render(); // this.layout({ outputView: true }); } + + _updateOutputContainerHeight(): void { + // throw new Error('Method not implemented.'); + } } export class InsertCell extends SingleSideCell { @@ -918,6 +877,11 @@ export class InsertCell extends SingleSideCell { this.cell.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; } + _updateOutputContainerHeight(): void { + // throw new Error('Method not implemented.'); + this.cell.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; + } + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { @@ -1001,14 +965,6 @@ export class ModifiedCell extends AbstractCellRenderer { this._metadataHeaderContainer.innerText = ''; this._metadataInfoContainer.innerText = ''; - const checkIfModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && hash(this._getFormatedMetadataJSON(cell.original?.metadata || {}, cell.original?.language)) !== hash(this._getFormatedMetadataJSON(cell.modified?.metadata ?? {}, cell.modified?.language)); - }; - - if (checkIfModified(this.cell)) { - this.cell.metadataFoldingState = PropertyFoldingState.Expanded; - } - this._metadataHeader = this.instantiationService.createInstance( PropertyHeader, this.cell, @@ -1017,7 +973,7 @@ export class ModifiedCell extends AbstractCellRenderer { { updateInfoRendering: this.updateMetadataRendering.bind(this), checkIfModified: (cell) => { - return checkIfModified(cell); + return cell.checkMetadataIfModified(); }, getFoldingState: (cell) => { return cell.metadataFoldingState; @@ -1047,18 +1003,10 @@ export class ModifiedCell extends AbstractCellRenderer { this._outputHeaderContainer.innerText = ''; this._outputInfoContainer.innerText = ''; - const checkIfOutputsModified = (cell: CellDiffViewModel) => { - return cell.type !== 'delete' && cell.type !== 'insert' && !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []); - }; - - if (checkIfOutputsModified(this.cell)) { + if (this.cell.checkIfOutputsModified()) { this._outputInfoContainer.classList.add('modified'); } - if (checkIfOutputsModified(this.cell)) { - this.cell.outputFoldingState = PropertyFoldingState.Expanded; - } - this._outputHeader = this.instantiationService.createInstance( PropertyHeader, this.cell, @@ -1067,7 +1015,7 @@ export class ModifiedCell extends AbstractCellRenderer { { updateInfoRendering: this.updateOutputRendering.bind(this), checkIfModified: (cell) => { - return checkIfOutputsModified(cell); + return cell.checkIfOutputsModified(); }, getFoldingState: (cell) => { return cell.outputFoldingState; @@ -1097,6 +1045,11 @@ export class ModifiedCell extends AbstractCellRenderer { this.cell.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); } + + _updateOutputContainerHeight(): void { + this.cell.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); + } + updateSourceEditor(): void { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index bda3804f7df..8eed8eff932 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -10,6 +10,11 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; +import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { hash } from 'vs/base/common/hash'; +import { format } from 'vs/base/common/jsonFormatter'; +import { applyEdits } from 'vs/base/common/jsonEdit'; +import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export enum PropertyFoldingState { Expanded, @@ -92,6 +97,7 @@ export class CellDiffViewModel extends Disposable { } constructor( + readonly documentTextModel: NotebookTextModel, readonly original: NotebookCellTextModel | undefined, readonly modified: NotebookCellTextModel | undefined, readonly type: 'unchanged' | 'insert' | 'delete' | 'modified', @@ -111,6 +117,14 @@ export class CellDiffViewModel extends Disposable { this.metadataFoldingState = PropertyFoldingState.Collapsed; this.outputFoldingState = PropertyFoldingState.Collapsed; + if (this.checkMetadataIfModified()) { + this.metadataFoldingState = PropertyFoldingState.Expanded; + } + + if (this.checkIfOutputsModified()) { + this.outputFoldingState = PropertyFoldingState.Expanded; + } + this._register(this.editorEventDispatcher.onDidChangeLayout(e => { this._layoutInfoEmitter.fire({ outerWidth: true }); })); @@ -120,6 +134,14 @@ export class CellDiffViewModel extends Disposable { this._layoutInfoEmitter.fire(state); } + checkIfOutputsModified() { + return this.type !== 'delete' && this.type !== 'insert' && !this.documentTextModel.transientOptions.transientOutputs && this.type === 'modified' && hash(this.original?.outputs ?? []) !== hash(this.modified?.outputs ?? []); + } + + checkMetadataIfModified() { + return this.type !== 'delete' && this.type !== 'insert' && hash(getFormatedMetadataJSON(this.documentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.documentTextModel, this.modified?.metadata ?? {}, this.modified?.language)); + } + getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { return layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0) - 2; @@ -128,3 +150,31 @@ export class CellDiffViewModel extends Disposable { return (layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)) / 2 - 18 - 2; } } + +export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, metadata: NotebookCellMetadata, language?: string) { + let filteredMetadata: { [key: string]: any } = {}; + + if (documentTextModel) { + const transientMetadata = documentTextModel.transientOptions.transientMetadata; + + const keys = new Set([...Object.keys(metadata)]); + for (let key of keys) { + if (!(transientMetadata[key as keyof NotebookCellMetadata]) + ) { + filteredMetadata[key] = metadata[key as keyof NotebookCellMetadata]; + } + } + } else { + filteredMetadata = metadata; + } + + const content = JSON.stringify({ + language, + ...filteredMetadata + }); + + const edits = format(content, undefined, {}); + const metadataSource = applyEdits(content, edits); + + return metadataSource; +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 473e3cea78d..1f838eecf76 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -244,6 +244,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const modifiedCell = modifiedModel.cells[modifiedCellIndex + j]; if (originalCell.getHashValue() === modifiedCell.getHashValue()) { cellDiffViewModels.push(new CellDiffViewModel( + this._model.modified.notebook, originalCell, modifiedCell, 'unchanged', @@ -255,6 +256,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } cellDiffViewModels.push(new CellDiffViewModel( + this._model.modified.notebook, originalCell, modifiedCell, 'modified', @@ -275,6 +277,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let i = originalCellIndex; i < originalModel.cells.length; i++) { cellDiffViewModels.push(new CellDiffViewModel( + this._model.modified.notebook, originalModel.cells[i], modifiedModel.cells[i - originalCellIndex + modifiedCellIndex], 'unchanged', @@ -298,6 +301,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = 0; j < modifiedLen; j++) { result.push(new CellDiffViewModel( + modifiedModel, originalModel.cells[change.originalStart + j], modifiedModel.cells[change.modifiedStart + j], 'modified', @@ -308,6 +312,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.originalLength; j++) { // deletion result.push(new CellDiffViewModel( + originalModel, originalModel.cells[change.originalStart + j], undefined, 'delete', @@ -318,6 +323,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.modifiedLength; j++) { // insertion result.push(new CellDiffViewModel( + modifiedModel, undefined, modifiedModel.cells[change.modifiedStart + j], 'insert', diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts index 1a4fbe7bfcc..08e8abf93ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts @@ -90,7 +90,6 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[] const lineCount = buffer.getLineCount(); const fullRange = new Range(1, 1, lineCount, Math.max(1, buffer.getLineLastNonWhitespaceColumn(lineCount))); - container.innerText = buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined); if (renderANSI) { container.appendChild(handleANSIOutput(buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined), themeService)); } else { From 5954c8366d9646958e40bb4e50357afe7f8c22d2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Sat, 12 Dec 2020 01:34:26 +0100 Subject: [PATCH 0871/1837] Fix #112267 - Revert listener inside Submenu action - Create listner for submenu action changes in view menu actions --- src/vs/base/common/actions.ts | 16 +--- src/vs/platform/actions/common/actions.ts | 26 +++--- .../browser/parts/views/viewMenuActions.ts | 93 ++++++++++++------- 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 0a27986a452..8be6f19aff5 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { IDisposable, Disposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; export interface ITelemetryData { @@ -248,18 +248,12 @@ export class ActionWithMenuAction extends Action { export class SubmenuAction extends Action { - private _actions: IAction[] = []; - get actions(): IAction[] { return this._actions; } - - constructor(id: string, label: string, actions: IAction[], cssClass?: string) { - super(id, label, cssClass); - this.setActions(actions); + get actions(): IAction[] { + return this._actions; } - protected setActions(actions: IAction[]) { - this._actions = actions; - this._register(combinedDisposable(...actions)); - this.enabled = !!actions.length; + constructor(id: string, label: string, private _actions: IAction[], cssClass?: string) { + super(id, label, cssClass, !!_actions?.length); } } diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 2903669e7f7..dcc37228225 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -304,21 +304,18 @@ export class ExecuteCommandAction extends Action { export class SubmenuItemAction extends SubmenuAction { - constructor( - readonly item: ISubmenuItem, - private readonly menuService: IMenuService, - private readonly contextKeyService: IContextKeyService, - private readonly options?: IMenuActionOptions - ) { - super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, [], 'submenu'); - const menu = this._register(this.menuService.createMenu(this.item.submenu, this.contextKeyService)); - this.update(menu); - this._register(menu.onDidChange(() => this.update(menu))); - } + readonly item: ISubmenuItem; - private update(menu: IMenu): void { + constructor( + item: ISubmenuItem, + menuService: IMenuService, + contextKeyService: IContextKeyService, + options?: IMenuActionOptions + ) { const result: IAction[] = []; - const groups = menu.getActions(this.options); + const menu = menuService.createMenu(item.submenu, contextKeyService); + const groups = menu.getActions(options); + menu.dispose(); for (let group of groups) { const [, actions] = group; @@ -333,7 +330,8 @@ export class SubmenuItemAction extends SubmenuAction { result.pop(); // remove last separator } - this.setActions(result); + super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, result, 'submenu'); + this.item = item; } } diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts index 3454853ee65..49ab90e9ab6 100644 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ b/src/vs/workbench/browser/parts/views/viewMenuActions.ts @@ -4,19 +4,65 @@ *--------------------------------------------------------------------------------------------*/ import { IAction } from 'vs/base/common/actions'; -import { combinedDisposable, Disposable, dispose, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; -import { MenuId, IMenuService } from 'vs/platform/actions/common/actions'; +import { MenuId, IMenuService, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IViewDescriptorService, ViewContainer, ViewContainerLocationToString } from 'vs/workbench/common/views'; +class MenuActions extends Disposable { + + private readonly menu: IMenu; + + private _primaryActions: IAction[] = []; + get primaryActions() { return this._primaryActions; } + + private _secondaryActions: IAction[] = []; + get secondaryActions() { return this._secondaryActions; } + + private readonly _onDidChange = new Emitter(); + readonly onDidChange = this._onDidChange.event; + + private disposables = this._register(new DisposableStore()); + + constructor( + menuId: MenuId, + private readonly menuService: IMenuService, + private readonly contextKeyService: IContextKeyService + ) { + super(); + this.menu = this._register(menuService.createMenu(menuId, contextKeyService)); + this._register(this.menu.onDidChange(() => this.updateActions())); + this.updateActions(); + } + + private updateActions(): void { + this.disposables.clear(); + this._primaryActions = []; + this._secondaryActions = []; + this.disposables.add(createAndFillInActionBarActions(this.menu, { shouldForwardArgs: true }, { primary: this._primaryActions, secondary: this._secondaryActions })); + this.disposables.add(this.updateSubmenus([...this._primaryActions, ...this._secondaryActions], {})); + this._onDidChange.fire(); + } + + private updateSubmenus(actions: IAction[], submenus: { [id: number]: IMenu }): IDisposable { + const disposables = new DisposableStore(); + for (const action of actions) { + if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) { + const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService)); + disposables.add(menu.onDidChange(() => this.updateActions())); + disposables.add(this.updateSubmenus(action.actions, submenus)); + } + } + return disposables; + } +} + export abstract class AbstractViewMenuActions extends Disposable { - private primaryActions: IAction[] = []; - private readonly titleActionsDisposable = this._register(new MutableDisposable()); - private secondaryActions: IAction[] = []; - private contextMenuActions: IAction[] = []; + private readonly menuActions: MenuActions; + private readonly contextMenuActions: MenuActions; private _onDidChangeTitle = this._register(new Emitter()); readonly onDidChangeTitle: Event = this._onDidChangeTitle.event; @@ -28,44 +74,21 @@ export abstract class AbstractViewMenuActions extends Disposable { @IMenuService menuService: IMenuService, ) { super(); - - const menu = this._register(menuService.createMenu(menuId, contextKeyService)); - const updateActions = () => { - dispose(combinedDisposable(...this.primaryActions, ...this.secondaryActions)); - this.primaryActions = []; - this.secondaryActions = []; - this.titleActionsDisposable.value = createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, { primary: this.primaryActions, secondary: this.secondaryActions }); - this._onDidChangeTitle.fire(); - }; - this._register(menu.onDidChange(updateActions)); - updateActions(); - - const contextMenu = this._register(menuService.createMenu(contextMenuId, contextKeyService)); - const updateContextMenuActions = () => { - dispose(combinedDisposable(...this.contextMenuActions)); - this.contextMenuActions = []; - this.titleActionsDisposable.value = createAndFillInActionBarActions(contextMenu, { shouldForwardArgs: true }, { primary: [], secondary: this.contextMenuActions }); - }; - this._register(contextMenu.onDidChange(updateContextMenuActions)); - updateContextMenuActions(); - - this._register(toDisposable(() => { - this.primaryActions = []; - this.secondaryActions = []; - this.contextMenuActions = []; - })); + this.menuActions = this._register(new MenuActions(menuId, menuService, contextKeyService)); + this._register(this.menuActions.onDidChange(() => this._onDidChangeTitle.fire())); + this.contextMenuActions = this._register(new MenuActions(contextMenuId, menuService, contextKeyService)); } getPrimaryActions(): IAction[] { - return this.primaryActions; + return this.menuActions.primaryActions; } getSecondaryActions(): IAction[] { - return this.secondaryActions; + return this.menuActions.secondaryActions; } getContextMenuActions(): IAction[] { - return this.contextMenuActions; + return this.contextMenuActions.secondaryActions; } } From fad4717a787c7e4b193776a8203c70c0e3bfb961 Mon Sep 17 00:00:00 2001 From: Mohsen Yovan Date: Sun, 13 Dec 2020 01:14:58 -0500 Subject: [PATCH 0872/1837] Fix issue with dragging to select text on Hover should not hide it --- src/vs/editor/contrib/hover/hover.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index c57fbadbb41..a1f38fea3e9 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -162,6 +162,10 @@ export class ModesHoverController implements IEditorContribution { return; } + if (this._isHoverSticky && !mouseEvent.event.browserEvent.view?.getSelection()?.isCollapsed) { + // selected text within content hover widget return; } + return; + } if ( !this._isHoverSticky && targetType === MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === ModesContentHoverWidget.ID From 7e16a1e72ed395c23aaa887ea4b9e2be4df2bc8c Mon Sep 17 00:00:00 2001 From: Mohsen Yovan Date: Sun, 13 Dec 2020 01:16:27 -0500 Subject: [PATCH 0873/1837] Fixed issue with dragging to select text on Hover should not hide it --- src/vs/editor/contrib/hover/hover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index a1f38fea3e9..83c26d73729 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -163,7 +163,7 @@ export class ModesHoverController implements IEditorContribution { } if (this._isHoverSticky && !mouseEvent.event.browserEvent.view?.getSelection()?.isCollapsed) { - // selected text within content hover widget return; } + // selected text within content hover widget return; } From 873f23dc4cf1084e285b32349ee73fcd433266c2 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 13 Dec 2020 11:55:32 -0800 Subject: [PATCH 0874/1837] Fix line highlight when navigating to search results Fix #106209 --- src/vs/workbench/contrib/search/browser/searchView.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 30dc713f0fb..96902f92a83 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1745,9 +1745,10 @@ export class SearchView extends ViewPane { revealIfVisible: true } }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(editor => { - if (element instanceof Match && preserveFocus && isCodeEditor(editor)) { + const editorControl = editor?.getControl(); + if (element instanceof Match && preserveFocus && isCodeEditor(editorControl)) { this.viewModel.searchResult.rangeHighlightDecorations.highlightRange( - (editor.getControl()).getModel()!, + editorControl.getModel()!, element.range() ); } else { From 96b426ef1da0f0a51ce9ef1931cd1fd2322547e4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 13 Dec 2020 12:15:35 -0800 Subject: [PATCH 0875/1837] Remove dupe context key service registration in cell Fix #111280 --- src/vs/platform/contextkey/browser/contextKeyService.ts | 7 ++++++- .../notebook/browser/view/renderers/cellRenderer.ts | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 21320c0d6b8..2573add2a3e 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -417,7 +417,12 @@ class ScopedContextKeyService extends AbstractContextKeyService { if (domNode) { this._domNode = domNode; if (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) { - console.error('Element already has context attribute'); + let extraInfo = ''; + if ((this._domNode as HTMLElement).classList) { + extraInfo = Array.from((this._domNode as HTMLElement).classList.values()).join(', '); + } + + console.error(`Element already has context attribute${extraInfo ? ': ' + extraInfo : ''}`); } this._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId)); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index ac81b9a601e..ba8b9bb81b1 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -712,13 +712,14 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende const executionOrderLabel = DOM.append(cellContainer, $('div.execution-count-label')); + const editorPart = DOM.append(cellContainer, $('.cell-editor-part')); + const editorContainer = DOM.append(editorPart, $('.cell-editor-container')); + // create a special context key service that set the inCompositeEditor-contextkey - const editorContextKeyService = disposables.add(this.contextKeyServiceProvider(container)); + const editorContextKeyService = disposables.add(this.contextKeyServiceProvider(editorPart)); const editorInstaService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, editorContextKeyService])); EditorContextKeys.inCompositeEditor.bindTo(editorContextKeyService).set(true); - const editorPart = DOM.append(cellContainer, $('.cell-editor-part')); - const editorContainer = DOM.append(editorPart, $('.cell-editor-container')); const editor = editorInstaService.createInstance(CodeEditorWidget, editorContainer, { ...this.editorOptions.value, dimension: { From 28964872e7bf24e65d58f5ba94316152fe908fc3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 08:13:35 +0100 Subject: [PATCH 0876/1837] lifecycle - log long running operations preventing shutdown (for #112278) --- src/vs/workbench/browser/web.main.ts | 3 +- .../contrib/backup/common/backupTracker.ts | 2 +- .../tasks/electron-browser/taskService.ts | 2 +- .../terminal/browser/terminalService.ts | 2 +- .../electron-browser/desktop.main.ts | 2 +- .../electron-sandbox/desktop.main.ts | 2 +- .../localProcessExtensionHost.ts | 2 +- .../host/browser/browserHostService.ts | 3 +- .../lifecycle/browser/lifecycleService.ts | 17 ++-- .../services/lifecycle/common/lifecycle.ts | 10 ++- .../electron-sandbox/lifecycleService.ts | 78 ++++++++++++++----- .../browser/browserTextFileService.ts | 4 +- .../browser/userDataSyncWorkbenchService.ts | 2 +- .../workspaceEditingService.ts | 32 ++++---- 14 files changed, 103 insertions(+), 58 deletions(-) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 564721dc09b..a8a86fd763c 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -145,8 +145,7 @@ class BrowserMain extends Disposable { // Workbench Lifecycle this._register(workbench.onBeforeShutdown(event => { if (storageService.hasPendingUpdate) { - logService.warn('Unload veto: pending storage update'); - event.veto(true); // prevent data loss from pending storage update + event.veto(true, 'veto.pendingStorageUpdate'); // prevent data loss from pending storage update } })); this._register(workbench.onWillShutdown(() => storageService.close())); diff --git a/src/vs/workbench/contrib/backup/common/backupTracker.ts b/src/vs/workbench/contrib/backup/common/backupTracker.ts index d8f35fc9dae..463d69e2355 100644 --- a/src/vs/workbench/contrib/backup/common/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/common/backupTracker.ts @@ -43,7 +43,7 @@ export abstract class BackupTracker extends Disposable { this._register(this.workingCopyService.onDidChangeContent(workingCopy => this.onDidChangeContent(workingCopy))); // Lifecycle (handled in subclasses) - this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason))); + this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason), 'veto.backups')); } private onDidRegister(workingCopy: IWorkingCopy): void { diff --git a/src/vs/workbench/contrib/tasks/electron-browser/taskService.ts b/src/vs/workbench/contrib/tasks/electron-browser/taskService.ts index 64fe0389f65..3df8b849992 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/taskService.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/taskService.ts @@ -116,7 +116,7 @@ export class TaskService extends AbstractTaskService { preferencesService, viewDescriptorService, logService); - this._register(lifecycleService.onBeforeShutdown(event => event.veto(this.beforeShutdown()))); + this._register(lifecycleService.onBeforeShutdown(event => event.veto(this.beforeShutdown(), 'veto.tasks'))); } protected getTaskSystem(): ITaskSystem { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index f82474d5f55..83b4cf26c03 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -123,7 +123,7 @@ export class TerminalService implements ITerminalService { this._activeTabIndex = 0; this._isShuttingDown = false; this._findState = new FindReplaceState(); - lifecycleService.onBeforeShutdown(async event => event.veto(this._onBeforeShutdown())); + lifecycleService.onBeforeShutdown(async event => event.veto(this._onBeforeShutdown(), 'veto.terminal')); lifecycleService.onShutdown(() => this._onShutdown()); this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); this._terminalShellTypeContextKey = KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE.bindTo(this._contextKeyService); diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index dd3d59cb4ea..c20dc166cde 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -145,7 +145,7 @@ class DesktopMain extends Disposable { // Workbench Lifecycle this._register(workbench.onShutdown(() => this.dispose())); - this._register(workbench.onWillShutdown(event => event.join(storageService.close()))); + this._register(workbench.onWillShutdown(event => event.join(storageService.close(), 'join.closeStorage'))); } private onWindowResize(e: Event, retry: boolean, workbench: Workbench): void { diff --git a/src/vs/workbench/electron-sandbox/desktop.main.ts b/src/vs/workbench/electron-sandbox/desktop.main.ts index dc8f60572cc..0ed5c1ff869 100644 --- a/src/vs/workbench/electron-sandbox/desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/desktop.main.ts @@ -117,7 +117,7 @@ class DesktopMain extends Disposable { // Workbench Lifecycle this._register(workbench.onShutdown(() => this.dispose())); - this._register(workbench.onWillShutdown(event => event.join(storageService.close()))); + this._register(workbench.onWillShutdown(event => event.join(storageService.close(), 'join.closeStorage'))); } private onWindowResize(e: Event, retry: boolean, workbench: Workbench): void { diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 34fa2c3b059..101ece12361 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -651,7 +651,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { // to communicate this back to the main side to terminate the debug session if (this._isExtensionDevHost && !this._isExtensionDevTestFromCli && !this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) { this._extensionHostDebugService.terminateSession(this._environmentService.debugExtensionHost.debugId); - event.join(timeout(100 /* wait a bit for IPC to get delivered */)); + event.join(timeout(100 /* wait a bit for IPC to get delivered */), 'join.extensionDevelopment'); } } } diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 61c461c75bf..88bd1f4f797 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -126,8 +126,7 @@ export class BrowserHostService extends Disposable implements IHostService { case HostShutdownReason.Keyboard: const confirmBeforeClose = this.configurationService.getValue<'always' | 'keyboardOnly' | 'never'>('window.confirmBeforeClose'); if (confirmBeforeClose === 'always' || (confirmBeforeClose === 'keyboardOnly' && this.shutdownReason === HostShutdownReason.Keyboard)) { - this.logService.warn(`Unload veto: window.confirmBeforeClose=${confirmBeforeClose}`); - e.veto(true); + e.veto(true, 'veto.confirmBeforeClose'); } break; diff --git a/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts b/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts index 77c97f2fd5d..fe323702d86 100644 --- a/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/browser/lifecycleService.ts @@ -77,12 +77,17 @@ export class BrowserLifecycleService extends AbstractLifecycleService { // Before Shutdown this._onBeforeShutdown.fire({ - veto(value) { + veto(value, id) { if (typeof handleVeto === 'function') { + if (value instanceof Promise) { + logService.error(`[lifecycle] Long running operations before shutdown are unsupported in the web (id: ${id})`); + + value = true; // implicitly vetos since we cannot handle promises in web + } + if (value === true) { - veto = true; - } else if (value instanceof Promise && !veto) { - logService.error('[lifecycle] Long running onBeforeShutdown currently not supported in the web'); + logService.info(`[lifecycle]: Unload was prevented (id: ${id})`); + veto = true; } } @@ -99,8 +104,8 @@ export class BrowserLifecycleService extends AbstractLifecycleService { // No Veto: continue with Will Shutdown this._onWillShutdown.fire({ - join() { - logService.error('[lifecycle] Long running onWillShutdown currently not supported in the web'); + join(promise, id) { + logService.error(`[lifecycle] Long running operations during shutdown are unsupported in the web (id: ${id})`); }, reason: ShutdownReason.QUIT }); diff --git a/src/vs/workbench/services/lifecycle/common/lifecycle.ts b/src/vs/workbench/services/lifecycle/common/lifecycle.ts index 876edba7db3..355cd49265c 100644 --- a/src/vs/workbench/services/lifecycle/common/lifecycle.ts +++ b/src/vs/workbench/services/lifecycle/common/lifecycle.ts @@ -22,8 +22,11 @@ export interface BeforeShutdownEvent { /** * Allows to veto the shutdown. The veto can be a long running operation but it * will block the application from closing. + * + * @param id to identify the veto operation in case it takes very long or never + * completes. */ - veto(value: boolean | Promise): void; + veto(value: boolean | Promise, id: string): void; /** * The reason why the application will be shutting down. @@ -44,8 +47,11 @@ export interface WillShutdownEvent { /** * Allows to join the shutdown. The promise can be a long running operation but it * will block the application from closing. + * + * @param id to identify the join operation in case it takes very long or never + * completes. */ - join(promise: Promise): void; + join(promise: Promise, id: string): void; /** * The reason why the application is shutting down. diff --git a/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts index e9fb6c211d0..61716c228f4 100644 --- a/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts @@ -16,11 +16,15 @@ import { AbstractLifecycleService } from 'vs/workbench/services/lifecycle/common import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import Severity from 'vs/base/common/severity'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; +import { disposableTimeout } from 'vs/base/common/async'; export class NativeLifecycleService extends AbstractLifecycleService { private static readonly LAST_SHUTDOWN_REASON_KEY = 'lifecyle.lastShutdownReason'; + private static readonly BEFORE_SHUTDOWN_WARNING_DELAY = 5000; + private static readonly WILL_SHUTDOWN_WARNING_DELAY = 5000; + declare readonly _serviceBrand: undefined; private shutdownReason: ShutdownReason | undefined; @@ -51,7 +55,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { startupKind = StartupKind.NewWindow; } - this.logService.trace(`lifecycle: starting up (startup kind: ${this._startupKind})`); + this.logService.trace(`[lifecycle] starting up (startup kind: ${this._startupKind})`); return startupKind; } @@ -61,16 +65,16 @@ export class NativeLifecycleService extends AbstractLifecycleService { // Main side indicates that window is about to unload, check for vetos ipcRenderer.on('vscode:onBeforeUnload', (event: unknown, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => { - this.logService.trace(`lifecycle: onBeforeUnload (reason: ${reply.reason})`); + this.logService.trace(`[lifecycle] onBeforeUnload (reason: ${reply.reason})`); // trigger onBeforeShutdown events and veto collecting this.handleBeforeShutdown(reply.reason).then(veto => { if (veto) { - this.logService.trace('lifecycle: onBeforeUnload prevented via veto'); + this.logService.trace('[lifecycle] onBeforeUnload prevented via veto'); ipcRenderer.send(reply.cancelChannel, windowId); } else { - this.logService.trace('lifecycle: onBeforeUnload continues without veto'); + this.logService.trace('[lifecycle] onBeforeUnload continues without veto'); this.shutdownReason = reply.reason; ipcRenderer.send(reply.okChannel, windowId); @@ -80,7 +84,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { // Main side indicates that we will indeed shutdown ipcRenderer.on('vscode:onWillUnload', async (event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => { - this.logService.trace(`lifecycle: onWillUnload (reason: ${reply.reason})`); + this.logService.trace(`[lifecycle] onWillUnload (reason: ${reply.reason})`); // trigger onWillShutdown events and joining await this.handleWillShutdown(reply.reason); @@ -100,35 +104,71 @@ export class NativeLifecycleService extends AbstractLifecycleService { }); } - private handleBeforeShutdown(reason: ShutdownReason): Promise { + private async handleBeforeShutdown(reason: ShutdownReason): Promise { + const logService = this.logService; const vetos: (boolean | Promise)[] = []; + const pendingVetos = new Set(); this._onBeforeShutdown.fire({ - veto(value) { + veto(value, id) { vetos.push(value); - }, - reason - }); - return handleVetos(vetos, error => this.onShutdownError(reason, error)); - } + // Log any veto instantly + if (value === true) { + logService.info(`[lifecycle]: Shutdown was prevented (id: ${id})`); + } - private async handleWillShutdown(reason: ShutdownReason): Promise { - const joiners: Promise[] = []; - - this._onWillShutdown.fire({ - join(promise) { - if (promise) { - joiners.push(promise); + // Track promise completion + else if (value instanceof Promise) { + pendingVetos.add(id); + value.then(veto => { + if (veto === true) { + logService.info(`[lifecycle]: Shutdown was prevented (id: ${id})`); + } + }).finally(() => pendingVetos.delete(id)); } }, reason }); + const longRunningBeforeShutdownWarning = disposableTimeout(() => { + logService.warn(`[lifecycle] onBeforeShutdown is taking a long time, pending operations: ${Array.from(pendingVetos).join(', ')}`); + }, NativeLifecycleService.BEFORE_SHUTDOWN_WARNING_DELAY); + + try { + return await handleVetos(vetos, error => this.onShutdownError(reason, error)); + } finally { + longRunningBeforeShutdownWarning.dispose(); + } + } + + private async handleWillShutdown(reason: ShutdownReason): Promise { + const joiners: Promise[] = []; + const pendingJoiners = new Set(); + + this._onWillShutdown.fire({ + join(promise, id) { + if (promise) { + joiners.push(promise); + + // Track promise completion + pendingJoiners.add(id); + promise.finally(() => pendingJoiners.delete(id)); + } + }, + reason + }); + + const longRunningWillShutdownWarning = disposableTimeout(() => { + this.logService.warn(`[lifecycle] onWillShutdown is taking a long time, pending operations: ${Array.from(pendingJoiners).join(', ')}`); + }, NativeLifecycleService.WILL_SHUTDOWN_WARNING_DELAY); + try { await Promise.all(joiners); } catch (error) { this.onShutdownError(reason, error); + } finally { + longRunningWillShutdownWarning.dispose(); } } diff --git a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts index 3e67665f82c..941b946dcb2 100644 --- a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts +++ b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts @@ -14,13 +14,11 @@ export class BrowserTextFileService extends AbstractTextFileService { super.registerListeners(); // Lifecycle - this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason))); + this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason), 'veto.textFiles')); } protected onBeforeShutdown(reason: ShutdownReason): boolean { if (this.files.models.some(model => model.hasState(TextFileEditorModelState.PENDING_SAVE))) { - this.logService.warn('Unload veto: pending file saves'); - return true; // files are pending to be saved: veto } diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts index 41b78ea3741..8daa50d6e3e 100644 --- a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts +++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts @@ -271,7 +271,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat const manualSyncTask = await this.userDataSyncService.createManualSyncTask(); const disposable = isWeb ? Disposable.None /* In web long running shutdown handlers will not work */ - : this.lifecycleService.onBeforeShutdown(e => e.veto(this.onBeforeShutdown(manualSyncTask))); + : this.lifecycleService.onBeforeShutdown(e => e.veto(this.onBeforeShutdown(manualSyncTask), 'veto.settingsSync')); try { await this.syncBeforeTurningOn(title, manualSyncTask); diff --git a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts index c48fc29d852..77847a0bd67 100644 --- a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { URI } from 'vs/base/common/uri'; -import * as nls from 'vs/nls'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IWorkspacesService, isUntitledWorkspace, IWorkspaceIdentifier, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; @@ -66,7 +66,7 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi this.lifecycleService.onBeforeShutdown(e => { const saveOperation = this.saveUntitledBeforeShutdown(e.reason); if (saveOperation) { - e.veto(saveOperation); + e.veto(saveOperation, 'veto.untitledWorkspace'); } }); } @@ -92,16 +92,14 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi CANCEL } - const buttons: { label: string; result: ConfirmResult; }[] = [ - { label: mnemonicButtonLabel(nls.localize('save', "Save")), result: ConfirmResult.SAVE }, - { label: mnemonicButtonLabel(nls.localize('doNotSave', "Don't Save")), result: ConfirmResult.DONT_SAVE }, - { label: nls.localize('cancel', "Cancel"), result: ConfirmResult.CANCEL } + const buttons = [ + { label: mnemonicButtonLabel(localize('save', "Save")), result: ConfirmResult.SAVE }, + { label: mnemonicButtonLabel(localize('doNotSave', "Don't Save")), result: ConfirmResult.DONT_SAVE }, + { label: localize('cancel', "Cancel"), result: ConfirmResult.CANCEL } ]; - const message = nls.localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"); - const detail = nls.localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."); - const cancelId = 2; - - const { choice } = await this.dialogService.show(Severity.Warning, message, buttons.map(button => button.label), { detail, cancelId }); + const message = localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"); + const detail = localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."); + const { choice } = await this.dialogService.show(Severity.Warning, message, buttons.map(button => button.label), { detail, cancelId: 2 }); switch (buttons[choice].result) { @@ -111,7 +109,7 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi // Don't Save: delete workspace case ConfirmResult.DONT_SAVE: - this.workspacesService.deleteUntitledWorkspace(workspaceIdentifier); + await this.workspacesService.deleteUntitledWorkspace(workspaceIdentifier); return false; // Save: save workspace, but do not veto unload if path provided @@ -126,13 +124,13 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi // Make sure to add the new workspace to the history to find it again const newWorkspaceIdentifier = await this.workspacesService.getWorkspaceIdentifier(newWorkspacePath); - this.workspacesService.addRecentlyOpened([{ + await this.workspacesService.addRecentlyOpened([{ label: this.labelService.getWorkspaceLabel(newWorkspaceIdentifier, { verbose: true }), workspace: newWorkspaceIdentifier }]); // Delete the untitled one - this.workspacesService.deleteUntitledWorkspace(workspaceIdentifier); + await this.workspacesService.deleteUntitledWorkspace(workspaceIdentifier); } catch (error) { // ignore } @@ -149,10 +147,10 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi if (windows.some(window => !!window.workspace && this.uriIdentityService.extUri.isEqual(window.workspace.configPath, path))) { await this.dialogService.show( Severity.Info, - nls.localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), - [nls.localize('ok', "OK")], + localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), + [localize('ok', "OK")], { - detail: nls.localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again.") + detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again.") } ); From 1a2132f16ee1652226ceb30e38ac19bf7100efa9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 08:14:07 +0100 Subject: [PATCH 0877/1837] web - show dispose dialog only upon user interaction --- src/vs/workbench/browser/window.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts index c6fa4c1f5e5..fb9fcb63913 100644 --- a/src/vs/workbench/browser/window.ts +++ b/src/vs/workbench/browser/window.ts @@ -3,7 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { windowOpenNoOpener } from 'vs/base/browser/dom'; +import { EventType, windowOpenNoOpener } from 'vs/base/browser/dom'; +import { domEvent } from 'vs/base/browser/event'; +import { timeout } from 'vs/base/common/async'; +import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; @@ -33,9 +36,19 @@ export class BrowserWindow extends Disposable { } private onWillShutdown(): void { - // Use a timeout so that the dialog does not appear on each reload - // that is triggered by the user itself. - setTimeout(async () => { + + // Try to detect some user interaction with the workbench + // when shutdown has happened to not show the dialog e.g. + // when navigation takes a longer time. + Event.toPromise(Event.any( + Event.once(domEvent(document.body, EventType.KEY_DOWN, true)), + Event.once(domEvent(document.body, EventType.MOUSE_DOWN, true)) + )).then(async () => { + + // Delay the dialog in case the user interacted + // with the page before it transitioned away + await timeout(3000); + // This should normally not happen, but if for some reason // the workbench was shutdown while the page is still there, // inform the user that only a reload can bring back a working @@ -54,7 +67,7 @@ export class BrowserWindow extends Disposable { if (res.choice === 0) { this.hostService.reload(); } - }, 1500); + }); } private create(): void { From 1a1db8f00e7eb08336046009c2938004123af225 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 08:15:31 +0100 Subject: [PATCH 0878/1837] bootstrap - add more typing info --- src/bootstrap-node.js | 2 +- src/bootstrap-window.js | 28 +++++++++++-------- src/main.js | 28 ++++++++++--------- .../electron-browser/workbench/workbench.js | 2 +- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/bootstrap-node.js b/src/bootstrap-node.js index 161d68d5941..eaaf1dc6100 100644 --- a/src/bootstrap-node.js +++ b/src/bootstrap-node.js @@ -62,7 +62,7 @@ exports.removeGlobalNodeModuleLookupPaths = function () { /** * Helper to enable portable mode. * - * @param {{ portable?: string; applicationName: string; }} product + * @param {Partial} product * @returns {{ portableDataPath: string; isPortable: boolean; }} */ exports.configurePortable = function (product) { diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index d7cc72d3bd8..fe6059c56de 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -34,7 +34,7 @@ /** * @param {string[]} modulePaths - * @param {(result, configuration: object) => any} resultCallback + * @param {(result: unknown, configuration: object) => Promise | undefined} resultCallback * @param {{ forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config: object) => void, beforeLoaderConfig?: (config: object, loaderConfig: object) => void, beforeRequire?: () => void }=} options */ function load(modulePaths, resultCallback, options) { @@ -166,7 +166,7 @@ } /** - * Parses the contents of the `INativeWindowConfiguration` that + * Parses the contents of the window condiguration that * is passed into the URL from the `electron-main` side. * * @returns {{ @@ -195,22 +195,26 @@ function registerDeveloperKeybindings(disallowReloadKeybinding) { const ipcRenderer = preloadGlobals.ipcRenderer; - const extractKey = function (e) { - return [ - e.ctrlKey ? 'ctrl-' : '', - e.metaKey ? 'meta-' : '', - e.altKey ? 'alt-' : '', - e.shiftKey ? 'shift-' : '', - e.keyCode - ].join(''); - }; + const extractKey = + /** + * @param {KeyboardEvent} e + */ + function (e) { + return [ + e.ctrlKey ? 'ctrl-' : '', + e.metaKey ? 'meta-' : '', + e.altKey ? 'alt-' : '', + e.shiftKey ? 'shift-' : '', + e.keyCode + ].join(''); + }; // Devtools & reload support const TOGGLE_DEV_TOOLS_KB = (safeProcess.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I const TOGGLE_DEV_TOOLS_KB_ALT = '123'; // F12 const RELOAD_KB = (safeProcess.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R - /** @type {((e: any) => void) | undefined} */ + /** @type {((e: KeyboardEvent) => void) | undefined} */ let listener = function (e) { const key = extractKey(e); if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) { diff --git a/src/main.js b/src/main.js index 0bc566099a2..b8a98c7d10f 100644 --- a/src/main.js +++ b/src/main.js @@ -7,17 +7,16 @@ 'use strict'; const perf = require('./vs/base/common/performance'); -const lp = require('./vs/base/node/languagePacks'); - perf.mark('main:started'); +const lp = require('./vs/base/node/languagePacks'); const path = require('path'); const fs = require('fs'); const os = require('os'); const bootstrap = require('./bootstrap'); const bootstrapNode = require('./bootstrap-node'); const paths = require('./paths'); -/** @type {any} */ +/** @type {Partial & { applicationName: string}} */ const product = require('../product.json'); const { app, protocol, crashReporter } = require('electron'); @@ -213,9 +212,7 @@ async function onReady() { } /** - * @typedef {{ [arg: string]: any; '--'?: string[]; _: string[]; }} NativeParsedArgs - * - * @param {NativeParsedArgs} cliArgs + * @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs */ function configureCommandlineSwitchesSync(cliArgs) { const SUPPORTED_ELECTRON_SWITCHES = [ @@ -368,7 +365,7 @@ function getArgvConfigPath() { } /** - * @param {NativeParsedArgs} cliArgs + * @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs * @returns {string | null} */ function getJSFlags(cliArgs) { @@ -388,7 +385,7 @@ function getJSFlags(cliArgs) { } /** - * @param {NativeParsedArgs} cliArgs + * @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs * * @returns {string} */ @@ -401,7 +398,7 @@ function getUserDataPath(cliArgs) { } /** - * @returns {NativeParsedArgs} + * @returns {import('./vs/platform/environment/common/argv').NativeParsedArgs} */ function parseCLIArgs() { const minimist = require('minimist'); @@ -450,11 +447,16 @@ function registerListeners() { * @type {string[]} */ const openUrls = []; - const onOpenUrl = function (event, url) { - event.preventDefault(); + const onOpenUrl = + /** + * @param {{ preventDefault: () => void; }} event + * @param {string} url + */ + function (event, url) { + event.preventDefault(); - openUrls.push(url); - }; + openUrls.push(url); + }; app.on('will-finish-launching', function () { app.on('open-url', onOpenUrl); diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 14c69946174..761ce9c812a 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -51,7 +51,7 @@ /** * @returns {{ - * load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown, + * load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => any, options: object) => unknown, * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals'), * perfLib: () => { mark: (name: string) => void } * }} From d8a4891005347b287fca620f2f20243e063f5807 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 08:23:23 +0100 Subject: [PATCH 0879/1837] windows - first cut cleanup of windows finding logic --- .../sharedProcess/sharedProcessMain.ts | 2 +- src/vs/code/electron-main/app.ts | 24 ++- .../electron-main/extensionHostDebugIpc.ts | 3 +- .../launch/electron-main/launchMainService.ts | 3 +- .../platform/menubar/electron-main/menubar.ts | 3 +- .../electron-main/nativeHostMainService.ts | 3 +- src/vs/platform/windows/common/windows.ts | 108 ++++++------- .../platform/windows/electron-main/window.ts | 150 ----------------- .../platform/windows/electron-main/windows.ts | 22 ++- .../windows/electron-main/windowsFinder.ts | 79 +++++++++ .../electron-main/windowsMainService.ts | 74 ++++----- .../electron-main/windowsStateStorage.ts | 22 +-- .../windows/{common => node}/windowTracker.ts | 0 .../windows/test/electron-main/window.test.ts | 153 ++++++++---------- .../electron-main/workspacesMainService.ts | 12 +- 15 files changed, 299 insertions(+), 359 deletions(-) delete mode 100644 src/vs/platform/windows/electron-main/window.ts create mode 100644 src/vs/platform/windows/electron-main/windowsFinder.ts rename src/vs/platform/windows/{common => node}/windowTracker.ts (100%) diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 3dcc360b59e..1224377cb0d 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -67,7 +67,7 @@ import { ExtensionTipsService } from 'vs/platform/extensionManagement/electron-s import { UserDataSyncMachinesService, IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines'; import { IExtensionRecommendationNotificationService } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { ExtensionRecommendationNotificationServiceChannelClient } from 'vs/platform/extensionRecommendations/electron-sandbox/extensionRecommendationsIpc'; -import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; +import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker'; import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender'; import { UserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataAutoSyncService'; import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions'; diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 6eb685b7926..920833f540a 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -7,7 +7,6 @@ import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindo import { IProcessEnvironment, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { resolveShellEnv } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; @@ -36,7 +35,7 @@ import product from 'vs/platform/product/common/product'; import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { FileProtocolHandler } from 'vs/code/electron-main/protocol'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, ICodeWindow, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { URI } from 'vs/base/common/uri'; import { hasWorkspaceFileExtension, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { WorkspacesService } from 'vs/platform/workspaces/electron-main/workspacesService'; @@ -80,7 +79,7 @@ import { stripComments } from 'vs/base/common/json'; import { generateUuid } from 'vs/base/common/uuid'; import { VSBuffer } from 'vs/base/common/buffer'; import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService'; -import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; +import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; @@ -89,6 +88,7 @@ import { isEqualOrParent } from 'vs/base/common/extpath'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService'; +import { once } from 'vs/base/common/functional'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -320,10 +320,10 @@ export class CodeApplication extends Disposable { acceptShellEnv(shellEnv); }); - ipcMain.handle('vscode:writeNlsFile', (event, path: unknown, data: unknown) => { + ipcMain.handle('vscode:writeNlsFile', async (event, path: unknown, data: unknown) => { const uri = this.validateNlsPath([path]); if (!uri || typeof data !== 'string') { - return Promise.reject('Invalid operation (vscode:writeNlsFile)'); + throw new Error('Invalid operation (vscode:writeNlsFile)'); } return this.fileService.writeFile(uri, VSBuffer.fromString(data)); @@ -332,7 +332,7 @@ export class CodeApplication extends Disposable { ipcMain.handle('vscode:readNlsFile', async (event, ...paths: unknown[]) => { const uri = this.validateNlsPath(paths); if (!uri) { - return Promise.reject('Invalid operation (vscode:readNlsFile)'); + throw new Error('Invalid operation (vscode:readNlsFile)'); } return (await this.fileService.readFile(uri)).value.toString(); @@ -896,6 +896,18 @@ export class CodeApplication extends Disposable { // Signal phase: after window open this.lifecycleMainService.phase = LifecycleMainPhase.AfterWindowOpen; + // Windows: install mutex + const win32MutexName = product.win32MutexName; + if (isWindows && win32MutexName) { + try { + const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex; + const mutex = new WindowsMutex(win32MutexName); + once(this.lifecycleMainService.onWillShutdown)(() => mutex.release()); + } catch (e) { + this.logService.error(e); + } + } + // Remote Authorities protocol.registerHttpProtocol(Schemas.vscodeRemoteResource, (request, callback) => { callback({ diff --git a/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts b/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts index 7cc40f9086d..f0ac255cb2a 100644 --- a/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts +++ b/src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts @@ -8,8 +8,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { createServer, AddressInfo } from 'net'; import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; -import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; +import { IWindowsMainService, OpenContext } from 'vs/platform/windows/electron-main/windows'; export class ElectronExtensionHostDebugBroadcastChannel extends ExtensionHostDebugBroadcastChannel { diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 61e66f0fd6a..97d251557da 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -9,8 +9,7 @@ import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWindowSettings } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; -import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, ICodeWindow, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { whenDeleted } from 'vs/base/node/pfs'; import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 215be10e210..ad187bf1770 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -8,7 +8,6 @@ import { isMacintosh, language } from 'vs/base/common/platform'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { app, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, KeyboardEvent } from 'electron'; import { getTitleBarStyle, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService, StateType } from 'vs/platform/update/common/update'; @@ -16,7 +15,7 @@ import product from 'vs/platform/product/common/product'; import { RunOnceScheduler } from 'vs/base/common/async'; import { ILogService } from 'vs/platform/log/common/log'; import { mnemonicMenuLabel } from 'vs/base/common/labels'; -import { IWindowsMainService, IWindowsCountChangedEvent } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, IWindowsCountChangedEvent, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IMenubarData, IMenubarKeybinding, MenubarMenuItem, isMenubarMenuItemSeparator, isMenubarMenuItemSubmenu, isMenubarMenuItemAction, IMenubarMenu, isMenubarMenuItemUriAction } from 'vs/platform/menubar/common/menubar'; import { URI } from 'vs/base/common/uri'; diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index 57b2a5c8822..9b655201eef 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -4,9 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; -import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, ICodeWindow, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme } from 'electron'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index ca3e63d96ed..cae49ffdd3f 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -18,38 +18,38 @@ export const WindowMinimumSize = { }; export interface IBaseOpenWindowsOptions { - forceReuseWindow?: boolean; + readonly forceReuseWindow?: boolean; } export interface IOpenWindowOptions extends IBaseOpenWindowsOptions { - forceNewWindow?: boolean; - preferNewWindow?: boolean; + readonly forceNewWindow?: boolean; + readonly preferNewWindow?: boolean; - noRecentEntry?: boolean; + readonly noRecentEntry?: boolean; - addMode?: boolean; + readonly addMode?: boolean; - diffMode?: boolean; - gotoLineMode?: boolean; + readonly diffMode?: boolean; + readonly gotoLineMode?: boolean; - waitMarkerFileURI?: URI; + readonly waitMarkerFileURI?: URI; } export interface IAddFoldersRequest { - foldersToAdd: UriComponents[]; + readonly foldersToAdd: UriComponents[]; } export interface IOpenedWindow { - id: number; - workspace?: IWorkspaceIdentifier; - folderUri?: ISingleFolderWorkspaceIdentifier; - title: string; - filename?: string; - dirty: boolean; + readonly id: number; + readonly workspace?: IWorkspaceIdentifier; + readonly folderUri?: ISingleFolderWorkspaceIdentifier; + readonly title: string; + readonly filename?: string; + readonly dirty: boolean; } export interface IOpenEmptyWindowOptions extends IBaseOpenWindowsOptions { - remoteAuthority?: string; + readonly remoteAuthority?: string; } export type IWindowOpenable = IWorkspaceToOpen | IFolderToOpen | IFileToOpen; @@ -59,15 +59,15 @@ export interface IBaseWindowOpenable { } export interface IWorkspaceToOpen extends IBaseWindowOpenable { - workspaceUri: URI; + readonly workspaceUri: URI; } export interface IFolderToOpen extends IBaseWindowOpenable { - folderUri: URI; + readonly folderUri: URI; } export interface IFileToOpen extends IBaseWindowOpenable { - fileUri: URI; + readonly fileUri: URI; } export function isWorkspaceToOpen(uriToOpen: IWindowOpenable): uriToOpen is IWorkspaceToOpen { @@ -96,25 +96,25 @@ export function getMenuBarVisibility(configurationService: IConfigurationService } export interface IWindowsConfiguration { - window: IWindowSettings; + readonly window: IWindowSettings; } export interface IWindowSettings { - openFilesInNewWindow: 'on' | 'off' | 'default'; - openFoldersInNewWindow: 'on' | 'off' | 'default'; - openWithoutArgumentsInNewWindow: 'on' | 'off'; - restoreWindows: 'preserve' | 'all' | 'folders' | 'one' | 'none'; - restoreFullscreen: boolean; - zoomLevel: number; - titleBarStyle: 'native' | 'custom'; - autoDetectHighContrast: boolean; - menuBarVisibility: MenuBarVisibility; - newWindowDimensions: 'default' | 'inherit' | 'offset' | 'maximized' | 'fullscreen'; - nativeTabs: boolean; - nativeFullScreen: boolean; - enableMenuBarMnemonics: boolean; - closeWhenEmpty: boolean; - clickThroughInactive: boolean; + readonly openFilesInNewWindow: 'on' | 'off' | 'default'; + readonly openFoldersInNewWindow: 'on' | 'off' | 'default'; + readonly openWithoutArgumentsInNewWindow: 'on' | 'off'; + readonly restoreWindows: 'preserve' | 'all' | 'folders' | 'one' | 'none'; + readonly restoreFullscreen: boolean; + readonly zoomLevel: number; + readonly titleBarStyle: 'native' | 'custom'; + readonly autoDetectHighContrast: boolean; + readonly menuBarVisibility: MenuBarVisibility; + readonly newWindowDimensions: 'default' | 'inherit' | 'offset' | 'maximized' | 'fullscreen'; + readonly nativeTabs: boolean; + readonly nativeFullScreen: boolean; + readonly enableMenuBarMnemonics: boolean; + readonly closeWhenEmpty: boolean; + readonly clickThroughInactive: boolean; } export function getTitleBarStyle(configurationService: IConfigurationService): 'native' | 'custom' { @@ -153,24 +153,24 @@ export interface IPath extends IPathData { export interface IPathData { // the file path to open within the instance - fileUri?: UriComponents; + readonly fileUri?: UriComponents; // the line number in the file path to open - lineNumber?: number; + readonly lineNumber?: number; // the column number in the file path to open - columnNumber?: number; + readonly columnNumber?: number; // a hint that the file exists. if true, the // file exists, if false it does not. with // undefined the state is unknown. - exists?: boolean; + readonly exists?: boolean; // Specifies if the file should be only be opened if it exists - openOnlyIfExists?: boolean; + readonly openOnlyIfExists?: boolean; // Specifies an optional id to override the editor used to edit the resource, e.g. custom editor. - overrideId?: string; + readonly overrideId?: string; } export interface IPathsToWaitFor extends IPathsToWaitForData { @@ -179,36 +179,36 @@ export interface IPathsToWaitFor extends IPathsToWaitForData { } interface IPathsToWaitForData { - paths: IPathData[]; - waitMarkerFileUri: UriComponents; + readonly paths: IPathData[]; + readonly waitMarkerFileUri: UriComponents; } export interface IOpenFileRequest { - filesToOpenOrCreate?: IPathData[]; - filesToDiff?: IPathData[]; + readonly filesToOpenOrCreate?: IPathData[]; + readonly filesToDiff?: IPathData[]; } /** * Additional context for the request on native only. */ export interface INativeOpenFileRequest extends IOpenFileRequest { - termProgram?: string; - filesToWait?: IPathsToWaitForData; + readonly termProgram?: string; + readonly filesToWait?: IPathsToWaitForData; } export interface INativeRunActionInWindowRequest { - id: string; - from: 'menu' | 'touchbar' | 'mouse'; - args?: any[]; + readonly id: string; + readonly from: 'menu' | 'touchbar' | 'mouse'; + readonly args?: any[]; } export interface INativeRunKeybindingInWindowRequest { - userSettingsLabel: string; + readonly userSettingsLabel: string; } export interface IColorScheme { - dark: boolean; - highContrast: boolean; + readonly dark: boolean; + readonly highContrast: boolean; } export interface IWindowConfiguration { @@ -224,7 +224,7 @@ export interface IWindowConfiguration { } export interface IOSConfiguration { - release: string; + readonly release: string; } export interface INativeWindowConfiguration extends IWindowConfiguration, NativeParsedArgs { diff --git a/src/vs/platform/windows/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts deleted file mode 100644 index 6859b36ab9f..00000000000 --- a/src/vs/platform/windows/electron-main/window.ts +++ /dev/null @@ -1,150 +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 { URI } from 'vs/base/common/uri'; -import * as platform from 'vs/base/common/platform'; -import * as extpath from 'vs/base/common/extpath'; -import { IWorkspaceIdentifier, IResolvedWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; -import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; - -export const enum OpenContext { - - // opening when running from the command line - CLI, - - // macOS only: opening from the dock (also when opening files to a running instance from desktop) - DOCK, - - // opening from the main application window - MENU, - - // opening from a file or folder dialog - DIALOG, - - // opening from the OS's UI - DESKTOP, - - // opening through the API - API -} - -export interface IWindowContext { - openedWorkspace?: IWorkspaceIdentifier; - openedFolderUri?: URI; - - extensionDevelopmentPath?: string[]; - lastFocusTime: number; -} - -export interface IBestWindowOrFolderOptions { - windows: W[]; - newWindow: boolean; - context: OpenContext; - fileUri?: URI; - codeSettingsFolder?: string; - localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null; -} - -export function findBestWindowOrFolderForFile({ windows, newWindow, context, fileUri, localWorkspaceResolver: workspaceResolver }: IBestWindowOrFolderOptions): W | undefined { - if (!newWindow && fileUri && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) { - const windowOnFilePath = findWindowOnFilePath(windows, fileUri, workspaceResolver); - if (windowOnFilePath) { - return windowOnFilePath; - } - } - return !newWindow ? getLastActiveWindow(windows) : undefined; -} - -function findWindowOnFilePath(windows: W[], fileUri: URI, localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): W | null { - - // First check for windows with workspaces that have a parent folder of the provided path opened - for (const window of windows) { - const workspace = window.openedWorkspace; - if (workspace) { - const resolvedWorkspace = localWorkspaceResolver(workspace); - if (resolvedWorkspace) { - // workspace could be resolved: It's in the local file system - if (resolvedWorkspace.folders.some(folder => extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, folder.uri))) { - return window; - } - } else { - // use the config path instead - if (extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, workspace.configPath)) { - return window; - } - } - } - } - - // Then go with single folder windows that are parent of the provided file path - const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, window.openedFolderUri)); - if (singleFolderWindowsOnFilePath.length) { - return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderUri!.path.length - b.openedFolderUri!.path.length))[0]; - } - - return null; -} - -export function getLastActiveWindow(windows: W[]): W | undefined { - const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime)); - - return windows.find(window => window.lastFocusTime === lastFocusedDate); -} - -export function findWindowOnWorkspace(windows: W[], workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)): W | null { - if (isSingleFolderWorkspaceIdentifier(workspace)) { - for (const window of windows) { - // match on folder - if (isSingleFolderWorkspaceIdentifier(workspace)) { - if (window.openedFolderUri && extUriBiasedIgnorePathCase.isEqual(window.openedFolderUri, workspace)) { - return window; - } - } - } - } else if (isWorkspaceIdentifier(workspace)) { - for (const window of windows) { - // match on workspace - if (window.openedWorkspace && window.openedWorkspace.id === workspace.id) { - return window; - } - } - } - return null; -} - -export function findWindowOnExtensionDevelopmentPath(windows: W[], extensionDevelopmentPaths: string[]): W | null { - - const matches = (uriString: string): boolean => { - return extensionDevelopmentPaths.some(p => extpath.isEqual(p, uriString, !platform.isLinux /* ignorecase */)); - }; - - for (const window of windows) { - // match on extension development path. The path can be one or more paths or uri strings, using paths.isEqual is not 100% correct but good enough - const currPaths = window.extensionDevelopmentPath; - if (currPaths?.some(p => matches(p))) { - return window; - } - } - - return null; -} - -export function findWindowOnWorkspaceOrFolderUri(windows: W[], uri: URI | undefined): W | null { - if (!uri) { - return null; - } - for (const window of windows) { - // check for workspace config path - if (window.openedWorkspace && extUriBiasedIgnorePathCase.isEqual(window.openedWorkspace.configPath, uri)) { - return window; - } - - // check for folder path - if (window.openedFolderUri && extUriBiasedIgnorePathCase.isEqual(window.openedFolderUri, uri)) { - return window; - } - } - return null; -} diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index e77f247e08a..0e04969f308 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { IWindowOpenable, IOpenEmptyWindowOptions, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { OpenContext } from 'vs/platform/windows/electron-main/window'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -16,6 +15,27 @@ import { Rectangle, BrowserWindow, WebContents } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; import { CancellationToken } from 'vs/base/common/cancellation'; +export const enum OpenContext { + + // opening when running from the command line + CLI, + + // macOS only: opening from the dock (also when opening files to a running instance from desktop) + DOCK, + + // opening from the main application window + MENU, + + // opening from a file or folder dialog + DIALOG, + + // opening from the OS's UI + DESKTOP, + + // opening through the API + API +} + export interface IWindowState { width?: number; height?: number; diff --git a/src/vs/platform/windows/electron-main/windowsFinder.ts b/src/vs/platform/windows/electron-main/windowsFinder.ts new file mode 100644 index 00000000000..58e42035f88 --- /dev/null +++ b/src/vs/platform/windows/electron-main/windowsFinder.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { URI } from 'vs/base/common/uri'; +import { IWorkspaceIdentifier, IResolvedWorkspace } from 'vs/platform/workspaces/common/workspaces'; +import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; +import { ICodeWindow } from 'vs/platform/windows/electron-main/windows'; + +export function findWindowOnFile(windows: ICodeWindow[], fileUri: URI, localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): ICodeWindow | undefined { + + // First check for windows with workspaces that have a parent folder of the provided path opened + for (const window of windows) { + const workspace = window.openedWorkspace; + if (workspace) { + const resolvedWorkspace = localWorkspaceResolver(workspace); + + // resolved workspace: folders are known and can be compared with + if (resolvedWorkspace) { + if (resolvedWorkspace.folders.some(folder => extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, folder.uri))) { + return window; + } + } + + // unresolved: can only compare with workspace location + else { + if (extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, workspace.configPath)) { + return window; + } + } + } + } + + // Then go with single folder windows that are parent of the provided file path + const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && extUriBiasedIgnorePathCase.isEqualOrParent(fileUri, window.openedFolderUri)); + if (singleFolderWindowsOnFilePath.length) { + return singleFolderWindowsOnFilePath.sort((windowA, windowB) => -(windowA.openedFolderUri!.path.length - windowB.openedFolderUri!.path.length))[0]; + } + + return undefined; +} + +export function findWindowOnWorkspaceOrFolder(windows: ICodeWindow[], folderOrWorkspaceConfigUri: URI): ICodeWindow | undefined { + + for (const window of windows) { + + // check for workspace config path + if (window.openedWorkspace && extUriBiasedIgnorePathCase.isEqual(window.openedWorkspace.configPath, folderOrWorkspaceConfigUri)) { + return window; + } + + // check for folder path + if (window.openedFolderUri && extUriBiasedIgnorePathCase.isEqual(window.openedFolderUri, folderOrWorkspaceConfigUri)) { + return window; + } + } + + return undefined; +} + + +export function findWindowOnExtensionDevelopmentPath(windows: ICodeWindow[], extensionDevelopmentPaths: string[]): ICodeWindow | undefined { + + const matches = (uriString: string): boolean => { + return extensionDevelopmentPaths.some(path => extUriBiasedIgnorePathCase.isEqual(URI.file(path), URI.file(uriString))); + }; + + for (const window of windows) { + + // match on extension development path. the path can be one or more paths + // so we check if any of the paths match on any of the provided ones + if (window.config?.extensionDevelopmentPath?.some(path => matches(path))) { + return window; + } + } + + return undefined; +} diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 0fe8e924f00..7b2fd10d40f 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -18,12 +18,12 @@ import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMai import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri, OpenContext } from 'vs/platform/windows/electron-main/window'; +import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder'; import { Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; -import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode, IOpenEmptyConfiguration } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; -import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; +import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Schemas } from 'vs/base/common/network'; @@ -194,20 +194,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners()); - this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex()); - } - - private installWindowsMutex(): void { - const win32MutexName = product.win32MutexName; - if (isWindows && win32MutexName) { - try { - const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex; - const mutex = new WindowsMutex(win32MutexName); - once(this.lifecycleMainService.onWillShutdown)(() => mutex.release()); - } catch (e) { - this.logService.error(e); - } - } } private registerListeners(): void { @@ -572,32 +558,40 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // only look at the windows with correct authority const windows = WindowsMainService.WINDOWS.filter(window => filesToOpen && window.remoteAuthority === filesToOpen.remoteAuthority); - const bestWindowOrFolder = findBestWindowOrFolderForFile({ - windows, - newWindow: openFilesInNewWindow, - context: openConfig.context, - fileUri: fileToCheck?.fileUri, - localWorkspaceResolver: workspace => workspace.configPath.scheme === Schemas.file ? this.workspacesMainService.resolveLocalWorkspaceSync(workspace.configPath) : null - }); + // figure out a good window to open the files in if any + // with a fallback to the last active window. + // + // in case `openFilesInNewWindow` is enforced, we skip + // this step. + let windowToUseForFiles: ICodeWindow | undefined = undefined; + if (fileToCheck?.fileUri && !openFilesInNewWindow) { + if (openConfig.context === OpenContext.DESKTOP || openConfig.context === OpenContext.CLI || openConfig.context === OpenContext.DOCK) { + windowToUseForFiles = findWindowOnFile(windows, fileToCheck.fileUri, workspace => workspace.configPath.scheme === Schemas.file ? this.workspacesMainService.resolveLocalWorkspaceSync(workspace.configPath) : null); + } + + if (!windowToUseForFiles) { + windowToUseForFiles = this.doGetLastActiveWindow(windows); + } + } // We found a window to open the files in - if (bestWindowOrFolder instanceof CodeWindow) { + if (windowToUseForFiles) { // Window is workspace - if (bestWindowOrFolder.openedWorkspace) { - workspacesToOpen.push({ workspace: bestWindowOrFolder.openedWorkspace, remoteAuthority: bestWindowOrFolder.remoteAuthority }); + if (windowToUseForFiles.openedWorkspace) { + workspacesToOpen.push({ workspace: windowToUseForFiles.openedWorkspace, remoteAuthority: windowToUseForFiles.remoteAuthority }); } // Window is single folder - else if (bestWindowOrFolder.openedFolderUri) { - foldersToOpen.push({ folderUri: bestWindowOrFolder.openedFolderUri, remoteAuthority: bestWindowOrFolder.remoteAuthority }); + else if (windowToUseForFiles.openedFolderUri) { + foldersToOpen.push({ folderUri: windowToUseForFiles.openedFolderUri, remoteAuthority: windowToUseForFiles.remoteAuthority }); } // Window is empty else { // Do open files - const window = this.doOpenFilesInExistingWindow(openConfig, bestWindowOrFolder, filesToOpen); + const window = this.doOpenFilesInExistingWindow(openConfig, windowToUseForFiles, filesToOpen); usedWindows.push(window); // Reset `filesToOpen` because we handled them and also remember window we used @@ -630,7 +624,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (allWorkspacesToOpen.length > 0) { // Check for existing instances - const windowsOnWorkspace = coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsMainService.WINDOWS, workspaceToOpen.workspace))); + const windowsOnWorkspace = coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, workspaceToOpen.workspace.configPath))); if (windowsOnWorkspace.length > 0) { const windowOnWorkspace = windowsOnWorkspace[0]; const filesToOpenInWindow = (filesToOpen?.remoteAuthority === windowOnWorkspace.remoteAuthority) ? filesToOpen : undefined; @@ -676,7 +670,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (allFoldersToOpen.length > 0) { // Check for existing instances - const windowsOnFolderPath = coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspace(WindowsMainService.WINDOWS, folderToOpen.folderUri))); + const windowsOnFolderPath = coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, folderToOpen.folderUri))); if (windowsOnFolderPath.length > 0) { const windowOnFolderPath = windowsOnFolderPath[0]; const filesToOpenInWindow = filesToOpen?.remoteAuthority === windowOnFolderPath.remoteAuthority ? filesToOpen : undefined; @@ -1347,7 +1341,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic cliArgs = cliArgs.filter(path => { const uri = URI.file(path); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, uri)) { + if (!!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, uri)) { return false; } @@ -1356,7 +1350,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic folderUris = folderUris.filter(folderUriStr => { const folderUri = this.argToUri(folderUriStr); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, folderUri)) { + if (folderUri && !!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, folderUri)) { return false; } @@ -1365,7 +1359,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic fileUris = fileUris.filter(fileUriStr => { const fileUri = this.argToUri(fileUriStr); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, fileUri)) { + if (fileUri && !!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, fileUri)) { return false; } @@ -1699,11 +1693,17 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } getLastActiveWindow(): ICodeWindow | undefined { - return getLastActiveWindow(WindowsMainService.WINDOWS); + return this.doGetLastActiveWindow(WindowsMainService.WINDOWS); } private getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined { - return getLastActiveWindow(WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); + return this.doGetLastActiveWindow(WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); + } + + private doGetLastActiveWindow(windows: ICodeWindow[]): ICodeWindow | undefined { + const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime)); + + return windows.find(window => window.lastFocusTime === lastFocusedDate); } sendToFocused(channel: string, ...args: any[]): void { diff --git a/src/vs/platform/windows/electron-main/windowsStateStorage.ts b/src/vs/platform/windows/electron-main/windowsStateStorage.ts index 165333950bc..6b9a0b38a11 100644 --- a/src/vs/platform/windows/electron-main/windowsStateStorage.ts +++ b/src/vs/platform/windows/electron-main/windowsStateStorage.ts @@ -10,22 +10,22 @@ import { IWindowState, IWindowsState } from 'vs/platform/windows/electron-main/w export type WindowsStateStorageData = object; interface ISerializedWindowsState { - lastActiveWindow?: ISerializedWindowState; - lastPluginDevelopmentHostWindow?: ISerializedWindowState; - openedWindows: ISerializedWindowState[]; + readonly lastActiveWindow?: ISerializedWindowState; + readonly lastPluginDevelopmentHostWindow?: ISerializedWindowState; + readonly openedWindows: ISerializedWindowState[]; } interface ISerializedWindowState { - workspaceIdentifier?: { id: string; configURIPath: string }; - folder?: string; - backupPath?: string; - remoteAuthority?: string; - uiState: IWindowUIState; + readonly workspaceIdentifier?: { id: string; configURIPath: string }; + readonly folder?: string; + readonly backupPath?: string; + readonly remoteAuthority?: string; + readonly uiState: IWindowUIState; // deprecated - folderUri?: UriComponents; - folderPath?: string; - workspace?: { id: string; configPath: string }; + readonly folderUri?: UriComponents; + readonly folderPath?: string; + readonly workspace?: { id: string; configPath: string }; } export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState { diff --git a/src/vs/platform/windows/common/windowTracker.ts b/src/vs/platform/windows/node/windowTracker.ts similarity index 100% rename from src/vs/platform/windows/common/windowTracker.ts rename to src/vs/platform/windows/node/windowTracker.ts diff --git a/src/vs/platform/windows/test/electron-main/window.test.ts b/src/vs/platform/windows/test/electron-main/window.test.ts index 1beec3358a4..1e0dd0f04c2 100644 --- a/src/vs/platform/windows/test/electron-main/window.test.ts +++ b/src/vs/platform/windows/test/electron-main/window.test.ts @@ -2,14 +2,22 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + import * as assert from 'assert'; import * as path from 'vs/base/common/path'; -import { IBestWindowOrFolderOptions, IWindowContext, findBestWindowOrFolderForFile, OpenContext } from 'vs/platform/windows/electron-main/window'; +import { findWindowOnFile } from 'vs/platform/windows/electron-main/windowsFinder'; +import { ICodeWindow, IWindowState } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { URI } from 'vs/base/common/uri'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Event } from 'vs/base/common/event'; +import { UriDto } from 'vs/base/common/types'; +import { ICommandAction } from 'vs/platform/actions/common/actions'; +import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; +import { INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; const fixturesFolder = getPathFromAmdModule(require, './fixtures'); @@ -19,22 +27,56 @@ const testWorkspace: IWorkspaceIdentifier = { }; const testWorkspaceFolders = toWorkspaceFolders([{ path: path.join(fixturesFolder, 'vscode_workspace_1_folder') }, { path: path.join(fixturesFolder, 'vscode_workspace_2_folder') }], testWorkspace.configPath, extUriBiasedIgnorePathCase); +const localWorkspaceResolver = (workspace: any) => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : null; }; -function options(custom?: Partial>): IBestWindowOrFolderOptions { - return { - windows: [], - newWindow: false, - context: OpenContext.CLI, - codeSettingsFolder: '_vscode', - localWorkspaceResolver: workspace => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : null; }, - ...custom +function createTestCodeWindow(options: { lastFocusTime: number, openedFolderUri?: URI, openedWorkspace?: IWorkspaceIdentifier }): ICodeWindow { + return new class implements ICodeWindow { + onLoad: Event = Event.None; + onReady: Event = Event.None; + onClose: Event = Event.None; + onDestroy: Event = Event.None; + whenClosedOrLoaded: Promise = Promise.resolve(); + id: number = -1; + win: Electron.BrowserWindow = undefined!; + config: INativeWindowConfiguration | undefined; + openedFolderUri = options.openedFolderUri; + openedWorkspace = options.openedWorkspace; + backupPath?: string | undefined; + remoteAuthority?: string | undefined; + isExtensionDevelopmentHost = false; + isExtensionTestHost = false; + lastFocusTime = options.lastFocusTime; + isFullScreen = false; + isReady = true; + hasHiddenTitleBarStyle = false; + + ready(): Promise { throw new Error('Method not implemented.'); } + setReady(): void { throw new Error('Method not implemented.'); } + addTabbedWindow(window: ICodeWindow): void { throw new Error('Method not implemented.'); } + load(config: INativeWindowConfiguration, isReload?: boolean): void { throw new Error('Method not implemented.'); } + reload(cli?: NativeParsedArgs): void { throw new Error('Method not implemented.'); } + focus(options?: { force: boolean; }): void { throw new Error('Method not implemented.'); } + close(): void { throw new Error('Method not implemented.'); } + getBounds(): Electron.Rectangle { throw new Error('Method not implemented.'); } + send(channel: string, ...args: any[]): void { throw new Error('Method not implemented.'); } + sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void { throw new Error('Method not implemented.'); } + toggleFullScreen(): void { throw new Error('Method not implemented.'); } + isMinimized(): boolean { throw new Error('Method not implemented.'); } + setRepresentedFilename(name: string): void { throw new Error('Method not implemented.'); } + getRepresentedFilename(): string | undefined { throw new Error('Method not implemented.'); } + setDocumentEdited(edited: boolean): void { throw new Error('Method not implemented.'); } + isDocumentEdited(): boolean { throw new Error('Method not implemented.'); } + handleTitleDoubleClick(): void { throw new Error('Method not implemented.'); } + updateTouchBar(items: UriDto[][]): void { throw new Error('Method not implemented.'); } + serializeWindowState(): IWindowState { throw new Error('Method not implemented'); } + dispose(): void { } }; } -const vscodeFolderWindow: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder')) }; -const lastActiveWindow: IWindowContext = { lastFocusTime: 3, openedFolderUri: undefined }; -const noVscodeFolderWindow: IWindowContext = { lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) }; -const windows: IWindowContext[] = [ +const vscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder')) }); +const lastActiveWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 3, openedFolderUri: undefined }); +const noVscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) }); +const windows: ICodeWindow[] = [ vscodeFolderWindow, lastActiveWindow, noVscodeFolderWindow, @@ -43,86 +85,27 @@ const windows: IWindowContext[] = [ suite('WindowsFinder', () => { test('New window without folder when no windows exist', () => { - assert.equal(findBestWindowOrFolderForFile(options()), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')) - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), - newWindow: true - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), - context: OpenContext.API - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')) - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'new_folder', 'new_file.txt')) - })), null); - }); - - test('New window without folder when windows exist', () => { - assert.equal(findBestWindowOrFolderForFile(options({ - windows, - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), - newWindow: true - })), null); - }); - - test('Last active window', () => { - assert.equal(findBestWindowOrFolderForFile(options({ - windows - })), lastActiveWindow); - assert.equal(findBestWindowOrFolderForFile(options({ - windows, - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder2', 'file.txt')) - })), lastActiveWindow); - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [lastActiveWindow, noVscodeFolderWindow], - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), - })), lastActiveWindow); - assert.equal(findBestWindowOrFolderForFile(options({ - windows, - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), - context: OpenContext.API - })), lastActiveWindow); + assert.equal(findWindowOnFile([], URI.file('nonexisting'), localWorkspaceResolver), null); + assert.equal(findWindowOnFile([], URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), null); }); test('Existing window with folder', () => { - assert.equal(findBestWindowOrFolderForFile(options({ - windows, - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')) - })), noVscodeFolderWindow); - assert.equal(findBestWindowOrFolderForFile(options({ - windows, - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')) - })), vscodeFolderWindow); - const window: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder')) }; - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window], - fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')) - })), window); + assert.equal(findWindowOnFile(windows, URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), noVscodeFolderWindow); + + assert.equal(findWindowOnFile(windows, URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), localWorkspaceResolver), vscodeFolderWindow); + + const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder')) }); + assert.equal(findWindowOnFile([window], URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window); }); test('More specific existing window wins', () => { - const window: IWindowContext = { lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) }; - const nestedFolderWindow: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder')) }; - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window, nestedFolderWindow], - fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt')) - })), nestedFolderWindow); + const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) }); + const nestedFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder')) }); + assert.equal(findWindowOnFile([window, nestedFolderWindow], URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), nestedFolderWindow); }); test('Workspace folder wins', () => { - const window: IWindowContext = { lastFocusTime: 1, openedWorkspace: testWorkspace }; - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window], - fileUri: URI.file(path.join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')) - })), window); + const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedWorkspace: testWorkspace }); + assert.equal(findWindowOnFile([window], URI.file(path.join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window); }); }); diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index 4663b2f7b3b..95e67c70a28 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -26,7 +26,7 @@ import { MessageBoxOptions, BrowserWindow } from 'electron'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; -import { findWindowOnWorkspace } from 'vs/platform/windows/electron-main/window'; +import { findWindowOnWorkspaceOrFolder } from 'vs/platform/windows/electron-main/windowsFinder'; export const IWorkspacesMainService = createDecorator('workspacesMainService'); @@ -266,22 +266,22 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain return result; } - private async isValidTargetWorkspacePath(window: ICodeWindow, windows: ICodeWindow[], path?: URI): Promise { - if (!path) { + private async isValidTargetWorkspacePath(window: ICodeWindow, windows: ICodeWindow[], workspacePath?: URI): Promise { + if (!workspacePath) { return true; } - if (window.openedWorkspace && extUriBiasedIgnorePathCase.isEqual(window.openedWorkspace.configPath, path)) { + if (window.openedWorkspace && extUriBiasedIgnorePathCase.isEqual(window.openedWorkspace.configPath, workspacePath)) { return false; // window is already opened on a workspace with that path } // Prevent overwriting a workspace that is currently opened in another window - if (findWindowOnWorkspace(windows, getWorkspaceIdentifier(path))) { + if (findWindowOnWorkspaceOrFolder(windows, workspacePath)) { const options: MessageBoxOptions = { title: product.nameLong, type: 'info', buttons: [localize('ok', "OK")], - message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), + message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(workspacePath)), detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."), noLink: true }; From 51f18c087dd96269db79da24ae53621baaafbad9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 08:55:34 +0100 Subject: [PATCH 0880/1837] windows main service :lipstick: --- .../electron-main/windowsMainService.ts | 109 +++++++++--------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 7b2fd10d40f..0c94302136e 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -62,51 +62,52 @@ interface INewWindowState extends ISingleWindowState { type RestoreWindowsSetting = 'preserve' | 'all' | 'folders' | 'one' | 'none'; interface IOpenBrowserWindowOptions { - userEnv?: IProcessEnvironment; - cli?: NativeParsedArgs; + readonly userEnv?: IProcessEnvironment; + readonly cli?: NativeParsedArgs; - workspace?: IWorkspaceIdentifier; - folderUri?: URI; + readonly workspace?: IWorkspaceIdentifier; + readonly folderUri?: URI; - remoteAuthority?: string; + readonly remoteAuthority?: string; - initialStartup?: boolean; + readonly initialStartup?: boolean; - filesToOpen?: IFilesToOpen; + readonly filesToOpen?: IFilesToOpen; - forceNewWindow?: boolean; - forceNewTabbedWindow?: boolean; - windowToUse?: ICodeWindow; + readonly forceNewWindow?: boolean; + readonly forceNewTabbedWindow?: boolean; + readonly windowToUse?: ICodeWindow; - emptyWindowBackupInfo?: IEmptyWindowBackupInfo; + readonly emptyWindowBackupInfo?: IEmptyWindowBackupInfo; } interface IPathParseOptions { - ignoreFileNotFound?: boolean; - gotoLineMode?: boolean; - remoteAuthority?: string; + readonly ignoreFileNotFound?: boolean; + readonly gotoLineMode?: boolean; + readonly remoteAuthority?: string; } interface IFilesToOpen { + readonly remoteAuthority?: string; + filesToOpenOrCreate: IPath[]; filesToDiff: IPath[]; filesToWait?: IPathsToWaitFor; - remoteAuthority?: string; } interface IPathToOpen extends IPath { // the workspace for a Code instance to open - workspace?: IWorkspaceIdentifier; + readonly workspace?: IWorkspaceIdentifier; // the folder path for a Code instance to open - folderUri?: URI; + readonly folderUri?: URI; // the backup path for a Code instance to use - backupPath?: string; + readonly backupPath?: string; // the remote authority for the Code instance to open. Undefined if not remote. - remoteAuthority?: string; + readonly remoteAuthority?: string; // optional label for the recent history label?: string; @@ -119,16 +120,16 @@ function isFolderPathToOpen(path: IPathToOpen): path is IFolderPathToOpen { interface IFolderPathToOpen { // the folder path for a Code instance to open - folderUri: URI; + readonly folderUri: URI; // the backup path for a Code instance to use - backupPath?: string; + readonly backupPath?: string; // the remote authority for the Code instance to open. Undefined if not remote. - remoteAuthority?: string; + readonly remoteAuthority?: string; // optional label for the recent history - label?: string; + readonly label?: string; } function isWorkspacePathToOpen(path: IPathToOpen): path is IWorkspacePathToOpen { @@ -138,16 +139,16 @@ function isWorkspacePathToOpen(path: IPathToOpen): path is IWorkspacePathToOpen interface IWorkspacePathToOpen { // the workspace for a Code instance to open - workspace: IWorkspaceIdentifier; + readonly workspace: IWorkspaceIdentifier; // the backup path for a Code instance to use - backupPath?: string; + readonly backupPath?: string; // the remote authority for the Code instance to open. Undefined if not remote. - remoteAuthority?: string; + readonly remoteAuthority?: string; // optional label for the recent history - label?: string; + readonly label?: string; } export class WindowsMainService extends Disposable implements IWindowsMainService { @@ -279,7 +280,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (!currentWindowsState.lastActiveWindow) { let activeWindow = this.getLastActiveWindow(); if (!activeWindow || activeWindow.isExtensionDevelopmentHost) { - activeWindow = WindowsMainService.WINDOWS.find(window => !window.isExtensionDevelopmentHost); + activeWindow = this.getWindows().find(window => !window.isExtensionDevelopmentHost); } if (activeWindow) { @@ -288,7 +289,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } // 2.) Find extension host window - const extensionHostWindow = WindowsMainService.WINDOWS.find(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost); + const extensionHostWindow = this.getWindows().find(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost); if (extensionHostWindow) { currentWindowsState.lastPluginDevelopmentHostWindow = this.toWindowState(extensionHostWindow); } @@ -299,7 +300,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // so if we ever want to persist the UI state of the last closed window (window count === 1), it has // to come from the stored lastClosedWindowState on Win/Linux at least if (this.getWindowCount() > 1) { - currentWindowsState.openedWindows = WindowsMainService.WINDOWS.filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); + currentWindowsState.openedWindows = this.getWindows().filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); } // Persist @@ -556,7 +557,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const fileToCheck = filesToOpen.filesToOpenOrCreate[0] || filesToOpen.filesToDiff[0]; // only look at the windows with correct authority - const windows = WindowsMainService.WINDOWS.filter(window => filesToOpen && window.remoteAuthority === filesToOpen.remoteAuthority); + const windows = this.getWindows().filter(window => filesToOpen && window.remoteAuthority === filesToOpen.remoteAuthority); // figure out a good window to open the files in if any // with a fallback to the last active window. @@ -624,7 +625,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (allWorkspacesToOpen.length > 0) { // Check for existing instances - const windowsOnWorkspace = coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, workspaceToOpen.workspace.configPath))); + const windowsOnWorkspace = coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspaceOrFolder(this.getWindows(), workspaceToOpen.workspace.configPath))); if (windowsOnWorkspace.length > 0) { const windowOnWorkspace = windowsOnWorkspace[0]; const filesToOpenInWindow = (filesToOpen?.remoteAuthority === windowOnWorkspace.remoteAuthority) ? filesToOpen : undefined; @@ -670,7 +671,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (allFoldersToOpen.length > 0) { // Check for existing instances - const windowsOnFolderPath = coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, folderToOpen.folderUri))); + const windowsOnFolderPath = coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspaceOrFolder(this.getWindows(), folderToOpen.folderUri))); if (windowsOnFolderPath.length > 0) { const windowOnFolderPath = windowsOnFolderPath[0]; const filesToOpenInWindow = filesToOpen?.remoteAuthority === windowOnFolderPath.remoteAuthority ? filesToOpen : undefined; @@ -1286,7 +1287,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Reload an existing extension development host window on the same path // We currently do not allow more than one extension development window // on the same extension path. - const existingWindow = findWindowOnExtensionDevelopmentPath(WindowsMainService.WINDOWS, extensionDevelopmentPath); + const existingWindow = findWindowOnExtensionDevelopmentPath(this.getWindows(), extensionDevelopmentPath); if (existingWindow) { this.lifecycleMainService.reload(existingWindow, openConfig.cli); existingWindow.focus(); // make sure it gets focus and is restored @@ -1341,7 +1342,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic cliArgs = cliArgs.filter(path => { const uri = URI.file(path); - if (!!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, uri)) { + if (!!findWindowOnWorkspaceOrFolder(this.getWindows(), uri)) { return false; } @@ -1350,7 +1351,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic folderUris = folderUris.filter(folderUriStr => { const folderUri = this.argToUri(folderUriStr); - if (folderUri && !!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, folderUri)) { + if (folderUri && !!findWindowOnWorkspaceOrFolder(this.getWindows(), folderUri)) { return false; } @@ -1359,7 +1360,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic fileUris = fileUris.filter(fileUriStr => { const fileUri = this.argToUri(fileUriStr); - if (fileUri && !!findWindowOnWorkspaceOrFolder(WindowsMainService.WINDOWS, fileUri)) { + if (fileUri && !!findWindowOnWorkspaceOrFolder(this.getWindows(), fileUri)) { return false; } @@ -1443,7 +1444,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic else { allowFullscreen = !!(this.lifecycleMainService.wasRestarted || windowConfig?.restoreFullscreen); - if (allowFullscreen && isMacintosh && WindowsMainService.WINDOWS.some(win => win.isFullScreen)) { + if (allowFullscreen && isMacintosh && this.getWindows().some(win => win.isFullScreen)) { // macOS: Electron does not allow to restore multiple windows in // fullscreen. As such, if we already restored a window in that // state, we cannot allow more fullscreen windows. See @@ -1479,7 +1480,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic this._onWindowOpened.fire(createdWindow); // Indicate number change via event - this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length - 1, newCount: WindowsMainService.WINDOWS.length }); + this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() - 1, newCount: this.getWindowCount() }); // Window Events once(createdWindow.onReady)(() => this._onWindowReady.fire(createdWindow)); @@ -1657,14 +1658,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } private ensureNoOverlap(state: ISingleWindowState): ISingleWindowState { - if (WindowsMainService.WINDOWS.length === 0) { + if (this.getWindows().length === 0) { return state; } state.x = typeof state.x === 'number' ? state.x : 0; state.y = typeof state.y === 'number' ? state.y : 0; - const existingWindowBounds = WindowsMainService.WINDOWS.map(win => win.getBounds()); + const existingWindowBounds = this.getWindows().map(win => win.getBounds()); while (existingWindowBounds.some(b => b.x === state.x || b.y === state.y)) { state.x += 30; state.y += 30; @@ -1680,7 +1681,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic WindowsMainService.WINDOWS.splice(index, 1); // Emit - this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length + 1, newCount: WindowsMainService.WINDOWS.length }); + this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() + 1, newCount: this.getWindowCount() }); } getFocusedWindow(): ICodeWindow | undefined { @@ -1693,11 +1694,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } getLastActiveWindow(): ICodeWindow | undefined { - return this.doGetLastActiveWindow(WindowsMainService.WINDOWS); + return this.doGetLastActiveWindow(this.getWindows()); } private getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined { - return this.doGetLastActiveWindow(WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); + return this.doGetLastActiveWindow(this.getWindows().filter(window => window.remoteAuthority === remoteAuthority)); } private doGetLastActiveWindow(windows: ICodeWindow[]): ICodeWindow | undefined { @@ -1715,7 +1716,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void { - for (const window of WindowsMainService.WINDOWS) { + for (const window of this.getWindows()) { if (windowIdsToIgnore && windowIdsToIgnore.indexOf(window.id) >= 0) { continue; // do not send if we are instructed to ignore it } @@ -1724,8 +1725,16 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } } + getWindows(): ICodeWindow[] { + return WindowsMainService.WINDOWS; + } + + getWindowCount(): number { + return WindowsMainService.WINDOWS.length; + } + getWindowById(windowId: number): ICodeWindow | undefined { - const res = WindowsMainService.WINDOWS.filter(window => window.id === windowId); + const res = this.getWindows().filter(window => window.id === windowId); return firstOrDefault(res); } @@ -1738,12 +1747,4 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return this.getWindowById(browserWindow.id); } - - getWindows(): ICodeWindow[] { - return WindowsMainService.WINDOWS; - } - - getWindowCount(): number { - return WindowsMainService.WINDOWS.length; - } } From 9489147837e377f440ef0df57e6a5c1829d60eca Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 09:25:45 +0100 Subject: [PATCH 0881/1837] Re-enable build jobs --- .github/workflows/ci.yml | 194 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fcca313b3dc..3470ab0af9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,121 +48,121 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check - # compile: - # name: Compile - # runs-on: ubuntu-latest - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v2 + compile: + name: Compile Build + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 - # - uses: actions/setup-node@v2-beta - # with: - # node-version: 12 + - uses: actions/setup-node@v2-beta + with: + node-version: 12 - # - name: Cache node modules - # id: cacheNodeModules - # uses: actions/cache@v2 - # with: - # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules- - # - name: Cache /build/ scripts - # id: cacheBuildScripts - # uses: actions/cache@v2 - # with: - # path: build/**/*.js - # key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - # - name: Execute yarn - # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} - # env: - # PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - # run: yarn --frozen-lockfile + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile - # - name: Cache compiled code - # id: cacheCompiledCode - # uses: actions/cache@v2 - # with: - # path: | - # .build - # out-build - # out-vscode-min - # key: cacheCompiledCode-${{ env.GITHUB_SHA }} + - name: Cache compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} - # - name: Compile Core - # run: yarn gulp compile-build + - name: Compile Core + run: yarn gulp compile-build - # - name: Compile Extensions - # run: yarn gulp compile-extensions-build + - name: Compile Extensions + run: yarn gulp compile-extensions-build - # - name: Minify VS Code - # run: yarn gulp minify-vscode + - name: Minify VS Code + run: yarn gulp minify-vscode - # linux-build: - # name: Linux Build - # needs: compile - # runs-on: ubuntu-latest - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v2 + linux-build: + name: Linux Build + needs: compile + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 - # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - # - name: Setup Build Environment - # run: | - # sudo apt-get update - # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - # sudo chmod +x /etc/init.d/xvfb - # sudo update-rc.d xvfb defaults - # sudo service xvfb start + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - name: Setup Build Environment + run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start - # - uses: actions/setup-node@v2-beta - # with: - # node-version: 12 + - uses: actions/setup-node@v2-beta + with: + node-version: 12 - # - name: Restore cached node modules - # id: cacheNodeModules - # uses: actions/cache@v2 - # with: - # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Restore cached node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- - # - name: Restore cached /build/ scripts - # id: cacheBuildScripts - # uses: actions/cache@v2 - # with: - # path: build/**/*.js - # key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Restore cached /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - # - name: Restore cached compiled code - # id: cacheCompiledCode - # uses: actions/cache@v2 - # with: - # path: | - # .build - # out-build - # out-vscode-min - # key: cacheCompiledCode-${{ env.GITHUB_SHA }} + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} - # - name: Build VS Code - # run: yarn gulp vscode-linux-x64-min-ci + - name: Build VS Code + run: yarn gulp vscode-linux-x64-min-ci - # - name: Download Electron - # run: yarn electron x64 + - name: Download Electron + run: yarn electron x64 - # - name: Run Unit Tests (Electron) - # run: DISPLAY=:10 ./scripts/test.sh --build + - name: Run Unit Tests (Electron) + run: DISPLAY=:10 ./scripts/test.sh --build - # - name: Download Playwright - # run: node ./node_modules/playwright/install.js + - name: Download Playwright + run: node ./node_modules/playwright/install.js - # - name: Run Unit Tests (Browser) - # run: DISPLAY=:10 yarn test-browser --build --browser chromium + - name: Run Unit Tests (Browser) + run: DISPLAY=:10 yarn test-browser --build --browser chromium - # - name: Run Integration Tests (Electron) - # run: DISPLAY=:10 ./scripts/test-integration.sh --build + - name: Run Integration Tests (Electron) + run: DISPLAY=:10 ./scripts/test-integration.sh --build linux: name: Linux From 18ded3c91b2bda6bf40f913fe39c9226d66b4b50 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 09:36:56 +0100 Subject: [PATCH 0882/1837] windows - shuffle state interfaces over --- .../platform/windows/electron-main/windows.ts | 5 +++-- .../electron-main/windowsMainService.ts | 22 ++++--------------- .../electron-main/windowsStateStorage.ts | 16 +++++++++++++- .../electron-main/windowsStateStorage.test.ts | 4 +--- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 0e04969f308..f5a42fb7311 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -135,13 +135,14 @@ export interface IWindowsMainService { sendToFocused(channel: string, ...args: any[]): void; sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void; + getWindows(): ICodeWindow[]; + getWindowCount(): number; + getFocusedWindow(): ICodeWindow | undefined; getLastActiveWindow(): ICodeWindow | undefined; getWindowById(windowId: number): ICodeWindow | undefined; getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined; - getWindows(): ICodeWindow[]; - getWindowCount(): number; } export interface IBaseOpenConfiguration { diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 0c94302136e..20c111f9afc 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -30,7 +30,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { normalizePath, originalFSPath, removeTrailingPathSeparator, extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; -import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage'; +import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateStorage'; import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -41,19 +41,7 @@ import { CharCode } from 'vs/base/common/charCode'; import { getPathLabel } from 'vs/base/common/labels'; import { CancellationToken } from 'vs/base/common/cancellation'; -export interface IWindowState { - workspace?: IWorkspaceIdentifier; - folderUri?: URI; - backupPath?: string; - remoteAuthority?: string; - uiState: ISingleWindowState; -} - -export interface IWindowsState { - lastActiveWindow?: IWindowState; - lastPluginDevelopmentHostWindow?: IWindowState; - openedWindows: IWindowState[]; -} +//#region Helper Interfaces interface INewWindowState extends ISingleWindowState { hasDefaultState?: boolean; @@ -151,6 +139,8 @@ interface IWorkspacePathToOpen { readonly label?: string; } +//#endregion + export class WindowsMainService extends Disposable implements IWindowsMainService { declare readonly _serviceBrand: undefined; @@ -190,10 +180,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic super(); this.windowsState = restoreWindowsState(this.stateService.getItem(WindowsMainService.windowsStateStorageKey)); - if (!Array.isArray(this.windowsState.openedWindows)) { - this.windowsState.openedWindows = []; - } - this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners()); } diff --git a/src/vs/platform/windows/electron-main/windowsStateStorage.ts b/src/vs/platform/windows/electron-main/windowsStateStorage.ts index 6b9a0b38a11..15a7d12dd0b 100644 --- a/src/vs/platform/windows/electron-main/windowsStateStorage.ts +++ b/src/vs/platform/windows/electron-main/windowsStateStorage.ts @@ -5,10 +5,24 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows'; -import { IWindowState, IWindowsState } from 'vs/platform/windows/electron-main/windowsMainService'; +import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; export type WindowsStateStorageData = object; +export interface IWindowState { + workspace?: IWorkspaceIdentifier; + folderUri?: URI; + backupPath?: string; + remoteAuthority?: string; + uiState: IWindowUIState; +} + +export interface IWindowsState { + lastActiveWindow?: IWindowState; + lastPluginDevelopmentHostWindow?: IWindowState; + openedWindows: IWindowState[]; +} + interface ISerializedWindowsState { readonly lastActiveWindow?: ISerializedWindowState; readonly lastPluginDevelopmentHostWindow?: ISerializedWindowState; diff --git a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts b/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts index e776f85c227..5ee6a8683a7 100644 --- a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts +++ b/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts @@ -6,12 +6,10 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; - -import { restoreWindowsState, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage'; +import { restoreWindowsState, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateStorage'; import { IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; -import { IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsMainService'; function getUIState(): IWindowUIState { return { From 75f3a503fc1f5cbd5766a2dbba88b069954f2b34 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 09:40:09 +0100 Subject: [PATCH 0883/1837] create and dispose menu for context menu actions --- .../browser/parts/views/viewMenuActions.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts index 49ab90e9ab6..37e0ce2237c 100644 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ b/src/vs/workbench/browser/parts/views/viewMenuActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IAction } from 'vs/base/common/actions'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; import { MenuId, IMenuService, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -62,21 +62,20 @@ class MenuActions extends Disposable { export abstract class AbstractViewMenuActions extends Disposable { private readonly menuActions: MenuActions; - private readonly contextMenuActions: MenuActions; + private readonly contextMenuActionsDisposable = this._register(new MutableDisposable()); private _onDidChangeTitle = this._register(new Emitter()); readonly onDidChangeTitle: Event = this._onDidChangeTitle.event; constructor( menuId: MenuId, - contextMenuId: MenuId, - @IContextKeyService contextKeyService: IContextKeyService, - @IMenuService menuService: IMenuService, + private readonly contextMenuId: MenuId, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IMenuService private readonly menuService: IMenuService, ) { super(); this.menuActions = this._register(new MenuActions(menuId, menuService, contextKeyService)); this._register(this.menuActions.onDidChange(() => this._onDidChangeTitle.fire())); - this.contextMenuActions = this._register(new MenuActions(contextMenuId, menuService, contextKeyService)); } getPrimaryActions(): IAction[] { @@ -88,7 +87,11 @@ export abstract class AbstractViewMenuActions extends Disposable { } getContextMenuActions(): IAction[] { - return this.contextMenuActions.secondaryActions; + const actions: IAction[] = []; + const menu = this.menuService.createMenu(this.contextMenuId, this.contextKeyService); + this.contextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, { primary: [], secondary: actions }); + menu.dispose(); + return actions; } } From 24b18f1bd1fcdfe67a126be63765c046bacf51a8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 08:58:12 +0100 Subject: [PATCH 0884/1837] add perfEntries2 --- src/vs/code/electron-main/window.ts | 1 + src/vs/platform/windows/common/windows.ts | 3 ++- .../workbench/test/electron-browser/workbenchTestServices.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 4379b1a8d6e..03fd4393564 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -806,6 +806,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { // Dump Perf Counters windowConfiguration.perfEntries = perf.exportEntries(); + windowConfiguration.perfEntries2 = perf.getEntries(); // Parts splash windowConfiguration.partsSplashPath = path.join(this.environmentService.userDataPath, 'rapid_render.json'); diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index cae49ffdd3f..c5b6ded57ea 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -9,7 +9,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { LogLevel } from 'vs/platform/log/common/log'; -import { ExportData } from 'vs/base/common/performance'; +import { ExportData, PerformanceEntry } from 'vs/base/common/performance'; export const WindowMinimumSize = { WIDTH: 400, @@ -250,6 +250,7 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native maximized?: boolean; accessibilitySupport?: boolean; perfEntries: ExportData; + perfEntries2: PerformanceEntry[]; userEnv: IProcessEnvironment; filesToWait?: IPathsToWaitFor; diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index 5bb6f74c670..d22b5a7e0bf 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -53,6 +53,7 @@ export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = { userEnv: {}, execPath: process.execPath, perfEntries: [], + perfEntries2: [], colorScheme: { dark: true, highContrast: false }, os: { release: release() }, ...parseArgs(process.argv, OPTIONS) From a4206d19b0db6477717d845c44727cd1a5a65626 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 09:41:12 +0100 Subject: [PATCH 0885/1837] rework perf-util, only allow for marks, separate perf-marks from renderer and main process (and future other processes) --- src/vs/base/common/performance.d.ts | 12 +- src/vs/base/common/performance.js | 37 +----- src/vs/code/electron-main/window.ts | 3 +- src/vs/platform/windows/common/windows.ts | 5 +- .../performance/browser/perfviewEditor.ts | 4 +- .../electron-browser/desktop.main.ts | 5 +- .../electron-sandbox/desktop.main.ts | 5 +- .../services/timer/browser/timerService.ts | 105 +++++++++++++----- .../timer/electron-sandbox/timerService.ts | 1 + .../electron-browser/workbenchTestServices.ts | 3 +- 10 files changed, 91 insertions(+), 89 deletions(-) diff --git a/src/vs/base/common/performance.d.ts b/src/vs/base/common/performance.d.ts index a26c1ebd731..fc233e6f834 100644 --- a/src/vs/base/common/performance.d.ts +++ b/src/vs/base/common/performance.d.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export interface PerformanceEntry { +export interface PerformanceMark { readonly name: string; readonly startTime: number; } @@ -11,12 +11,6 @@ export interface PerformanceEntry { export function mark(name: string): void; /** - * All entries filtered by type and sorted by `startTime`. + * Returns all marks, sorted by `startTime`. */ -export function getEntries(): PerformanceEntry[]; - -export function getDuration(from: string, to: string): number; - -type ExportData = any[]; -export function importEntries(data: ExportData): void; -export function exportEntries(): ExportData; +export function getMarks(): PerformanceMark[]; diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index b10f9b1d68c..46c834352b9 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -14,15 +14,7 @@ function _factory(sharedObj) { const _dataLen = 2; const _nativeMark = typeof performance === 'object' && typeof performance.mark === 'function' ? performance.mark.bind(performance) : () => { }; - function importEntries(entries) { - sharedObj.MonacoPerformanceMarks.splice(0, 0, ...entries); - } - - function exportEntries() { - return sharedObj.MonacoPerformanceMarks.slice(0); - } - - function getEntries() { + function getMarks() { const result = []; const entries = sharedObj.MonacoPerformanceMarks; for (let i = 0; i < entries.length; i += _dataLen) { @@ -34,37 +26,12 @@ function _factory(sharedObj) { return result; } - function getDuration(from, to) { - const entries = sharedObj.MonacoPerformanceMarks; - let target = to; - let endIndex = 0; - for (let i = entries.length - _dataLen; i >= 0; i -= _dataLen) { - if (entries[i] === target) { - if (target === to) { - // found `to` (end of interval) - endIndex = i; - target = from; - } else { - // found `from` (start of interval) - return entries[endIndex + 1] - entries[i + 1]; - } - } - } - return 0; - } - function mark(name) { sharedObj.MonacoPerformanceMarks.push(name, Date.now()); _nativeMark(name); } - const exports = { - mark: mark, - getEntries: getEntries, - getDuration: getDuration, - importEntries: importEntries, - exportEntries: exportEntries - }; + const exports = { mark, getMarks }; return exports; } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 03fd4393564..ea7cc2f97d0 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -805,8 +805,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { windowConfiguration.maximized = this._win.isMaximized(); // Dump Perf Counters - windowConfiguration.perfEntries = perf.exportEntries(); - windowConfiguration.perfEntries2 = perf.getEntries(); + windowConfiguration.perfMarks = perf.getMarks(); // Parts splash windowConfiguration.partsSplashPath = path.join(this.environmentService.userDataPath, 'rapid_render.json'); diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index c5b6ded57ea..68516bc2694 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -9,7 +9,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { LogLevel } from 'vs/platform/log/common/log'; -import { ExportData, PerformanceEntry } from 'vs/base/common/performance'; +import { PerformanceMark } from 'vs/base/common/performance'; export const WindowMinimumSize = { WIDTH: 400, @@ -249,8 +249,7 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native fullscreen?: boolean; maximized?: boolean; accessibilitySupport?: boolean; - perfEntries: ExportData; - perfEntries2: PerformanceEntry[]; + perfMarks: PerformanceMark[]; userEnv: IProcessEnvironment; filesToWait?: IPathsToWaitFor; diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index 60f7caa47e1..5bf819734e5 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -168,7 +168,7 @@ class PerfModelContentProvider implements ITextModelContentProvider { const table: Array> = []; table.push(['start => app.isReady', metrics.timers.ellapsedAppReady, '[main]', `initial startup: ${metrics.initialStartup}`]); table.push(['nls:start => nls:end', metrics.timers.ellapsedNlsGeneration, '[main]', `initial startup: ${metrics.initialStartup}`]); - table.push(['require(main.bundle.js)', metrics.initialStartup ? perf.getDuration('willLoadMainBundle', 'didLoadMainBundle') : undefined, '[main]', `initial startup: ${metrics.initialStartup}`]); + table.push(['require(main.bundle.js)', metrics.timers.ellapsedLoadMainBundle, '[main]', `initial startup: ${metrics.initialStartup}`]); table.push(['app.isReady => window.loadUrl()', metrics.timers.ellapsedWindowLoad, '[main]', `initial startup: ${metrics.initialStartup}`]); table.push(['window.loadUrl() => begin to require(workbench.desktop.main.js)', metrics.timers.ellapsedWindowLoadToRequire, '[main->renderer]', StartupKindToString(metrics.windowKind)]); table.push(['require(workbench.desktop.main.js)', metrics.timers.ellapsedRequire, '[renderer]', `cached data: ${(metrics.didUseCachedData ? 'YES' : 'NO')}${stats ? `, node_modules took ${stats.nodeRequireTotal}ms` : ''}`]); @@ -225,7 +225,7 @@ class PerfModelContentProvider implements ITextModelContentProvider { md.value += `Name\tTimestamp\tDelta\tTotal\n`; let lastStartTime = -1; let total = 0; - for (const { name, startTime } of perf.getEntries()) { + for (const { name, startTime } of perf.getMarks()) { let delta = lastStartTime !== -1 ? startTime - lastStartTime : 0; total += delta; md.value += `${name}\t${startTime}\t${delta}\t${total}\n`; diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index c20dc166cde..a14a1e1359c 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -9,7 +9,7 @@ import { createHash } from 'crypto'; import { stat } from 'vs/base/node/pfs'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows'; -import { importEntries, mark } from 'vs/base/common/performance'; +import { mark } from 'vs/base/common/performance'; import { Workbench } from 'vs/workbench/browser/workbench'; import { NativeWindow } from 'vs/workbench/electron-sandbox/window'; import { setZoomLevel, setZoomFactor, setFullscreen } from 'vs/base/browser/browser'; @@ -75,9 +75,6 @@ class DesktopMain extends Disposable { // Massage configuration file URIs this.reviveUris(); - // Setup perf - importEntries(this.configuration.perfEntries); - // Browser config const zoomLevel = this.configuration.zoomLevel || 0; setZoomFactor(zoomLevelToZoomFactor(zoomLevel)); diff --git a/src/vs/workbench/electron-sandbox/desktop.main.ts b/src/vs/workbench/electron-sandbox/desktop.main.ts index 0ed5c1ff869..5d98d5ac3f7 100644 --- a/src/vs/workbench/electron-sandbox/desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/desktop.main.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows'; -import { importEntries, mark } from 'vs/base/common/performance'; +import { mark } from 'vs/base/common/performance'; import { Workbench } from 'vs/workbench/browser/workbench'; import { NativeWindow } from 'vs/workbench/electron-sandbox/window'; import { setZoomLevel, setZoomFactor, setFullscreen } from 'vs/base/browser/browser'; @@ -52,9 +52,6 @@ class DesktopMain extends Disposable { // Massage configuration file URIs this.reviveUris(); - // Setup perf - importEntries(this.configuration.perfEntries); - // Browser config const zoomLevel = this.configuration.zoomLevel || 0; setZoomFactor(zoomLevelToZoomFactor(zoomLevel)); diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index ae099e6c787..874fca2c1aa 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -166,6 +166,14 @@ export interface IStartupMetrics { */ readonly ellapsedNlsGeneration?: number; + /** + * The time it took to load the main bundle. + * + * * Happens in the main-process + * * Measured with the `willLoadMainBundle` and `didLoadMainBundle` performance marks. + */ + readonly ellapsedLoadMainBundle?: number; + /** * The time it took to tell electron to open/restore a renderer (browser window). * @@ -324,10 +332,46 @@ export interface IStartupMetrics { export interface ITimerService { readonly _serviceBrand: undefined; readonly startupMetrics: Promise; + + submitPerformanceMarks(marks: perf.PerformanceMark[]): void; } export const ITimerService = createDecorator('timerService'); + +class PerfMarks { + + private readonly _entries: perf.PerformanceMark[][] = []; + + submitMarks(entries: perf.PerformanceMark[]): void { + this._entries.push(entries); + } + + getDuration(from: string, to: string): number { + const fromEntry = this._findEntry(from); + if (!fromEntry) { + return 0; + } + const toEntry = this._findEntry(to); + if (!toEntry) { + return 0; + } + return toEntry.startTime - fromEntry.startTime; + } + + + private _findEntry(name: string): perf.PerformanceMark | void { + for (let entries of this._entries) { + for (let i = entries.length - 1; i >= 0; i--) { + if (entries[i].name === name) { + return entries[i]; + } + } + } + } +} + + export type Writeable = { -readonly [P in keyof T]: Writeable }; export abstract class AbstractTimerService implements ITimerService { @@ -335,6 +379,7 @@ export abstract class AbstractTimerService implements ITimerService { declare readonly _serviceBrand: undefined; private readonly _startupMetrics: Promise; + private readonly _marks = new PerfMarks(); constructor( @ILifecycleService private readonly _lifecycleService: ILifecycleService, @@ -350,12 +395,17 @@ export abstract class AbstractTimerService implements ITimerService { this._startupMetrics = Promise.all([ this._extensionService.whenInstalledExtensionsRegistered(), _lifecycleService.when(LifecyclePhase.Restored) - ]) - .then(() => this._computeStartupMetrics()) - .then(metrics => { - this._reportStartupTimes(metrics); - return metrics; - }); + ]).then(() => { + this.submitPerformanceMarks(perf.getMarks()); + return this._computeStartupMetrics(); + }).then(metrics => { + this._reportStartupTimes(metrics); + return metrics; + }); + } + + submitPerformanceMarks(marks: perf.PerformanceMark[]): void { + this._marks.submitMarks(marks); } get startupMetrics(): Promise { @@ -363,7 +413,6 @@ export abstract class AbstractTimerService implements ITimerService { } private _reportStartupTimes(metrics: IStartupMetrics): void { - // report IStartupMetrics as telemetry /* __GDPR__ "startupTimeVaried" : { @@ -375,13 +424,12 @@ export abstract class AbstractTimerService implements ITimerService { this._telemetryService.publicLog('startupTimeVaried', metrics); // report raw timers as telemetry - type Durations = { entries: perf.PerformanceEntry[]; }; + type Durations = { entries: perf.PerformanceMark[]; }; type DurationsClassification = { entries: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; - this._telemetryService.publicLog2('startup.timers.raw', { entries: perf.getEntries() }); + this._telemetryService.publicLog2('startup.timers.raw', { entries: perf.getMarks() }); } private async _computeStartupMetrics(): Promise { - const now = Date.now(); const initialStartup = this._isInitialStartup(); const startMark = initialStartup ? 'main:started' : 'main:loadWindow'; @@ -390,7 +438,7 @@ export abstract class AbstractTimerService implements ITimerService { const activePanel = this._panelService.getActivePanel(); const info: Writeable = { version: 2, - ellapsed: perf.getDuration(startMark, 'didStartWorkbench'), + ellapsed: this._marks.getDuration(startMark, 'didStartWorkbench'), // reflections isLatestVersion: Boolean(await this._updateService.isLatestVersion()), @@ -403,23 +451,24 @@ export abstract class AbstractTimerService implements ITimerService { // timers timers: { - ellapsedAppReady: initialStartup ? perf.getDuration('main:started', 'main:appReady') : undefined, - ellapsedNlsGeneration: initialStartup ? perf.getDuration('nlsGeneration:start', 'nlsGeneration:end') : undefined, - ellapsedWindowLoad: initialStartup ? perf.getDuration('main:appReady', 'main:loadWindow') : undefined, - ellapsedWindowLoadToRequire: perf.getDuration('main:loadWindow', 'willLoadWorkbenchMain'), - ellapsedRequire: perf.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain'), - ellapsedWaitForShellEnv: perf.getDuration('willWaitForShellEnv', 'didWaitForShellEnv'), - ellapsedWorkspaceStorageInit: perf.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage'), - ellapsedWorkspaceServiceInit: perf.getDuration('willInitWorkspaceService', 'didInitWorkspaceService'), - ellapsedRequiredUserDataInit: perf.getDuration('willInitRequiredUserData', 'didInitRequiredUserData'), - ellapsedOtherUserDataInit: perf.getDuration('willInitOtherUserData', 'didInitOtherUserData'), - ellapsedExtensions: perf.getDuration('willLoadExtensions', 'didLoadExtensions'), - ellapsedEditorRestore: perf.getDuration('willRestoreEditors', 'didRestoreEditors'), - ellapsedViewletRestore: perf.getDuration('willRestoreViewlet', 'didRestoreViewlet'), - ellapsedPanelRestore: perf.getDuration('willRestorePanel', 'didRestorePanel'), - ellapsedWorkbench: perf.getDuration('willStartWorkbench', 'didStartWorkbench'), - ellapsedExtensionsReady: perf.getDuration(startMark, 'didLoadExtensions'), - ellapsedRenderer: perf.getDuration('renderer/started', 'didStartWorkbench'), + ellapsedAppReady: initialStartup ? this._marks.getDuration('main:started', 'main:appReady') : undefined, + ellapsedNlsGeneration: initialStartup ? this._marks.getDuration('nlsGeneration:start', 'nlsGeneration:end') : undefined, + ellapsedLoadMainBundle: initialStartup ? this._marks.getDuration('willLoadMainBundle', 'didLoadMainBundle') : undefined, + ellapsedWindowLoad: initialStartup ? this._marks.getDuration('main:appReady', 'main:loadWindow') : undefined, + ellapsedWindowLoadToRequire: this._marks.getDuration('main:loadWindow', 'willLoadWorkbenchMain'), + ellapsedRequire: this._marks.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain'), + ellapsedWaitForShellEnv: this._marks.getDuration('willWaitForShellEnv', 'didWaitForShellEnv'), + ellapsedWorkspaceStorageInit: this._marks.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage'), + ellapsedWorkspaceServiceInit: this._marks.getDuration('willInitWorkspaceService', 'didInitWorkspaceService'), + ellapsedRequiredUserDataInit: this._marks.getDuration('willInitRequiredUserData', 'didInitRequiredUserData'), + ellapsedOtherUserDataInit: this._marks.getDuration('willInitOtherUserData', 'didInitOtherUserData'), + ellapsedExtensions: this._marks.getDuration('willLoadExtensions', 'didLoadExtensions'), + ellapsedEditorRestore: this._marks.getDuration('willRestoreEditors', 'didRestoreEditors'), + ellapsedViewletRestore: this._marks.getDuration('willRestoreViewlet', 'didRestoreViewlet'), + ellapsedPanelRestore: this._marks.getDuration('willRestorePanel', 'didRestorePanel'), + ellapsedWorkbench: this._marks.getDuration('willStartWorkbench', 'didStartWorkbench'), + ellapsedExtensionsReady: this._marks.getDuration(startMark, 'didLoadExtensions'), + ellapsedRenderer: this._marks.getDuration('renderer/started', 'didStartWorkbench'), ellapsedTimersToTimersComputed: Date.now() - now, }, diff --git a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts index 1192fb67378..f3e99027475 100644 --- a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts +++ b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts @@ -33,6 +33,7 @@ export class TimerService extends AbstractTimerService { @ITelemetryService telemetryService: ITelemetryService, ) { super(lifecycleService, contextService, extensionService, updateService, viewletService, panelService, editorService, accessibilityService, telemetryService); + this.submitPerformanceMarks(_environmentService.configuration.perfMarks); } protected _isInitialStartup(): boolean { diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index d22b5a7e0bf..668b17333f2 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -52,8 +52,7 @@ export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = { appRoot: '', userEnv: {}, execPath: process.execPath, - perfEntries: [], - perfEntries2: [], + perfMarks: [], colorScheme: { dark: true, highContrast: false }, os: { release: release() }, ...parseArgs(process.argv, OPTIONS) From 6f08741eb919eb3838a70e1af5a034f704ea8a9b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 09:53:23 +0100 Subject: [PATCH 0886/1837] separate viewPane and viewPaneContainer --- .../workbench/browser/parts/views/treeView.ts | 2 +- .../workbench/browser/parts/views/viewPane.ts | 618 ++++++++++++++++++ .../browser/parts/views/viewPaneContainer.ts | 614 +---------------- .../browser/parts/views/viewsViewlet.ts | 3 +- .../bulkEdit/browser/preview/bulkEditPane.ts | 2 +- .../contrib/comments/browser/commentsView.ts | 2 +- .../contrib/debug/browser/breakpointsView.ts | 2 +- .../contrib/debug/browser/callStackView.ts | 2 +- .../contrib/debug/browser/debugViewlet.ts | 3 +- .../debug/browser/loadedScriptsView.ts | 2 +- .../workbench/contrib/debug/browser/repl.ts | 2 +- .../contrib/debug/browser/variablesView.ts | 2 +- .../debug/browser/watchExpressionsView.ts | 2 +- .../contrib/debug/browser/welcomeView.ts | 2 +- .../extensions/browser/extensionsViewlet.ts | 3 +- .../extensions/browser/extensionsViews.ts | 2 +- .../contrib/files/browser/explorerViewlet.ts | 3 +- .../contrib/files/browser/views/emptyView.ts | 2 +- .../files/browser/views/explorerView.ts | 2 +- .../files/browser/views/openEditorsView.ts | 2 +- .../contrib/markers/browser/markersView.ts | 2 +- .../contrib/outline/browser/outlinePane.ts | 2 +- .../contrib/output/browser/outputView.ts | 2 +- .../contrib/remote/browser/remote.ts | 2 +- .../contrib/remote/browser/tunnelView.ts | 2 +- .../scm/browser/scmRepositoriesViewPane.ts | 2 +- .../contrib/scm/browser/scmViewPane.ts | 2 +- .../contrib/search/browser/searchView.ts | 2 +- .../contrib/terminal/browser/terminalView.ts | 2 +- .../testing/browser/testingExplorerView.ts | 2 +- .../contrib/timeline/browser/timelinePane.ts | 2 +- .../webviewView/browser/webviewViewPane.ts | 2 +- 32 files changed, 663 insertions(+), 633 deletions(-) create mode 100644 src/vs/workbench/browser/parts/views/viewPane.ts diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index dbd8ffce1a9..c6febce166d 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -14,7 +14,7 @@ import { ITreeView, ITreeViewDescriptor, IViewsRegistry, Extensions, IViewDescri import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IThemeService, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { Registry } from 'vs/platform/registry/common/platform'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts new file mode 100644 index 00000000000..c4026faa203 --- /dev/null +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -0,0 +1,618 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/paneviewlet'; +import * as nls from 'vs/nls'; +import { Event, Emitter } from 'vs/base/common/event'; +import { foreground } from 'vs/platform/theme/common/colorRegistry'; +import { attachButtonStyler, attachLinkStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler'; +import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; +import { after, append, $, trackFocus, EventType, addDisposableListener, createCSSRule, asCSSUrl } from 'vs/base/browser/dom'; +import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IAction, IActionViewItem } from 'vs/base/common/actions'; +import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IPaneOptions, Pane, IPaneStyles } from 'vs/base/browser/ui/splitview/paneview'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptorService, ViewContainerLocation, IViewsRegistry, IViewContentDescriptor, defaultViewIcon, IViewsService } from 'vs/workbench/common/views'; +import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { assertIsDefined } from 'vs/base/common/types'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { MenuId, MenuItemAction, Action2, IAction2Options, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; +import { parseLinkedText } from 'vs/base/common/linkedText'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { Button } from 'vs/base/browser/ui/button/button'; +import { Link } from 'vs/platform/opener/browser/link'; +import { Orientation } from 'vs/base/browser/ui/sash/sash'; +import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; +import { CompositeProgressIndicator } from 'vs/workbench/services/progress/browser/progressIndicator'; +import { IProgressIndicator } from 'vs/platform/progress/common/progress'; +import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { URI } from 'vs/base/common/uri'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { Codicon } from 'vs/base/common/codicons'; + +export interface IViewPaneOptions extends IPaneOptions { + id: string; + showActionsAlways?: boolean; + titleMenuId?: MenuId; +} + +type WelcomeActionClassification = { + viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + uri: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; +}; + +const viewPaneContainerExpandedIcon = registerIcon('view-pane-container-expanded', Codicon.chevronDown, nls.localize('viewPaneContainerExpandedIcon', 'Icon for an expanded view pane container.')); +const viewPaneContainerCollapsedIcon = registerIcon('view-pane-container-collapsed', Codicon.chevronRight, nls.localize('viewPaneContainerCollapsedIcon', 'Icon for a collapsed view pane container.')); + +const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); + +interface IItem { + readonly descriptor: IViewContentDescriptor; + visible: boolean; +} + +class ViewWelcomeController { + + private _onDidChange = new Emitter(); + readonly onDidChange = this._onDidChange.event; + + private defaultItem: IItem | undefined; + private items: IItem[] = []; + get contents(): IViewContentDescriptor[] { + const visibleItems = this.items.filter(v => v.visible); + + if (visibleItems.length === 0 && this.defaultItem) { + return [this.defaultItem.descriptor]; + } + + return visibleItems.map(v => v.descriptor); + } + + private contextKeyService: IContextKeyService; + private disposables = new DisposableStore(); + + constructor( + private id: string, + @IContextKeyService contextKeyService: IContextKeyService, + ) { + this.contextKeyService = contextKeyService.createScoped(); + this.disposables.add(this.contextKeyService); + + contextKeyService.onDidChangeContext(this.onDidChangeContext, this, this.disposables); + Event.filter(viewsRegistry.onDidChangeViewWelcomeContent, id => id === this.id)(this.onDidChangeViewWelcomeContent, this, this.disposables); + this.onDidChangeViewWelcomeContent(); + } + + private onDidChangeViewWelcomeContent(): void { + const descriptors = viewsRegistry.getViewWelcomeContent(this.id); + + this.items = []; + + for (const descriptor of descriptors) { + if (descriptor.when === 'default') { + this.defaultItem = { descriptor, visible: true }; + } else { + const visible = descriptor.when ? this.contextKeyService.contextMatchesRules(descriptor.when) : true; + this.items.push({ descriptor, visible }); + } + } + + this._onDidChange.fire(); + } + + private onDidChangeContext(): void { + let didChange = false; + + for (const item of this.items) { + if (!item.descriptor.when || item.descriptor.when === 'default') { + continue; + } + + const visible = this.contextKeyService.contextMatchesRules(item.descriptor.when); + + if (item.visible === visible) { + continue; + } + + item.visible = visible; + didChange = true; + } + + if (didChange) { + this._onDidChange.fire(); + } + } + + dispose(): void { + this.disposables.dispose(); + } +} + +export abstract class ViewPane extends Pane implements IView { + + private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions'; + + private _onDidFocus = this._register(new Emitter()); + readonly onDidFocus: Event = this._onDidFocus.event; + + private _onDidBlur = this._register(new Emitter()); + readonly onDidBlur: Event = this._onDidBlur.event; + + private _onDidChangeBodyVisibility = this._register(new Emitter()); + readonly onDidChangeBodyVisibility: Event = this._onDidChangeBodyVisibility.event; + + protected _onDidChangeTitleArea = this._register(new Emitter()); + readonly onDidChangeTitleArea: Event = this._onDidChangeTitleArea.event; + + protected _onDidChangeViewWelcomeState = this._register(new Emitter()); + readonly onDidChangeViewWelcomeState: Event = this._onDidChangeViewWelcomeState.event; + + private focusedViewContextKey: IContextKey; + + private _isVisible: boolean = false; + readonly id: string; + + private _title: string; + public get title(): string { + return this._title; + } + + private _titleDescription: string | undefined; + public get titleDescription(): string | undefined { + return this._titleDescription; + } + + private readonly menuActions: ViewMenuActions; + private progressBar!: ProgressBar; + private progressIndicator!: IProgressIndicator; + + private toolbar?: ToolBar; + private readonly showActionsAlways: boolean = false; + private headerContainer?: HTMLElement; + private titleContainer?: HTMLElement; + private titleDescriptionContainer?: HTMLElement; + private iconContainer?: HTMLElement; + protected twistiesContainer?: HTMLElement; + + private bodyContainer!: HTMLElement; + private viewWelcomeContainer!: HTMLElement; + private viewWelcomeDisposable: IDisposable = Disposable.None; + private viewWelcomeController: ViewWelcomeController; + + constructor( + options: IViewPaneOptions, + @IKeybindingService protected keybindingService: IKeybindingService, + @IContextMenuService protected contextMenuService: IContextMenuService, + @IConfigurationService protected readonly configurationService: IConfigurationService, + @IContextKeyService protected contextKeyService: IContextKeyService, + @IViewDescriptorService protected viewDescriptorService: IViewDescriptorService, + @IInstantiationService protected instantiationService: IInstantiationService, + @IOpenerService protected openerService: IOpenerService, + @IThemeService protected themeService: IThemeService, + @ITelemetryService protected telemetryService: ITelemetryService, + ) { + super({ ...options, ...{ orientation: viewDescriptorService.getViewLocationById(options.id) === ViewContainerLocation.Panel ? Orientation.HORIZONTAL : Orientation.VERTICAL } }); + + this.id = options.id; + this._title = options.title; + this._titleDescription = options.titleDescription; + this.showActionsAlways = !!options.showActionsAlways; + this.focusedViewContextKey = FocusedViewContext.bindTo(contextKeyService); + + this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext)); + this._register(this.menuActions.onDidChangeTitle(() => this.updateActions())); + + this.viewWelcomeController = new ViewWelcomeController(this.id, contextKeyService); + } + + get headerVisible(): boolean { + return super.headerVisible; + } + + set headerVisible(visible: boolean) { + super.headerVisible = visible; + this.element.classList.toggle('merged-header', !visible); + } + + setVisible(visible: boolean): void { + if (this._isVisible !== visible) { + this._isVisible = visible; + + if (this.isExpanded()) { + this._onDidChangeBodyVisibility.fire(visible); + } + } + } + + isVisible(): boolean { + return this._isVisible; + } + + isBodyVisible(): boolean { + return this._isVisible && this.isExpanded(); + } + + setExpanded(expanded: boolean): boolean { + const changed = super.setExpanded(expanded); + if (changed) { + this._onDidChangeBodyVisibility.fire(expanded); + } + if (this.twistiesContainer) { + this.twistiesContainer.classList.remove(...ThemeIcon.asClassNameArray(this.getTwistyIcon(!expanded))); + this.twistiesContainer.classList.add(...ThemeIcon.asClassNameArray(this.getTwistyIcon(expanded))); + } + return changed; + } + + render(): void { + super.render(); + + const focusTracker = trackFocus(this.element); + this._register(focusTracker); + this._register(focusTracker.onDidFocus(() => { + this.focusedViewContextKey.set(this.id); + this._onDidFocus.fire(); + })); + this._register(focusTracker.onDidBlur(() => { + if (this.focusedViewContextKey.get() === this.id) { + this.focusedViewContextKey.reset(); + } + + this._onDidBlur.fire(); + })); + } + + protected renderHeader(container: HTMLElement): void { + this.headerContainer = container; + + this.twistiesContainer = append(container, $(ThemeIcon.asCSSSelector(this.getTwistyIcon(this.isExpanded())))); + + this.renderHeaderTitle(container, this.title); + + const actions = append(container, $('.actions')); + actions.classList.toggle('show', this.showActionsAlways); + this.toolbar = new ToolBar(actions, this.contextMenuService, { + orientation: ActionsOrientation.HORIZONTAL, + actionViewItemProvider: action => this.getActionViewItem(action), + ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.title), + getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id), + renderDropdownAsChildElement: true + }); + + this._register(this.toolbar); + this.setActions(); + + this._register(addDisposableListener(actions, EventType.CLICK, e => e.preventDefault())); + + this._register(this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!.onDidChangeContainerInfo(({ title }) => { + this.updateTitle(this.title); + })); + + const onDidRelevantConfigurationChange = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewPane.AlwaysShowActionsConfig)); + this._register(onDidRelevantConfigurationChange(this.updateActionsVisibility, this)); + this.updateActionsVisibility(); + } + + protected getTwistyIcon(expanded: boolean): ThemeIcon { + return expanded ? viewPaneContainerExpandedIcon : viewPaneContainerCollapsedIcon; + } + + style(styles: IPaneStyles): void { + super.style(styles); + + const icon = this.getIcon(); + if (this.iconContainer) { + const fgColor = styles.headerForeground || this.themeService.getColorTheme().getColor(foreground); + if (URI.isUri(icon)) { + // Apply background color to activity bar item provided with iconUrls + this.iconContainer.style.backgroundColor = fgColor ? fgColor.toString() : ''; + this.iconContainer.style.color = ''; + } else { + // Apply foreground color to activity bar items provided with codicons + this.iconContainer.style.color = fgColor ? fgColor.toString() : ''; + this.iconContainer.style.backgroundColor = ''; + } + } + } + + private getIcon(): ThemeIcon | URI { + return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || defaultViewIcon; + } + + protected renderHeaderTitle(container: HTMLElement, title: string): void { + this.iconContainer = append(container, $('.icon', undefined)); + const icon = this.getIcon(); + + let cssClass: string | undefined = undefined; + if (URI.isUri(icon)) { + cssClass = `view-${this.id.replace(/[\.\:]/g, '-')}`; + const iconClass = `.pane-header .icon.${cssClass}`; + + createCSSRule(iconClass, ` + mask: ${asCSSUrl(icon)} no-repeat 50% 50%; + mask-size: 24px; + -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; + -webkit-mask-size: 16px; + `); + } else if (ThemeIcon.isThemeIcon(icon)) { + cssClass = ThemeIcon.asClassName(icon); + } + + if (cssClass) { + this.iconContainer.classList.add(...cssClass.split(' ')); + } + + const calculatedTitle = this.calculateTitle(title); + this.titleContainer = append(container, $('h3.title', { title: calculatedTitle }, calculatedTitle)); + + if (this._titleDescription) { + this.setTitleDescription(this._titleDescription); + } + + this.iconContainer.title = calculatedTitle; + this.iconContainer.setAttribute('aria-label', calculatedTitle); + } + + protected updateTitle(title: string): void { + const calculatedTitle = this.calculateTitle(title); + if (this.titleContainer) { + this.titleContainer.textContent = calculatedTitle; + this.titleContainer.setAttribute('title', calculatedTitle); + } + + if (this.iconContainer) { + this.iconContainer.title = calculatedTitle; + this.iconContainer.setAttribute('aria-label', calculatedTitle); + } + + this._title = title; + this._onDidChangeTitleArea.fire(); + } + + private setTitleDescription(description: string | undefined) { + if (this.titleDescriptionContainer) { + this.titleDescriptionContainer.textContent = description ?? ''; + this.titleDescriptionContainer.setAttribute('title', description ?? ''); + } + else if (description && this.titleContainer) { + this.titleDescriptionContainer = after(this.titleContainer, $('span.description', { title: description }, description)); + } + } + + protected updateTitleDescription(description?: string | undefined): void { + this.setTitleDescription(description); + + this._titleDescription = description; + this._onDidChangeTitleArea.fire(); + } + + private calculateTitle(title: string): string { + const viewContainer = this.viewDescriptorService.getViewContainerByViewId(this.id)!; + const model = this.viewDescriptorService.getViewContainerModel(viewContainer); + const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.id); + const isDefault = this.viewDescriptorService.getDefaultContainerById(this.id) === viewContainer; + + if (!isDefault && viewDescriptor?.containerTitle && model.title !== viewDescriptor.containerTitle) { + return `${viewDescriptor.containerTitle}: ${title}`; + } + + return title; + } + + private scrollableElement!: DomScrollableElement; + + protected renderBody(container: HTMLElement): void { + this.bodyContainer = container; + + const viewWelcomeContainer = append(container, $('.welcome-view')); + this.viewWelcomeContainer = $('.welcome-view-content', { tabIndex: 0 }); + this.scrollableElement = this._register(new DomScrollableElement(this.viewWelcomeContainer, { + alwaysConsumeMouseWheel: true, + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Visible, + })); + + append(viewWelcomeContainer, this.scrollableElement.getDomNode()); + + const onViewWelcomeChange = Event.any(this.viewWelcomeController.onDidChange, this.onDidChangeViewWelcomeState); + this._register(onViewWelcomeChange(this.updateViewWelcome, this)); + this.updateViewWelcome(); + } + + protected layoutBody(height: number, width: number): void { + this.viewWelcomeContainer.style.height = `${height}px`; + this.viewWelcomeContainer.style.width = `${width}px`; + this.scrollableElement.scanDomNode(); + } + + getProgressIndicator() { + if (this.progressBar === undefined) { + // Progress bar + this.progressBar = this._register(new ProgressBar(this.element)); + this._register(attachProgressBarStyler(this.progressBar, this.themeService)); + this.progressBar.hide(); + } + + if (this.progressIndicator === undefined) { + this.progressIndicator = this.instantiationService.createInstance(CompositeProgressIndicator, assertIsDefined(this.progressBar), this.id, this.isBodyVisible()); + } + return this.progressIndicator; + } + + protected getProgressLocation(): string { + return this.viewDescriptorService.getViewContainerByViewId(this.id)!.id; + } + + protected getBackgroundColor(): string { + return this.viewDescriptorService.getViewLocationById(this.id) === ViewContainerLocation.Panel ? PANEL_BACKGROUND : SIDE_BAR_BACKGROUND; + } + + focus(): void { + if (this.shouldShowWelcome()) { + this.viewWelcomeContainer.focus(); + } else if (this.element) { + this.element.focus(); + this._onDidFocus.fire(); + } + } + + private setActions(): void { + if (this.toolbar) { + this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions())); + this.toolbar.context = this.getActionsContext(); + } + } + + private updateActionsVisibility(): void { + if (!this.headerContainer) { + return; + } + const shouldAlwaysShowActions = this.configurationService.getValue('workbench.view.alwaysShowHeaderActions'); + this.headerContainer.classList.toggle('actions-always-visible', shouldAlwaysShowActions); + } + + protected updateActions(): void { + this.setActions(); + this._onDidChangeTitleArea.fire(); + } + + getActions(): IAction[] { + return this.menuActions.getPrimaryActions(); + } + + getSecondaryActions(): IAction[] { + return this.menuActions.getSecondaryActions(); + } + + getContextMenuActions(): IAction[] { + return this.menuActions.getContextMenuActions(); + } + + getActionViewItem(action: IAction): IActionViewItem | undefined { + if (action instanceof MenuItemAction) { + return this.instantiationService.createInstance(MenuEntryActionViewItem, action); + } else if (action instanceof SubmenuItemAction) { + return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action); + } + return undefined; + } + + getActionsContext(): unknown { + return undefined; + } + + getOptimalWidth(): number { + return 0; + } + + saveState(): void { + // Subclasses to implement for saving state + } + + private updateViewWelcome(): void { + this.viewWelcomeDisposable.dispose(); + + if (!this.shouldShowWelcome()) { + this.bodyContainer.classList.remove('welcome'); + this.viewWelcomeContainer.innerText = ''; + this.scrollableElement.scanDomNode(); + return; + } + + const contents = this.viewWelcomeController.contents; + + if (contents.length === 0) { + this.bodyContainer.classList.remove('welcome'); + this.viewWelcomeContainer.innerText = ''; + this.scrollableElement.scanDomNode(); + return; + } + + const disposables = new DisposableStore(); + this.bodyContainer.classList.add('welcome'); + this.viewWelcomeContainer.innerText = ''; + + for (const { content, precondition } of contents) { + const lines = content.split('\n'); + + for (let line of lines) { + line = line.trim(); + + if (!line) { + continue; + } + + const linkedText = parseLinkedText(line); + + if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') { + const node = linkedText.nodes[0]; + const button = new Button(this.viewWelcomeContainer, { title: node.title, supportCodicons: true }); + button.label = node.label; + button.onDidClick(_ => { + this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href }); + this.openerService.open(node.href); + }, null, disposables); + disposables.add(button); + disposables.add(attachButtonStyler(button, this.themeService)); + + if (precondition) { + const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); + updateEnablement(); + + const keys = new Set(); + precondition.keys().forEach(key => keys.add(key)); + const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); + onDidChangeContext(updateEnablement, null, disposables); + } + } else { + const p = append(this.viewWelcomeContainer, $('p')); + + for (const node of linkedText.nodes) { + if (typeof node === 'string') { + append(p, document.createTextNode(node)); + } else { + const link = this.instantiationService.createInstance(Link, node); + append(p, link.el); + disposables.add(link); + disposables.add(attachLinkStyler(link, this.themeService)); + } + } + } + } + } + + this.scrollableElement.scanDomNode(); + this.viewWelcomeDisposable = disposables; + } + + shouldShowWelcome(): boolean { + return false; + } +} + +export abstract class ViewAction extends Action2 { + constructor(readonly desc: Readonly & { viewId: string }) { + super(desc); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const view = accessor.get(IViewsService).getActiveViewWithId(this.desc.viewId); + if (view) { + return this.runInView(accessor, view, ...args); + } + } + + abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; +} diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 97e62752246..9f28f536afc 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -6,52 +6,35 @@ import 'vs/css!./media/paneviewlet'; import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; -import { ColorIdentifier, activeContrastBorder, foreground } from 'vs/platform/theme/common/colorRegistry'; -import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler'; -import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme'; -import { after, append, $, trackFocus, EventType, isAncestor, Dimension, addDisposableListener, createCSSRule, asCSSUrl } from 'vs/base/browser/dom'; -import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { ColorIdentifier, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler'; +import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme'; +import { EventType, isAncestor, Dimension, addDisposableListener } from 'vs/base/browser/dom'; +import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions'; -import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { PaneView, IPaneViewOptions, IPaneOptions, Pane, IPaneStyles } from 'vs/base/browser/ui/splitview/paneview'; +import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; +import { PaneView, IPaneViewOptions } from 'vs/base/browser/ui/splitview/paneview'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon, IViewsService } from 'vs/workbench/common/views'; +import { IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, IViewsService } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined } from 'vs/base/common/types'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Component } from 'vs/workbench/common/component'; -import { MenuId, MenuItemAction, registerAction2, Action2, IAction2Options, SubmenuItemAction } from 'vs/platform/actions/common/actions'; -import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; -import { parseLinkedText } from 'vs/base/common/linkedText'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { Button } from 'vs/base/browser/ui/button/button'; -import { Link } from 'vs/platform/opener/browser/link'; +import { registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions'; import { CompositeDragAndDropObserver, DragAndDropObserver, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; -import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; -import { CompositeProgressIndicator } from 'vs/workbench/services/progress/browser/progressIndicator'; -import { IProgressIndicator } from 'vs/platform/progress/common/progress'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; -import { ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { URI } from 'vs/base/common/uri'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -import { Codicon } from 'vs/base/common/codicons'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; @@ -61,566 +44,6 @@ export interface IPaneColors extends IColorMapping { leftBorder?: ColorIdentifier; } -export interface IViewPaneOptions extends IPaneOptions { - id: string; - showActionsAlways?: boolean; - titleMenuId?: MenuId; -} - -type WelcomeActionClassification = { - viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - uri: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; -}; - -const viewPaneContainerExpandedIcon = registerIcon('view-pane-container-expanded', Codicon.chevronDown, nls.localize('viewPaneContainerExpandedIcon', 'Icon for an expanded view pane container.')); -const viewPaneContainerCollapsedIcon = registerIcon('view-pane-container-collapsed', Codicon.chevronRight, nls.localize('viewPaneContainerCollapsedIcon', 'Icon for a collapsed view pane container.')); - -const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); - -interface IItem { - readonly descriptor: IViewContentDescriptor; - visible: boolean; -} - -class ViewWelcomeController { - - private _onDidChange = new Emitter(); - readonly onDidChange = this._onDidChange.event; - - private defaultItem: IItem | undefined; - private items: IItem[] = []; - get contents(): IViewContentDescriptor[] { - const visibleItems = this.items.filter(v => v.visible); - - if (visibleItems.length === 0 && this.defaultItem) { - return [this.defaultItem.descriptor]; - } - - return visibleItems.map(v => v.descriptor); - } - - private contextKeyService: IContextKeyService; - private disposables = new DisposableStore(); - - constructor( - private id: string, - @IContextKeyService contextKeyService: IContextKeyService, - ) { - this.contextKeyService = contextKeyService.createScoped(); - this.disposables.add(this.contextKeyService); - - contextKeyService.onDidChangeContext(this.onDidChangeContext, this, this.disposables); - Event.filter(viewsRegistry.onDidChangeViewWelcomeContent, id => id === this.id)(this.onDidChangeViewWelcomeContent, this, this.disposables); - this.onDidChangeViewWelcomeContent(); - } - - private onDidChangeViewWelcomeContent(): void { - const descriptors = viewsRegistry.getViewWelcomeContent(this.id); - - this.items = []; - - for (const descriptor of descriptors) { - if (descriptor.when === 'default') { - this.defaultItem = { descriptor, visible: true }; - } else { - const visible = descriptor.when ? this.contextKeyService.contextMatchesRules(descriptor.when) : true; - this.items.push({ descriptor, visible }); - } - } - - this._onDidChange.fire(); - } - - private onDidChangeContext(): void { - let didChange = false; - - for (const item of this.items) { - if (!item.descriptor.when || item.descriptor.when === 'default') { - continue; - } - - const visible = this.contextKeyService.contextMatchesRules(item.descriptor.when); - - if (item.visible === visible) { - continue; - } - - item.visible = visible; - didChange = true; - } - - if (didChange) { - this._onDidChange.fire(); - } - } - - dispose(): void { - this.disposables.dispose(); - } -} - -export abstract class ViewPane extends Pane implements IView { - - private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions'; - - private _onDidFocus = this._register(new Emitter()); - readonly onDidFocus: Event = this._onDidFocus.event; - - private _onDidBlur = this._register(new Emitter()); - readonly onDidBlur: Event = this._onDidBlur.event; - - private _onDidChangeBodyVisibility = this._register(new Emitter()); - readonly onDidChangeBodyVisibility: Event = this._onDidChangeBodyVisibility.event; - - protected _onDidChangeTitleArea = this._register(new Emitter()); - readonly onDidChangeTitleArea: Event = this._onDidChangeTitleArea.event; - - protected _onDidChangeViewWelcomeState = this._register(new Emitter()); - readonly onDidChangeViewWelcomeState: Event = this._onDidChangeViewWelcomeState.event; - - private focusedViewContextKey: IContextKey; - - private _isVisible: boolean = false; - readonly id: string; - - private _title: string; - public get title(): string { - return this._title; - } - - private _titleDescription: string | undefined; - public get titleDescription(): string | undefined { - return this._titleDescription; - } - - private readonly menuActions: ViewMenuActions; - private progressBar!: ProgressBar; - private progressIndicator!: IProgressIndicator; - - private toolbar?: ToolBar; - private readonly showActionsAlways: boolean = false; - private headerContainer?: HTMLElement; - private titleContainer?: HTMLElement; - private titleDescriptionContainer?: HTMLElement; - private iconContainer?: HTMLElement; - protected twistiesContainer?: HTMLElement; - - private bodyContainer!: HTMLElement; - private viewWelcomeContainer!: HTMLElement; - private viewWelcomeDisposable: IDisposable = Disposable.None; - private viewWelcomeController: ViewWelcomeController; - - constructor( - options: IViewPaneOptions, - @IKeybindingService protected keybindingService: IKeybindingService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IConfigurationService protected readonly configurationService: IConfigurationService, - @IContextKeyService protected contextKeyService: IContextKeyService, - @IViewDescriptorService protected viewDescriptorService: IViewDescriptorService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IOpenerService protected openerService: IOpenerService, - @IThemeService protected themeService: IThemeService, - @ITelemetryService protected telemetryService: ITelemetryService, - ) { - super({ ...options, ...{ orientation: viewDescriptorService.getViewLocationById(options.id) === ViewContainerLocation.Panel ? Orientation.HORIZONTAL : Orientation.VERTICAL } }); - - this.id = options.id; - this._title = options.title; - this._titleDescription = options.titleDescription; - this.showActionsAlways = !!options.showActionsAlways; - this.focusedViewContextKey = FocusedViewContext.bindTo(contextKeyService); - - this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext)); - this._register(this.menuActions.onDidChangeTitle(() => this.updateActions())); - - this.viewWelcomeController = new ViewWelcomeController(this.id, contextKeyService); - } - - get headerVisible(): boolean { - return super.headerVisible; - } - - set headerVisible(visible: boolean) { - super.headerVisible = visible; - this.element.classList.toggle('merged-header', !visible); - } - - setVisible(visible: boolean): void { - if (this._isVisible !== visible) { - this._isVisible = visible; - - if (this.isExpanded()) { - this._onDidChangeBodyVisibility.fire(visible); - } - } - } - - isVisible(): boolean { - return this._isVisible; - } - - isBodyVisible(): boolean { - return this._isVisible && this.isExpanded(); - } - - setExpanded(expanded: boolean): boolean { - const changed = super.setExpanded(expanded); - if (changed) { - this._onDidChangeBodyVisibility.fire(expanded); - } - if (this.twistiesContainer) { - this.twistiesContainer.classList.remove(...ThemeIcon.asClassNameArray(this.getTwistyIcon(!expanded))); - this.twistiesContainer.classList.add(...ThemeIcon.asClassNameArray(this.getTwistyIcon(expanded))); - } - return changed; - } - - render(): void { - super.render(); - - const focusTracker = trackFocus(this.element); - this._register(focusTracker); - this._register(focusTracker.onDidFocus(() => { - this.focusedViewContextKey.set(this.id); - this._onDidFocus.fire(); - })); - this._register(focusTracker.onDidBlur(() => { - if (this.focusedViewContextKey.get() === this.id) { - this.focusedViewContextKey.reset(); - } - - this._onDidBlur.fire(); - })); - } - - protected renderHeader(container: HTMLElement): void { - this.headerContainer = container; - - this.twistiesContainer = append(container, $(ThemeIcon.asCSSSelector(this.getTwistyIcon(this.isExpanded())))); - - this.renderHeaderTitle(container, this.title); - - const actions = append(container, $('.actions')); - actions.classList.toggle('show', this.showActionsAlways); - this.toolbar = new ToolBar(actions, this.contextMenuService, { - orientation: ActionsOrientation.HORIZONTAL, - actionViewItemProvider: action => this.getActionViewItem(action), - ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.title), - getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id), - renderDropdownAsChildElement: true - }); - - this._register(this.toolbar); - this.setActions(); - - this._register(addDisposableListener(actions, EventType.CLICK, e => e.preventDefault())); - - this._register(this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!.onDidChangeContainerInfo(({ title }) => { - this.updateTitle(this.title); - })); - - const onDidRelevantConfigurationChange = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewPane.AlwaysShowActionsConfig)); - this._register(onDidRelevantConfigurationChange(this.updateActionsVisibility, this)); - this.updateActionsVisibility(); - } - - protected getTwistyIcon(expanded: boolean): ThemeIcon { - return expanded ? viewPaneContainerExpandedIcon : viewPaneContainerCollapsedIcon; - } - - style(styles: IPaneStyles): void { - super.style(styles); - - const icon = this.getIcon(); - if (this.iconContainer) { - const fgColor = styles.headerForeground || this.themeService.getColorTheme().getColor(foreground); - if (URI.isUri(icon)) { - // Apply background color to activity bar item provided with iconUrls - this.iconContainer.style.backgroundColor = fgColor ? fgColor.toString() : ''; - this.iconContainer.style.color = ''; - } else { - // Apply foreground color to activity bar items provided with codicons - this.iconContainer.style.color = fgColor ? fgColor.toString() : ''; - this.iconContainer.style.backgroundColor = ''; - } - } - } - - private getIcon(): ThemeIcon | URI { - return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || defaultViewIcon; - } - - protected renderHeaderTitle(container: HTMLElement, title: string): void { - this.iconContainer = append(container, $('.icon', undefined)); - const icon = this.getIcon(); - - let cssClass: string | undefined = undefined; - if (URI.isUri(icon)) { - cssClass = `view-${this.id.replace(/[\.\:]/g, '-')}`; - const iconClass = `.pane-header .icon.${cssClass}`; - - createCSSRule(iconClass, ` - mask: ${asCSSUrl(icon)} no-repeat 50% 50%; - mask-size: 24px; - -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; - -webkit-mask-size: 16px; - `); - } else if (ThemeIcon.isThemeIcon(icon)) { - cssClass = ThemeIcon.asClassName(icon); - } - - if (cssClass) { - this.iconContainer.classList.add(...cssClass.split(' ')); - } - - const calculatedTitle = this.calculateTitle(title); - this.titleContainer = append(container, $('h3.title', { title: calculatedTitle }, calculatedTitle)); - - if (this._titleDescription) { - this.setTitleDescription(this._titleDescription); - } - - this.iconContainer.title = calculatedTitle; - this.iconContainer.setAttribute('aria-label', calculatedTitle); - } - - protected updateTitle(title: string): void { - const calculatedTitle = this.calculateTitle(title); - if (this.titleContainer) { - this.titleContainer.textContent = calculatedTitle; - this.titleContainer.setAttribute('title', calculatedTitle); - } - - if (this.iconContainer) { - this.iconContainer.title = calculatedTitle; - this.iconContainer.setAttribute('aria-label', calculatedTitle); - } - - this._title = title; - this._onDidChangeTitleArea.fire(); - } - - private setTitleDescription(description: string | undefined) { - if (this.titleDescriptionContainer) { - this.titleDescriptionContainer.textContent = description ?? ''; - this.titleDescriptionContainer.setAttribute('title', description ?? ''); - } - else if (description && this.titleContainer) { - this.titleDescriptionContainer = after(this.titleContainer, $('span.description', { title: description }, description)); - } - } - - protected updateTitleDescription(description?: string | undefined): void { - this.setTitleDescription(description); - - this._titleDescription = description; - this._onDidChangeTitleArea.fire(); - } - - private calculateTitle(title: string): string { - const viewContainer = this.viewDescriptorService.getViewContainerByViewId(this.id)!; - const model = this.viewDescriptorService.getViewContainerModel(viewContainer); - const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.id); - const isDefault = this.viewDescriptorService.getDefaultContainerById(this.id) === viewContainer; - - if (!isDefault && viewDescriptor?.containerTitle && model.title !== viewDescriptor.containerTitle) { - return `${viewDescriptor.containerTitle}: ${title}`; - } - - return title; - } - - private scrollableElement!: DomScrollableElement; - - protected renderBody(container: HTMLElement): void { - this.bodyContainer = container; - - const viewWelcomeContainer = append(container, $('.welcome-view')); - this.viewWelcomeContainer = $('.welcome-view-content', { tabIndex: 0 }); - this.scrollableElement = this._register(new DomScrollableElement(this.viewWelcomeContainer, { - alwaysConsumeMouseWheel: true, - horizontal: ScrollbarVisibility.Hidden, - vertical: ScrollbarVisibility.Visible, - })); - - append(viewWelcomeContainer, this.scrollableElement.getDomNode()); - - const onViewWelcomeChange = Event.any(this.viewWelcomeController.onDidChange, this.onDidChangeViewWelcomeState); - this._register(onViewWelcomeChange(this.updateViewWelcome, this)); - this.updateViewWelcome(); - } - - protected layoutBody(height: number, width: number): void { - this.viewWelcomeContainer.style.height = `${height}px`; - this.viewWelcomeContainer.style.width = `${width}px`; - this.scrollableElement.scanDomNode(); - } - - getProgressIndicator() { - if (this.progressBar === undefined) { - // Progress bar - this.progressBar = this._register(new ProgressBar(this.element)); - this._register(attachProgressBarStyler(this.progressBar, this.themeService)); - this.progressBar.hide(); - } - - if (this.progressIndicator === undefined) { - this.progressIndicator = this.instantiationService.createInstance(CompositeProgressIndicator, assertIsDefined(this.progressBar), this.id, this.isBodyVisible()); - } - return this.progressIndicator; - } - - protected getProgressLocation(): string { - return this.viewDescriptorService.getViewContainerByViewId(this.id)!.id; - } - - protected getBackgroundColor(): string { - return this.viewDescriptorService.getViewLocationById(this.id) === ViewContainerLocation.Panel ? PANEL_BACKGROUND : SIDE_BAR_BACKGROUND; - } - - focus(): void { - if (this.shouldShowWelcome()) { - this.viewWelcomeContainer.focus(); - } else if (this.element) { - this.element.focus(); - this._onDidFocus.fire(); - } - } - - private setActions(): void { - if (this.toolbar) { - this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions())); - this.toolbar.context = this.getActionsContext(); - } - } - - private updateActionsVisibility(): void { - if (!this.headerContainer) { - return; - } - const shouldAlwaysShowActions = this.configurationService.getValue('workbench.view.alwaysShowHeaderActions'); - this.headerContainer.classList.toggle('actions-always-visible', shouldAlwaysShowActions); - } - - protected updateActions(): void { - this.setActions(); - this._onDidChangeTitleArea.fire(); - } - - getActions(): IAction[] { - return this.menuActions.getPrimaryActions(); - } - - getSecondaryActions(): IAction[] { - return this.menuActions.getSecondaryActions(); - } - - getContextMenuActions(): IAction[] { - return this.menuActions.getContextMenuActions(); - } - - getActionViewItem(action: IAction): IActionViewItem | undefined { - if (action instanceof MenuItemAction) { - return this.instantiationService.createInstance(MenuEntryActionViewItem, action); - } else if (action instanceof SubmenuItemAction) { - return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action); - } - return undefined; - } - - getActionsContext(): unknown { - return undefined; - } - - getOptimalWidth(): number { - return 0; - } - - saveState(): void { - // Subclasses to implement for saving state - } - - private updateViewWelcome(): void { - this.viewWelcomeDisposable.dispose(); - - if (!this.shouldShowWelcome()) { - this.bodyContainer.classList.remove('welcome'); - this.viewWelcomeContainer.innerText = ''; - this.scrollableElement.scanDomNode(); - return; - } - - const contents = this.viewWelcomeController.contents; - - if (contents.length === 0) { - this.bodyContainer.classList.remove('welcome'); - this.viewWelcomeContainer.innerText = ''; - this.scrollableElement.scanDomNode(); - return; - } - - const disposables = new DisposableStore(); - this.bodyContainer.classList.add('welcome'); - this.viewWelcomeContainer.innerText = ''; - - for (const { content, precondition } of contents) { - const lines = content.split('\n'); - - for (let line of lines) { - line = line.trim(); - - if (!line) { - continue; - } - - const linkedText = parseLinkedText(line); - - if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') { - const node = linkedText.nodes[0]; - const button = new Button(this.viewWelcomeContainer, { title: node.title, supportCodicons: true }); - button.label = node.label; - button.onDidClick(_ => { - this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href }); - this.openerService.open(node.href); - }, null, disposables); - disposables.add(button); - disposables.add(attachButtonStyler(button, this.themeService)); - - if (precondition) { - const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); - updateEnablement(); - - const keys = new Set(); - precondition.keys().forEach(key => keys.add(key)); - const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); - onDidChangeContext(updateEnablement, null, disposables); - } - } else { - const p = append(this.viewWelcomeContainer, $('p')); - - for (const node of linkedText.nodes) { - if (typeof node === 'string') { - append(p, document.createTextNode(node)); - } else { - const link = this.instantiationService.createInstance(Link, node); - append(p, link.el); - disposables.add(link); - disposables.add(attachLinkStyler(link, this.themeService)); - } - } - } - } - } - - this.scrollableElement.scanDomNode(); - this.viewWelcomeDisposable = disposables; - } - - shouldShowWelcome(): boolean { - return false; - } -} - export interface IViewPaneContainerOptions extends IPaneViewOptions { mergeViewWithContainerWhenSingleView: boolean; } @@ -1680,21 +1103,6 @@ export abstract class ViewPaneContainerAction exte abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; } -export abstract class ViewAction extends Action2 { - constructor(readonly desc: Readonly & { viewId: string }) { - super(desc); - } - - run(accessor: ServicesAccessor, ...args: any[]) { - const view = accessor.get(IViewsService).getActiveViewWithId(this.desc.viewId); - if (view) { - return this.runInView(accessor, view, ...args); - } - } - - abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; -} - class MoveViewPosition extends Action2 { constructor(desc: Readonly, private readonly offset: number) { super(desc); diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 47b8f051583..9df0fa0263e 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -12,7 +12,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ViewPaneContainer, ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { Event } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts index ab0172eeca7..3b35a67b71c 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts @@ -17,7 +17,7 @@ import { BulkEditPreviewProvider, BulkFileOperations, BulkFileOperationType } fr import { ILabelService } from 'vs/platform/label/common/label'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { URI } from 'vs/base/common/uri'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/workbench/contrib/comments/browser/commentsView.ts b/src/vs/workbench/contrib/comments/browser/commentsView.ts index d917b578057..b83fb80517a 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsView.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsView.ts @@ -20,7 +20,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { textLinkForeground, textLinkActiveForeground, focusBorder, textPreformatForeground } from 'vs/platform/theme/common/colorRegistry'; import { ResourceLabels } from 'vs/workbench/browser/labels'; import { CommentsList, COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE } from 'vs/workbench/contrib/comments/browser/commentsTreeViewer'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index dbbddbd426d..cc8b4a9ef12 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -27,7 +27,7 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Gesture } from 'vs/base/browser/touch'; diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 70851479da9..e443fd1e5e6 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -18,7 +18,7 @@ import { IAction, Action } from 'vs/base/common/actions'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 91187dd3a53..cd4038aab03 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -22,7 +22,8 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { memoize } from 'vs/base/common/decorators'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; -import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IMenu, MenuId, IMenuService, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; diff --git a/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts b/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts index 198da910875..6ebf580c295 100644 --- a/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts +++ b/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { normalize, isAbsolute, posix } from 'vs/base/common/path'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 724d265ca97..f4a61cdcaa0 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -50,7 +50,7 @@ import { FuzzyScore } from 'vs/base/common/filters'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ReplDelegate, ReplVariablesRenderer, ReplSimpleElementsRenderer, ReplEvaluationInputsRenderer, ReplEvaluationResultsRenderer, ReplRawObjectsRenderer, ReplDataSource, ReplAccessibilityProvider, ReplGroupRenderer } from 'vs/workbench/contrib/debug/browser/replViewer'; import { localize } from 'vs/nls'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index 7c8acdc4176..57fc19ff931 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -16,7 +16,7 @@ import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRe import { IAction } from 'vs/base/common/actions'; import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { ITreeRenderer, ITreeNode, ITreeMouseEvent, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index 2e18414c9db..3d7452aa018 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -16,7 +16,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IAction, Action, Separator } from 'vs/base/common/actions'; import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index c88b28e8b6f..8129475f305 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -13,7 +13,7 @@ import { localize } from 'vs/nls'; import { StartAction, ConfigureAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IViewDescriptorService, IViewsRegistry, Extensions, ViewContentGroups } from 'vs/workbench/common/views'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 9b8d0bb370f..9858def3b4d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -39,7 +39,8 @@ import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery'; import { SuggestEnabledInput, attachSuggestEnabledInputBoxStyler } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput'; import { alert } from 'vs/base/browser/ui/aria/aria'; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index 42ef838cce3..5fc6793be3a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -29,7 +29,7 @@ import { ManageExtensionAction, getContextMenuActions, ExtensionAction } from 'v import { WorkbenchPagedList, ListResourceNavigator } from 'vs/platform/list/browser/listService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { coalesce, distinct, flatten } from 'vs/base/common/arrays'; import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/common/experimentService'; diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 9745ec52db6..3b0e5404104 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -28,7 +28,8 @@ import { DelegatingEditorService } from 'vs/workbench/services/editor/browser/ed import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorPane } from 'vs/workbench/common/editor'; -import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { KeyChord, KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Registry } from 'vs/platform/registry/common/platform'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index d649859fc42..7e70f008f29 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -11,7 +11,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { ResourcesDropHandler, DragAndDropObserver } from 'vs/workbench/browser/dnd'; import { listDropBackground } from 'vs/platform/theme/common/colorRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index a9309b46767..75aa6726d94 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -25,7 +25,7 @@ import { IDecorationsService } from 'vs/workbench/services/decorations/browser/d import { WorkbenchCompressibleAsyncDataTree } from 'vs/platform/list/browser/listService'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; import { ExplorerDelegate, ExplorerDataSource, FilesRenderer, ICompressedNavigationController, FilesFilter, FileSorter, FileDragAndDrop, ExplorerCompressionDelegate, isCompressedFolderName } from 'vs/workbench/contrib/files/browser/views/explorerViewer'; import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService'; diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 3535108c329..c925f2ad8ad 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -34,7 +34,7 @@ import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions' import { OpenEditorsDirtyEditorContext, OpenEditorsGroupContext, OpenEditorsReadonlyEditorContext } from 'vs/workbench/contrib/files/browser/fileCommands'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ResourcesDropHandler, fillResourceDataTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IDragAndDropData, DataTransfers } from 'vs/base/browser/dnd'; import { memoize } from 'vs/base/common/decorators'; diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 8046070b68e..589b0a2ec81 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -45,7 +45,7 @@ import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { KeyCode } from 'vs/base/common/keyCodes'; import { editorLightBulbForeground, editorLightBulbAutoFixForeground } from 'vs/platform/theme/common/colorRegistry'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { Codicon } from 'vs/base/common/codicons'; diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 1bc3e714c6f..b1317b559f4 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -30,7 +30,7 @@ import { WorkbenchDataTree } from 'vs/platform/list/browser/listService'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ViewAction, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewAction, ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { OutlineConfigKeys, OutlineViewFocused, OutlineViewFiltered, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index a01c54ae7e8..ddd71be77d1 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -21,7 +21,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { CancellationToken } from 'vs/base/common/cancellation'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IViewDescriptorService } from 'vs/workbench/common/views'; diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 29ab926a392..5549a5f8935 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -44,7 +44,7 @@ import { Action, IActionViewItem, IAction } from 'vs/base/common/actions'; import { isStringArray } from 'vs/base/common/types'; import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { ITreeRenderer, ITreeNode, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 7ed9fa790e0..8ceda9778c8 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -35,7 +35,7 @@ import { once } from 'vs/base/common/functional'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { URI } from 'vs/base/common/uri'; import { RemoteTunnel } from 'vs/platform/remote/common/tunnel'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; diff --git a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts index 1a5d3329ac4..7945dc95a48 100644 --- a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/scm'; import { localize } from 'vs/nls'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { append, $ } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list'; import { ISCMRepository, ISCMService, ISCMViewService } from 'vs/workbench/contrib/scm/common/scm'; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 4095bee2080..a9394a6bf58 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/scm'; import { Event, Emitter } from 'vs/base/common/event'; import { basename, dirname } from 'vs/base/common/resources'; import { IDisposable, Disposable, DisposableStore, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { append, $, Dimension, asCSSUrl } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMRepository, ISCMInput, IInputValidation, ISCMViewService, ISCMViewVisibleRepositoryChangeEvent, ISCMService, SCMInputChangeReason } from 'vs/workbench/contrib/scm/common/scm'; diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 96902f92a83..408270cc7a6 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -57,7 +57,7 @@ import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/servic import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { relativePath } from 'vs/base/common/resources'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalView.ts b/src/vs/workbench/contrib/terminal/browser/terminalView.ts index 2d2f0a1b21f..df2a73c8538 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalView.ts @@ -21,7 +21,7 @@ import { DataTransfers } from 'vs/base/browser/dnd'; import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; import { ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IViewDescriptorService } from 'vs/workbench/common/views'; diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index 5e9a0f28166..80e9bfbdb5f 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -31,7 +31,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IResourceLabel, IResourceLabelOptions, IResourceLabelProps, ResourceLabels } from 'vs/workbench/browser/labels'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { isTestItem, ITestingCollectionService, ITestSubscriptionFolder, ITestSubscriptionItem } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 64f30027e35..106ec7cbbcc 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -21,7 +21,7 @@ import { URI } from 'vs/base/common/uri'; import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { IListVirtualDelegate, IIdentityProvider, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list'; import { ITreeNode, ITreeRenderer, ITreeContextMenuEvent, ITreeElement } from 'vs/base/browser/ui/tree/tree'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts index d9beb099f06..eed36d2b0a9 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts @@ -19,7 +19,7 @@ import { IProgressService } from 'vs/platform/progress/common/progress'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; From 75eeac010491c7156941d7fbb3751541e48b4f15 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 09:54:41 +0100 Subject: [PATCH 0887/1837] Split Linux Build, add macOS jobs --- .github/workflows/ci.yml | 225 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 220 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3470ab0af9a..f3d140b7b94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,8 +48,8 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check - compile: - name: Compile Build + build-compile: + name: "Build: Compile" runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -98,9 +98,9 @@ jobs: - name: Minify VS Code run: yarn gulp minify-vscode - linux-build: - name: Linux Build - needs: compile + build-linux-unit-tests: + name: "Build: Linux Unit Tests" + needs: build-compile runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -161,9 +161,224 @@ jobs: - name: Run Unit Tests (Browser) run: DISPLAY=:10 yarn test-browser --build --browser chromium + build-linux-integration-tests: + name: "Build: Linux Integration Tests" + needs: build-compile + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + - name: Setup Build Environment + run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Restore cached node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + + - name: Restore cached /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} + + - name: Build VS Code + run: yarn gulp vscode-linux-x64-min-ci + + - name: Download Electron + run: yarn electron x64 + - name: Run Integration Tests (Electron) run: DISPLAY=:10 ./scripts/test-integration.sh --build + build-darwin-unit-tests: + name: "Build: macOS Unit Tests" + needs: build-compile + runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} + + - name: Build VS Code + run: yarn gulp vscode-darwin-x64-min-ci + + - name: Download Electron + run: yarn electron x64 + + - name: Run Unit Tests (Electron) + run: ./scripts/test.sh --build + + - name: Download Playwright + run: node ./node_modules/playwright/install.js + + - name: Run Unit Tests (Browser) + run: yarn test-browser --build --browser chromium --browser webkit --browser firefox + + build-darwin-integration-tests: + name: "Build: macOS Integration Tests" + needs: build-compile + runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} + + - name: Build VS Code + run: yarn gulp vscode-darwin-x64-min-ci + + - name: Download Electron + run: yarn electron x64 + + - name: Run Integration Tests (Electron) + run: ./scripts/test-integration.sh --build + + build-darwin-smoke-tests: + name: "Build: macOS Smoke Tests" + needs: build-compile + runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Cache /build/ scripts + id: cacheBuildScripts + uses: actions/cache@v2 + with: + path: build/**/*.js + key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Restore cached compiled code + id: cacheCompiledCode + uses: actions/cache@v2 + with: + path: | + .build + out-build + out-vscode-min + key: cacheCompiledCode-${{ env.GITHUB_SHA }} + + - name: Build VS Code + run: yarn gulp vscode-darwin-x64-min-ci + + - name: Run Smoke Tests (Electron) + continue-on-error: true + run: | + set -e + APP_ROOT=$(GITHUB_WORKSPACE)/VSCode-darwin-x64 + APP_NAME="`ls $APP_ROOT | head -n 1`" + yarn smoketest --build "$APP_ROOT/$APP_NAME" + linux: name: Linux runs-on: ubuntu-latest From f413b81fcda270e6fbbeef96456bd2bd7774e8eb Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 09:59:07 +0100 Subject: [PATCH 0888/1837] windows - move state handling into own class --- .../launch/electron-main/launchMainService.ts | 6 +- .../platform/windows/electron-main/windows.ts | 4 +- .../electron-main/windowsMainService.ts | 201 ++---------- .../electron-main/windowsStateHandler.ts | 295 ++++++++++++++++++ .../electron-main/windowsStateStorage.ts | 107 ------- ...ge.test.ts => windowsStateHandler.test.ts} | 2 +- 6 files changed, 325 insertions(+), 290 deletions(-) create mode 100644 src/vs/platform/windows/electron-main/windowsStateHandler.ts delete mode 100644 src/vs/platform/windows/electron-main/windowsStateStorage.ts rename src/vs/platform/windows/test/electron-main/{windowsStateStorage.test.ts => windowsStateHandler.test.ts} (99%) diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 97d251557da..54a02fdefac 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -297,10 +297,10 @@ export class LaunchMainService implements ILaunchMainService { return this.browserWindowToInfo(window.win, folderURIs, window.remoteAuthority); } - private browserWindowToInfo(win: BrowserWindow, folderURIs: URI[] = [], remoteAuthority?: string): IWindowInfo { + private browserWindowToInfo(window: BrowserWindow, folderURIs: URI[] = [], remoteAuthority?: string): IWindowInfo { return { - pid: win.webContents.getOSProcessId(), - title: win.getTitle(), + pid: window.webContents.getOSProcessId(), + title: window.getTitle(), folderURIs, remoteAuthority }; diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index f5a42fb7311..9fd013da6ad 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -124,9 +124,11 @@ export interface IWindowsMainService { readonly _serviceBrand: undefined; + readonly onWindowsCountChanged: Event; + readonly onWindowOpened: Event; readonly onWindowReady: Event; - readonly onWindowsCountChanged: Event; + readonly onWindowDestroyed: Event; open(openConfig: IOpenConfiguration): ICodeWindow[]; openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[]; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 20c111f9afc..005897bc0af 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -13,7 +13,7 @@ import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/e import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateService } from 'vs/platform/state/node/state'; import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; -import { screen, BrowserWindow, MessageBoxOptions, Display, app, WebContents } from 'electron'; +import { screen, BrowserWindow, MessageBoxOptions, Display, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; @@ -30,7 +30,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { normalizePath, originalFSPath, removeTrailingPathSeparator, extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; -import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateStorage'; +import { IWindowState, WindowsStateHandler } from 'vs/platform/windows/electron-main/windowsStateHandler'; import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -145,24 +145,22 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic declare readonly _serviceBrand: undefined; - private static readonly windowsStateStorageKey = 'windowsState'; - private static readonly WINDOWS: ICodeWindow[] = []; - private readonly windowsState: IWindowsState; - private lastClosedWindowState?: IWindowState; - - private shuttingDown = false; - private readonly _onWindowOpened = this._register(new Emitter()); readonly onWindowOpened = this._onWindowOpened.event; private readonly _onWindowReady = this._register(new Emitter()); readonly onWindowReady = this._onWindowReady.event; + private readonly _onWindowDestroyed = this._register(new Emitter()); + readonly onWindowDestroyed = this._onWindowDestroyed.event; + private readonly _onWindowsCountChanged = this._register(new Emitter()); readonly onWindowsCountChanged = this._onWindowsCountChanged.event; + private readonly windowsStateHandler = this._register(new WindowsStateHandler(this.stateService, this.lifecycleMainService, this, this.logService)); + constructor( private readonly machineId: string, private readonly initialUserEnv: IProcessEnvironment, @@ -179,166 +177,13 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic ) { super(); - this.windowsState = restoreWindowsState(this.stateService.getItem(WindowsMainService.windowsStateStorageKey)); this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners()); } private registerListeners(): void { - // When a window looses focus, save all windows state. This allows to - // prevent loss of window-state data when OS is restarted without properly - // shutting down the application (https://github.com/microsoft/vscode/issues/87171) - app.on('browser-window-blur', () => { - if (!this.shuttingDown) { - this.saveWindowsState(); - } - }); - - // Handle various lifecycle events around windows - this.lifecycleMainService.onBeforeWindowClose(window => this.onBeforeWindowClose(window)); - this.lifecycleMainService.onBeforeShutdown(() => this.onBeforeShutdown()); - this.onWindowsCountChanged(e => { - if (e.newCount - e.oldCount > 0) { - // clear last closed window state when a new window opens. this helps on macOS where - // otherwise closing the last window, opening a new window and then quitting would - // use the state of the previously closed window when restarting. - this.lastClosedWindowState = undefined; - } - }); - // Signal a window is ready after having entered a workspace - this._register(this.workspacesMainService.onWorkspaceEntered(event => { - this._onWindowReady.fire(event.window); - })); - } - - // Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS: - // - macOS: since the app will not quit when closing the last window, you will always first get - // the onBeforeShutdown() event followed by N onBeforeWindowClose() events for each window - // - other: on other OS, closing the last window will quit the app so the order depends on the - // user interaction: closing the last window will first trigger onBeforeWindowClose() - // and then onBeforeShutdown(). Using the quit action however will first issue onBeforeShutdown() - // and then onBeforeWindowClose(). - // - // Here is the behavior on different OS depending on action taken (Electron 1.7.x): - // - // Legend - // - quit(N): quit application with N windows opened - // - close(1): close one window via the window close button - // - closeAll: close all windows via the taskbar command - // - onBeforeShutdown(N): number of windows reported in this event handler - // - onBeforeWindowClose(N, M): number of windows reported and quitRequested boolean in this event handler - // - // macOS - // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) - // - quit(0): onBeforeShutdown(0) - // - close(1): onBeforeWindowClose(1, false) - // - // Windows - // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) - // - close(1): onBeforeWindowClose(2, false)[not last window] - // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] - // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) - // - // Linux - // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) - // - close(1): onBeforeWindowClose(2, false)[not last window] - // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] - // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) - // - private onBeforeShutdown(): void { - this.shuttingDown = true; - - this.saveWindowsState(); - } - - private saveWindowsState(): void { - const currentWindowsState: IWindowsState = { - openedWindows: [], - lastPluginDevelopmentHostWindow: this.windowsState.lastPluginDevelopmentHostWindow, - lastActiveWindow: this.lastClosedWindowState - }; - - // 1.) Find a last active window (pick any other first window otherwise) - if (!currentWindowsState.lastActiveWindow) { - let activeWindow = this.getLastActiveWindow(); - if (!activeWindow || activeWindow.isExtensionDevelopmentHost) { - activeWindow = this.getWindows().find(window => !window.isExtensionDevelopmentHost); - } - - if (activeWindow) { - currentWindowsState.lastActiveWindow = this.toWindowState(activeWindow); - } - } - - // 2.) Find extension host window - const extensionHostWindow = this.getWindows().find(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost); - if (extensionHostWindow) { - currentWindowsState.lastPluginDevelopmentHostWindow = this.toWindowState(extensionHostWindow); - } - - // 3.) All windows (except extension host) for N >= 2 to support `restoreWindows: all` or for auto update - // - // Careful here: asking a window for its window state after it has been closed returns bogus values (width: 0, height: 0) - // so if we ever want to persist the UI state of the last closed window (window count === 1), it has - // to come from the stored lastClosedWindowState on Win/Linux at least - if (this.getWindowCount() > 1) { - currentWindowsState.openedWindows = this.getWindows().filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); - } - - // Persist - const state = getWindowsStateStoreData(currentWindowsState); - this.stateService.setItem(WindowsMainService.windowsStateStorageKey, state); - - if (this.shuttingDown) { - this.logService.trace('onBeforeShutdown', state); - } - } - - // See note on #onBeforeShutdown() for details how these events are flowing - private onBeforeWindowClose(win: ICodeWindow): void { - if (this.lifecycleMainService.quitRequested) { - return; // during quit, many windows close in parallel so let it be handled in the before-quit handler - } - - // On Window close, update our stored UI state of this window - const state: IWindowState = this.toWindowState(win); - if (win.isExtensionDevelopmentHost && !win.isExtensionTestHost) { - this.windowsState.lastPluginDevelopmentHostWindow = state; // do not let test run window state overwrite our extension development state - } - - // Any non extension host window with same workspace or folder - else if (!win.isExtensionDevelopmentHost && (!!win.openedWorkspace || !!win.openedFolderUri)) { - this.windowsState.openedWindows.forEach(o => { - const sameWorkspace = win.openedWorkspace && o.workspace && o.workspace.id === win.openedWorkspace.id; - const sameFolder = win.openedFolderUri && o.folderUri && extUriBiasedIgnorePathCase.isEqual(o.folderUri, win.openedFolderUri); - - if (sameWorkspace || sameFolder) { - o.uiState = state.uiState; - } - }); - } - - // On Windows and Linux closing the last window will trigger quit. Since we are storing all UI state - // before quitting, we need to remember the UI state of this window to be able to persist it. - // On macOS we keep the last closed window state ready in case the user wants to quit right after or - // wants to open another window, in which case we use this state over the persisted one. - if (this.getWindowCount() === 1) { - this.lastClosedWindowState = state; - } - } - - private toWindowState(win: ICodeWindow): IWindowState { - return { - workspace: win.openedWorkspace, - folderUri: win.openedFolderUri, - backupPath: win.backupPath, - remoteAuthority: win.remoteAuthority, - uiState: win.serializeWindowState() - }; + this._register(this.workspacesMainService.onWorkspaceEntered(event => this._onWindowReady.fire(event.window))); } openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[] { @@ -434,13 +279,13 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Otherwise, find a good window based on open params else { - const focusLastActive = this.windowsState.lastActiveWindow && !openConfig.forceEmpty && !openConfig.cli._.length && !openConfig.cli['file-uri'] && !openConfig.cli['folder-uri'] && !(openConfig.urisToOpen && openConfig.urisToOpen.length); + const focusLastActive = this.windowsStateHandler.state.lastActiveWindow && !openConfig.forceEmpty && !openConfig.cli._.length && !openConfig.cli['file-uri'] && !openConfig.cli['folder-uri'] && !(openConfig.urisToOpen && openConfig.urisToOpen.length); let focusLastOpened = true; let focusLastWindow = true; // 2.) focus last active window if we are not instructed to open any paths if (focusLastActive) { - const lastActiveWindow = usedWindows.filter(window => this.windowsState.lastActiveWindow && window.backupPath === this.windowsState.lastActiveWindow.backupPath); + const lastActiveWindow = usedWindows.filter(window => this.windowsStateHandler.state.lastActiveWindow && window.backupPath === this.windowsStateHandler.state.lastActiveWindow.backupPath); if (lastActiveWindow.length) { lastActiveWindow[0].focus(); focusLastOpened = false; @@ -987,10 +832,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Collect previously opened windows const openedWindows: IWindowState[] = []; if (restoreWindowsSetting !== 'one') { - openedWindows.push(...this.windowsState.openedWindows); + openedWindows.push(...this.windowsStateHandler.state.openedWindows); } - if (this.windowsState.lastActiveWindow) { - openedWindows.push(this.windowsState.lastActiveWindow); + if (this.windowsStateHandler.state.lastActiveWindow) { + openedWindows.push(this.windowsStateHandler.state.lastActiveWindow); } const windowsToOpen: IPathToOpen[] = []; @@ -1287,7 +1132,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Fill in previously opened workspace unless an explicit path is provided and we are not unit testing if (!cliArgs.length && !folderUris.length && !fileUris.length && !openConfig.cli.extensionTestsPath) { - const extensionDevelopmentWindowState = this.windowsState.lastPluginDevelopmentHostWindow; + const extensionDevelopmentWindowState = this.windowsStateHandler.state.lastPluginDevelopmentHostWindow; const workspaceToOpen = extensionDevelopmentWindowState && (extensionDevelopmentWindowState.workspace || extensionDevelopmentWindowState.folderUri); if (workspaceToOpen) { if (isSingleFolderWorkspaceIdentifier(workspaceToOpen)) { @@ -1471,7 +1316,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Window Events once(createdWindow.onReady)(() => this._onWindowReady.fire(createdWindow)); once(createdWindow.onClose)(() => this.onWindowClosed(createdWindow)); - once(createdWindow.onDestroy)(() => this.onBeforeWindowClose(createdWindow)); // try to save state before destroy because close will not fire + once(createdWindow.onDestroy)(() => this._onWindowDestroyed.fire(createdWindow)); createdWindow.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own createdWindow.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow)); @@ -1536,14 +1381,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic if (!configuration.extensionTestsPath) { // extension development host Window - load from stored settings if any - if (!!configuration.extensionDevelopmentPath && this.windowsState.lastPluginDevelopmentHostWindow) { - return this.windowsState.lastPluginDevelopmentHostWindow.uiState; + if (!!configuration.extensionDevelopmentPath && this.windowsStateHandler.state.lastPluginDevelopmentHostWindow) { + return this.windowsStateHandler.state.lastPluginDevelopmentHostWindow.uiState; } // Known Workspace - load from stored settings const workspace = configuration.workspace; if (workspace) { - const stateForWorkspace = this.windowsState.openedWindows.filter(o => o.workspace && o.workspace.id === workspace.id).map(o => o.uiState); + const stateForWorkspace = this.windowsStateHandler.state.openedWindows.filter(o => o.workspace && o.workspace.id === workspace.id).map(o => o.uiState); if (stateForWorkspace.length) { return stateForWorkspace[0]; } @@ -1551,7 +1396,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Known Folder - load from stored settings if (configuration.folderUri) { - const stateForFolder = this.windowsState.openedWindows.filter(o => o.folderUri && extUriBiasedIgnorePathCase.isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState); + const stateForFolder = this.windowsStateHandler.state.openedWindows.filter(o => o.folderUri && extUriBiasedIgnorePathCase.isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState); if (stateForFolder.length) { return stateForFolder[0]; } @@ -1559,14 +1404,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Empty windows with backups else if (configuration.backupPath) { - const stateForEmptyWindow = this.windowsState.openedWindows.filter(o => o.backupPath === configuration.backupPath).map(o => o.uiState); + const stateForEmptyWindow = this.windowsStateHandler.state.openedWindows.filter(o => o.backupPath === configuration.backupPath).map(o => o.uiState); if (stateForEmptyWindow.length) { return stateForEmptyWindow[0]; } } // First Window - const lastActiveState = this.lastClosedWindowState || this.windowsState.lastActiveWindow; + const lastActiveState = this.windowsStateHandler.lastClosedState || this.windowsStateHandler.state.lastActiveWindow; if (!lastActive && lastActiveState) { return lastActiveState.uiState; } @@ -1660,10 +1505,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return state; } - private onWindowClosed(win: ICodeWindow): void { + private onWindowClosed(window: ICodeWindow): void { // Remove from our list so that Electron can clean it up - const index = WindowsMainService.WINDOWS.indexOf(win); + const index = WindowsMainService.WINDOWS.indexOf(window); WindowsMainService.WINDOWS.splice(index, 1); // Emit diff --git a/src/vs/platform/windows/electron-main/windowsStateHandler.ts b/src/vs/platform/windows/electron-main/windowsStateHandler.ts new file mode 100644 index 00000000000..453b786f763 --- /dev/null +++ b/src/vs/platform/windows/electron-main/windowsStateHandler.ts @@ -0,0 +1,295 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { app } from 'electron'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IStateService } from 'vs/platform/state/node/state'; +import { ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows'; +import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; + +export type WindowsStateStorageData = object; + +export interface IWindowState { + workspace?: IWorkspaceIdentifier; + folderUri?: URI; + backupPath?: string; + remoteAuthority?: string; + uiState: IWindowUIState; +} + +export interface IWindowsState { + lastActiveWindow?: IWindowState; + lastPluginDevelopmentHostWindow?: IWindowState; + openedWindows: IWindowState[]; +} + +interface ISerializedWindowsState { + readonly lastActiveWindow?: ISerializedWindowState; + readonly lastPluginDevelopmentHostWindow?: ISerializedWindowState; + readonly openedWindows: ISerializedWindowState[]; +} + +interface ISerializedWindowState { + readonly workspaceIdentifier?: { id: string; configURIPath: string }; + readonly folder?: string; + readonly backupPath?: string; + readonly remoteAuthority?: string; + readonly uiState: IWindowUIState; + + // deprecated + readonly folderUri?: UriComponents; + readonly folderPath?: string; + readonly workspace?: { id: string; configPath: string }; +} + +export class WindowsStateHandler extends Disposable { + + private static readonly windowsStateStorageKey = 'windowsState'; + + get state() { return this._windowsState; } + private readonly _windowsState: IWindowsState; + + get lastClosedState() { return this._lastClosedState; } + private _lastClosedState?: IWindowState; + + private shuttingDown = false; + + constructor( + @IStateService private readonly stateService: IStateService, + @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, + @IWindowsMainService private readonly windowsMainService: IWindowsMainService, + @ILogService private readonly logService: ILogService + ) { + super(); + + this._windowsState = restoreWindowsState(this.stateService.getItem(WindowsStateHandler.windowsStateStorageKey)); + + this.registerListeners(); + } + + private registerListeners(): void { + + // When a window looses focus, save all windows state. This allows to + // prevent loss of window-state data when OS is restarted without properly + // shutting down the application (https://github.com/microsoft/vscode/issues/87171) + app.on('browser-window-blur', () => { + if (!this.shuttingDown) { + this.saveWindowsState(); + } + }); + + // Handle various lifecycle events around windows + this.lifecycleMainService.onBeforeWindowClose(window => this.onBeforeWindowClose(window)); + this.lifecycleMainService.onBeforeShutdown(() => this.onBeforeShutdown()); + this.windowsMainService.onWindowsCountChanged(e => { + if (e.newCount - e.oldCount > 0) { + // clear last closed window state when a new window opens. this helps on macOS where + // otherwise closing the last window, opening a new window and then quitting would + // use the state of the previously closed window when restarting. + this._lastClosedState = undefined; + } + }); + + // try to save state before destroy because close will not fire + this.windowsMainService.onWindowDestroyed(window => this.onBeforeWindowClose(window)); + } + + // Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS: + // - macOS: since the app will not quit when closing the last window, you will always first get + // the onBeforeShutdown() event followed by N onBeforeWindowClose() events for each window + // - other: on other OS, closing the last window will quit the app so the order depends on the + // user interaction: closing the last window will first trigger onBeforeWindowClose() + // and then onBeforeShutdown(). Using the quit action however will first issue onBeforeShutdown() + // and then onBeforeWindowClose(). + // + // Here is the behavior on different OS depending on action taken (Electron 1.7.x): + // + // Legend + // - quit(N): quit application with N windows opened + // - close(1): close one window via the window close button + // - closeAll: close all windows via the taskbar command + // - onBeforeShutdown(N): number of windows reported in this event handler + // - onBeforeWindowClose(N, M): number of windows reported and quitRequested boolean in this event handler + // + // macOS + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - quit(0): onBeforeShutdown(0) + // - close(1): onBeforeWindowClose(1, false) + // + // Windows + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - close(1): onBeforeWindowClose(2, false)[not last window] + // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] + // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) + // + // Linux + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - close(1): onBeforeWindowClose(2, false)[not last window] + // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] + // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) + // + private onBeforeShutdown(): void { + this.shuttingDown = true; + + this.saveWindowsState(); + } + + private saveWindowsState(): void { + const currentWindowsState: IWindowsState = { + openedWindows: [], + lastPluginDevelopmentHostWindow: this._windowsState.lastPluginDevelopmentHostWindow, + lastActiveWindow: this._lastClosedState + }; + + // 1.) Find a last active window (pick any other first window otherwise) + if (!currentWindowsState.lastActiveWindow) { + let activeWindow = this.windowsMainService.getLastActiveWindow(); + if (!activeWindow || activeWindow.isExtensionDevelopmentHost) { + activeWindow = this.windowsMainService.getWindows().find(window => !window.isExtensionDevelopmentHost); + } + + if (activeWindow) { + currentWindowsState.lastActiveWindow = this.toWindowState(activeWindow); + } + } + + // 2.) Find extension host window + const extensionHostWindow = this.windowsMainService.getWindows().find(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost); + if (extensionHostWindow) { + currentWindowsState.lastPluginDevelopmentHostWindow = this.toWindowState(extensionHostWindow); + } + + // 3.) All windows (except extension host) for N >= 2 to support `restoreWindows: all` or for auto update + // + // Careful here: asking a window for its window state after it has been closed returns bogus values (width: 0, height: 0) + // so if we ever want to persist the UI state of the last closed window (window count === 1), it has + // to come from the stored lastClosedWindowState on Win/Linux at least + if (this.windowsMainService.getWindowCount() > 1) { + currentWindowsState.openedWindows = this.windowsMainService.getWindows().filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); + } + + // Persist + const state = getWindowsStateStoreData(currentWindowsState); + this.stateService.setItem(WindowsStateHandler.windowsStateStorageKey, state); + + if (this.shuttingDown) { + this.logService.trace('[WindowsStateHandler] onBeforeShutdown', state); + } + } + + // See note on #onBeforeShutdown() for details how these events are flowing + private onBeforeWindowClose(window: ICodeWindow): void { + if (this.lifecycleMainService.quitRequested) { + return; // during quit, many windows close in parallel so let it be handled in the before-quit handler + } + + // On Window close, update our stored UI state of this window + const state: IWindowState = this.toWindowState(window); + if (window.isExtensionDevelopmentHost && !window.isExtensionTestHost) { + this._windowsState.lastPluginDevelopmentHostWindow = state; // do not let test run window state overwrite our extension development state + } + + // Any non extension host window with same workspace or folder + else if (!window.isExtensionDevelopmentHost && (!!window.openedWorkspace || !!window.openedFolderUri)) { + this._windowsState.openedWindows.forEach(openedWindow => { + const sameWorkspace = window.openedWorkspace && openedWindow.workspace && openedWindow.workspace.id === window.openedWorkspace.id; + const sameFolder = window.openedFolderUri && openedWindow.folderUri && extUriBiasedIgnorePathCase.isEqual(openedWindow.folderUri, window.openedFolderUri); + + if (sameWorkspace || sameFolder) { + openedWindow.uiState = state.uiState; + } + }); + } + + // On Windows and Linux closing the last window will trigger quit. Since we are storing all UI state + // before quitting, we need to remember the UI state of this window to be able to persist it. + // On macOS we keep the last closed window state ready in case the user wants to quit right after or + // wants to open another window, in which case we use this state over the persisted one. + if (this.windowsMainService.getWindowCount() === 1) { + this._lastClosedState = state; + } + } + + private toWindowState(window: ICodeWindow): IWindowState { + return { + workspace: window.openedWorkspace, + folderUri: window.openedFolderUri, + backupPath: window.backupPath, + remoteAuthority: window.remoteAuthority, + uiState: window.serializeWindowState() + }; + } +} + +export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState { + const result: IWindowsState = { openedWindows: [] }; + const windowsState = data as ISerializedWindowsState || { openedWindows: [] }; + + if (windowsState.lastActiveWindow) { + result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow); + } + + if (windowsState.lastPluginDevelopmentHostWindow) { + result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow); + } + + if (Array.isArray(windowsState.openedWindows)) { + result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState)); + } + + return result; +} + +function restoreWindowState(windowState: ISerializedWindowState): IWindowState { + const result: IWindowState = { uiState: windowState.uiState }; + if (windowState.backupPath) { + result.backupPath = windowState.backupPath; + } + + if (windowState.remoteAuthority) { + result.remoteAuthority = windowState.remoteAuthority; + } + + if (windowState.folder) { + result.folderUri = URI.parse(windowState.folder); + } else if (windowState.folderUri) { + result.folderUri = URI.revive(windowState.folderUri); + } else if (windowState.folderPath) { + result.folderUri = URI.file(windowState.folderPath); + } + + if (windowState.workspaceIdentifier) { + result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) }; + } else if (windowState.workspace) { + result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) }; + } + + return result; +} + +export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData { + return { + lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow), + lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow), + openedWindows: windowsState.openedWindows.map(ws => serializeWindowState(ws)) + }; +} + +function serializeWindowState(windowState: IWindowState): ISerializedWindowState { + return { + workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() }, + folder: windowState.folderUri && windowState.folderUri.toString(), + backupPath: windowState.backupPath, + remoteAuthority: windowState.remoteAuthority, + uiState: windowState.uiState + }; +} diff --git a/src/vs/platform/windows/electron-main/windowsStateStorage.ts b/src/vs/platform/windows/electron-main/windowsStateStorage.ts deleted file mode 100644 index 15a7d12dd0b..00000000000 --- a/src/vs/platform/windows/electron-main/windowsStateStorage.ts +++ /dev/null @@ -1,107 +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 { URI, UriComponents } from 'vs/base/common/uri'; -import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows'; -import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; - -export type WindowsStateStorageData = object; - -export interface IWindowState { - workspace?: IWorkspaceIdentifier; - folderUri?: URI; - backupPath?: string; - remoteAuthority?: string; - uiState: IWindowUIState; -} - -export interface IWindowsState { - lastActiveWindow?: IWindowState; - lastPluginDevelopmentHostWindow?: IWindowState; - openedWindows: IWindowState[]; -} - -interface ISerializedWindowsState { - readonly lastActiveWindow?: ISerializedWindowState; - readonly lastPluginDevelopmentHostWindow?: ISerializedWindowState; - readonly openedWindows: ISerializedWindowState[]; -} - -interface ISerializedWindowState { - readonly workspaceIdentifier?: { id: string; configURIPath: string }; - readonly folder?: string; - readonly backupPath?: string; - readonly remoteAuthority?: string; - readonly uiState: IWindowUIState; - - // deprecated - readonly folderUri?: UriComponents; - readonly folderPath?: string; - readonly workspace?: { id: string; configPath: string }; -} - -export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState { - const result: IWindowsState = { openedWindows: [] }; - const windowsState = data as ISerializedWindowsState || { openedWindows: [] }; - - if (windowsState.lastActiveWindow) { - result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow); - } - - if (windowsState.lastPluginDevelopmentHostWindow) { - result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow); - } - - if (Array.isArray(windowsState.openedWindows)) { - result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState)); - } - - return result; -} - -function restoreWindowState(windowState: ISerializedWindowState): IWindowState { - const result: IWindowState = { uiState: windowState.uiState }; - if (windowState.backupPath) { - result.backupPath = windowState.backupPath; - } - - if (windowState.remoteAuthority) { - result.remoteAuthority = windowState.remoteAuthority; - } - - if (windowState.folder) { - result.folderUri = URI.parse(windowState.folder); - } else if (windowState.folderUri) { - result.folderUri = URI.revive(windowState.folderUri); - } else if (windowState.folderPath) { - result.folderUri = URI.file(windowState.folderPath); - } - - if (windowState.workspaceIdentifier) { - result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) }; - } else if (windowState.workspace) { - result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) }; - } - - return result; -} - -export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData { - return { - lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow), - lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow), - openedWindows: windowsState.openedWindows.map(ws => serializeWindowState(ws)) - }; -} - -function serializeWindowState(windowState: IWindowState): ISerializedWindowState { - return { - workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() }, - folder: windowState.folderUri && windowState.folderUri.toString(), - backupPath: windowState.backupPath, - remoteAuthority: windowState.remoteAuthority, - uiState: windowState.uiState - }; -} diff --git a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts b/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts similarity index 99% rename from src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts rename to src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts index 5ee6a8683a7..b5b38d68845 100644 --- a/src/vs/platform/windows/test/electron-main/windowsStateStorage.test.ts +++ b/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; -import { restoreWindowsState, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateStorage'; +import { restoreWindowsState, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateHandler'; import { IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; From 36b48f498496556eef561e5f4a369f766e28ec81 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 09:58:58 +0100 Subject: [PATCH 0889/1837] milestone update --- .vscode/notebooks/api.github-issues | 2 +- .vscode/notebooks/my-work.github-issues | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/api.github-issues b/.vscode/notebooks/api.github-issues index 8ff55e2c6ee..36ac402da84 100644 --- a/.vscode/notebooks/api.github-issues +++ b/.vscode/notebooks/api.github-issues @@ -8,7 +8,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"November 2020\"", + "value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"January 2021\"", "editable": true }, { diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index 1065e31dc43..3dd5c22cb2c 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -8,7 +8,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\n\n// current milestone name\n$milestone=milestone:\"December/January 2021\"", + "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\n\n// current milestone name\n$milestone=milestone:\"January 2021\"", "editable": true }, { From 707afc26d6f0c6db8cdb36f29ba953537e6151c6 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:08:36 +0100 Subject: [PATCH 0890/1837] Skip compilation if the cache is hit --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3d140b7b94..43089b111eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,12 +90,15 @@ jobs: key: cacheCompiledCode-${{ env.GITHUB_SHA }} - name: Compile Core + if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} run: yarn gulp compile-build - name: Compile Extensions + if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} run: yarn gulp compile-extensions-build - name: Minify VS Code + if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} run: yarn gulp minify-vscode build-linux-unit-tests: From b742a4c8ea12475d499f951e972e315c17e58b04 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:24:28 +0100 Subject: [PATCH 0891/1837] Create issue on test failure --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43089b111eb..fe0fe4f1d98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -427,14 +427,37 @@ jobs: run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - name: Run Unit Tests (Electron) + id: electron-unit-tests run: DISPLAY=:10 ./scripts/test.sh - name: Run Unit Tests (Browser) + id: browser-unit-tests run: DISPLAY=:10 yarn test-browser --browser chromium - name: Run Integration Tests (Electron) + id: electron-integration-tests run: DISPLAY=:10 ./scripts/test-integration.sh + - name: Create Issue on Unit Test Failure + uses: nashmaniac/create-issue-action@v1.1 + if: ${{ steps.electron-unit-tests.outputs.status == 'failure' || steps.browser-unit-tests.outputs.status == 'failure' }} + with: + title: Unit Test Failed + token: ${{secrets.GITHUB_TOKEN}} + assignees: ${{github.actor}} + labels: unit-test-failure + body: Running unit tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} + + - name: Create Issue on Integration Test Failure + uses: nashmaniac/create-issue-action@v1.1 + if: ${{ steps.electron-integration-tests.outputs.status == 'failure' && steps.electron-unit-tests.outputs.status != 'failure' && steps.browser-unit-tests.outputs.status != 'failure' }} + with: + title: Integration Test Failed + token: ${{secrets.GITHUB_TOKEN}} + assignees: ${{github.actor}} + labels: integration-test-failure + body: Running integration tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} + windows: name: Windows runs-on: windows-latest From a861e22c7cc0d453d7344090382b53e6565861e5 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:27:24 +0100 Subject: [PATCH 0892/1837] Switch to using `github.sha` --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe0fe4f1d98..4b32f27f6d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,7 +87,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Compile Core if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} @@ -147,7 +147,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-linux-x64-min-ci @@ -210,7 +210,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-linux-x64-min-ci @@ -261,7 +261,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci @@ -318,7 +318,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci @@ -369,7 +369,7 @@ jobs: .build out-build out-vscode-min - key: cacheCompiledCode-${{ env.GITHUB_SHA }} + key: cacheCompiledCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci From b7f7b9fb8bdae452a687200900c12824425a343a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:29:04 +0100 Subject: [PATCH 0893/1837] Intentionally fail to test issue creation --- .github/workflows/ci.yml | 4 ++-- src/vs/editor/test/browser/controller/cursor.test.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b32f27f6d0..e86409986dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -444,7 +444,7 @@ jobs: with: title: Unit Test Failed token: ${{secrets.GITHUB_TOKEN}} - assignees: ${{github.actor}} + assignees: alexdima #${{github.actor}} labels: unit-test-failure body: Running unit tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} @@ -454,7 +454,7 @@ jobs: with: title: Integration Test Failed token: ${{secrets.GITHUB_TOKEN}} - assignees: ${{github.actor}} + assignees: alexdima #${{github.actor}} labels: integration-test-failure body: Running integration tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 9dc368f6998..7a2daec0163 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import * as platform from 'vs/base/common/platform'; import { CoreEditingCommands, CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -168,6 +169,11 @@ suite('Editor Controller - Cursor', () => { test('cursor initialized', () => { runTest((editor, viewModel) => { assertCursor(viewModel, new Position(1, 1)); + + // TODO: intentionally fail on Linux to test issue creation + if (platform.isLinux) { + assert.ok(false); + } }); }); From db4264eb3f8fdfa89d7e79b284778d7434c54343 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:33:46 +0100 Subject: [PATCH 0894/1837] Fix variable --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e86409986dd..f3c973cdef6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -446,7 +446,7 @@ jobs: token: ${{secrets.GITHUB_TOKEN}} assignees: alexdima #${{github.actor}} labels: unit-test-failure - body: Running unit tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} + body: Running unit tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} - name: Create Issue on Integration Test Failure uses: nashmaniac/create-issue-action@v1.1 @@ -456,7 +456,7 @@ jobs: token: ${{secrets.GITHUB_TOKEN}} assignees: alexdima #${{github.actor}} labels: integration-test-failure - body: Running integration tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{GITHUB_RUN_ID}} + body: Running integration tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} windows: name: Windows From cb84c32f5ace13914fccfa771af85ee8beb1fc24 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 10:51:17 +0100 Subject: [PATCH 0895/1837] fix #112448 --- src/vs/platform/storage/test/node/storageService.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index e0a410ef604..5ee00224650 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -24,7 +24,7 @@ suite('NativeStorageService', function () { return join(tmpdir(), 'vsctests', id, 'storage2', id); } - test('Migrate Data', async () => { + test('Migrate Data', async function () { // Given issues such as https://github.com/microsoft/vscode/issues/108113 // we see random test failures when accessing the native file system. From 614e183e9a2e31a70ee4d49ab9f590c1c29072be Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 10:53:08 +0100 Subject: [PATCH 0896/1837] Attempt to avoid skipping steps on failure --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3c973cdef6..99e572db88d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -440,7 +440,7 @@ jobs: - name: Create Issue on Unit Test Failure uses: nashmaniac/create-issue-action@v1.1 - if: ${{ steps.electron-unit-tests.outputs.status == 'failure' || steps.browser-unit-tests.outputs.status == 'failure' }} + if: ${{ failure() && (steps.electron-unit-tests.outputs.status == 'failure' || steps.browser-unit-tests.outputs.status == 'failure') }} with: title: Unit Test Failed token: ${{secrets.GITHUB_TOKEN}} @@ -450,7 +450,7 @@ jobs: - name: Create Issue on Integration Test Failure uses: nashmaniac/create-issue-action@v1.1 - if: ${{ steps.electron-integration-tests.outputs.status == 'failure' && steps.electron-unit-tests.outputs.status != 'failure' && steps.browser-unit-tests.outputs.status != 'failure' }} + if: ${{ failure() && (steps.electron-integration-tests.outputs.status == 'failure' && steps.electron-unit-tests.outputs.status != 'failure' && steps.browser-unit-tests.outputs.status != 'failure') }} with: title: Integration Test Failed token: ${{secrets.GITHUB_TOKEN}} From eeded3b8c4537451e446d0816a25d4286002c2b8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 10:54:56 +0100 Subject: [PATCH 0897/1837] fix #112447 --- src/vs/platform/state/test/node/state.test.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index 82166e204d3..362b9de2882 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -14,11 +14,13 @@ suite('StateService', () => { const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); const storageFile = path.join(parentDir, 'storage.json'); - teardown(async () => { - await rimraf(parentDir, RimRafMode.MOVE); - }); + test('Basics', async function () { + + // Given issues such as https://github.com/microsoft/vscode/issues/112447 + // we see random test failures when accessing the native file system. + this.retries(3); + this.timeout(1000 * 20); - test('Basics', async () => { await mkdirp(parentDir); writeFileSync(storageFile, ''); @@ -46,5 +48,7 @@ suite('StateService', () => { service.setItem('some.null.key', null); assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default'); + + await rimraf(parentDir, RimRafMode.MOVE); }); -}); \ No newline at end of file +}); From e25373f16ea98a821321286516232ee02f59c58e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 11:03:14 +0100 Subject: [PATCH 0898/1837] One last try at automatic issue creation --- .github/workflows/ci.yml | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99e572db88d..2851c5c54cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -440,23 +440,13 @@ jobs: - name: Create Issue on Unit Test Failure uses: nashmaniac/create-issue-action@v1.1 - if: ${{ failure() && (steps.electron-unit-tests.outputs.status == 'failure' || steps.browser-unit-tests.outputs.status == 'failure') }} + if: ${{ failure() }} with: - title: Unit Test Failed + title: "CI: Test Failure" token: ${{secrets.GITHUB_TOKEN}} assignees: alexdima #${{github.actor}} - labels: unit-test-failure - body: Running unit tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} - - - name: Create Issue on Integration Test Failure - uses: nashmaniac/create-issue-action@v1.1 - if: ${{ failure() && (steps.electron-integration-tests.outputs.status == 'failure' && steps.electron-unit-tests.outputs.status != 'failure' && steps.browser-unit-tests.outputs.status != 'failure') }} - with: - title: Integration Test Failed - token: ${{secrets.GITHUB_TOKEN}} - assignees: alexdima #${{github.actor}} - labels: integration-test-failure - body: Running integration tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} + labels: unit-test-failure linux + body: Running tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} windows: name: Windows From 71aa067bbd37355b56127f23626d6a5a8fe9378a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 11:04:19 +0100 Subject: [PATCH 0899/1837] Fix intentional failing test --- src/vs/editor/test/browser/controller/cursor.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 7a2daec0163..9dc368f6998 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as platform from 'vs/base/common/platform'; import { CoreEditingCommands, CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -169,11 +168,6 @@ suite('Editor Controller - Cursor', () => { test('cursor initialized', () => { runTest((editor, viewModel) => { assertCursor(viewModel, new Position(1, 1)); - - // TODO: intentionally fail on Linux to test issue creation - if (platform.isLinux) { - assert.ok(false); - } }); }); From 4b88174158f5e99cab609d19b5b73c549dd74455 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 14 Dec 2020 09:47:32 +0100 Subject: [PATCH 0900/1837] notebook: use icon names in registerThemingParticipant --- .../contrib/notebook/browser/notebookEditorWidget.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 9b650c94323..2b4a41c1747 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -61,7 +61,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { configureKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; const $ = DOM.$; @@ -2191,12 +2191,12 @@ registerThemingParticipant((theme, collector) => { const cellStatusSuccessIcon = theme.getColor(cellStatusIconSuccess); if (cellStatusSuccessIcon) { - collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-notebook-state-success { color: ${cellStatusSuccessIcon} }`); + collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status ${ThemeIcon.asCSSSelector(successStateIcon)} { color: ${cellStatusSuccessIcon} }`); } const cellStatusErrorIcon = theme.getColor(cellStatusIconError); if (cellStatusErrorIcon) { - collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status .codicon-notebook-state-error { color: ${cellStatusErrorIcon} }`); + collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status ${ThemeIcon.asCSSSelector(errorStateIcon)} { color: ${cellStatusErrorIcon} }`); } const cellStatusRunningIcon = theme.getColor(cellStatusIconRunning); From ec5da6d09c191910d0aa9890c9e5a11e72ac817f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 11:12:23 +0100 Subject: [PATCH 0901/1837] remove direct writes to `globalThis.MonacoPerformanceMarks`, use native performance instead, import native performance entries into timer service, fyi @bpasero --- src/bootstrap-window.js | 25 ++-------------- .../code/browser/workbench/workbench-dev.html | 5 ++-- src/vs/code/browser/workbench/workbench.html | 5 ++-- .../electron-browser/workbench/workbench.js | 14 ++++----- .../electron-sandbox/workbench/workbench.js | 8 ++--- .../services/timer/browser/timerService.ts | 30 +++++++++++++++++-- 6 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index fe6059c56de..03491d0fb22 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -145,10 +145,9 @@ try { // Wait for process environment being fully resolved - const perf = perfLib(); - perf.mark('willWaitForShellEnv'); + performance.mark('willWaitForShellEnv'); await whenEnvResolved; - perf.mark('didWaitForShellEnv'); + performance.mark('didWaitForShellEnv'); // Callback only after process environment is resolved const callbackResult = resultCallback(result, configuration); @@ -267,26 +266,8 @@ return window.vscode; } - /** - * @return {{ mark: (name: string) => void }} - */ - function perfLib() { - globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || []; - - return { - /** - * @param {string} name - */ - mark(name) { - globalThis.MonacoPerformanceMarks.push(name, Date.now()); - performance.mark(name); - } - }; - } - return { load, - globals, - perfLib + globals }; })); diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 8b1869294e6..20dbd370976 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -3,8 +3,7 @@ @@ -56,7 +55,7 @@ @@ -55,7 +54,7 @@ diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 761ce9c812a..e53c44eb702 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -12,8 +12,7 @@ const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - const perf = bootstrapWindow.perfLib(); - perf.mark('renderer/started'); + performance.mark('renderer/started'); // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because @@ -27,7 +26,7 @@ async function (workbench, configuration) { // Mark start of workbench - perf.mark('didLoadWorkbenchMain'); + performance.mark('didLoadWorkbenchMain'); // @ts-ignore return require('vs/workbench/electron-browser/desktop.main').main(configuration); @@ -41,7 +40,7 @@ loaderConfig.recordStats = true; }, beforeRequire: function () { - perf.mark('willLoadWorkbenchMain'); + performance.mark('willLoadWorkbenchMain'); } } ); @@ -52,8 +51,7 @@ /** * @returns {{ * load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => any, options: object) => unknown, - * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals'), - * perfLib: () => { mark: (name: string) => void } + * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals') * }} */ function bootstrapWindowLib() { @@ -72,7 +70,7 @@ * }} configuration */ function showPartsSplash(configuration) { - perf.mark('willShowPartsSplash'); + performance.mark('willShowPartsSplash'); let data; if (typeof configuration.partsSplashPath === 'string') { @@ -162,7 +160,7 @@ document.body.appendChild(splash); } - perf.mark('didShowPartsSplash'); + performance.mark('didShowPartsSplash'); } //#endregion diff --git a/src/vs/code/electron-sandbox/workbench/workbench.js b/src/vs/code/electron-sandbox/workbench/workbench.js index 6a46ef2b080..e90d470d057 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.js +++ b/src/vs/code/electron-sandbox/workbench/workbench.js @@ -12,8 +12,7 @@ const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - const perf = bootstrapWindow.perfLib(); - perf.mark('renderer/started'); + performance.mark('renderer/started'); // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because @@ -27,7 +26,7 @@ async function (workbench, configuration) { // Mark start of workbench - perf.mark('didLoadWorkbenchMain'); + performance.mark('didLoadWorkbenchMain'); // @ts-ignore return require('vs/workbench/electron-sandbox/desktop.main').main(configuration); @@ -41,7 +40,7 @@ loaderConfig.recordStats = true; }, beforeRequire: function () { - perf.mark('willLoadWorkbenchMain'); + performance.mark('willLoadWorkbenchMain'); } } ); @@ -53,7 +52,6 @@ * @returns {{ * load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown, * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals'), - * perfLib: () => { mark: (name: string) => void } * }} */ function bootstrapWindowLib() { diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 874fca2c1aa..a3988e8c8e7 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -356,7 +356,7 @@ class PerfMarks { if (!toEntry) { return 0; } - return toEntry.startTime - fromEntry.startTime; + return Math.round(toEntry.startTime - fromEntry.startTime); } @@ -396,7 +396,15 @@ export abstract class AbstractTimerService implements ITimerService { this._extensionService.whenInstalledExtensionsRegistered(), _lifecycleService.when(LifecyclePhase.Restored) ]).then(() => { - this.submitPerformanceMarks(perf.getMarks()); + + // import native-browser marks + this._submitNativeMarks(); + + // because "our" perf.mark-util also adds native performance marks + // no extra import of "our" marks is needed, they are already imported + // by importing native perf marks (see above) + // this.submitPerformanceMarks(perf.getMarks()); + return this._computeStartupMetrics(); }).then(metrics => { this._reportStartupTimes(metrics); @@ -404,6 +412,24 @@ export abstract class AbstractTimerService implements ITimerService { }); } + private _submitNativeMarks(): void { + + let timeOrigin = performance.timeOrigin; + if (!timeOrigin) { + // polyfill for Safari + const entry = performance.timing; + timeOrigin = entry.navigationStart || entry.redirectStart || entry.fetchStart; + } + + const marks: perf.PerformanceMark[] = performance.getEntriesByType('mark').map(entry => { + return { + name: entry.name, + startTime: timeOrigin + entry.startTime + }; + }); + this.submitPerformanceMarks(marks); + } + submitPerformanceMarks(marks: perf.PerformanceMark[]): void { this._marks.submitMarks(marks); } From d1fff1a08360f0d35f124c990dc65a6bccd748d2 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 11:13:08 +0100 Subject: [PATCH 0902/1837] Check in `.js` files from the `/build/` folder to improve build speeds --- .github/workflows/ci.yml | 86 +- build/.gitignore | 3 - build/azure-pipelines/common/.gitignore | 2 - build/azure-pipelines/common/createAsset.js | 94 ++ build/azure-pipelines/common/createBuild.js | 51 + .../azure-pipelines/common/publish-webview.js | 71 + build/azure-pipelines/common/releaseBuild.js | 50 + build/azure-pipelines/common/retry.js | 25 + build/azure-pipelines/common/sync-mooncake.js | 87 ++ build/azure-pipelines/mixin.js | 58 + .../azure-pipelines/publish-types/.gitignore | 2 - .../publish-types/check-version.js | 36 + .../publish-types/update-types.js | 72 + build/azure-pipelines/upload-cdn.js | 35 + build/azure-pipelines/upload-sourcemaps.js | 55 + build/darwin/sign.js | 58 + build/lib/asar.js | 118 ++ build/lib/builtInExtensions.js | 113 ++ build/lib/bundle.js | 464 +++++++ build/lib/compilation.js | 174 +++ build/lib/electron.js | 111 ++ build/lib/eslint/code-import-patterns.js | 59 + build/lib/eslint/code-layering.js | 68 + .../code-no-nls-in-standalone-editor.js | 38 + build/lib/eslint/code-no-standalone-editor.js | 41 + .../eslint/code-no-unexternalized-strings.js | 111 ++ .../lib/eslint/code-no-unused-expressions.js | 122 ++ build/lib/eslint/code-translation-remind.js | 57 + build/lib/eslint/utils.js | 37 + build/lib/eslint/vscode-dts-create-func.js | 35 + build/lib/eslint/vscode-dts-event-naming.js | 87 ++ .../lib/eslint/vscode-dts-interface-naming.js | 30 + .../lib/eslint/vscode-dts-literal-or-types.js | 27 + build/lib/extensions.js | 325 +++++ build/lib/git.js | 54 + build/lib/i18n.js | 1204 +++++++++++++++++ build/lib/layersChecker.js | 283 ++++ build/lib/monaco-api.js | 627 +++++++++ build/lib/nls.js | 354 +++++ build/lib/node.js | 15 + build/lib/optimize.js | 235 ++++ build/lib/preLaunch.js | 55 + build/lib/reporter.js | 102 ++ build/lib/snapshotLoader.js | 55 + build/lib/standalone.js | 321 +++++ build/lib/stats.js | 137 ++ build/lib/task.js | 97 ++ build/lib/test/i18n.test.js | 40 + build/lib/treeshaking.js | 779 +++++++++++ build/lib/util.js | 276 ++++ build/lib/watch/index.js | 9 + build/lib/watch/watch-win32.js | 100 ++ 52 files changed, 7461 insertions(+), 84 deletions(-) delete mode 100644 build/.gitignore delete mode 100644 build/azure-pipelines/common/.gitignore create mode 100644 build/azure-pipelines/common/createAsset.js create mode 100644 build/azure-pipelines/common/createBuild.js create mode 100644 build/azure-pipelines/common/publish-webview.js create mode 100644 build/azure-pipelines/common/releaseBuild.js create mode 100644 build/azure-pipelines/common/retry.js create mode 100644 build/azure-pipelines/common/sync-mooncake.js create mode 100644 build/azure-pipelines/mixin.js delete mode 100644 build/azure-pipelines/publish-types/.gitignore create mode 100644 build/azure-pipelines/publish-types/check-version.js create mode 100644 build/azure-pipelines/publish-types/update-types.js create mode 100644 build/azure-pipelines/upload-cdn.js create mode 100644 build/azure-pipelines/upload-sourcemaps.js create mode 100644 build/darwin/sign.js create mode 100644 build/lib/asar.js create mode 100644 build/lib/builtInExtensions.js create mode 100644 build/lib/bundle.js create mode 100644 build/lib/compilation.js create mode 100644 build/lib/electron.js create mode 100644 build/lib/eslint/code-import-patterns.js create mode 100644 build/lib/eslint/code-layering.js create mode 100644 build/lib/eslint/code-no-nls-in-standalone-editor.js create mode 100644 build/lib/eslint/code-no-standalone-editor.js create mode 100644 build/lib/eslint/code-no-unexternalized-strings.js create mode 100644 build/lib/eslint/code-no-unused-expressions.js create mode 100644 build/lib/eslint/code-translation-remind.js create mode 100644 build/lib/eslint/utils.js create mode 100644 build/lib/eslint/vscode-dts-create-func.js create mode 100644 build/lib/eslint/vscode-dts-event-naming.js create mode 100644 build/lib/eslint/vscode-dts-interface-naming.js create mode 100644 build/lib/eslint/vscode-dts-literal-or-types.js create mode 100644 build/lib/extensions.js create mode 100644 build/lib/git.js create mode 100644 build/lib/i18n.js create mode 100644 build/lib/layersChecker.js create mode 100644 build/lib/monaco-api.js create mode 100644 build/lib/nls.js create mode 100644 build/lib/node.js create mode 100644 build/lib/optimize.js create mode 100644 build/lib/preLaunch.js create mode 100644 build/lib/reporter.js create mode 100644 build/lib/snapshotLoader.js create mode 100644 build/lib/standalone.js create mode 100644 build/lib/stats.js create mode 100644 build/lib/task.js create mode 100644 build/lib/test/i18n.test.js create mode 100644 build/lib/treeshaking.js create mode 100644 build/lib/util.js create mode 100644 build/lib/watch/index.js create mode 100644 build/lib/watch/watch-win32.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2851c5c54cf..c2637ae7be4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,14 +30,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -67,14 +61,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -132,13 +120,6 @@ jobs: key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Restore cached /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Restore cached compiled code id: cacheCompiledCode uses: actions/cache@v2 @@ -195,13 +176,6 @@ jobs: key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Restore cached /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - - name: Restore cached compiled code id: cacheCompiledCode uses: actions/cache@v2 @@ -241,14 +215,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -298,14 +266,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -349,14 +311,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -411,14 +367,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -472,14 +422,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -515,14 +459,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile @@ -558,14 +496,8 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Cache /build/ scripts - id: cacheBuildScripts - uses: actions/cache@v2 - with: - path: build/**/*.js - key: ${{ runner.os }}-cacheBuildScripts-${{ hashFiles('build/yarn.lock', 'build/tsconfig.json', 'build/tsconfig.build.json', 'build/**/*.ts', '!**/node_modules/**/*.ts') }} - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' || steps.cacheBuildScripts.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100644 index 01e8737ef58..00000000000 --- a/build/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -azure-pipelines/**/*.js -darwin/**/*.js -lib/**/*.js diff --git a/build/azure-pipelines/common/.gitignore b/build/azure-pipelines/common/.gitignore deleted file mode 100644 index e94ecda764e..00000000000 --- a/build/azure-pipelines/common/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -*.js \ No newline at end of file diff --git a/build/azure-pipelines/common/createAsset.js b/build/azure-pipelines/common/createAsset.js new file mode 100644 index 00000000000..3038ff62b82 --- /dev/null +++ b/build/azure-pipelines/common/createAsset.js @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const crypto = require("crypto"); +const azure = require("azure-storage"); +const mime = require("mime"); +const cosmos_1 = require("@azure/cosmos"); +const retry_1 = require("./retry"); +if (process.argv.length !== 6) { + console.error('Usage: node createAsset.js PLATFORM TYPE NAME FILE'); + process.exit(-1); +} +function hashStream(hashName, stream) { + return new Promise((c, e) => { + const shasum = crypto.createHash(hashName); + stream + .on('data', shasum.update.bind(shasum)) + .on('error', e) + .on('close', () => c(shasum.digest('hex'))); + }); +} +async function doesAssetExist(blobService, quality, blobName) { + const existsResult = await new Promise((c, e) => blobService.doesBlobExist(quality, blobName, (err, r) => err ? e(err) : c(r))); + return existsResult.exists; +} +async function uploadBlob(blobService, quality, blobName, filePath, fileName) { + const blobOptions = { + contentSettings: { + contentType: mime.lookup(filePath), + contentDisposition: `attachment; filename="${fileName}"`, + cacheControl: 'max-age=31536000, public' + } + }; + await new Promise((c, e) => blobService.createBlockBlobFromLocalFile(quality, blobName, filePath, blobOptions, err => err ? e(err) : c())); +} +function getEnv(name) { + const result = process.env[name]; + if (typeof result === 'undefined') { + throw new Error('Missing env: ' + name); + } + return result; +} +async function main() { + const [, , platform, type, fileName, filePath] = process.argv; + const quality = getEnv('VSCODE_QUALITY'); + const commit = getEnv('BUILD_SOURCEVERSION'); + console.log('Creating asset...'); + const stat = await new Promise((c, e) => fs.stat(filePath, (err, stat) => err ? e(err) : c(stat))); + const size = stat.size; + console.log('Size:', size); + const stream = fs.createReadStream(filePath); + const [sha1hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]); + console.log('SHA1:', sha1hash); + console.log('SHA256:', sha256hash); + const blobName = commit + '/' + fileName; + const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']; + const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + const blobExists = await doesAssetExist(blobService, quality, blobName); + if (blobExists) { + console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`); + return; + } + console.log('Uploading blobs to Azure storage...'); + await uploadBlob(blobService, quality, blobName, filePath, fileName); + console.log('Blobs successfully uploaded.'); + const asset = { + platform, + type, + url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`, + hash: sha1hash, + sha256hash, + size + }; + // Remove this if we ever need to rollback fast updates for windows + if (/win32/.test(platform)) { + asset.supportsFastUpdate = true; + } + console.log('Asset:', JSON.stringify(asset, null, ' ')); + const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const scripts = client.database('builds').container(quality).scripts; + await retry_1.retry(() => scripts.storedProcedure('createAsset').execute('', [commit, asset, true])); +} +main().then(() => { + console.log('Asset successfully created'); + process.exit(0); +}, err => { + console.error(err); + process.exit(1); +}); diff --git a/build/azure-pipelines/common/createBuild.js b/build/azure-pipelines/common/createBuild.js new file mode 100644 index 00000000000..afa150b910e --- /dev/null +++ b/build/azure-pipelines/common/createBuild.js @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const cosmos_1 = require("@azure/cosmos"); +const retry_1 = require("./retry"); +if (process.argv.length !== 3) { + console.error('Usage: node createBuild.js VERSION'); + process.exit(-1); +} +function getEnv(name) { + const result = process.env[name]; + if (typeof result === 'undefined') { + throw new Error('Missing env: ' + name); + } + return result; +} +async function main() { + const [, , _version] = process.argv; + const quality = getEnv('VSCODE_QUALITY'); + const commit = getEnv('BUILD_SOURCEVERSION'); + const queuedBy = getEnv('BUILD_QUEUEDBY'); + const sourceBranch = getEnv('BUILD_SOURCEBRANCH'); + const version = _version + (quality === 'stable' ? '' : `-${quality}`); + console.log('Creating build...'); + console.log('Quality:', quality); + console.log('Version:', version); + console.log('Commit:', commit); + const build = { + id: commit, + timestamp: (new Date()).getTime(), + version, + isReleased: false, + sourceBranch, + queuedBy, + assets: [], + updates: {} + }; + const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const scripts = client.database('builds').container(quality).scripts; + await retry_1.retry(() => scripts.storedProcedure('createBuild').execute('', [Object.assign(Object.assign({}, build), { _partitionKey: '' })])); +} +main().then(() => { + console.log('Build successfully created'); + process.exit(0); +}, err => { + console.error(err); + process.exit(1); +}); diff --git a/build/azure-pipelines/common/publish-webview.js b/build/azure-pipelines/common/publish-webview.js new file mode 100644 index 00000000000..27804624126 --- /dev/null +++ b/build/azure-pipelines/common/publish-webview.js @@ -0,0 +1,71 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const azure = require("azure-storage"); +const mime = require("mime"); +const minimist = require("minimist"); +const path_1 = require("path"); +const fileNames = [ + 'fake.html', + 'host.js', + 'index.html', + 'main.js', + 'service-worker.js' +]; +async function assertContainer(blobService, container) { + await new Promise((c, e) => blobService.createContainerIfNotExists(container, { publicAccessLevel: 'blob' }, err => err ? e(err) : c())); +} +async function doesBlobExist(blobService, container, blobName) { + const existsResult = await new Promise((c, e) => blobService.doesBlobExist(container, blobName, (err, r) => err ? e(err) : c(r))); + return existsResult.exists; +} +async function uploadBlob(blobService, container, blobName, file) { + const blobOptions = { + contentSettings: { + contentType: mime.lookup(file), + cacheControl: 'max-age=31536000, public' + } + }; + await new Promise((c, e) => blobService.createBlockBlobFromLocalFile(container, blobName, file, blobOptions, err => err ? e(err) : c())); +} +async function publish(commit, files) { + console.log('Publishing...'); + console.log('Commit:', commit); + const storageAccount = process.env['AZURE_WEBVIEW_STORAGE_ACCOUNT']; + const blobService = azure.createBlobService(storageAccount, process.env['AZURE_WEBVIEW_STORAGE_ACCESS_KEY']) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + await assertContainer(blobService, commit); + for (const file of files) { + const blobName = path_1.basename(file); + const blobExists = await doesBlobExist(blobService, commit, blobName); + if (blobExists) { + console.log(`Blob ${commit}, ${blobName} already exists, not publishing again.`); + continue; + } + console.log('Uploading blob to Azure storage...'); + await uploadBlob(blobService, commit, blobName, file); + } + console.log('Blobs successfully uploaded.'); +} +function main() { + const commit = process.env['BUILD_SOURCEVERSION']; + if (!commit) { + console.warn('Skipping publish due to missing BUILD_SOURCEVERSION'); + return; + } + const opts = minimist(process.argv.slice(2)); + const [directory] = opts._; + const files = fileNames.map(fileName => path_1.join(directory, fileName)); + publish(commit, files).catch(err => { + console.error(err); + process.exit(1); + }); +} +if (process.argv.length < 3) { + console.error('Usage: node publish.js '); + process.exit(-1); +} +main(); diff --git a/build/azure-pipelines/common/releaseBuild.js b/build/azure-pipelines/common/releaseBuild.js new file mode 100644 index 00000000000..c2438ca9e9d --- /dev/null +++ b/build/azure-pipelines/common/releaseBuild.js @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const cosmos_1 = require("@azure/cosmos"); +const retry_1 = require("./retry"); +function getEnv(name) { + const result = process.env[name]; + if (typeof result === 'undefined') { + throw new Error('Missing env: ' + name); + } + return result; +} +function createDefaultConfig(quality) { + return { + id: quality, + frozen: false + }; +} +async function getConfig(client, quality) { + const query = `SELECT TOP 1 * FROM c WHERE c.id = "${quality}"`; + const res = await client.database('builds').container('config').items.query(query).fetchAll(); + if (res.resources.length === 0) { + return createDefaultConfig(quality); + } + return res.resources[0]; +} +async function main() { + const commit = getEnv('BUILD_SOURCEVERSION'); + const quality = getEnv('VSCODE_QUALITY'); + const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const config = await getConfig(client, quality); + console.log('Quality config:', config); + if (config.frozen) { + console.log(`Skipping release because quality ${quality} is frozen.`); + return; + } + console.log(`Releasing build ${commit}...`); + const scripts = client.database('builds').container(quality).scripts; + await retry_1.retry(() => scripts.storedProcedure('releaseBuild').execute('', [commit])); +} +main().then(() => { + console.log('Build successfully released'); + process.exit(0); +}, err => { + console.error(err); + process.exit(1); +}); diff --git a/build/azure-pipelines/common/retry.js b/build/azure-pipelines/common/retry.js new file mode 100644 index 00000000000..41136b52b93 --- /dev/null +++ b/build/azure-pipelines/common/retry.js @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.retry = void 0; +async function retry(fn) { + for (let run = 1; run <= 10; run++) { + try { + return await fn(); + } + catch (err) { + if (!/ECONNRESET/.test(err.message)) { + throw err; + } + const millis = (Math.random() * 200) + (50 * Math.pow(1.5, run)); + console.log(`Failed with ECONNRESET, retrying in ${millis}ms...`); + // maximum delay is 10th retry: ~3 seconds + await new Promise(c => setTimeout(c, millis)); + } + } + throw new Error('Retried too many times'); +} +exports.retry = retry; diff --git a/build/azure-pipelines/common/sync-mooncake.js b/build/azure-pipelines/common/sync-mooncake.js new file mode 100644 index 00000000000..1f335422651 --- /dev/null +++ b/build/azure-pipelines/common/sync-mooncake.js @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const url = require("url"); +const azure = require("azure-storage"); +const mime = require("mime"); +const cosmos_1 = require("@azure/cosmos"); +const retry_1 = require("./retry"); +function log(...args) { + console.log(...[`[${new Date().toISOString()}]`, ...args]); +} +function error(...args) { + console.error(...[`[${new Date().toISOString()}]`, ...args]); +} +if (process.argv.length < 3) { + error('Usage: node sync-mooncake.js '); + process.exit(-1); +} +async function sync(commit, quality) { + log(`Synchronizing Mooncake assets for ${quality}, ${commit}...`); + const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const container = client.database('builds').container(quality); + const query = `SELECT TOP 1 * FROM c WHERE c.id = "${commit}"`; + const res = await container.items.query(query, {}).fetchAll(); + if (res.resources.length !== 1) { + throw new Error(`No builds found for ${commit}`); + } + const build = res.resources[0]; + log(`Found build for ${commit}, with ${build.assets.length} assets`); + const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']; + const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY'], `${storageAccount}.blob.core.chinacloudapi.cn`) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + // mooncake is fussy and far away, this is needed! + blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000; + mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000; + for (const asset of build.assets) { + try { + const blobPath = url.parse(asset.url).path; + if (!blobPath) { + throw new Error(`Failed to parse URL: ${asset.url}`); + } + const blobName = blobPath.replace(/^\/\w+\//, ''); + log(`Found ${blobName}`); + if (asset.mooncakeUrl) { + log(` Already in Mooncake ✔️`); + continue; + } + const readStream = blobService.createReadStream(quality, blobName, undefined); + const blobOptions = { + contentSettings: { + contentType: mime.lookup(blobPath), + cacheControl: 'max-age=31536000, public' + } + }; + const writeStream = mooncakeBlobService.createWriteStreamToBlockBlob(quality, blobName, blobOptions, undefined); + log(` Uploading to Mooncake...`); + await new Promise((c, e) => readStream.pipe(writeStream).on('finish', c).on('error', e)); + log(` Updating build in DB...`); + const mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`; + await retry_1.retry(() => container.scripts.storedProcedure('setAssetMooncakeUrl') + .execute('', [commit, asset.platform, asset.type, mooncakeUrl])); + log(` Done ✔️`); + } + catch (err) { + error(err); + } + } + log(`All done ✔️`); +} +function main() { + const commit = process.env['BUILD_SOURCEVERSION']; + if (!commit) { + error('Skipping publish due to missing BUILD_SOURCEVERSION'); + return; + } + const quality = process.argv[2]; + sync(commit, quality).catch(err => { + error(err); + process.exit(1); + }); +} +main(); diff --git a/build/azure-pipelines/mixin.js b/build/azure-pipelines/mixin.js new file mode 100644 index 00000000000..62ad40ba099 --- /dev/null +++ b/build/azure-pipelines/mixin.js @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const json = require("gulp-json-editor"); +const buffer = require('gulp-buffer'); +const filter = require("gulp-filter"); +const es = require("event-stream"); +const vfs = require("vinyl-fs"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const fs = require("fs"); +const path = require("path"); +function main() { + const quality = process.env['VSCODE_QUALITY']; + if (!quality) { + console.log('Missing VSCODE_QUALITY, skipping mixin'); + return; + } + const productJsonFilter = filter(f => f.relative === 'product.json', { restore: true }); + fancyLog(ansiColors.blue('[mixin]'), `Mixing in sources:`); + return vfs + .src(`quality/${quality}/**`, { base: `quality/${quality}` }) + .pipe(filter(f => !f.isDirectory())) + .pipe(productJsonFilter) + .pipe(buffer()) + .pipe(json((o) => { + const ossProduct = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'product.json'), 'utf8')); + let builtInExtensions = ossProduct.builtInExtensions; + if (Array.isArray(o.builtInExtensions)) { + fancyLog(ansiColors.blue('[mixin]'), 'Overwriting built-in extensions:', o.builtInExtensions.map(e => e.name)); + builtInExtensions = o.builtInExtensions; + } + else if (o.builtInExtensions) { + const include = o.builtInExtensions['include'] || []; + const exclude = o.builtInExtensions['exclude'] || []; + fancyLog(ansiColors.blue('[mixin]'), 'OSS built-in extensions:', builtInExtensions.map(e => e.name)); + fancyLog(ansiColors.blue('[mixin]'), 'Including built-in extensions:', include.map(e => e.name)); + fancyLog(ansiColors.blue('[mixin]'), 'Excluding built-in extensions:', exclude); + builtInExtensions = builtInExtensions.filter(ext => !include.find(e => e.name === ext.name) && !exclude.find(name => name === ext.name)); + builtInExtensions = [...builtInExtensions, ...include]; + fancyLog(ansiColors.blue('[mixin]'), 'Final built-in extensions:', builtInExtensions.map(e => e.name)); + } + else { + fancyLog(ansiColors.blue('[mixin]'), 'Inheriting OSS built-in extensions', builtInExtensions.map(e => e.name)); + } + return Object.assign(Object.assign({ webBuiltInExtensions: ossProduct.webBuiltInExtensions }, o), { builtInExtensions }); + })) + .pipe(productJsonFilter.restore) + .pipe(es.mapSync(function (f) { + fancyLog(ansiColors.blue('[mixin]'), f.relative, ansiColors.green('✔︎')); + return f; + })) + .pipe(vfs.dest('.')); +} +main(); diff --git a/build/azure-pipelines/publish-types/.gitignore b/build/azure-pipelines/publish-types/.gitignore deleted file mode 100644 index e94ecda764e..00000000000 --- a/build/azure-pipelines/publish-types/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -*.js \ No newline at end of file diff --git a/build/azure-pipelines/publish-types/check-version.js b/build/azure-pipelines/publish-types/check-version.js new file mode 100644 index 00000000000..b45ad3f4cc0 --- /dev/null +++ b/build/azure-pipelines/publish-types/check-version.js @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const cp = require("child_process"); +let tag = ''; +try { + tag = cp + .execSync('git describe --tags `git rev-list --tags --max-count=1`') + .toString() + .trim(); + if (!isValidTag(tag)) { + throw Error(`Invalid tag ${tag}`); + } +} +catch (err) { + console.error(err); + console.error('Failed to update types'); + process.exit(1); +} +function isValidTag(t) { + if (t.split('.').length !== 3) { + return false; + } + const [major, minor, bug] = t.split('.'); + // Only release for tags like 1.34.0 + if (bug !== '0') { + return false; + } + if (isNaN(parseInt(major, 10)) || isNaN(parseInt(minor, 10))) { + return false; + } + return true; +} diff --git a/build/azure-pipelines/publish-types/update-types.js b/build/azure-pipelines/publish-types/update-types.js new file mode 100644 index 00000000000..0957c5a894e --- /dev/null +++ b/build/azure-pipelines/publish-types/update-types.js @@ -0,0 +1,72 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const cp = require("child_process"); +const path = require("path"); +let tag = ''; +try { + tag = cp + .execSync('git describe --tags `git rev-list --tags --max-count=1`') + .toString() + .trim(); + const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vs/vscode.d.ts`; + const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts'); + cp.execSync(`curl ${dtsUri} --output ${outPath}`); + updateDTSFile(outPath, tag); + console.log(`Done updating vscode.d.ts at ${outPath}`); +} +catch (err) { + console.error(err); + console.error('Failed to update types'); + process.exit(1); +} +function updateDTSFile(outPath, tag) { + const oldContent = fs.readFileSync(outPath, 'utf-8'); + const newContent = getNewFileContent(oldContent, tag); + fs.writeFileSync(outPath, newContent); +} +function repeat(str, times) { + const result = new Array(times); + for (let i = 0; i < times; i++) { + result[i] = str; + } + return result.join(''); +} +function convertTabsToSpaces(str) { + return str.replace(/\t/gm, value => repeat(' ', value.length)); +} +function getNewFileContent(content, tag) { + const oldheader = [ + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License. See License.txt in the project root for license information.`, + ` *--------------------------------------------------------------------------------------------*/` + ].join('\n'); + return convertTabsToSpaces(getNewFileHeader(tag) + content.slice(oldheader.length)); +} +function getNewFileHeader(tag) { + const [major, minor] = tag.split('.'); + const shorttag = `${major}.${minor}`; + const header = [ + `// Type definitions for Visual Studio Code ${shorttag}`, + `// Project: https://github.com/microsoft/vscode`, + `// Definitions by: Visual Studio Code Team, Microsoft `, + `// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`, + ``, + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License.`, + ` * See https://github.com/microsoft/vscode/blob/master/LICENSE.txt for license information.`, + ` *--------------------------------------------------------------------------------------------*/`, + ``, + `/**`, + ` * Type Definition for Visual Studio Code ${shorttag} Extension API`, + ` * See https://code.visualstudio.com/api for more information`, + ` */` + ].join('\n'); + return header; +} diff --git a/build/azure-pipelines/upload-cdn.js b/build/azure-pipelines/upload-cdn.js new file mode 100644 index 00000000000..16a072905a0 --- /dev/null +++ b/build/azure-pipelines/upload-cdn.js @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const es = require("event-stream"); +const vfs = require("vinyl-fs"); +const util = require("../lib/util"); +const filter = require("gulp-filter"); +const gzip = require("gulp-gzip"); +const azure = require('gulp-azure-storage'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); +function main() { + return vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true }) + .pipe(filter(f => !f.isDirectory())) + .pipe(gzip({ append: false })) + .pipe(es.through(function (data) { + console.log('Uploading CDN file:', data.relative); // debug + this.emit('data', data); + })) + .pipe(azure.upload({ + account: process.env.AZURE_STORAGE_ACCOUNT, + key: process.env.AZURE_STORAGE_ACCESS_KEY, + container: process.env.VSCODE_QUALITY, + prefix: commit + '/', + contentSettings: { + contentEncoding: 'gzip', + cacheControl: 'max-age=31536000, public' + } + })); +} +main(); diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js new file mode 100644 index 00000000000..f19d79549d0 --- /dev/null +++ b/build/azure-pipelines/upload-sourcemaps.js @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const es = require("event-stream"); +const vfs = require("vinyl-fs"); +const util = require("../lib/util"); +// @ts-ignore +const deps = require("../dependencies"); +const azure = require('gulp-azure-storage'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); +// optionally allow to pass in explicit base/maps to upload +const [, , base, maps] = process.argv; +function src(base, maps = `${base}/**/*.map`) { + return vfs.src(maps, { base }) + .pipe(es.mapSync((f) => { + f.path = `${f.base}/core/${f.relative}`; + return f; + })); +} +function main() { + const sources = []; + // vscode client maps (default) + if (!base) { + const vs = src('out-vscode-min'); // client source-maps only + sources.push(vs); + const productionDependencies = deps.getProductionDependencies(root); + const productionDependenciesSrc = productionDependencies.map(d => path.relative(root, d.path)).map(d => `./${d}/**/*.map`); + const nodeModules = vfs.src(productionDependenciesSrc, { base: '.' }) + .pipe(util.cleanNodeModules(path.join(root, 'build', '.moduleignore'))); + sources.push(nodeModules); + const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' }); + sources.push(extensionsOut); + } + // specific client base/maps + else { + sources.push(src(base, maps)); + } + return es.merge(...sources) + .pipe(es.through(function (data) { + console.log('Uploading Sourcemap', data.relative); // debug + this.emit('data', data); + })) + .pipe(azure.upload({ + account: process.env.AZURE_STORAGE_ACCOUNT, + key: process.env.AZURE_STORAGE_ACCESS_KEY, + container: 'sourcemaps', + prefix: commit + '/' + })); +} +main(); diff --git a/build/darwin/sign.js b/build/darwin/sign.js new file mode 100644 index 00000000000..e086b681a6d --- /dev/null +++ b/build/darwin/sign.js @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const codesign = require("electron-osx-sign"); +const path = require("path"); +const util = require("../lib/util"); +const product = require("../../product.json"); +async function main() { + const buildDir = process.env['AGENT_BUILDDIRECTORY']; + const tempDir = process.env['AGENT_TEMPDIRECTORY']; + const arch = process.env['VSCODE_ARCH']; + if (!buildDir) { + throw new Error('$AGENT_BUILDDIRECTORY not set'); + } + if (!tempDir) { + throw new Error('$AGENT_TEMPDIRECTORY not set'); + } + const baseDir = path.dirname(__dirname); + const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`); + const appName = product.nameLong + '.app'; + const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks'); + const helperAppBaseName = product.nameShort; + const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app'; + const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app'; + const defaultOpts = { + app: path.join(appRoot, appName), + platform: 'darwin', + entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'), + 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'), + hardenedRuntime: true, + 'pre-auto-entitlements': false, + 'pre-embed-provisioning-profile': false, + keychain: path.join(tempDir, 'buildagent.keychain'), + version: util.getElectronVersion(), + identity: '99FM488X57', + 'gatekeeper-assess': false + }; + const appOpts = Object.assign(Object.assign({}, defaultOpts), { + // TODO(deepak1556): Incorrectly declared type in electron-osx-sign + ignore: (filePath) => { + return filePath.includes(gpuHelperAppName) || + filePath.includes(rendererHelperAppName); + } }); + const gpuHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, gpuHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist') }); + const rendererHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, rendererHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist') }); + await codesign.signAsync(gpuHelperOpts); + await codesign.signAsync(rendererHelperOpts); + await codesign.signAsync(appOpts); +} +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/lib/asar.js b/build/lib/asar.js new file mode 100644 index 00000000000..708005791f6 --- /dev/null +++ b/build/lib/asar.js @@ -0,0 +1,118 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createAsar = void 0; +const path = require("path"); +const es = require("event-stream"); +const pickle = require('chromium-pickle-js'); +const Filesystem = require('asar/lib/filesystem'); +const VinylFile = require("vinyl"); +const minimatch = require("minimatch"); +function createAsar(folderPath, unpackGlobs, destFilename) { + const shouldUnpackFile = (file) => { + for (let i = 0; i < unpackGlobs.length; i++) { + if (minimatch(file.relative, unpackGlobs[i])) { + return true; + } + } + return false; + }; + const filesystem = new Filesystem(folderPath); + const out = []; + // Keep track of pending inserts + let pendingInserts = 0; + let onFileInserted = () => { pendingInserts--; }; + // Do not insert twice the same directory + const seenDir = {}; + const insertDirectoryRecursive = (dir) => { + if (seenDir[dir]) { + return; + } + let lastSlash = dir.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = dir.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(dir.substring(0, lastSlash)); + } + seenDir[dir] = true; + filesystem.insertDirectory(dir); + }; + const insertDirectoryForFile = (file) => { + let lastSlash = file.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = file.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(file.substring(0, lastSlash)); + } + }; + const insertFile = (relativePath, stat, shouldUnpack) => { + insertDirectoryForFile(relativePath); + pendingInserts++; + // Do not pass `onFileInserted` directly because it gets overwritten below. + // Create a closure capturing `onFileInserted`. + filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted()); + }; + return es.through(function (file) { + if (file.stat.isDirectory()) { + return; + } + if (!file.stat.isFile()) { + throw new Error(`unknown item in stream!`); + } + const shouldUnpack = shouldUnpackFile(file); + insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack); + if (shouldUnpack) { + // The file goes outside of xx.asar, in a folder xx.asar.unpacked + const relative = path.relative(folderPath, file.path); + this.queue(new VinylFile({ + base: '.', + path: path.join(destFilename + '.unpacked', relative), + stat: file.stat, + contents: file.contents + })); + } + else { + // The file goes inside of xx.asar + out.push(file.contents); + } + }, function () { + let finish = () => { + { + const headerPickle = pickle.createEmpty(); + headerPickle.writeString(JSON.stringify(filesystem.header)); + const headerBuf = headerPickle.toBuffer(); + const sizePickle = pickle.createEmpty(); + sizePickle.writeUInt32(headerBuf.length); + const sizeBuf = sizePickle.toBuffer(); + out.unshift(headerBuf); + out.unshift(sizeBuf); + } + const contents = Buffer.concat(out); + out.length = 0; + this.queue(new VinylFile({ + base: '.', + path: destFilename, + contents: contents + })); + this.queue(null); + }; + // Call finish() only when all file inserts have finished... + if (pendingInserts === 0) { + finish(); + } + else { + onFileInserted = () => { + pendingInserts--; + if (pendingInserts === 0) { + finish(); + } + }; + } + }); +} +exports.createAsar = createAsar; diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js new file mode 100644 index 00000000000..54db11e0c46 --- /dev/null +++ b/build/lib/builtInExtensions.js @@ -0,0 +1,113 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getBuiltInExtensions = void 0; +const fs = require("fs"); +const path = require("path"); +const os = require("os"); +const rimraf = require("rimraf"); +const es = require("event-stream"); +const rename = require("gulp-rename"); +const vfs = require("vinyl-fs"); +const ext = require("./extensions"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const mkdirp = require('mkdirp'); +const root = path.dirname(path.dirname(__dirname)); +const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')); +const builtInExtensions = productjson.builtInExtensions; +const webBuiltInExtensions = productjson.webBuiltInExtensions; +const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json'); +const ENABLE_LOGGING = !process.env['VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE']; +function log(...messages) { + if (ENABLE_LOGGING) { + fancyLog(...messages); + } +} +function getExtensionPath(extension) { + return path.join(root, '.build', 'builtInExtensions', extension.name); +} +function isUpToDate(extension) { + const packagePath = path.join(getExtensionPath(extension), 'package.json'); + if (!fs.existsSync(packagePath)) { + return false; + } + const packageContents = fs.readFileSync(packagePath, { encoding: 'utf8' }); + try { + const diskVersion = JSON.parse(packageContents).version; + return (diskVersion === extension.version); + } + catch (err) { + return false; + } +} +function syncMarketplaceExtension(extension) { + if (isUpToDate(extension)) { + log(ansiColors.blue('[marketplace]'), `${extension.name}@${extension.version}`, ansiColors.green('✔︎')); + return es.readArray([]); + } + rimraf.sync(getExtensionPath(extension)); + return ext.fromMarketplace(extension.name, extension.version, extension.metadata) + .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)) + .pipe(vfs.dest('.build/builtInExtensions')) + .on('end', () => log(ansiColors.blue('[marketplace]'), extension.name, ansiColors.green('✔︎'))); +} +function syncExtension(extension, controlState) { + switch (controlState) { + case 'disabled': + log(ansiColors.blue('[disabled]'), ansiColors.gray(extension.name)); + return es.readArray([]); + case 'marketplace': + return syncMarketplaceExtension(extension); + default: + if (!fs.existsSync(controlState)) { + log(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`)); + return es.readArray([]); + } + else if (!fs.existsSync(path.join(controlState, 'package.json'))) { + log(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`)); + return es.readArray([]); + } + log(ansiColors.blue('[local]'), `${extension.name}: ${ansiColors.cyan(controlState)}`, ansiColors.green('✔︎')); + return es.readArray([]); + } +} +function readControlFile() { + try { + return JSON.parse(fs.readFileSync(controlFilePath, 'utf8')); + } + catch (err) { + return {}; + } +} +function writeControlFile(control) { + mkdirp.sync(path.dirname(controlFilePath)); + fs.writeFileSync(controlFilePath, JSON.stringify(control, null, 2)); +} +function getBuiltInExtensions() { + log('Syncronizing built-in extensions...'); + log(`You can manage built-in extensions with the ${ansiColors.cyan('--builtin')} flag`); + const control = readControlFile(); + const streams = []; + for (const extension of [...builtInExtensions, ...webBuiltInExtensions]) { + let controlState = control[extension.name] || 'marketplace'; + control[extension.name] = controlState; + streams.push(syncExtension(extension, controlState)); + } + writeControlFile(control); + return new Promise((resolve, reject) => { + es.merge(streams) + .on('error', reject) + .on('end', resolve); + }); +} +exports.getBuiltInExtensions = getBuiltInExtensions; +if (require.main === module) { + getBuiltInExtensions().then(() => process.exit(0)).catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/lib/bundle.js b/build/lib/bundle.js new file mode 100644 index 00000000000..7d0c8d9b55e --- /dev/null +++ b/build/lib/bundle.js @@ -0,0 +1,464 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bundle = void 0; +const fs = require("fs"); +const path = require("path"); +const vm = require("vm"); +/** + * Bundle `entryPoints` given config `config`. + */ +function bundle(entryPoints, config, callback) { + const entryPointsMap = {}; + entryPoints.forEach((module) => { + entryPointsMap[module.name] = module; + }); + const allMentionedModulesMap = {}; + entryPoints.forEach((module) => { + allMentionedModulesMap[module.name] = true; + (module.include || []).forEach(function (includedModule) { + allMentionedModulesMap[includedModule] = true; + }); + (module.exclude || []).forEach(function (excludedModule) { + allMentionedModulesMap[excludedModule] = true; + }); + }); + const code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js')); + const r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});'); + const loaderModule = { exports: {} }; + r.call({}, require, loaderModule, loaderModule.exports); + const loader = loaderModule.exports; + config.isBuild = true; + config.paths = config.paths || {}; + if (!config.paths['vs/nls']) { + config.paths['vs/nls'] = 'out-build/vs/nls.build'; + } + if (!config.paths['vs/css']) { + config.paths['vs/css'] = 'out-build/vs/css.build'; + } + loader.config(config); + loader(['require'], (localRequire) => { + const resolvePath = (path) => { + const r = localRequire.toUrl(path); + if (!/\.js/.test(r)) { + return r + '.js'; + } + return r; + }; + for (const moduleId in entryPointsMap) { + const entryPoint = entryPointsMap[moduleId]; + if (entryPoint.append) { + entryPoint.append = entryPoint.append.map(resolvePath); + } + if (entryPoint.prepend) { + entryPoint.prepend = entryPoint.prepend.map(resolvePath); + } + } + }); + loader(Object.keys(allMentionedModulesMap), () => { + const modules = loader.getBuildInfo(); + const partialResult = emitEntryPoints(modules, entryPointsMap); + const cssInlinedResources = loader('vs/css').getInlinedResources(); + callback(null, { + files: partialResult.files, + cssInlinedResources: cssInlinedResources, + bundleData: partialResult.bundleData + }); + }, (err) => callback(err, null)); +} +exports.bundle = bundle; +function emitEntryPoints(modules, entryPoints) { + const modulesMap = {}; + modules.forEach((m) => { + modulesMap[m.id] = m; + }); + const modulesGraph = {}; + modules.forEach((m) => { + modulesGraph[m.id] = m.dependencies; + }); + const sortedModules = topologicalSort(modulesGraph); + let result = []; + const usedPlugins = {}; + const bundleData = { + graph: modulesGraph, + bundles: {} + }; + Object.keys(entryPoints).forEach((moduleToBundle) => { + const info = entryPoints[moduleToBundle]; + const rootNodes = [moduleToBundle].concat(info.include || []); + const allDependencies = visit(rootNodes, modulesGraph); + const excludes = ['require', 'exports', 'module'].concat(info.exclude || []); + excludes.forEach((excludeRoot) => { + const allExcludes = visit([excludeRoot], modulesGraph); + Object.keys(allExcludes).forEach((exclude) => { + delete allDependencies[exclude]; + }); + }); + const includedModules = sortedModules.filter((module) => { + return allDependencies[module]; + }); + bundleData.bundles[moduleToBundle] = includedModules; + const res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend || [], info.append || [], info.dest); + result = result.concat(res.files); + for (const pluginName in res.usedPlugins) { + usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName]; + } + }); + Object.keys(usedPlugins).forEach((pluginName) => { + const plugin = usedPlugins[pluginName]; + if (typeof plugin.finishBuild === 'function') { + const write = (filename, contents) => { + result.push({ + dest: filename, + sources: [{ + path: null, + contents: contents + }] + }); + }; + plugin.finishBuild(write); + } + }); + return { + // TODO@TS 2.1.2 + files: extractStrings(removeDuplicateTSBoilerplate(result)), + bundleData: bundleData + }; +} +function extractStrings(destFiles) { + const parseDefineCall = (moduleMatch, depsMatch) => { + const module = moduleMatch.replace(/^"|"$/g, ''); + let deps = depsMatch.split(','); + deps = deps.map((dep) => { + dep = dep.trim(); + dep = dep.replace(/^"|"$/g, ''); + dep = dep.replace(/^'|'$/g, ''); + let prefix = null; + let _path = null; + const pieces = dep.split('!'); + if (pieces.length > 1) { + prefix = pieces[0] + '!'; + _path = pieces[1]; + } + else { + prefix = ''; + _path = pieces[0]; + } + if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) { + const res = path.join(path.dirname(module), _path).replace(/\\/g, '/'); + return prefix + res; + } + return prefix + _path; + }); + return { + module: module, + deps: deps + }; + }; + destFiles.forEach((destFile) => { + if (!/\.js$/.test(destFile.dest)) { + return; + } + if (/\.nls\.js$/.test(destFile.dest)) { + return; + } + // Do one pass to record the usage counts for each module id + const useCounts = {}; + destFile.sources.forEach((source) => { + const matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/); + if (!matches) { + return; + } + const defineCall = parseDefineCall(matches[1], matches[2]); + useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1; + defineCall.deps.forEach((dep) => { + useCounts[dep] = (useCounts[dep] || 0) + 1; + }); + }); + const sortedByUseModules = Object.keys(useCounts); + sortedByUseModules.sort((a, b) => { + return useCounts[b] - useCounts[a]; + }); + const replacementMap = {}; + sortedByUseModules.forEach((module, index) => { + replacementMap[module] = index; + }); + destFile.sources.forEach((source) => { + source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => { + const defineCall = parseDefineCall(moduleMatch, depsMatch); + return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`; + }); + }); + destFile.sources.unshift({ + path: null, + contents: [ + '(function() {', + `var __m = ${JSON.stringify(sortedByUseModules)};`, + `var __M = function(deps) {`, + ` var result = [];`, + ` for (var i = 0, len = deps.length; i < len; i++) {`, + ` result[i] = __m[deps[i]];`, + ` }`, + ` return result;`, + `};` + ].join('\n') + }); + destFile.sources.push({ + path: null, + contents: '}).call(this);' + }); + }); + return destFiles; +} +function removeDuplicateTSBoilerplate(destFiles) { + // Taken from typescript compiler => emitFiles + const BOILERPLATE = [ + { start: /^var __extends/, end: /^}\)\(\);$/ }, + { start: /^var __assign/, end: /^};$/ }, + { start: /^var __decorate/, end: /^};$/ }, + { start: /^var __metadata/, end: /^};$/ }, + { start: /^var __param/, end: /^};$/ }, + { start: /^var __awaiter/, end: /^};$/ }, + { start: /^var __generator/, end: /^};$/ }, + ]; + destFiles.forEach((destFile) => { + const SEEN_BOILERPLATE = []; + destFile.sources.forEach((source) => { + const lines = source.contents.split(/\r\n|\n|\r/); + const newLines = []; + let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (IS_REMOVING_BOILERPLATE) { + newLines.push(''); + if (END_BOILERPLATE.test(line)) { + IS_REMOVING_BOILERPLATE = false; + } + } + else { + for (let j = 0; j < BOILERPLATE.length; j++) { + const boilerplate = BOILERPLATE[j]; + if (boilerplate.start.test(line)) { + if (SEEN_BOILERPLATE[j]) { + IS_REMOVING_BOILERPLATE = true; + END_BOILERPLATE = boilerplate.end; + } + else { + SEEN_BOILERPLATE[j] = true; + } + } + } + if (IS_REMOVING_BOILERPLATE) { + newLines.push(''); + } + else { + newLines.push(line); + } + } + } + source.contents = newLines.join('\n'); + }); + }); + return destFiles; +} +function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend, append, dest) { + if (!dest) { + dest = entryPoint + '.js'; + } + const mainResult = { + sources: [], + dest: dest + }, results = [mainResult]; + const usedPlugins = {}; + const getLoaderPlugin = (pluginName) => { + if (!usedPlugins[pluginName]) { + usedPlugins[pluginName] = modulesMap[pluginName].exports; + } + return usedPlugins[pluginName]; + }; + includedModules.forEach((c) => { + const bangIndex = c.indexOf('!'); + if (bangIndex >= 0) { + const pluginName = c.substr(0, bangIndex); + const plugin = getLoaderPlugin(pluginName); + mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1))); + return; + } + const module = modulesMap[c]; + if (module.path === 'empty:') { + return; + } + const contents = readFileAndRemoveBOM(module.path); + if (module.shim) { + mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents)); + } + else { + mainResult.sources.push(emitNamedModule(c, module.defineLocation, module.path, contents)); + } + }); + Object.keys(usedPlugins).forEach((pluginName) => { + const plugin = usedPlugins[pluginName]; + if (typeof plugin.writeFile === 'function') { + const req = (() => { + throw new Error('no-no!'); + }); + req.toUrl = something => something; + const write = (filename, contents) => { + results.push({ + dest: filename, + sources: [{ + path: null, + contents: contents + }] + }); + }; + plugin.writeFile(pluginName, entryPoint, req, write, {}); + } + }); + const toIFile = (path) => { + const contents = readFileAndRemoveBOM(path); + return { + path: path, + contents: contents + }; + }; + const toPrepend = (prepend || []).map(toIFile); + const toAppend = (append || []).map(toIFile); + mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend); + return { + files: results, + usedPlugins: usedPlugins + }; +} +function readFileAndRemoveBOM(path) { + const BOM_CHAR_CODE = 65279; + let contents = fs.readFileSync(path, 'utf8'); + // Remove BOM + if (contents.charCodeAt(0) === BOM_CHAR_CODE) { + contents = contents.substring(1); + } + return contents; +} +function emitPlugin(entryPoint, plugin, pluginName, moduleName) { + let result = ''; + if (typeof plugin.write === 'function') { + const write = ((what) => { + result += what; + }); + write.getEntryPoint = () => { + return entryPoint; + }; + write.asModule = (moduleId, code) => { + code = code.replace(/^define\(/, 'define("' + moduleId + '",'); + result += code; + }; + plugin.write(pluginName, moduleName, write); + } + return { + path: null, + contents: result + }; +} +function emitNamedModule(moduleId, defineCallPosition, path, contents) { + // `defineCallPosition` is the position in code: |define() + const defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col); + // `parensOffset` is the position in code: define|() + const parensOffset = contents.indexOf('(', defineCallOffset); + const insertStr = '"' + moduleId + '", '; + return { + path: path, + contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1) + }; +} +function emitShimmedModule(moduleId, myDeps, factory, path, contents) { + const strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : ''); + const strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');'; + return { + path: path, + contents: contents + '\n;\n' + strDefine + }; +} +/** + * Convert a position (line:col) to (offset) in string `str` + */ +function positionToOffset(str, desiredLine, desiredCol) { + if (desiredLine === 1) { + return desiredCol - 1; + } + let line = 1; + let lastNewLineOffset = -1; + do { + if (desiredLine === line) { + return lastNewLineOffset + 1 + desiredCol - 1; + } + lastNewLineOffset = str.indexOf('\n', lastNewLineOffset + 1); + line++; + } while (lastNewLineOffset >= 0); + return -1; +} +/** + * Return a set of reachable nodes in `graph` starting from `rootNodes` + */ +function visit(rootNodes, graph) { + const result = {}; + const queue = rootNodes; + rootNodes.forEach((node) => { + result[node] = true; + }); + while (queue.length > 0) { + const el = queue.shift(); + const myEdges = graph[el] || []; + myEdges.forEach((toNode) => { + if (!result[toNode]) { + result[toNode] = true; + queue.push(toNode); + } + }); + } + return result; +} +/** + * Perform a topological sort on `graph` + */ +function topologicalSort(graph) { + const allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {}; + Object.keys(graph).forEach((fromNode) => { + allNodes[fromNode] = true; + outgoingEdgeCount[fromNode] = graph[fromNode].length; + graph[fromNode].forEach((toNode) => { + allNodes[toNode] = true; + outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0; + inverseEdges[toNode] = inverseEdges[toNode] || []; + inverseEdges[toNode].push(fromNode); + }); + }); + // https://en.wikipedia.org/wiki/Topological_sorting + const S = [], L = []; + Object.keys(allNodes).forEach((node) => { + if (outgoingEdgeCount[node] === 0) { + delete outgoingEdgeCount[node]; + S.push(node); + } + }); + while (S.length > 0) { + // Ensure the exact same order all the time with the same inputs + S.sort(); + const n = S.shift(); + L.push(n); + const myInverseEdges = inverseEdges[n] || []; + myInverseEdges.forEach((m) => { + outgoingEdgeCount[m]--; + if (outgoingEdgeCount[m] === 0) { + delete outgoingEdgeCount[m]; + S.push(m); + } + }); + } + if (Object.keys(outgoingEdgeCount).length > 0) { + throw new Error('Cannot do topological sort on cyclic graph, remaining nodes: ' + Object.keys(outgoingEdgeCount)); + } + return L; +} diff --git a/build/lib/compilation.js b/build/lib/compilation.js new file mode 100644 index 00000000000..be5324f54f8 --- /dev/null +++ b/build/lib/compilation.js @@ -0,0 +1,174 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.watchTask = exports.compileTask = void 0; +const es = require("event-stream"); +const fs = require("fs"); +const gulp = require("gulp"); +const bom = require("gulp-bom"); +const sourcemaps = require("gulp-sourcemaps"); +const tsb = require("gulp-tsb"); +const path = require("path"); +const monacodts = require("./monaco-api"); +const nls = require("./nls"); +const reporter_1 = require("./reporter"); +const util = require("./util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const os = require("os"); +const watch = require('./watch'); +const reporter = reporter_1.createReporter(); +function getTypeScriptCompilerOptions(src) { + const rootDir = path.join(__dirname, `../../${src}`); + let options = {}; + options.verbose = false; + options.sourceMap = true; + if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry + options.sourceMap = false; + } + options.rootDir = rootDir; + options.baseUrl = rootDir; + options.sourceRoot = util.toFileUri(rootDir); + options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 0 : 1; + return options; +} +function createCompile(src, build, emitError) { + const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json'); + const overrideOptions = Object.assign(Object.assign({}, getTypeScriptCompilerOptions(src)), { inlineSources: Boolean(build) }); + const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err)); + function pipeline(token) { + const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path)); + const tsFilter = util.filter(data => /\.ts$/.test(data.path)); + const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path))); + const input = es.through(); + const output = input + .pipe(utf8Filter) + .pipe(bom()) // this is required to preserve BOM in test files that loose it otherwise + .pipe(utf8Filter.restore) + .pipe(tsFilter) + .pipe(util.loadSourcemaps()) + .pipe(compilation(token)) + .pipe(noDeclarationsFilter) + .pipe(build ? nls() : es.through()) + .pipe(noDeclarationsFilter.restore) + .pipe(sourcemaps.write('.', { + addComment: false, + includeContent: !!build, + sourceRoot: overrideOptions.sourceRoot + })) + .pipe(tsFilter.restore) + .pipe(reporter.end(!!emitError)); + return es.duplex(input, output); + } + pipeline.tsProjectSrc = () => { + return compilation.src({ base: src }); + }; + return pipeline; +} +function compileTask(src, out, build) { + return function () { + if (os.totalmem() < 4000000000) { + throw new Error('compilation requires 4GB of RAM'); + } + const compile = createCompile(src, build, true); + const srcPipe = gulp.src(`${src}/**`, { base: `${src}` }); + let generator = new MonacoGenerator(false); + if (src === 'src') { + generator.execute(); + } + return srcPipe + .pipe(generator.stream) + .pipe(compile()) + .pipe(gulp.dest(out)); + }; +} +exports.compileTask = compileTask; +function watchTask(out, build) { + return function () { + const compile = createCompile('src', build); + const src = gulp.src('src/**', { base: 'src' }); + const watchSrc = watch('src/**', { base: 'src', readDelay: 200 }); + let generator = new MonacoGenerator(true); + generator.execute(); + return watchSrc + .pipe(generator.stream) + .pipe(util.incremental(compile, src, true)) + .pipe(gulp.dest(out)); + }; +} +exports.watchTask = watchTask; +const REPO_SRC_FOLDER = path.join(__dirname, '../../src'); +class MonacoGenerator { + constructor(isWatch) { + this._executeSoonTimer = null; + this._isWatch = isWatch; + this.stream = es.through(); + this._watchedFiles = {}; + let onWillReadFile = (moduleId, filePath) => { + if (!this._isWatch) { + return; + } + if (this._watchedFiles[filePath]) { + return; + } + this._watchedFiles[filePath] = true; + fs.watchFile(filePath, () => { + this._declarationResolver.invalidateCache(moduleId); + this._executeSoon(); + }); + }; + this._fsProvider = new class extends monacodts.FSProvider { + readFileSync(moduleId, filePath) { + onWillReadFile(moduleId, filePath); + return super.readFileSync(moduleId, filePath); + } + }; + this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider); + if (this._isWatch) { + fs.watchFile(monacodts.RECIPE_PATH, () => { + this._executeSoon(); + }); + } + } + _executeSoon() { + if (this._executeSoonTimer !== null) { + clearTimeout(this._executeSoonTimer); + this._executeSoonTimer = null; + } + this._executeSoonTimer = setTimeout(() => { + this._executeSoonTimer = null; + this.execute(); + }, 20); + } + _run() { + let r = monacodts.run3(this._declarationResolver); + if (!r && !this._isWatch) { + // The build must always be able to generate the monaco.d.ts + throw new Error(`monaco.d.ts generation error - Cannot continue`); + } + return r; + } + _log(message, ...rest) { + fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest); + } + execute() { + const startTime = Date.now(); + const result = this._run(); + if (!result) { + // nothing really changed + return; + } + if (result.isTheSame) { + return; + } + fs.writeFileSync(result.filePath, result.content); + fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums); + this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`); + if (!this._isWatch) { + this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.'); + } + } +} diff --git a/build/lib/electron.js b/build/lib/electron.js new file mode 100644 index 00000000000..2ef8883ac04 --- /dev/null +++ b/build/lib/electron.js @@ -0,0 +1,111 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.config = void 0; +const fs = require("fs"); +const path = require("path"); +const vfs = require("vinyl-fs"); +const filter = require("gulp-filter"); +const json = require("gulp-json-editor"); +const _ = require("underscore"); +const util = require("./util"); +const electron = require('gulp-atom-electron'); +const root = path.dirname(path.dirname(__dirname)); +const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8')); +const commit = util.getVersion(root); +const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8')); +function darwinBundleDocumentType(extensions, icon) { + return { + name: product.nameLong + ' document', + role: 'Editor', + ostypes: ['TEXT', 'utxt', 'TUTX', '****'], + extensions: extensions, + iconFile: icon + }; +} +exports.config = { + version: util.getElectronVersion(), + productAppName: product.nameLong, + companyName: 'Microsoft Corporation', + copyright: 'Copyright (C) 2019 Microsoft. All rights reserved', + darwinIcon: 'resources/darwin/code.icns', + darwinBundleIdentifier: product.darwinBundleIdentifier, + darwinApplicationCategoryType: 'public.app-category.developer-tools', + darwinHelpBookFolder: 'VS Code HelpBook', + darwinHelpBookName: 'VS Code HelpBook', + darwinBundleDocumentTypes: [ + darwinBundleDocumentType(['bat', 'cmd'], 'resources/darwin/bat.icns'), + darwinBundleDocumentType(['bowerrc'], 'resources/darwin/bower.icns'), + darwinBundleDocumentType(['c', 'h'], 'resources/darwin/c.icns'), + darwinBundleDocumentType(['config', 'editorconfig', 'gitattributes', 'gitconfig', 'gitignore', 'ini'], 'resources/darwin/config.icns'), + darwinBundleDocumentType(['cc', 'cpp', 'cxx', 'c++', 'hh', 'hpp', 'hxx', 'h++'], 'resources/darwin/cpp.icns'), + darwinBundleDocumentType(['cs', 'csx'], 'resources/darwin/csharp.icns'), + darwinBundleDocumentType(['css'], 'resources/darwin/css.icns'), + darwinBundleDocumentType(['go'], 'resources/darwin/go.icns'), + darwinBundleDocumentType(['asp', 'aspx', 'cshtml', 'htm', 'html', 'jshtm', 'jsp', 'phtml', 'shtml'], 'resources/darwin/html.icns'), + darwinBundleDocumentType(['jade'], 'resources/darwin/jade.icns'), + darwinBundleDocumentType(['jav', 'java'], 'resources/darwin/java.icns'), + darwinBundleDocumentType(['js', 'jscsrc', 'jshintrc', 'mjs', 'cjs'], 'resources/darwin/javascript.icns'), + darwinBundleDocumentType(['json'], 'resources/darwin/json.icns'), + darwinBundleDocumentType(['less'], 'resources/darwin/less.icns'), + darwinBundleDocumentType(['markdown', 'md', 'mdoc', 'mdown', 'mdtext', 'mdtxt', 'mdwn', 'mkd', 'mkdn'], 'resources/darwin/markdown.icns'), + darwinBundleDocumentType(['php'], 'resources/darwin/php.icns'), + darwinBundleDocumentType(['ps1', 'psd1', 'psm1'], 'resources/darwin/powershell.icns'), + darwinBundleDocumentType(['py'], 'resources/darwin/python.icns'), + darwinBundleDocumentType(['gemspec', 'rb'], 'resources/darwin/ruby.icns'), + darwinBundleDocumentType(['scss'], 'resources/darwin/sass.icns'), + darwinBundleDocumentType(['bash', 'bash_login', 'bash_logout', 'bash_profile', 'bashrc', 'profile', 'rhistory', 'rprofile', 'sh', 'zlogin', 'zlogout', 'zprofile', 'zsh', 'zshenv', 'zshrc'], 'resources/darwin/shell.icns'), + darwinBundleDocumentType(['sql'], 'resources/darwin/sql.icns'), + darwinBundleDocumentType(['ts'], 'resources/darwin/typescript.icns'), + darwinBundleDocumentType(['tsx', 'jsx'], 'resources/darwin/react.icns'), + darwinBundleDocumentType(['vue'], 'resources/darwin/vue.icns'), + darwinBundleDocumentType(['ascx', 'csproj', 'dtd', 'wxi', 'wxl', 'wxs', 'xml', 'xaml'], 'resources/darwin/xml.icns'), + darwinBundleDocumentType(['eyaml', 'eyml', 'yaml', 'yml'], 'resources/darwin/yaml.icns'), + darwinBundleDocumentType(['clj', 'cljs', 'cljx', 'clojure', 'code-workspace', 'coffee', 'containerfile', 'ctp', 'dockerfile', 'dot', 'edn', 'fs', 'fsi', 'fsscript', 'fsx', 'handlebars', 'hbs', 'lua', 'm', 'makefile', 'ml', 'mli', 'pl', 'pl6', 'pm', 'pm6', 'pod', 'pp', 'properties', 'psgi', 'pug', 'r', 'rs', 'rt', 'svg', 'svgz', 't', 'txt', 'vb', 'xcodeproj', 'xcworkspace'], 'resources/darwin/default.icns') + ], + darwinBundleURLTypes: [{ + role: 'Viewer', + name: product.nameLong, + urlSchemes: [product.urlProtocol] + }], + darwinForceDarkModeSupport: true, + darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined, + linuxExecutableName: product.applicationName, + winIcon: 'resources/win32/code.ico', + token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined, + repo: product.electronRepository || undefined +}; +function getElectron(arch) { + return () => { + const electronOpts = _.extend({}, exports.config, { + platform: process.platform, + arch: arch === 'armhf' ? 'arm' : arch, + ffmpegChromium: true, + keepDefaultApp: true + }); + return vfs.src('package.json') + .pipe(json({ name: product.nameShort })) + .pipe(electron(electronOpts)) + .pipe(filter(['**', '!**/app/package.json'])) + .pipe(vfs.dest('.build/electron')); + }; +} +async function main(arch = process.arch) { + const version = util.getElectronVersion(); + const electronPath = path.join(root, '.build', 'electron'); + const versionFile = path.join(electronPath, 'version'); + const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`; + if (!isUpToDate) { + await util.rimraf(electronPath)(); + await util.streamToPromise(getElectron(arch)()); + } +} +if (require.main === module) { + main(process.argv[2]).catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/lib/eslint/code-import-patterns.js b/build/lib/eslint/code-import-patterns.js new file mode 100644 index 00000000000..0d508d1d00e --- /dev/null +++ b/build/lib/eslint/code-import-patterns.js @@ -0,0 +1,59 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path_1 = require("path"); +const minimatch = require("minimatch"); +const utils_1 = require("./utils"); +module.exports = new class { + constructor() { + this.meta = { + messages: { + badImport: 'Imports violates \'{{restrictions}}\' restrictions. See https://github.com/microsoft/vscode/wiki/Source-Code-Organization' + }, + docs: { + url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization' + } + }; + } + create(context) { + const configs = context.options; + for (const config of configs) { + if (minimatch(context.getFilename(), config.target)) { + return utils_1.createImportRuleListener((node, value) => this._checkImport(context, config, node, value)); + } + } + return {}; + } + _checkImport(context, config, node, path) { + // resolve relative paths + if (path[0] === '.') { + path = path_1.join(context.getFilename(), path); + } + let restrictions; + if (typeof config.restrictions === 'string') { + restrictions = [config.restrictions]; + } + else { + restrictions = config.restrictions; + } + let matched = false; + for (const pattern of restrictions) { + if (minimatch(path, pattern)) { + matched = true; + break; + } + } + if (!matched) { + // None of the restrictions matched + context.report({ + loc: node.loc, + messageId: 'badImport', + data: { + restrictions: restrictions.join(' or ') + } + }); + } + } +}; diff --git a/build/lib/eslint/code-layering.js b/build/lib/eslint/code-layering.js new file mode 100644 index 00000000000..db591f789c7 --- /dev/null +++ b/build/lib/eslint/code-layering.js @@ -0,0 +1,68 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path_1 = require("path"); +const utils_1 = require("./utils"); +module.exports = new class { + constructor() { + this.meta = { + messages: { + layerbreaker: 'Bad layering. You are not allowed to access {{from}} from here, allowed layers are: [{{allowed}}]' + }, + docs: { + url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization' + } + }; + } + create(context) { + const fileDirname = path_1.dirname(context.getFilename()); + const parts = fileDirname.split(/\\|\//); + const ruleArgs = context.options[0]; + let config; + for (let i = parts.length - 1; i >= 0; i--) { + if (ruleArgs[parts[i]]) { + config = { + allowed: new Set(ruleArgs[parts[i]]).add(parts[i]), + disallowed: new Set() + }; + Object.keys(ruleArgs).forEach(key => { + if (!config.allowed.has(key)) { + config.disallowed.add(key); + } + }); + break; + } + } + if (!config) { + // nothing + return {}; + } + return utils_1.createImportRuleListener((node, path) => { + if (path[0] === '.') { + path = path_1.join(path_1.dirname(context.getFilename()), path); + } + const parts = path_1.dirname(path).split(/\\|\//); + for (let i = parts.length - 1; i >= 0; i--) { + const part = parts[i]; + if (config.allowed.has(part)) { + // GOOD - same layer + break; + } + if (config.disallowed.has(part)) { + // BAD - wrong layer + context.report({ + loc: node.loc, + messageId: 'layerbreaker', + data: { + from: part, + allowed: [...config.allowed.keys()].join(', ') + } + }); + break; + } + } + }); + } +}; diff --git a/build/lib/eslint/code-no-nls-in-standalone-editor.js b/build/lib/eslint/code-no-nls-in-standalone-editor.js new file mode 100644 index 00000000000..d8955507bed --- /dev/null +++ b/build/lib/eslint/code-no-nls-in-standalone-editor.js @@ -0,0 +1,38 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path_1 = require("path"); +const utils_1 = require("./utils"); +module.exports = new class NoNlsInStandaloneEditorRule { + constructor() { + this.meta = { + messages: { + noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts' + } + }; + } + create(context) { + const fileName = context.getFilename(); + if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(fileName) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(fileName) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(fileName)) { + return utils_1.createImportRuleListener((node, path) => { + // resolve relative paths + if (path[0] === '.') { + path = path_1.join(context.getFilename(), path); + } + if (/vs(\/|\\)nls/.test(path)) { + context.report({ + loc: node.loc, + messageId: 'noNls' + }); + } + }); + } + return {}; + } +}; diff --git a/build/lib/eslint/code-no-standalone-editor.js b/build/lib/eslint/code-no-standalone-editor.js new file mode 100644 index 00000000000..d9d6bb55b87 --- /dev/null +++ b/build/lib/eslint/code-no-standalone-editor.js @@ -0,0 +1,41 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path_1 = require("path"); +const utils_1 = require("./utils"); +module.exports = new class NoNlsInStandaloneEditorRule { + constructor() { + this.meta = { + messages: { + badImport: 'Not allowed to import standalone editor modules.' + }, + docs: { + url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization' + } + }; + } + create(context) { + if (/vs(\/|\\)editor/.test(context.getFilename())) { + // the vs/editor folder is allowed to use the standalone editor + return {}; + } + return utils_1.createImportRuleListener((node, path) => { + // resolve relative paths + if (path[0] === '.') { + path = path_1.join(context.getFilename(), path); + } + if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)) { + context.report({ + loc: node.loc, + messageId: 'badImport' + }); + } + }); + } +}; diff --git a/build/lib/eslint/code-no-unexternalized-strings.js b/build/lib/eslint/code-no-unexternalized-strings.js new file mode 100644 index 00000000000..b603f4d8e09 --- /dev/null +++ b/build/lib/eslint/code-no-unexternalized-strings.js @@ -0,0 +1,111 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var _a; +const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); +function isStringLiteral(node) { + return !!node && node.type === experimental_utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string'; +} +function isDoubleQuoted(node) { + return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"'; +} +module.exports = new (_a = class NoUnexternalizedStrings { + constructor() { + this.meta = { + messages: { + doubleQuoted: 'Only use double-quoted strings for externalized strings.', + badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.', + duplicateKey: 'Duplicate key \'{{key}}\' with different message value.', + badMessage: 'Message argument to \'{{message}}\' must be a string literal.' + } + }; + } + create(context) { + const externalizedStringLiterals = new Map(); + const doubleQuotedStringLiterals = new Set(); + function collectDoubleQuotedStrings(node) { + if (isStringLiteral(node) && isDoubleQuoted(node)) { + doubleQuotedStringLiterals.add(node); + } + } + function visitLocalizeCall(node) { + // localize(key, message) + const [keyNode, messageNode] = node.arguments; + // (1) + // extract key so that it can be checked later + let key; + if (isStringLiteral(keyNode)) { + doubleQuotedStringLiterals.delete(keyNode); + key = keyNode.value; + } + else if (keyNode.type === experimental_utils_1.AST_NODE_TYPES.ObjectExpression) { + for (let property of keyNode.properties) { + if (property.type === experimental_utils_1.AST_NODE_TYPES.Property && !property.computed) { + if (property.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier && property.key.name === 'key') { + if (isStringLiteral(property.value)) { + doubleQuotedStringLiterals.delete(property.value); + key = property.value.value; + break; + } + } + } + } + } + if (typeof key === 'string') { + let array = externalizedStringLiterals.get(key); + if (!array) { + array = []; + externalizedStringLiterals.set(key, array); + } + array.push({ call: node, message: messageNode }); + } + // (2) + // remove message-argument from doubleQuoted list and make + // sure it is a string-literal + doubleQuotedStringLiterals.delete(messageNode); + if (!isStringLiteral(messageNode)) { + context.report({ + loc: messageNode.loc, + messageId: 'badMessage', + data: { message: context.getSourceCode().getText(node) } + }); + } + } + function reportBadStringsAndBadKeys() { + // (1) + // report all strings that are in double quotes + for (const node of doubleQuotedStringLiterals) { + context.report({ loc: node.loc, messageId: 'doubleQuoted' }); + } + for (const [key, values] of externalizedStringLiterals) { + // (2) + // report all invalid NLS keys + if (!key.match(NoUnexternalizedStrings._rNlsKeys)) { + for (let value of values) { + context.report({ loc: value.call.loc, messageId: 'badKey', data: { key } }); + } + } + // (2) + // report all invalid duplicates (same key, different message) + if (values.length > 1) { + for (let i = 1; i < values.length; i++) { + if (context.getSourceCode().getText(values[i - 1].message) !== context.getSourceCode().getText(values[i].message)) { + context.report({ loc: values[i].call.loc, messageId: 'duplicateKey', data: { key } }); + } + } + } + } + } + return { + ['Literal']: (node) => collectDoubleQuotedStrings(node), + ['ExpressionStatement[directive] Literal:exit']: (node) => doubleQuotedStringLiterals.delete(node), + ['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node) => visitLocalizeCall(node), + ['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node) => visitLocalizeCall(node), + ['Program:exit']: reportBadStringsAndBadKeys, + }; + } + }, + _a._rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/, + _a); diff --git a/build/lib/eslint/code-no-unused-expressions.js b/build/lib/eslint/code-no-unused-expressions.js new file mode 100644 index 00000000000..d8ee6ca46f3 --- /dev/null +++ b/build/lib/eslint/code-no-unused-expressions.js @@ -0,0 +1,122 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// FORKED FROM https://github.com/eslint/eslint/blob/b23ad0d789a909baf8d7c41a35bc53df932eaf30/lib/rules/no-unused-expressions.js +// and added support for `OptionalCallExpression`, see https://github.com/facebook/create-react-app/issues/8107 and https://github.com/eslint/eslint/issues/12642 +/** + * @fileoverview Flag expressions in statement position that do not side effect + * @author Michael Ficarra + */ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ +module.exports = { + meta: { + type: 'suggestion', + docs: { + description: 'disallow unused expressions', + category: 'Best Practices', + recommended: false, + url: 'https://eslint.org/docs/rules/no-unused-expressions' + }, + schema: [ + { + type: 'object', + properties: { + allowShortCircuit: { + type: 'boolean', + default: false + }, + allowTernary: { + type: 'boolean', + default: false + }, + allowTaggedTemplates: { + type: 'boolean', + default: false + } + }, + additionalProperties: false + } + ] + }, + create(context) { + const config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, allowTernary = config.allowTernary || false, allowTaggedTemplates = config.allowTaggedTemplates || false; + // eslint-disable-next-line jsdoc/require-description + /** + * @param node any node + * @returns whether the given node structurally represents a directive + */ + function looksLikeDirective(node) { + return node.type === 'ExpressionStatement' && + node.expression.type === 'Literal' && typeof node.expression.value === 'string'; + } + // eslint-disable-next-line jsdoc/require-description + /** + * @param predicate ([a] -> Boolean) the function used to make the determination + * @param list the input list + * @returns the leading sequence of members in the given list that pass the given predicate + */ + function takeWhile(predicate, list) { + for (let i = 0; i < list.length; ++i) { + if (!predicate(list[i])) { + return list.slice(0, i); + } + } + return list.slice(); + } + // eslint-disable-next-line jsdoc/require-description + /** + * @param node a Program or BlockStatement node + * @returns the leading sequence of directive nodes in the given node's body + */ + function directives(node) { + return takeWhile(looksLikeDirective, node.body); + } + // eslint-disable-next-line jsdoc/require-description + /** + * @param node any node + * @param ancestors the given node's ancestors + * @returns whether the given node is considered a directive in its current position + */ + function isDirective(node, ancestors) { + const parent = ancestors[ancestors.length - 1], grandparent = ancestors[ancestors.length - 2]; + return (parent.type === 'Program' || parent.type === 'BlockStatement' && + (/Function/u.test(grandparent.type))) && + directives(parent).indexOf(node) >= 0; + } + /** + * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags. + * @param node any node + * @returns whether the given node is a valid expression + */ + function isValidExpression(node) { + if (allowTernary) { + // Recursive check for ternary and logical expressions + if (node.type === 'ConditionalExpression') { + return isValidExpression(node.consequent) && isValidExpression(node.alternate); + } + } + if (allowShortCircuit) { + if (node.type === 'LogicalExpression') { + return isValidExpression(node.right); + } + } + if (allowTaggedTemplates && node.type === 'TaggedTemplateExpression') { + return true; + } + return /^(?:Assignment|OptionalCall|Call|New|Update|Yield|Await)Expression$/u.test(node.type) || + (node.type === 'UnaryExpression' && ['delete', 'void'].indexOf(node.operator) >= 0); + } + return { + ExpressionStatement(node) { + if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) { + context.report({ node: node, message: 'Expected an assignment or function call and instead saw an expression.' }); + } + } + }; + } +}; diff --git a/build/lib/eslint/code-translation-remind.js b/build/lib/eslint/code-translation-remind.js new file mode 100644 index 00000000000..a276e7c0028 --- /dev/null +++ b/build/lib/eslint/code-translation-remind.js @@ -0,0 +1,57 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var _a; +const fs_1 = require("fs"); +const utils_1 = require("./utils"); +module.exports = new (_a = class TranslationRemind { + constructor() { + this.meta = { + messages: { + missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.' + } + }; + } + create(context) { + return utils_1.createImportRuleListener((node, path) => this._checkImport(context, node, path)); + } + _checkImport(context, node, path) { + if (path !== TranslationRemind.NLS_MODULE) { + return; + } + const currentFile = context.getFilename(); + const matchService = currentFile.match(/vs\/workbench\/services\/\w+/); + const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/); + if (!matchService && !matchPart) { + return; + } + const resource = matchService ? matchService[0] : matchPart[0]; + let resourceDefined = false; + let json; + try { + json = fs_1.readFileSync('./build/lib/i18n.resources.json', 'utf8'); + } + catch (e) { + console.error('[translation-remind rule]: File with resources to pull from Transifex was not found. Aborting translation resource check for newly defined workbench part/service.'); + return; + } + const workbenchResources = JSON.parse(json).workbench; + workbenchResources.forEach((existingResource) => { + if (existingResource.name === resource) { + resourceDefined = true; + return; + } + }); + if (!resourceDefined) { + context.report({ + loc: node.loc, + messageId: 'missing', + data: { resource } + }); + } + } + }, + _a.NLS_MODULE = 'vs/nls', + _a); diff --git a/build/lib/eslint/utils.js b/build/lib/eslint/utils.js new file mode 100644 index 00000000000..c58e4e24be1 --- /dev/null +++ b/build/lib/eslint/utils.js @@ -0,0 +1,37 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createImportRuleListener = void 0; +function createImportRuleListener(validateImport) { + function _checkImport(node) { + if (node && node.type === 'Literal' && typeof node.value === 'string') { + validateImport(node, node.value); + } + } + return { + // import ??? from 'module' + ImportDeclaration: (node) => { + _checkImport(node.source); + }, + // import('module').then(...) OR await import('module') + ['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node) => { + _checkImport(node); + }, + // import foo = ... + ['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node) => { + _checkImport(node); + }, + // export ?? from 'module' + ExportAllDeclaration: (node) => { + _checkImport(node.source); + }, + // export {foo} from 'module' + ExportNamedDeclaration: (node) => { + _checkImport(node.source); + }, + }; +} +exports.createImportRuleListener = createImportRuleListener; diff --git a/build/lib/eslint/vscode-dts-create-func.js b/build/lib/eslint/vscode-dts-create-func.js new file mode 100644 index 00000000000..5a27bf51c80 --- /dev/null +++ b/build/lib/eslint/vscode-dts-create-func.js @@ -0,0 +1,35 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); +module.exports = new class ApiLiteralOrTypes { + constructor() { + this.meta = { + docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' }, + messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', } + }; + } + create(context) { + return { + ['TSDeclareFunction Identifier[name=/create.*/]']: (node) => { + var _a; + const decl = node.parent; + if (((_a = decl.returnType) === null || _a === void 0 ? void 0 : _a.typeAnnotation.type) !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) { + return; + } + if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) { + return; + } + const ident = decl.returnType.typeAnnotation.typeName.name; + if (ident === 'Promise' || ident === 'Thenable') { + context.report({ + node, + messageId: 'sync' + }); + } + } + }; + } +}; diff --git a/build/lib/eslint/vscode-dts-event-naming.js b/build/lib/eslint/vscode-dts-event-naming.js new file mode 100644 index 00000000000..388ccf2f804 --- /dev/null +++ b/build/lib/eslint/vscode-dts-event-naming.js @@ -0,0 +1,87 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var _a; +const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); +module.exports = new (_a = class ApiEventNaming { + constructor() { + this.meta = { + docs: { + url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#event-naming' + }, + messages: { + naming: 'Event names must follow this patten: `on[Did|Will]`', + verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration', + subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API', + unknown: 'UNKNOWN event declaration, lint-rule needs tweaking' + } + }; + } + create(context) { + const config = context.options[0]; + const allowed = new Set(config.allowed); + const verbs = new Set(config.verbs); + return { + ['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => { + var _a, _b; + const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent; + const ident = this.getIdent(def); + if (!ident) { + // event on unknown structure... + return context.report({ + node, + message: 'unknown' + }); + } + if (allowed.has(ident.name)) { + // configured exception + return; + } + const match = ApiEventNaming._nameRegExp.exec(ident.name); + if (!match) { + context.report({ + node: ident, + messageId: 'naming' + }); + return; + } + // check that is spelled out (configured) as verb + if (!verbs.has(match[2].toLowerCase())) { + context.report({ + node: ident, + messageId: 'verb', + data: { verb: match[2] } + }); + } + // check that a subject (if present) has occurred + if (match[3]) { + const regex = new RegExp(match[3], 'ig'); + const parts = context.getSourceCode().getText().split(regex); + if (parts.length < 3) { + context.report({ + node: ident, + messageId: 'subject', + data: { subject: match[3] } + }); + } + } + } + }; + } + getIdent(def) { + if (!def) { + return; + } + if (def.type === experimental_utils_1.AST_NODE_TYPES.Identifier) { + return def; + } + else if ((def.type === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || def.type === experimental_utils_1.AST_NODE_TYPES.ClassProperty) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) { + return def.key; + } + return this.getIdent(def.parent); + } + }, + _a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/, + _a); diff --git a/build/lib/eslint/vscode-dts-interface-naming.js b/build/lib/eslint/vscode-dts-interface-naming.js new file mode 100644 index 00000000000..70ca810825b --- /dev/null +++ b/build/lib/eslint/vscode-dts-interface-naming.js @@ -0,0 +1,30 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var _a; +module.exports = new (_a = class ApiInterfaceNaming { + constructor() { + this.meta = { + messages: { + naming: 'Interfaces must not be prefixed with uppercase `I`', + } + }; + } + create(context) { + return { + ['TSInterfaceDeclaration Identifier']: (node) => { + const name = node.name; + if (ApiInterfaceNaming._nameRegExp.test(name)) { + context.report({ + node, + messageId: 'naming' + }); + } + } + }; + } + }, + _a._nameRegExp = /I[A-Z]/, + _a); diff --git a/build/lib/eslint/vscode-dts-literal-or-types.js b/build/lib/eslint/vscode-dts-literal-or-types.js new file mode 100644 index 00000000000..e07dfc6de28 --- /dev/null +++ b/build/lib/eslint/vscode-dts-literal-or-types.js @@ -0,0 +1,27 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +module.exports = new class ApiLiteralOrTypes { + constructor() { + this.meta = { + docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' }, + messages: { useEnum: 'Use enums, not literal-or-types', } + }; + } + create(context) { + return { + ['TSTypeAnnotation TSUnionType TSLiteralType']: (node) => { + var _a; + if (((_a = node.literal) === null || _a === void 0 ? void 0 : _a.type) === 'TSNullKeyword') { + return; + } + context.report({ + node: node, + messageId: 'useEnum' + }); + } + }; + } +}; diff --git a/build/lib/extensions.js b/build/lib/extensions.js new file mode 100644 index 00000000000..fe0deffc6d0 --- /dev/null +++ b/build/lib/extensions.js @@ -0,0 +1,325 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.translatePackageJSON = exports.scanBuiltinExtensions = exports.packageMarketplaceExtensionsStream = exports.packageLocalExtensionsStream = exports.fromMarketplace = void 0; +const es = require("event-stream"); +const fs = require("fs"); +const glob = require("glob"); +const gulp = require("gulp"); +const path = require("path"); +const File = require("vinyl"); +const vsce = require("vsce"); +const stats_1 = require("./stats"); +const util2 = require("./util"); +const remote = require("gulp-remote-retry-src"); +const vzip = require('gulp-vinyl-zip'); +const filter = require("gulp-filter"); +const rename = require("gulp-rename"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const buffer = require('gulp-buffer'); +const json = require("gulp-json-editor"); +const jsoncParser = require("jsonc-parser"); +const webpack = require('webpack'); +const webpackGulp = require('webpack-stream'); +const util = require('./util'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); +const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; +function minifyExtensionResources(input) { + const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true }); + return input + .pipe(jsonFilter) + .pipe(buffer()) + .pipe(es.mapSync((f) => { + const errors = []; + const value = jsoncParser.parse(f.contents.toString('utf8'), errors); + if (errors.length === 0) { + // file parsed OK => just stringify to drop whitespace and comments + f.contents = Buffer.from(JSON.stringify(value)); + } + return f; + })) + .pipe(jsonFilter.restore); +} +function updateExtensionPackageJSON(input, update) { + const packageJsonFilter = filter('extensions/*/package.json', { restore: true }); + return input + .pipe(packageJsonFilter) + .pipe(buffer()) + .pipe(es.mapSync((f) => { + const data = JSON.parse(f.contents.toString('utf8')); + f.contents = Buffer.from(JSON.stringify(update(data))); + return f; + })) + .pipe(packageJsonFilter.restore); +} +function fromLocal(extensionPath, forWeb) { + const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js'; + const isWebPacked = fs.existsSync(path.join(extensionPath, webpackConfigFileName)); + let input = isWebPacked + ? fromLocalWebpack(extensionPath, webpackConfigFileName) + : fromLocalNormal(extensionPath); + if (isWebPacked) { + input = updateExtensionPackageJSON(input, (data) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; + if (data.main) { + data.main = data.main.replace('/out/', /dist/); + } + return data; + }); + } + return input; +} +function fromLocalWebpack(extensionPath, webpackConfigFileName) { + const result = es.through(); + const packagedDependencies = []; + const packageJsonConfig = require(path.join(extensionPath, 'package.json')); + if (packageJsonConfig.dependencies) { + const webpackRootConfig = require(path.join(extensionPath, webpackConfigFileName)); + for (const key in webpackRootConfig.externals) { + if (key in packageJsonConfig.dependencies) { + packagedDependencies.push(key); + } + } + } + vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn, packagedDependencies }).then(fileNames => { + const files = fileNames + .map(fileName => path.join(extensionPath, fileName)) + .map(filePath => new File({ + path: filePath, + stat: fs.statSync(filePath), + base: extensionPath, + contents: fs.createReadStream(filePath) + })); + // check for a webpack configuration files, then invoke webpack + // and merge its output with the files stream. + const webpackConfigLocations = glob.sync(path.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] }); + const webpackStreams = webpackConfigLocations.map(webpackConfigPath => { + const webpackDone = (err, stats) => { + fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`); + if (err) { + result.emit('error', err); + } + const { compilation } = stats; + if (compilation.errors.length > 0) { + result.emit('error', compilation.errors.join('\n')); + } + if (compilation.warnings.length > 0) { + result.emit('error', compilation.warnings.join('\n')); + } + }; + const webpackConfig = Object.assign(Object.assign({}, require(webpackConfigPath)), { mode: 'production' }); + const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path); + return webpackGulp(webpackConfig, webpack, webpackDone) + .pipe(es.through(function (data) { + data.stat = data.stat || {}; + data.base = extensionPath; + this.emit('data', data); + })) + .pipe(es.through(function (data) { + // source map handling: + // * rewrite sourceMappingURL + // * save to disk so that upload-task picks this up + const contents = data.contents.toString('utf8'); + data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) { + return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`; + }), 'utf8'); + this.emit('data', data); + })); + }); + es.merge(...webpackStreams, es.readArray(files)) + // .pipe(es.through(function (data) { + // // debug + // console.log('out', data.path, data.contents.length); + // this.emit('data', data); + // })) + .pipe(result); + }).catch(err => { + console.error(extensionPath); + console.error(packagedDependencies); + result.emit('error', err); + }); + return result.pipe(stats_1.createStatsStream(path.basename(extensionPath))); +} +function fromLocalNormal(extensionPath) { + const result = es.through(); + vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn }) + .then(fileNames => { + const files = fileNames + .map(fileName => path.join(extensionPath, fileName)) + .map(filePath => new File({ + path: filePath, + stat: fs.statSync(filePath), + base: extensionPath, + contents: fs.createReadStream(filePath) + })); + es.readArray(files).pipe(result); + }) + .catch(err => result.emit('error', err)); + return result.pipe(stats_1.createStatsStream(path.basename(extensionPath))); +} +const baseHeaders = { + 'X-Market-Client-Id': 'VSCode Build', + 'User-Agent': 'VSCode Build', + 'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2', +}; +function fromMarketplace(extensionName, version, metadata) { + const [publisher, name] = extensionName.split('.'); + const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`; + fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); + const options = { + base: url, + requestOptions: { + gzip: true, + headers: baseHeaders + } + }; + const packageJsonFilter = filter('package.json', { restore: true }); + return remote('', options) + .pipe(vzip.src()) + .pipe(filter('extension/**')) + .pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, ''))) + .pipe(packageJsonFilter) + .pipe(buffer()) + .pipe(json({ __metadata: metadata })) + .pipe(packageJsonFilter.restore); +} +exports.fromMarketplace = fromMarketplace; +const excludedExtensions = [ + 'vscode-api-tests', + 'vscode-colorize-tests', + 'vscode-test-resolver', + 'ms-vscode.node-debug', + 'ms-vscode.node-debug2', + 'vscode-notebook-tests', + 'vscode-custom-editor-tests', +]; +const marketplaceWebExtensions = [ + 'ms-vscode.references-view' +]; +const productJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')); +const builtInExtensions = productJson.builtInExtensions || []; +const webBuiltInExtensions = productJson.webBuiltInExtensions || []; +/** + * Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionsUtil.ts` + */ +function isWebExtension(manifest) { + if (typeof manifest.extensionKind !== 'undefined') { + const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind]; + return (extensionKind.indexOf('web') >= 0); + } + return (!Boolean(manifest.main) || Boolean(manifest.browser)); +} +function packageLocalExtensionsStream(forWeb) { + const localExtensionsDescriptions = (glob.sync('extensions/*/package.json') + .map(manifestPath => { + const absoluteManifestPath = path.join(root, manifestPath); + const extensionPath = path.dirname(path.join(root, manifestPath)); + const extensionName = path.basename(extensionPath); + return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath }; + }) + .filter(({ name }) => excludedExtensions.indexOf(name) === -1) + .filter(({ name }) => builtInExtensions.every(b => b.name !== name)) + .filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true))); + const localExtensionsStream = minifyExtensionResources(es.merge(...localExtensionsDescriptions.map(extension => { + return fromLocal(extension.path, forWeb) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + }))); + let result; + if (forWeb) { + result = localExtensionsStream; + } + else { + // also include shared node modules + result = es.merge(localExtensionsStream, gulp.src('extensions/node_modules/**', { base: '.' })); + } + return (result + .pipe(util2.setExecutableBit(['**/*.sh']))); +} +exports.packageLocalExtensionsStream = packageLocalExtensionsStream; +function packageMarketplaceExtensionsStream(forWeb) { + const marketplaceExtensionsDescriptions = [ + ...builtInExtensions.filter(({ name }) => (forWeb ? marketplaceWebExtensions.indexOf(name) >= 0 : true)), + ...(forWeb ? webBuiltInExtensions : []) + ]; + const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions + .map(extension => { + const input = fromMarketplace(extension.name, extension.version, extension.metadata) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + return updateExtensionPackageJSON(input, (data) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; + return data; + }); + }))); + return (marketplaceExtensionsStream + .pipe(util2.setExecutableBit(['**/*.sh']))); +} +exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream; +function scanBuiltinExtensions(extensionsRoot, exclude = []) { + const scannedExtensions = []; + try { + const extensionsFolders = fs.readdirSync(extensionsRoot); + for (const extensionFolder of extensionsFolders) { + if (exclude.indexOf(extensionFolder) >= 0) { + continue; + } + const packageJSONPath = path.join(extensionsRoot, extensionFolder, 'package.json'); + if (!fs.existsSync(packageJSONPath)) { + continue; + } + let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8')); + if (!isWebExtension(packageJSON)) { + continue; + } + const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder)); + const packageNLSPath = children.filter(child => child === 'package.nls.json')[0]; + const packageNLS = packageNLSPath ? JSON.parse(fs.readFileSync(path.join(extensionsRoot, extensionFolder, packageNLSPath)).toString()) : undefined; + const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; + const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0]; + scannedExtensions.push({ + extensionPath: extensionFolder, + packageJSON, + packageNLS, + readmePath: readme ? path.join(extensionFolder, readme) : undefined, + changelogPath: changelog ? path.join(extensionFolder, changelog) : undefined, + }); + } + return scannedExtensions; + } + catch (ex) { + return scannedExtensions; + } +} +exports.scanBuiltinExtensions = scanBuiltinExtensions; +function translatePackageJSON(packageJSON, packageNLSPath) { + const CharCode_PC = '%'.charCodeAt(0); + const packageNls = JSON.parse(fs.readFileSync(packageNLSPath).toString()); + const translate = (obj) => { + for (let key in obj) { + const val = obj[key]; + if (Array.isArray(val)) { + val.forEach(translate); + } + else if (val && typeof val === 'object') { + translate(val); + } + else if (typeof val === 'string' && val.charCodeAt(0) === CharCode_PC && val.charCodeAt(val.length - 1) === CharCode_PC) { + const translated = packageNls[val.substr(1, val.length - 2)]; + if (translated) { + obj[key] = translated; + } + } + } + }; + translate(packageJSON); + return packageJSON; +} +exports.translatePackageJSON = translatePackageJSON; diff --git a/build/lib/git.js b/build/lib/git.js new file mode 100644 index 00000000000..1726f76fcc7 --- /dev/null +++ b/build/lib/git.js @@ -0,0 +1,54 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getVersion = void 0; +const path = require("path"); +const fs = require("fs"); +/** + * Returns the sha1 commit version of a repository or undefined in case of failure. + */ +function getVersion(repo) { + const git = path.join(repo, '.git'); + const headPath = path.join(git, 'HEAD'); + let head; + try { + head = fs.readFileSync(headPath, 'utf8').trim(); + } + catch (e) { + return undefined; + } + if (/^[0-9a-f]{40}$/i.test(head)) { + return head; + } + const refMatch = /^ref: (.*)$/.exec(head); + if (!refMatch) { + return undefined; + } + const ref = refMatch[1]; + const refPath = path.join(git, ref); + try { + return fs.readFileSync(refPath, 'utf8').trim(); + } + catch (e) { + // noop + } + const packedRefsPath = path.join(git, 'packed-refs'); + let refsRaw; + try { + refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim(); + } + catch (e) { + return undefined; + } + const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm; + let refsMatch; + let refs = {}; + while (refsMatch = refsRegex.exec(refsRaw)) { + refs[refsMatch[2]] = refsMatch[1]; + } + return refs[ref]; +} +exports.getVersion = getVersion; diff --git a/build/lib/i18n.js b/build/lib/i18n.js new file mode 100644 index 00000000000..7a529824a5a --- /dev/null +++ b/build/lib/i18n.js @@ -0,0 +1,1204 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.prepareIslFiles = exports.prepareI18nPackFiles = exports.pullI18nPackFiles = exports.prepareI18nFiles = exports.pullSetupXlfFiles = exports.pullCoreAndExtensionsXlfFiles = exports.findObsoleteResources = exports.pushXlfFiles = exports.createXlfFilesForIsl = exports.createXlfFilesForExtensions = exports.createXlfFilesForCoreBundle = exports.getResource = exports.processNlsFiles = exports.Limiter = exports.XLF = exports.Line = exports.externalExtensionsWithTranslations = exports.extraLanguages = exports.defaultLanguages = void 0; +const path = require("path"); +const fs = require("fs"); +const event_stream_1 = require("event-stream"); +const File = require("vinyl"); +const Is = require("is"); +const xml2js = require("xml2js"); +const glob = require("glob"); +const https = require("https"); +const gulp = require("gulp"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const iconv = require("iconv-lite-umd"); +const NUMBER_OF_CONCURRENT_DOWNLOADS = 4; +function log(message, ...rest) { + fancyLog(ansiColors.green('[i18n]'), message, ...rest); +} +exports.defaultLanguages = [ + { id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' }, + { id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' }, + { id: 'ja', folderName: 'jpn' }, + { id: 'ko', folderName: 'kor' }, + { id: 'de', folderName: 'deu' }, + { id: 'fr', folderName: 'fra' }, + { id: 'es', folderName: 'esn' }, + { id: 'ru', folderName: 'rus' }, + { id: 'it', folderName: 'ita' } +]; +// languages requested by the community to non-stable builds +exports.extraLanguages = [ + { id: 'pt-br', folderName: 'ptb' }, + { id: 'hu', folderName: 'hun' }, + { id: 'tr', folderName: 'trk' } +]; +// non built-in extensions also that are transifex and need to be part of the language packs +exports.externalExtensionsWithTranslations = { + 'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome', + 'vscode-node-debug': 'ms-vscode.node-debug', + 'vscode-node-debug2': 'ms-vscode.node-debug2' +}; +var LocalizeInfo; +(function (LocalizeInfo) { + function is(value) { + let candidate = value; + return Is.defined(candidate) && Is.string(candidate.key) && (Is.undef(candidate.comment) || (Is.array(candidate.comment) && candidate.comment.every(element => Is.string(element)))); + } + LocalizeInfo.is = is; +})(LocalizeInfo || (LocalizeInfo = {})); +var BundledFormat; +(function (BundledFormat) { + function is(value) { + if (Is.undef(value)) { + return false; + } + let candidate = value; + let length = Object.keys(value).length; + return length === 3 && Is.defined(candidate.keys) && Is.defined(candidate.messages) && Is.defined(candidate.bundles); + } + BundledFormat.is = is; +})(BundledFormat || (BundledFormat = {})); +var PackageJsonFormat; +(function (PackageJsonFormat) { + function is(value) { + if (Is.undef(value) || !Is.object(value)) { + return false; + } + return Object.keys(value).every(key => { + let element = value[key]; + return Is.string(element) || (Is.object(element) && Is.defined(element.message) && Is.defined(element.comment)); + }); + } + PackageJsonFormat.is = is; +})(PackageJsonFormat || (PackageJsonFormat = {})); +class Line { + constructor(indent = 0) { + this.buffer = []; + if (indent > 0) { + this.buffer.push(new Array(indent + 1).join(' ')); + } + } + append(value) { + this.buffer.push(value); + return this; + } + toString() { + return this.buffer.join(''); + } +} +exports.Line = Line; +class TextModel { + constructor(contents) { + this._lines = contents.split(/\r\n|\r|\n/); + } + get lines() { + return this._lines; + } +} +class XLF { + constructor(project) { + this.project = project; + this.buffer = []; + this.files = Object.create(null); + this.numberOfMessages = 0; + } + toString() { + this.appendHeader(); + for (let file in this.files) { + this.appendNewLine(``, 2); + for (let item of this.files[file]) { + this.addStringItem(file, item); + } + this.appendNewLine('', 2); + } + this.appendFooter(); + return this.buffer.join('\r\n'); + } + addFile(original, keys, messages) { + if (keys.length === 0) { + console.log('No keys in ' + original); + return; + } + if (keys.length !== messages.length) { + throw new Error(`Unmatching keys(${keys.length}) and messages(${messages.length}).`); + } + this.numberOfMessages += keys.length; + this.files[original] = []; + let existingKeys = new Set(); + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + let realKey; + let comment; + if (Is.string(key)) { + realKey = key; + comment = undefined; + } + else if (LocalizeInfo.is(key)) { + realKey = key.key; + if (key.comment && key.comment.length > 0) { + comment = key.comment.map(comment => encodeEntities(comment)).join('\r\n'); + } + } + if (!realKey || existingKeys.has(realKey)) { + continue; + } + existingKeys.add(realKey); + let message = encodeEntities(messages[i]); + this.files[original].push({ id: realKey, message: message, comment: comment }); + } + } + addStringItem(file, item) { + if (!item.id || item.message === undefined || item.message === null) { + throw new Error(`No item ID or value specified: ${JSON.stringify(item)}. File: ${file}`); + } + if (item.message.length === 0) { + log(`Item with id ${item.id} in file ${file} has an empty message.`); + } + this.appendNewLine(``, 4); + this.appendNewLine(`${item.message}`, 6); + if (item.comment) { + this.appendNewLine(`${item.comment}`, 6); + } + this.appendNewLine('', 4); + } + appendHeader() { + this.appendNewLine('', 0); + this.appendNewLine('', 0); + } + appendFooter() { + this.appendNewLine('', 0); + } + appendNewLine(content, indent) { + let line = new Line(indent); + line.append(content); + this.buffer.push(line.toString()); + } +} +exports.XLF = XLF; +XLF.parsePseudo = function (xlfString) { + return new Promise((resolve) => { + let parser = new xml2js.Parser(); + let files = []; + parser.parseString(xlfString, function (_err, result) { + const fileNodes = result['xliff']['file']; + fileNodes.forEach(file => { + const originalFilePath = file.$.original; + const messages = {}; + const transUnits = file.body[0]['trans-unit']; + if (transUnits) { + transUnits.forEach((unit) => { + const key = unit.$.id; + const val = pseudify(unit.source[0]['_'].toString()); + if (key && val) { + messages[key] = decodeEntities(val); + } + }); + files.push({ messages: messages, originalFilePath: originalFilePath, language: 'ps' }); + } + }); + resolve(files); + }); + }); +}; +XLF.parse = function (xlfString) { + return new Promise((resolve, reject) => { + let parser = new xml2js.Parser(); + let files = []; + parser.parseString(xlfString, function (err, result) { + if (err) { + reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`)); + } + const fileNodes = result['xliff']['file']; + if (!fileNodes) { + reject(new Error(`XLF parsing error: XLIFF file does not contain "xliff" or "file" node(s) required for parsing.`)); + } + fileNodes.forEach((file) => { + const originalFilePath = file.$.original; + if (!originalFilePath) { + reject(new Error(`XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.`)); + } + let language = file.$['target-language']; + if (!language) { + reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`)); + } + const messages = {}; + const transUnits = file.body[0]['trans-unit']; + if (transUnits) { + transUnits.forEach((unit) => { + const key = unit.$.id; + if (!unit.target) { + return; // No translation available + } + let val = unit.target[0]; + if (typeof val !== 'string') { + val = val._; + } + if (key && val) { + messages[key] = decodeEntities(val); + } + else { + reject(new Error(`XLF parsing error: XLIFF file ${originalFilePath} does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.`)); + } + }); + files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() }); + } + }); + resolve(files); + }); + }); +}; +class Limiter { + constructor(maxDegreeOfParalellism) { + this.maxDegreeOfParalellism = maxDegreeOfParalellism; + this.outstandingPromises = []; + this.runningPromises = 0; + } + queue(factory) { + return new Promise((c, e) => { + this.outstandingPromises.push({ factory, c, e }); + this.consume(); + }); + } + consume() { + while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { + const iLimitedTask = this.outstandingPromises.shift(); + this.runningPromises++; + const promise = iLimitedTask.factory(); + promise.then(iLimitedTask.c).catch(iLimitedTask.e); + promise.then(() => this.consumed()).catch(() => this.consumed()); + } + } + consumed() { + this.runningPromises--; + this.consume(); + } +} +exports.Limiter = Limiter; +function sortLanguages(languages) { + return languages.sort((a, b) => { + return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0); + }); +} +function stripComments(content) { + /** + * First capturing group matches double quoted string + * Second matches single quotes string + * Third matches block comments + * Fourth matches line comments + */ + const regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; + let result = content.replace(regexp, (match, _m1, _m2, m3, m4) => { + // Only one of m1, m2, m3, m4 matches + if (m3) { + // A block comment. Replace with nothing + return ''; + } + else if (m4) { + // A line comment. If it ends in \r?\n then keep it. + let length = m4.length; + if (length > 2 && m4[length - 1] === '\n') { + return m4[length - 2] === '\r' ? '\r\n' : '\n'; + } + else { + return ''; + } + } + else { + // We match a string + return match; + } + }); + return result; +} +function escapeCharacters(value) { + const result = []; + for (let i = 0; i < value.length; i++) { + const ch = value.charAt(i); + switch (ch) { + case '\'': + result.push('\\\''); + break; + case '"': + result.push('\\"'); + break; + case '\\': + result.push('\\\\'); + break; + case '\n': + result.push('\\n'); + break; + case '\r': + result.push('\\r'); + break; + case '\t': + result.push('\\t'); + break; + case '\b': + result.push('\\b'); + break; + case '\f': + result.push('\\f'); + break; + default: + result.push(ch); + } + } + return result.join(''); +} +function processCoreBundleFormat(fileHeader, languages, json, emitter) { + let keysSection = json.keys; + let messageSection = json.messages; + let bundleSection = json.bundles; + let statistics = Object.create(null); + let defaultMessages = Object.create(null); + let modules = Object.keys(keysSection); + modules.forEach((module) => { + let keys = keysSection[module]; + let messages = messageSection[module]; + if (!messages || keys.length !== messages.length) { + emitter.emit('error', `Message for module ${module} corrupted. Mismatch in number of keys and messages.`); + return; + } + let messageMap = Object.create(null); + defaultMessages[module] = messageMap; + keys.map((key, i) => { + if (typeof key === 'string') { + messageMap[key] = messages[i]; + } + else { + messageMap[key.key] = messages[i]; + } + }); + }); + let languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); + if (!fs.existsSync(languageDirectory)) { + log(`No VS Code localization repository found. Looking at ${languageDirectory}`); + log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + } + let sortedLanguages = sortLanguages(languages); + sortedLanguages.forEach((language) => { + if (process.env['VSCODE_BUILD_VERBOSE']) { + log(`Generating nls bundles for: ${language.id}`); + } + statistics[language.id] = 0; + let localizedModules = Object.create(null); + let languageFolderName = language.translationId || language.id; + let i18nFile = path.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json'); + let allMessages; + if (fs.existsSync(i18nFile)) { + let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); + allMessages = JSON.parse(content); + } + modules.forEach((module) => { + let order = keysSection[module]; + let moduleMessage; + if (allMessages) { + moduleMessage = allMessages.contents[module]; + } + if (!moduleMessage) { + if (process.env['VSCODE_BUILD_VERBOSE']) { + log(`No localized messages found for module ${module}. Using default messages.`); + } + moduleMessage = defaultMessages[module]; + statistics[language.id] = statistics[language.id] + Object.keys(moduleMessage).length; + } + let localizedMessages = []; + order.forEach((keyInfo) => { + let key = null; + if (typeof keyInfo === 'string') { + key = keyInfo; + } + else { + key = keyInfo.key; + } + let message = moduleMessage[key]; + if (!message) { + if (process.env['VSCODE_BUILD_VERBOSE']) { + log(`No localized message found for key ${key} in module ${module}. Using default message.`); + } + message = defaultMessages[module][key]; + statistics[language.id] = statistics[language.id] + 1; + } + localizedMessages.push(message); + }); + localizedModules[module] = localizedMessages; + }); + Object.keys(bundleSection).forEach((bundle) => { + let modules = bundleSection[bundle]; + let contents = [ + fileHeader, + `define("${bundle}.nls.${language.id}", {` + ]; + modules.forEach((module, index) => { + contents.push(`\t"${module}": [`); + let messages = localizedModules[module]; + if (!messages) { + emitter.emit('error', `Didn't find messages for module ${module}.`); + return; + } + messages.forEach((message, index) => { + contents.push(`\t\t"${escapeCharacters(message)}${index < messages.length ? '",' : '"'}`); + }); + contents.push(index < modules.length - 1 ? '\t],' : '\t]'); + }); + contents.push('});'); + emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: Buffer.from(contents.join('\n'), 'utf-8') })); + }); + }); + Object.keys(statistics).forEach(key => { + let value = statistics[key]; + log(`${key} has ${value} untranslated strings.`); + }); + sortedLanguages.forEach(language => { + let stats = statistics[language.id]; + if (Is.undef(stats)) { + log(`\tNo translations found for language ${language.id}. Using default language instead.`); + } + }); +} +function processNlsFiles(opts) { + return event_stream_1.through(function (file) { + let fileName = path.basename(file.path); + if (fileName === 'nls.metadata.json') { + let json = null; + if (file.isBuffer()) { + json = JSON.parse(file.contents.toString('utf8')); + } + else { + this.emit('error', `Failed to read component file: ${file.relative}`); + return; + } + if (BundledFormat.is(json)) { + processCoreBundleFormat(opts.fileHeader, opts.languages, json, this); + } + } + this.queue(file); + }); +} +exports.processNlsFiles = processNlsFiles; +const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup'; +function getResource(sourceFile) { + let resource; + if (/^vs\/platform/.test(sourceFile)) { + return { name: 'vs/platform', project: editorProject }; + } + else if (/^vs\/editor\/contrib/.test(sourceFile)) { + return { name: 'vs/editor/contrib', project: editorProject }; + } + else if (/^vs\/editor/.test(sourceFile)) { + return { name: 'vs/editor', project: editorProject }; + } + else if (/^vs\/base/.test(sourceFile)) { + return { name: 'vs/base', project: editorProject }; + } + else if (/^vs\/code/.test(sourceFile)) { + return { name: 'vs/code', project: workbenchProject }; + } + else if (/^vs\/workbench\/contrib/.test(sourceFile)) { + resource = sourceFile.split('/', 4).join('/'); + return { name: resource, project: workbenchProject }; + } + else if (/^vs\/workbench\/services/.test(sourceFile)) { + resource = sourceFile.split('/', 4).join('/'); + return { name: resource, project: workbenchProject }; + } + else if (/^vs\/workbench/.test(sourceFile)) { + return { name: 'vs/workbench', project: workbenchProject }; + } + throw new Error(`Could not identify the XLF bundle for ${sourceFile}`); +} +exports.getResource = getResource; +function createXlfFilesForCoreBundle() { + return event_stream_1.through(function (file) { + const basename = path.basename(file.path); + if (basename === 'nls.metadata.json') { + if (file.isBuffer()) { + const xlfs = Object.create(null); + const json = JSON.parse(file.contents.toString('utf8')); + for (let coreModule in json.keys) { + const projectResource = getResource(coreModule); + const resource = projectResource.name; + const project = projectResource.project; + const keys = json.keys[coreModule]; + const messages = json.messages[coreModule]; + if (keys.length !== messages.length) { + this.emit('error', `There is a mismatch between keys and messages in ${file.relative} for module ${coreModule}`); + return; + } + else { + let xlf = xlfs[resource]; + if (!xlf) { + xlf = new XLF(project); + xlfs[resource] = xlf; + } + xlf.addFile(`src/${coreModule}`, keys, messages); + } + } + for (let resource in xlfs) { + const xlf = xlfs[resource]; + const filePath = `${xlf.project}/${resource.replace(/\//g, '_')}.xlf`; + const xlfFile = new File({ + path: filePath, + contents: Buffer.from(xlf.toString(), 'utf8') + }); + this.queue(xlfFile); + } + } + else { + this.emit('error', new Error(`File ${file.relative} is not using a buffer content`)); + return; + } + } + else { + this.emit('error', new Error(`File ${file.relative} is not a core meta data file.`)); + return; + } + }); +} +exports.createXlfFilesForCoreBundle = createXlfFilesForCoreBundle; +function createXlfFilesForExtensions() { + let counter = 0; + let folderStreamEnded = false; + let folderStreamEndEmitted = false; + return event_stream_1.through(function (extensionFolder) { + const folderStream = this; + const stat = fs.statSync(extensionFolder.path); + if (!stat.isDirectory()) { + return; + } + let extensionName = path.basename(extensionFolder.path); + if (extensionName === 'node_modules') { + return; + } + counter++; + let _xlf; + function getXlf() { + if (!_xlf) { + _xlf = new XLF(extensionsProject); + } + return _xlf; + } + gulp.src([`.build/extensions/${extensionName}/package.nls.json`, `.build/extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe(event_stream_1.through(function (file) { + if (file.isBuffer()) { + const buffer = file.contents; + const basename = path.basename(file.path); + if (basename === 'package.nls.json') { + const json = JSON.parse(buffer.toString('utf8')); + const keys = Object.keys(json); + const messages = keys.map((key) => { + const value = json[key]; + if (Is.string(value)) { + return value; + } + else if (value) { + return value.message; + } + else { + return `Unknown message for key: ${key}`; + } + }); + getXlf().addFile(`extensions/${extensionName}/package`, keys, messages); + } + else if (basename === 'nls.metadata.json') { + const json = JSON.parse(buffer.toString('utf8')); + const relPath = path.relative(`.build/extensions/${extensionName}`, path.dirname(file.path)); + for (let file in json) { + const fileContent = json[file]; + getXlf().addFile(`extensions/${extensionName}/${relPath}/${file}`, fileContent.keys, fileContent.messages); + } + } + else { + this.emit('error', new Error(`${file.path} is not a valid extension nls file`)); + return; + } + } + }, function () { + if (_xlf) { + let xlfFile = new File({ + path: path.join(extensionsProject, extensionName + '.xlf'), + contents: Buffer.from(_xlf.toString(), 'utf8') + }); + folderStream.queue(xlfFile); + } + this.queue(null); + counter--; + if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) { + folderStreamEndEmitted = true; + folderStream.queue(null); + } + })); + }, function () { + folderStreamEnded = true; + if (counter === 0) { + folderStreamEndEmitted = true; + this.queue(null); + } + }); +} +exports.createXlfFilesForExtensions = createXlfFilesForExtensions; +function createXlfFilesForIsl() { + return event_stream_1.through(function (file) { + let projectName, resourceFile; + if (path.basename(file.path) === 'Default.isl') { + projectName = setupProject; + resourceFile = 'setup_default.xlf'; + } + else { + projectName = workbenchProject; + resourceFile = 'setup_messages.xlf'; + } + let xlf = new XLF(projectName), keys = [], messages = []; + let model = new TextModel(file.contents.toString()); + let inMessageSection = false; + model.lines.forEach(line => { + if (line.length === 0) { + return; + } + let firstChar = line.charAt(0); + switch (firstChar) { + case ';': + // Comment line; + return; + case '[': + inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; + return; + } + if (!inMessageSection) { + return; + } + let sections = line.split('='); + if (sections.length !== 2) { + throw new Error(`Badly formatted message found: ${line}`); + } + else { + let key = sections[0]; + let value = sections[1]; + if (key.length > 0 && value.length > 0) { + keys.push(key); + messages.push(value); + } + } + }); + const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/'); + xlf.addFile(originalPath, keys, messages); + // Emit only upon all ISL files combined into single XLF instance + const newFilePath = path.join(projectName, resourceFile); + const xlfFile = new File({ path: newFilePath, contents: Buffer.from(xlf.toString(), 'utf-8') }); + this.queue(xlfFile); + }); +} +exports.createXlfFilesForIsl = createXlfFilesForIsl; +function pushXlfFiles(apiHostname, username, password) { + let tryGetPromises = []; + let updateCreatePromises = []; + return event_stream_1.through(function (file) { + const project = path.dirname(file.relative); + const fileName = path.basename(file.path); + const slug = fileName.substr(0, fileName.length - '.xlf'.length); + const credentials = `${username}:${password}`; + // Check if resource already exists, if not, then create it. + let promise = tryGetResource(project, slug, apiHostname, credentials); + tryGetPromises.push(promise); + promise.then(exists => { + if (exists) { + promise = updateResource(project, slug, file, apiHostname, credentials); + } + else { + promise = createResource(project, slug, file, apiHostname, credentials); + } + updateCreatePromises.push(promise); + }); + }, function () { + // End the pipe only after all the communication with Transifex API happened + Promise.all(tryGetPromises).then(() => { + Promise.all(updateCreatePromises).then(() => { + this.queue(null); + }).catch((reason) => { throw new Error(reason); }); + }).catch((reason) => { throw new Error(reason); }); + }); +} +exports.pushXlfFiles = pushXlfFiles; +function getAllResources(project, apiHostname, username, password) { + return new Promise((resolve, reject) => { + const credentials = `${username}:${password}`; + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resources`, + auth: credentials, + method: 'GET' + }; + const request = https.request(options, (res) => { + let buffer = []; + res.on('data', (chunk) => buffer.push(chunk)); + res.on('end', () => { + if (res.statusCode === 200) { + let json = JSON.parse(Buffer.concat(buffer).toString()); + if (Array.isArray(json)) { + resolve(json.map(o => o.slug)); + return; + } + reject(`Unexpected data format. Response code: ${res.statusCode}.`); + } + else { + reject(`No resources in ${project} returned no data. Response code: ${res.statusCode}.`); + } + }); + }); + request.on('error', (err) => { + reject(`Failed to query resources in ${project} with the following error: ${err}. ${options.path}`); + }); + request.end(); + }); +} +function findObsoleteResources(apiHostname, username, password) { + let resourcesByProject = Object.create(null); + resourcesByProject[extensionsProject] = [].concat(exports.externalExtensionsWithTranslations); // clone + return event_stream_1.through(function (file) { + const project = path.dirname(file.relative); + const fileName = path.basename(file.path); + const slug = fileName.substr(0, fileName.length - '.xlf'.length); + let slugs = resourcesByProject[project]; + if (!slugs) { + resourcesByProject[project] = slugs = []; + } + slugs.push(slug); + this.push(file); + }, function () { + const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8')); + let i18Resources = [...json.editor, ...json.workbench].map((r) => r.project + '/' + r.name.replace(/\//g, '_')); + let extractedResources = []; + for (let project of [workbenchProject, editorProject]) { + for (let resource of resourcesByProject[project]) { + if (resource !== 'setup_messages') { + extractedResources.push(project + '/' + resource); + } + } + } + if (i18Resources.length !== extractedResources.length) { + console.log(`[i18n] Obsolete resources in file 'build/lib/i18n.resources.json': JSON.stringify(${i18Resources.filter(p => extractedResources.indexOf(p) === -1)})`); + console.log(`[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(${extractedResources.filter(p => i18Resources.indexOf(p) === -1)})`); + } + let promises = []; + for (let project in resourcesByProject) { + promises.push(getAllResources(project, apiHostname, username, password).then(resources => { + let expectedResources = resourcesByProject[project]; + let unusedResources = resources.filter(resource => resource && expectedResources.indexOf(resource) === -1); + if (unusedResources.length) { + console.log(`[transifex] Obsolete resources in project '${project}': ${unusedResources.join(', ')}`); + } + })); + } + return Promise.all(promises).then(_ => { + this.push(null); + }).catch((reason) => { throw new Error(reason); }); + }); +} +exports.findObsoleteResources = findObsoleteResources; +function tryGetResource(project, slug, apiHostname, credentials) { + return new Promise((resolve, reject) => { + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resource/${slug}/?details`, + auth: credentials, + method: 'GET' + }; + const request = https.request(options, (response) => { + if (response.statusCode === 404) { + resolve(false); + } + else if (response.statusCode === 200) { + resolve(true); + } + else { + reject(`Failed to query resource ${project}/${slug}. Response: ${response.statusCode} ${response.statusMessage}`); + } + }); + request.on('error', (err) => { + reject(`Failed to get ${project}/${slug} on Transifex: ${err}`); + }); + request.end(); + }); +} +function createResource(project, slug, xlfFile, apiHostname, credentials) { + return new Promise((_resolve, reject) => { + const data = JSON.stringify({ + 'content': xlfFile.contents.toString(), + 'name': slug, + 'slug': slug, + 'i18n_type': 'XLIFF' + }); + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resources`, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + }, + auth: credentials, + method: 'POST' + }; + let request = https.request(options, (res) => { + if (res.statusCode === 201) { + log(`Resource ${project}/${slug} successfully created on Transifex.`); + } + else { + reject(`Something went wrong in the request creating ${slug} in ${project}. ${res.statusCode}`); + } + }); + request.on('error', (err) => { + reject(`Failed to create ${project}/${slug} on Transifex: ${err}`); + }); + request.write(data); + request.end(); + }); +} +/** + * The following link provides information about how Transifex handles updates of a resource file: + * https://dev.befoolish.co/tx-docs/public/projects/updating-content#what-happens-when-you-update-files + */ +function updateResource(project, slug, xlfFile, apiHostname, credentials) { + return new Promise((resolve, reject) => { + const data = JSON.stringify({ content: xlfFile.contents.toString() }); + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resource/${slug}/content`, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + }, + auth: credentials, + method: 'PUT' + }; + let request = https.request(options, (res) => { + if (res.statusCode === 200) { + res.setEncoding('utf8'); + let responseBuffer = ''; + res.on('data', function (chunk) { + responseBuffer += chunk; + }); + res.on('end', () => { + const response = JSON.parse(responseBuffer); + log(`Resource ${project}/${slug} successfully updated on Transifex. Strings added: ${response.strings_added}, updated: ${response.strings_added}, deleted: ${response.strings_added}`); + resolve(); + }); + } + else { + reject(`Something went wrong in the request updating ${slug} in ${project}. ${res.statusCode}`); + } + }); + request.on('error', (err) => { + reject(`Failed to update ${project}/${slug} on Transifex: ${err}`); + }); + request.write(data); + request.end(); + }); +} +// cache resources +let _coreAndExtensionResources; +function pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language, externalExtensions) { + if (!_coreAndExtensionResources) { + _coreAndExtensionResources = []; + // editor and workbench + const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8')); + _coreAndExtensionResources.push(...json.editor); + _coreAndExtensionResources.push(...json.workbench); + // extensions + let extensionsToLocalize = Object.create(null); + glob.sync('.build/extensions/**/*.nls.json').forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); + glob.sync('.build/extensions/*/node_modules/vscode-nls').forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); + Object.keys(extensionsToLocalize).forEach(extension => { + _coreAndExtensionResources.push({ name: extension, project: extensionsProject }); + }); + if (externalExtensions) { + for (let resourceName in externalExtensions) { + _coreAndExtensionResources.push({ name: resourceName, project: extensionsProject }); + } + } + } + return pullXlfFiles(apiHostname, username, password, language, _coreAndExtensionResources); +} +exports.pullCoreAndExtensionsXlfFiles = pullCoreAndExtensionsXlfFiles; +function pullSetupXlfFiles(apiHostname, username, password, language, includeDefault) { + let setupResources = [{ name: 'setup_messages', project: workbenchProject }]; + if (includeDefault) { + setupResources.push({ name: 'setup_default', project: setupProject }); + } + return pullXlfFiles(apiHostname, username, password, language, setupResources); +} +exports.pullSetupXlfFiles = pullSetupXlfFiles; +function pullXlfFiles(apiHostname, username, password, language, resources) { + const credentials = `${username}:${password}`; + let expectedTranslationsCount = resources.length; + let translationsRetrieved = 0, called = false; + return event_stream_1.readable(function (_count, callback) { + // Mark end of stream when all resources were retrieved + if (translationsRetrieved === expectedTranslationsCount) { + return this.emit('end'); + } + if (!called) { + called = true; + const stream = this; + resources.map(function (resource) { + retrieveResource(language, resource, apiHostname, credentials).then((file) => { + if (file) { + stream.emit('data', file); + } + translationsRetrieved++; + }).catch(error => { throw new Error(error); }); + }); + } + callback(); + }); +} +const limiter = new Limiter(NUMBER_OF_CONCURRENT_DOWNLOADS); +function retrieveResource(language, resource, apiHostname, credentials) { + return limiter.queue(() => new Promise((resolve, reject) => { + const slug = resource.name.replace(/\//g, '_'); + const project = resource.project; + let transifexLanguageId = language.id === 'ps' ? 'en' : language.translationId || language.id; + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`, + auth: credentials, + port: 443, + method: 'GET' + }; + console.log('[transifex] Fetching ' + options.path); + let request = https.request(options, (res) => { + let xlfBuffer = []; + res.on('data', (chunk) => xlfBuffer.push(chunk)); + res.on('end', () => { + if (res.statusCode === 200) { + resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${slug}.xlf` })); + } + else if (res.statusCode === 404) { + console.log(`[transifex] ${slug} in ${project} returned no data.`); + resolve(null); + } + else { + reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`); + } + }); + }); + request.on('error', (err) => { + reject(`Failed to query resource ${slug} with the following error: ${err}. ${options.path}`); + }); + request.end(); + })); +} +function prepareI18nFiles() { + let parsePromises = []; + return event_stream_1.through(function (xlf) { + let stream = this; + let parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then(resolvedFiles => { + resolvedFiles.forEach(file => { + let translatedFile = createI18nFile(file.originalFilePath, file.messages); + stream.queue(translatedFile); + }); + }); + }, function () { + Promise.all(parsePromises) + .then(() => { this.queue(null); }) + .catch(reason => { throw new Error(reason); }); + }); +} +exports.prepareI18nFiles = prepareI18nFiles; +function createI18nFile(originalFilePath, messages) { + let result = Object.create(null); + result[''] = [ + '--------------------------------------------------------------------------------------------', + 'Copyright (c) Microsoft Corporation. All rights reserved.', + 'Licensed under the MIT License. See License.txt in the project root for license information.', + '--------------------------------------------------------------------------------------------', + 'Do not edit this file. It is machine generated.' + ]; + for (let key of Object.keys(messages)) { + result[key] = messages[key]; + } + let content = JSON.stringify(result, null, '\t'); + if (process.platform === 'win32') { + content = content.replace(/\n/g, '\r\n'); + } + return new File({ + path: path.join(originalFilePath + '.i18n.json'), + contents: Buffer.from(content, 'utf8') + }); +} +const i18nPackVersion = '1.0.0'; +function pullI18nPackFiles(apiHostname, username, password, language, resultingTranslationPaths) { + return pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language, exports.externalExtensionsWithTranslations) + .pipe(prepareI18nPackFiles(exports.externalExtensionsWithTranslations, resultingTranslationPaths, language.id === 'ps')); +} +exports.pullI18nPackFiles = pullI18nPackFiles; +function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pseudo = false) { + let parsePromises = []; + let mainPack = { version: i18nPackVersion, contents: {} }; + let extensionsPacks = {}; + let errors = []; + return event_stream_1.through(function (xlf) { + let project = path.basename(path.dirname(xlf.relative)); + let resource = path.basename(xlf.relative, '.xlf'); + let contents = xlf.contents.toString(); + let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents); + parsePromises.push(parsePromise); + parsePromise.then(resolvedFiles => { + resolvedFiles.forEach(file => { + const path = file.originalFilePath; + const firstSlash = path.indexOf('/'); + if (project === extensionsProject) { + let extPack = extensionsPacks[resource]; + if (!extPack) { + extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} }; + } + const externalId = externalExtensions[resource]; + if (!externalId) { // internal extension: remove 'extensions/extensionId/' segnent + const secondSlash = path.indexOf('/', firstSlash + 1); + extPack.contents[path.substr(secondSlash + 1)] = file.messages; + } + else { + extPack.contents[path] = file.messages; + } + } + else { + mainPack.contents[path.substr(firstSlash + 1)] = file.messages; + } + }); + }).catch(reason => { + errors.push(reason); + }); + }, function () { + Promise.all(parsePromises) + .then(() => { + if (errors.length > 0) { + throw errors; + } + const translatedMainFile = createI18nFile('./main', mainPack); + resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' }); + this.queue(translatedMainFile); + for (let extension in extensionsPacks) { + const translatedExtFile = createI18nFile(`extensions/${extension}`, extensionsPacks[extension]); + this.queue(translatedExtFile); + const externalExtensionId = externalExtensions[extension]; + if (externalExtensionId) { + resultingTranslationPaths.push({ id: externalExtensionId, resourceName: `extensions/${extension}.i18n.json` }); + } + else { + resultingTranslationPaths.push({ id: `vscode.${extension}`, resourceName: `extensions/${extension}.i18n.json` }); + } + } + this.queue(null); + }) + .catch((reason) => { + this.emit('error', reason); + }); + }); +} +exports.prepareI18nPackFiles = prepareI18nPackFiles; +function prepareIslFiles(language, innoSetupConfig) { + let parsePromises = []; + return event_stream_1.through(function (xlf) { + let stream = this; + let parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then(resolvedFiles => { + resolvedFiles.forEach(file => { + if (path.basename(file.originalFilePath) === 'Default' && !innoSetupConfig.defaultInfo) { + return; + } + let translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig); + stream.queue(translatedFile); + }); + }).catch(reason => { + this.emit('error', reason); + }); + }, function () { + Promise.all(parsePromises) + .then(() => { this.queue(null); }) + .catch(reason => { + this.emit('error', reason); + }); + }); +} +exports.prepareIslFiles = prepareIslFiles; +function createIslFile(originalFilePath, messages, language, innoSetup) { + let content = []; + let originalContent; + if (path.basename(originalFilePath) === 'Default') { + originalContent = new TextModel(fs.readFileSync(originalFilePath + '.isl', 'utf8')); + } + else { + originalContent = new TextModel(fs.readFileSync(originalFilePath + '.en.isl', 'utf8')); + } + originalContent.lines.forEach(line => { + if (line.length > 0) { + let firstChar = line.charAt(0); + if (firstChar === '[' || firstChar === ';') { + content.push(line); + } + else { + let sections = line.split('='); + let key = sections[0]; + let translated = line; + if (key) { + if (key === 'LanguageName') { + translated = `${key}=${innoSetup.defaultInfo.name}`; + } + else if (key === 'LanguageID') { + translated = `${key}=${innoSetup.defaultInfo.id}`; + } + else if (key === 'LanguageCodePage') { + translated = `${key}=${innoSetup.codePage.substr(2)}`; + } + else { + let translatedMessage = messages[key]; + if (translatedMessage) { + translated = `${key}=${translatedMessage}`; + } + } + } + content.push(translated); + } + } + }); + const basename = path.basename(originalFilePath); + const filePath = `${basename}.${language.id}.isl`; + const encoded = iconv.encode(Buffer.from(content.join('\r\n'), 'utf8').toString(), innoSetup.codePage); + return new File({ + path: filePath, + contents: Buffer.from(encoded), + }); +} +function encodeEntities(value) { + let result = []; + for (let i = 0; i < value.length; i++) { + let ch = value[i]; + switch (ch) { + case '<': + result.push('<'); + break; + case '>': + result.push('>'); + break; + case '&': + result.push('&'); + break; + default: + result.push(ch); + } + } + return result.join(''); +} +function decodeEntities(value) { + return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); +} +function pseudify(message) { + return '\uFF3B' + message.replace(/[aouei]/g, '$&$&') + '\uFF3D'; +} diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js new file mode 100644 index 00000000000..9ef9dc5914d --- /dev/null +++ b/build/lib/layersChecker.js @@ -0,0 +1,283 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const ts = require("typescript"); +const fs_1 = require("fs"); +const path_1 = require("path"); +const minimatch_1 = require("minimatch"); +// +// ############################################################################################# +// +// A custom typescript checker for the specific task of detecting the use of certain types in a +// layer that does not allow such use. For example: +// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement) +// - using node.js globals in common/browser layer (e.g. process) +// +// Make changes to below RULES to lift certain files from these checks only if absolutely needed +// +// ############################################################################################# +// +// Types we assume are present in all implementations of JS VMs (node.js, browsers) +// Feel free to add more core types as you see needed if present in node.js and browsers +const CORE_TYPES = [ + 'require', + 'setTimeout', + 'clearTimeout', + 'setInterval', + 'clearInterval', + 'console', + 'log', + 'info', + 'warn', + 'error', + 'group', + 'groupEnd', + 'table', + 'assert', + 'Error', + 'String', + 'throws', + 'stack', + 'captureStackTrace', + 'stackTraceLimit', + 'TextDecoder', + 'TextEncoder', + 'encode', + 'decode', + 'self', + 'trimLeft', + 'trimRight' +]; +// Types that are defined in a common layer but are known to be only +// available in native environments should not be allowed in browser +const NATIVE_TYPES = [ + 'NativeParsedArgs', + 'INativeEnvironmentService', + 'INativeWindowConfiguration', + 'ICommonNativeHostService' +]; +const RULES = [ + // Tests: skip + { + target: '**/vs/**/test/**', + skip: true // -> skip all test files + }, + // Common: vs/base/common/platform.ts + { + target: '**/vs/base/common/platform.ts', + allowedTypes: [ + ...CORE_TYPES, + // Safe access to postMessage() and friends + 'MessageEvent', + 'data' + ], + disallowedTypes: NATIVE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common: vs/platform/environment/common/argv.ts + { + target: '**/vs/platform/environment/common/argv.ts', + disallowedTypes: [ /* Ignore native types that are defined from here */], + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common: vs/platform/environment/common/environment.ts + { + target: '**/vs/platform/environment/common/environment.ts', + disallowedTypes: [ /* Ignore native types that are defined from here */], + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common: vs/platform/windows/common/windows.ts + { + target: '**/vs/platform/windows/common/windows.ts', + disallowedTypes: [ /* Ignore native types that are defined from here */], + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common: vs/platform/native/common/native.ts + { + target: '**/vs/platform/native/common/native.ts', + disallowedTypes: [ /* Ignore native types that are defined from here */], + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common: vs/workbench/api/common/extHostExtensionService.ts + { + target: '**/vs/workbench/api/common/extHostExtensionService.ts', + allowedTypes: [ + ...CORE_TYPES, + // Safe access to global + 'global' + ], + disallowedTypes: NATIVE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Common + { + target: '**/vs/**/common/**', + allowedTypes: CORE_TYPES, + disallowedTypes: NATIVE_TYPES, + disallowedDefinitions: [ + 'lib.dom.d.ts', + '@types/node' // no node.js + ] + }, + // Browser + { + target: '**/vs/**/browser/**', + allowedTypes: CORE_TYPES, + disallowedTypes: NATIVE_TYPES, + disallowedDefinitions: [ + '@types/node' // no node.js + ] + }, + // Browser (editor contrib) + { + target: '**/src/vs/editor/contrib/**', + allowedTypes: CORE_TYPES, + disallowedTypes: NATIVE_TYPES, + disallowedDefinitions: [ + '@types/node' // no node.js + ] + }, + // node.js + { + target: '**/vs/**/node/**', + allowedTypes: [ + ...CORE_TYPES, + // --> types from node.d.ts that duplicate from lib.dom.d.ts + 'URL', + 'protocol', + 'hostname', + 'port', + 'pathname', + 'search', + 'username', + 'password' + ], + disallowedDefinitions: [ + 'lib.dom.d.ts' // no DOM + ] + }, + // Electron (sandbox) + { + target: '**/vs/**/electron-sandbox/**', + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + '@types/node' // no node.js + ] + }, + // Electron (renderer): skip + { + target: '**/vs/**/electron-browser/**', + skip: true // -> supports all types + }, + // Electron (main) + { + target: '**/vs/**/electron-main/**', + allowedTypes: [ + ...CORE_TYPES, + // --> types from electron.d.ts that duplicate from lib.dom.d.ts + 'Event', + 'Request' + ], + disallowedDefinitions: [ + 'lib.dom.d.ts' // no DOM + ] + } +]; +const TS_CONFIG_PATH = path_1.join(__dirname, '../../', 'src', 'tsconfig.json'); +let hasErrors = false; +function checkFile(program, sourceFile, rule) { + checkNode(sourceFile); + function checkNode(node) { + var _a, _b; + if (node.kind !== ts.SyntaxKind.Identifier) { + return ts.forEachChild(node, checkNode); // recurse down + } + const text = node.getText(sourceFile); + if ((_a = rule.allowedTypes) === null || _a === void 0 ? void 0 : _a.some(allowed => allowed === text)) { + return; // override + } + if ((_b = rule.disallowedTypes) === null || _b === void 0 ? void 0 : _b.some(disallowed => disallowed === text)) { + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); + console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`); + hasErrors = true; + return; + } + const checker = program.getTypeChecker(); + const symbol = checker.getSymbolAtLocation(node); + if (symbol) { + const declarations = symbol.declarations; + if (Array.isArray(declarations)) { + for (const declaration of declarations) { + if (declaration) { + const parent = declaration.parent; + if (parent) { + const parentSourceFile = parent.getSourceFile(); + if (parentSourceFile) { + const definitionFileName = parentSourceFile.fileName; + if (rule.disallowedDefinitions) { + for (const disallowedDefinition of rule.disallowedDefinitions) { + if (definitionFileName.indexOf(disallowedDefinition) >= 0) { + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); + console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' from '${disallowedDefinition}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`); + hasErrors = true; + return; + } + } + } + } + } + } + } + } + } + } +} +function createProgram(tsconfigPath) { + const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + const configHostParser = { fileExists: fs_1.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs_1.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' }; + const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path_1.resolve(path_1.dirname(tsconfigPath)), { noEmit: true }); + const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true); + return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost); +} +// +// Create program and start checking +// +const program = createProgram(TS_CONFIG_PATH); +for (const sourceFile of program.getSourceFiles()) { + for (const rule of RULES) { + if (minimatch_1.match([sourceFile.fileName], rule.target).length > 0) { + if (!rule.skip) { + checkFile(program, sourceFile, rule); + } + break; + } + } +} +if (hasErrors) { + process.exit(1); +} diff --git a/build/lib/monaco-api.js b/build/lib/monaco-api.js new file mode 100644 index 00000000000..dcd6ac26fe3 --- /dev/null +++ b/build/lib/monaco-api.js @@ -0,0 +1,627 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.execute = exports.run3 = exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0; +const fs = require("fs"); +const ts = require("typescript"); +const path = require("path"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const dtsv = '3'; +const tsfmt = require('../../tsfmt.json'); +const SRC = path.join(__dirname, '../../src'); +exports.RECIPE_PATH = path.join(__dirname, '../monaco/monaco.d.ts.recipe'); +const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts'); +function logErr(message, ...rest) { + fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest); +} +function isDeclaration(a) { + return (a.kind === ts.SyntaxKind.InterfaceDeclaration + || a.kind === ts.SyntaxKind.EnumDeclaration + || a.kind === ts.SyntaxKind.ClassDeclaration + || a.kind === ts.SyntaxKind.TypeAliasDeclaration + || a.kind === ts.SyntaxKind.FunctionDeclaration + || a.kind === ts.SyntaxKind.ModuleDeclaration); +} +function visitTopLevelDeclarations(sourceFile, visitor) { + let stop = false; + let visit = (node) => { + if (stop) { + return; + } + switch (node.kind) { + case ts.SyntaxKind.InterfaceDeclaration: + case ts.SyntaxKind.EnumDeclaration: + case ts.SyntaxKind.ClassDeclaration: + case ts.SyntaxKind.VariableStatement: + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.FunctionDeclaration: + case ts.SyntaxKind.ModuleDeclaration: + stop = visitor(node); + } + if (stop) { + return; + } + ts.forEachChild(node, visit); + }; + visit(sourceFile); +} +function getAllTopLevelDeclarations(sourceFile) { + let all = []; + visitTopLevelDeclarations(sourceFile, (node) => { + if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) { + let interfaceDeclaration = node; + let triviaStart = interfaceDeclaration.pos; + let triviaEnd = interfaceDeclaration.name.pos; + let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd }); + if (triviaText.indexOf('@internal') === -1) { + all.push(node); + } + } + else { + let nodeText = getNodeText(sourceFile, node); + if (nodeText.indexOf('@internal') === -1) { + all.push(node); + } + } + return false /*continue*/; + }); + return all; +} +function getTopLevelDeclaration(sourceFile, typeName) { + let result = null; + visitTopLevelDeclarations(sourceFile, (node) => { + if (isDeclaration(node) && node.name) { + if (node.name.text === typeName) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + } + // node is ts.VariableStatement + if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + }); + return result; +} +function getNodeText(sourceFile, node) { + return sourceFile.getFullText().substring(node.pos, node.end); +} +function hasModifier(modifiers, kind) { + if (modifiers) { + for (let i = 0; i < modifiers.length; i++) { + let mod = modifiers[i]; + if (mod.kind === kind) { + return true; + } + } + } + return false; +} +function isStatic(member) { + return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword); +} +function isDefaultExport(declaration) { + return (hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword) + && hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword)); +} +function getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums) { + let result = getNodeText(sourceFile, declaration); + if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) { + let interfaceDeclaration = declaration; + const staticTypeName = (isDefaultExport(interfaceDeclaration) + ? `${importName}.default` + : `${importName}.${declaration.name.text}`); + let instanceTypeName = staticTypeName; + const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0); + if (typeParametersCnt > 0) { + let arr = []; + for (let i = 0; i < typeParametersCnt; i++) { + arr.push('any'); + } + instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`; + } + const members = interfaceDeclaration.members; + members.forEach((member) => { + try { + let memberText = getNodeText(sourceFile, member); + if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) { + result = result.replace(memberText, ''); + } + else { + const memberName = member.name.text; + const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`); + if (isStatic(member)) { + usage.push(`a = ${staticTypeName}${memberAccess};`); + } + else { + usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`); + } + } + } + catch (err) { + // life.. + } + }); + } + else if (declaration.kind === ts.SyntaxKind.VariableStatement) { + const jsDoc = result.substr(0, declaration.getLeadingTriviaWidth(sourceFile)); + if (jsDoc.indexOf('@monacodtsreplace') >= 0) { + const jsDocLines = jsDoc.split(/\r\n|\r|\n/); + let directives = []; + for (const jsDocLine of jsDocLines) { + const m = jsDocLine.match(/^\s*\* \/([^/]+)\/([^/]+)\/$/); + if (m) { + directives.push([new RegExp(m[1], 'g'), m[2]]); + } + } + // remove the jsdoc + result = result.substr(jsDoc.length); + if (directives.length > 0) { + // apply replace directives + const replacer = createReplacerFromDirectives(directives); + result = replacer(result); + } + } + } + result = result.replace(/export default /g, 'export '); + result = result.replace(/export declare /g, 'export '); + result = result.replace(/declare /g, ''); + let lines = result.split(/\r\n|\r|\n/); + for (let i = 0; i < lines.length; i++) { + if (/\s*\*/.test(lines[i])) { + // very likely a comment + continue; + } + lines[i] = lines[i].replace(/"/g, '\''); + } + result = lines.join('\n'); + if (declaration.kind === ts.SyntaxKind.EnumDeclaration) { + result = result.replace(/const enum/, 'enum'); + enums.push({ + enumName: declaration.name.getText(sourceFile), + text: result + }); + } + return result; +} +function format(text, endl) { + const REALLY_FORMAT = false; + text = preformat(text, endl); + if (!REALLY_FORMAT) { + return text; + } + // Parse the source text + let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true); + // Get the formatting edits on the input sources + let edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt); + // Apply the edits on the input code + return applyEdits(text, edits); + function countParensCurly(text) { + let cnt = 0; + for (let i = 0; i < text.length; i++) { + if (text.charAt(i) === '(' || text.charAt(i) === '{') { + cnt++; + } + if (text.charAt(i) === ')' || text.charAt(i) === '}') { + cnt--; + } + } + return cnt; + } + function repeatStr(s, cnt) { + let r = ''; + for (let i = 0; i < cnt; i++) { + r += s; + } + return r; + } + function preformat(text, endl) { + let lines = text.split(endl); + let inComment = false; + let inCommentDeltaIndent = 0; + let indent = 0; + for (let i = 0; i < lines.length; i++) { + let line = lines[i].replace(/\s$/, ''); + let repeat = false; + let lineIndent = 0; + do { + repeat = false; + if (line.substring(0, 4) === ' ') { + line = line.substring(4); + lineIndent++; + repeat = true; + } + if (line.charAt(0) === '\t') { + line = line.substring(1); + lineIndent++; + repeat = true; + } + } while (repeat); + if (line.length === 0) { + continue; + } + if (inComment) { + if (/\*\//.test(line)) { + inComment = false; + } + lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line; + continue; + } + if (/\/\*/.test(line)) { + inComment = true; + inCommentDeltaIndent = indent - lineIndent; + lines[i] = repeatStr('\t', indent) + line; + continue; + } + const cnt = countParensCurly(line); + let shouldUnindentAfter = false; + let shouldUnindentBefore = false; + if (cnt < 0) { + if (/[({]/.test(line)) { + shouldUnindentAfter = true; + } + else { + shouldUnindentBefore = true; + } + } + else if (cnt === 0) { + shouldUnindentBefore = /^\}/.test(line); + } + let shouldIndentAfter = false; + if (cnt > 0) { + shouldIndentAfter = true; + } + else if (cnt === 0) { + shouldIndentAfter = /{$/.test(line); + } + if (shouldUnindentBefore) { + indent--; + } + lines[i] = repeatStr('\t', indent) + line; + if (shouldUnindentAfter) { + indent--; + } + if (shouldIndentAfter) { + indent++; + } + } + return lines.join(endl); + } + function getRuleProvider(options) { + // Share this between multiple formatters using the same options. + // This represents the bulk of the space the formatter uses. + return ts.formatting.getFormatContext(options); + } + function applyEdits(text, edits) { + // Apply edits in reverse on the existing text + let result = text; + for (let i = edits.length - 1; i >= 0; i--) { + let change = edits[i]; + let head = result.slice(0, change.span.start); + let tail = result.slice(change.span.start + change.span.length); + result = head + change.newText + tail; + } + return result; + } +} +function createReplacerFromDirectives(directives) { + return (str) => { + for (let i = 0; i < directives.length; i++) { + str = str.replace(directives[i][0], directives[i][1]); + } + return str; + }; +} +function createReplacer(data) { + data = data || ''; + let rawDirectives = data.split(';'); + let directives = []; + rawDirectives.forEach((rawDirective) => { + if (rawDirective.length === 0) { + return; + } + let pieces = rawDirective.split('=>'); + let findStr = pieces[0]; + let replaceStr = pieces[1]; + findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&'); + findStr = '\\b' + findStr + '\\b'; + directives.push([new RegExp(findStr, 'g'), replaceStr]); + }); + return createReplacerFromDirectives(directives); +} +function generateDeclarationFile(recipe, sourceFileGetter) { + const endl = /\r\n/.test(recipe) ? '\r\n' : '\n'; + let lines = recipe.split(endl); + let result = []; + let usageCounter = 0; + let usageImports = []; + let usage = []; + let failed = false; + usage.push(`var a: any;`); + usage.push(`var b: any;`); + const generateUsageImport = (moduleId) => { + let importName = 'm' + (++usageCounter); + usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`); + return importName; + }; + let enums = []; + let version = null; + lines.forEach(line => { + if (failed) { + return; + } + let m0 = line.match(/^\/\/dtsv=(\d+)$/); + if (m0) { + version = m0[1]; + } + let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/); + if (m1) { + let moduleId = m1[1]; + const sourceFile = sourceFileGetter(moduleId); + if (!sourceFile) { + logErr(`While handling ${line}`); + logErr(`Cannot find ${moduleId}`); + failed = true; + return; + } + const importName = generateUsageImport(moduleId); + let replacer = createReplacer(m1[2]); + let typeNames = m1[3].split(/,/); + typeNames.forEach((typeName) => { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + let declaration = getTopLevelDeclaration(sourceFile, typeName); + if (!declaration) { + logErr(`While handling ${line}`); + logErr(`Cannot find ${typeName}`); + failed = true; + return; + } + result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums))); + }); + return; + } + let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/); + if (m2) { + let moduleId = m2[1]; + const sourceFile = sourceFileGetter(moduleId); + if (!sourceFile) { + logErr(`While handling ${line}`); + logErr(`Cannot find ${moduleId}`); + failed = true; + return; + } + const importName = generateUsageImport(moduleId); + let replacer = createReplacer(m2[2]); + let typeNames = m2[3].split(/,/); + let typesToExcludeMap = {}; + let typesToExcludeArr = []; + typeNames.forEach((typeName) => { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + typesToExcludeMap[typeName] = true; + typesToExcludeArr.push(typeName); + }); + getAllTopLevelDeclarations(sourceFile).forEach((declaration) => { + if (isDeclaration(declaration) && declaration.name) { + if (typesToExcludeMap[declaration.name.text]) { + return; + } + } + else { + // node is ts.VariableStatement + let nodeText = getNodeText(sourceFile, declaration); + for (let i = 0; i < typesToExcludeArr.length; i++) { + if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) { + return; + } + } + } + result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums))); + }); + return; + } + result.push(line); + }); + if (failed) { + return null; + } + if (version !== dtsv) { + if (!version) { + logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`); + } + else { + logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`); + } + return null; + } + let resultTxt = result.join(endl); + resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri'); + resultTxt = resultTxt.replace(/\bEvent { + if (e1.enumName < e2.enumName) { + return -1; + } + if (e1.enumName > e2.enumName) { + return 1; + } + return 0; + }); + let resultEnums = [ + '/*---------------------------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * Licensed under the MIT License. See License.txt in the project root for license information.', + ' *--------------------------------------------------------------------------------------------*/', + '', + '// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.', + '' + ].concat(enums.map(e => e.text)).join(endl); + resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl); + resultEnums = format(resultEnums, endl); + resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl); + return { + result: resultTxt, + usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`, + enums: resultEnums + }; +} +function _run(sourceFileGetter) { + const recipe = fs.readFileSync(exports.RECIPE_PATH).toString(); + const t = generateDeclarationFile(recipe, sourceFileGetter); + if (!t) { + return null; + } + const result = t.result; + const usageContent = t.usageContent; + const enums = t.enums; + const currentContent = fs.readFileSync(DECLARATION_PATH).toString(); + const one = currentContent.replace(/\r\n/gm, '\n'); + const other = result.replace(/\r\n/gm, '\n'); + const isTheSame = (one === other); + return { + content: result, + usageContent: usageContent, + enums: enums, + filePath: DECLARATION_PATH, + isTheSame + }; +} +class FSProvider { + existsSync(filePath) { + return fs.existsSync(filePath); + } + statSync(filePath) { + return fs.statSync(filePath); + } + readFileSync(_moduleId, filePath) { + return fs.readFileSync(filePath); + } +} +exports.FSProvider = FSProvider; +class CacheEntry { + constructor(sourceFile, mtime) { + this.sourceFile = sourceFile; + this.mtime = mtime; + } +} +class DeclarationResolver { + constructor(_fsProvider) { + this._fsProvider = _fsProvider; + this._sourceFileCache = Object.create(null); + } + invalidateCache(moduleId) { + this._sourceFileCache[moduleId] = null; + } + getDeclarationSourceFile(moduleId) { + if (this._sourceFileCache[moduleId]) { + // Since we cannot trust file watching to invalidate the cache, check also the mtime + const fileName = this._getFileName(moduleId); + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (this._sourceFileCache[moduleId].mtime !== mtime) { + this._sourceFileCache[moduleId] = null; + } + } + if (!this._sourceFileCache[moduleId]) { + this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId); + } + return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null; + } + _getFileName(moduleId) { + if (/\.d\.ts$/.test(moduleId)) { + return path.join(SRC, moduleId); + } + return path.join(SRC, `${moduleId}.ts`); + } + _getDeclarationSourceFile(moduleId) { + const fileName = this._getFileName(moduleId); + if (!this._fsProvider.existsSync(fileName)) { + return null; + } + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (/\.d\.ts$/.test(moduleId)) { + // const mtime = this._fsProvider.statFileSync() + const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); + return new CacheEntry(ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), mtime); + } + const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); + const fileMap = { + 'file.ts': fileContents + }; + const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {})); + const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text; + return new CacheEntry(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), mtime); + } +} +exports.DeclarationResolver = DeclarationResolver; +function run3(resolver) { + const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId); + return _run(sourceFileGetter); +} +exports.run3 = run3; +class TypeScriptLanguageServiceHost { + constructor(libs, files, compilerOptions) { + this._libs = libs; + this._files = files; + this._compilerOptions = compilerOptions; + } + // --- language service host --------------- + getCompilationSettings() { + return this._compilerOptions; + } + getScriptFileNames() { + return ([] + .concat(Object.keys(this._libs)) + .concat(Object.keys(this._files))); + } + getScriptVersion(_fileName) { + return '1'; + } + getProjectVersion() { + return '1'; + } + getScriptSnapshot(fileName) { + if (this._files.hasOwnProperty(fileName)) { + return ts.ScriptSnapshot.fromString(this._files[fileName]); + } + else if (this._libs.hasOwnProperty(fileName)) { + return ts.ScriptSnapshot.fromString(this._libs[fileName]); + } + else { + return ts.ScriptSnapshot.fromString(''); + } + } + getScriptKind(_fileName) { + return ts.ScriptKind.TS; + } + getCurrentDirectory() { + return ''; + } + getDefaultLibFileName(_options) { + return 'defaultLib:es5'; + } + isDefaultLibFileName(fileName) { + return fileName === this.getDefaultLibFileName(this._compilerOptions); + } +} +function execute() { + let r = run3(new DeclarationResolver(new FSProvider())); + if (!r) { + throw new Error(`monaco.d.ts generation error - Cannot continue`); + } + return r; +} +exports.execute = execute; diff --git a/build/lib/nls.js b/build/lib/nls.js new file mode 100644 index 00000000000..3807e90a612 --- /dev/null +++ b/build/lib/nls.js @@ -0,0 +1,354 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const ts = require("typescript"); +const lazy = require("lazy.js"); +const event_stream_1 = require("event-stream"); +const File = require("vinyl"); +const sm = require("source-map"); +const path = require("path"); +var CollectStepResult; +(function (CollectStepResult) { + CollectStepResult[CollectStepResult["Yes"] = 0] = "Yes"; + CollectStepResult[CollectStepResult["YesAndRecurse"] = 1] = "YesAndRecurse"; + CollectStepResult[CollectStepResult["No"] = 2] = "No"; + CollectStepResult[CollectStepResult["NoAndRecurse"] = 3] = "NoAndRecurse"; +})(CollectStepResult || (CollectStepResult = {})); +function collect(node, fn) { + const result = []; + function loop(node) { + const stepResult = fn(node); + if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) { + result.push(node); + } + if (stepResult === CollectStepResult.YesAndRecurse || stepResult === CollectStepResult.NoAndRecurse) { + ts.forEachChild(node, loop); + } + } + loop(node); + return result; +} +function clone(object) { + const result = {}; + for (const id in object) { + result[id] = object[id]; + } + return result; +} +function template(lines) { + let indent = '', wrap = ''; + if (lines.length > 1) { + indent = '\t'; + wrap = '\n'; + } + return `/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ +define([], [${wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`; +} +/** + * Returns a stream containing the patched JavaScript and source maps. + */ +function nls() { + const input = event_stream_1.through(); + const output = input.pipe(event_stream_1.through(function (f) { + if (!f.sourceMap) { + return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`)); + } + let source = f.sourceMap.sources[0]; + if (!source) { + return this.emit('error', new Error(`File ${f.relative} does not have a source in the source map.`)); + } + const root = f.sourceMap.sourceRoot; + if (root) { + source = path.join(root, source); + } + const typescript = f.sourceMap.sourcesContent[0]; + if (!typescript) { + return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`)); + } + nls.patchFiles(f, typescript).forEach(f => this.emit('data', f)); + })); + return event_stream_1.duplex(input, output); +} +function isImportNode(node) { + return node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration; +} +(function (nls_1) { + function fileFrom(file, contents, path = file.path) { + return new File({ + contents: Buffer.from(contents), + base: file.base, + cwd: file.cwd, + path: path + }); + } + nls_1.fileFrom = fileFrom; + function mappedPositionFrom(source, lc) { + return { source, line: lc.line + 1, column: lc.character }; + } + nls_1.mappedPositionFrom = mappedPositionFrom; + function lcFrom(position) { + return { line: position.line - 1, character: position.column }; + } + nls_1.lcFrom = lcFrom; + class SingleFileServiceHost { + constructor(options, filename, contents) { + this.options = options; + this.filename = filename; + this.getCompilationSettings = () => this.options; + this.getScriptFileNames = () => [this.filename]; + this.getScriptVersion = () => '1'; + this.getScriptSnapshot = (name) => name === this.filename ? this.file : this.lib; + this.getCurrentDirectory = () => ''; + this.getDefaultLibFileName = () => 'lib.d.ts'; + this.file = ts.ScriptSnapshot.fromString(contents); + this.lib = ts.ScriptSnapshot.fromString(''); + } + } + nls_1.SingleFileServiceHost = SingleFileServiceHost; + function isCallExpressionWithinTextSpanCollectStep(textSpan, node) { + if (!ts.textSpanContainsTextSpan({ start: node.pos, length: node.end - node.pos }, textSpan)) { + return CollectStepResult.No; + } + return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse; + } + function analyze(contents, options = {}) { + const filename = 'file.ts'; + const serviceHost = new SingleFileServiceHost(Object.assign(clone(options), { noResolve: true }), filename, contents); + const service = ts.createLanguageService(serviceHost); + const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true); + // all imports + const imports = lazy(collect(sourceFile, n => isImportNode(n) ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse)); + // import nls = require('vs/nls'); + const importEqualsDeclarations = imports + .filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration) + .map(n => n) + .filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) + .filter(d => d.moduleReference.expression.getText() === '\'vs/nls\''); + // import ... from 'vs/nls'; + const importDeclarations = imports + .filter(n => n.kind === ts.SyntaxKind.ImportDeclaration) + .map(n => n) + .filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) + .filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'') + .filter(d => !!d.importClause && !!d.importClause.namedBindings); + const nlsExpressions = importEqualsDeclarations + .map(d => d.moduleReference.expression) + .concat(importDeclarations.map(d => d.moduleSpecifier)) + .map(d => ({ + start: ts.getLineAndCharacterOfPosition(sourceFile, d.getStart()), + end: ts.getLineAndCharacterOfPosition(sourceFile, d.getEnd()) + })); + // `nls.localize(...)` calls + const nlsLocalizeCallExpressions = importDeclarations + .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport)) + .map(d => d.importClause.namedBindings.name) + .concat(importEqualsDeclarations.map(d => d.name)) + // find read-only references to `nls` + .map(n => service.getReferencesAtPosition(filename, n.pos + 1)) + .flatten() + .filter(r => !r.isWriteAccess) + // find the deepest call expressions AST nodes that contain those references + .map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n))) + .map(a => lazy(a).last()) + .filter(n => !!n) + .map(n => n) + // only `localize` calls + .filter(n => n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize'); + // `localize` named imports + const allLocalizeImportDeclarations = importDeclarations + .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports)) + .map(d => [].concat(d.importClause.namedBindings.elements)) + .flatten(); + // `localize` read-only references + const localizeReferences = allLocalizeImportDeclarations + .filter(d => d.name.getText() === 'localize') + .map(n => service.getReferencesAtPosition(filename, n.pos + 1)) + .flatten() + .filter(r => !r.isWriteAccess); + // custom named `localize` read-only references + const namedLocalizeReferences = allLocalizeImportDeclarations + .filter(d => d.propertyName && d.propertyName.getText() === 'localize') + .map(n => service.getReferencesAtPosition(filename, n.name.pos + 1)) + .flatten() + .filter(r => !r.isWriteAccess); + // find the deepest call expressions AST nodes that contain those references + const localizeCallExpressions = localizeReferences + .concat(namedLocalizeReferences) + .map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n))) + .map(a => lazy(a).last()) + .filter(n => !!n) + .map(n => n); + // collect everything + const localizeCalls = nlsLocalizeCallExpressions + .concat(localizeCallExpressions) + .map(e => e.arguments) + .filter(a => a.length > 1) + .sort((a, b) => a[0].getStart() - b[0].getStart()) + .map(a => ({ + keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, + key: a[0].getText(), + valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) }, + value: a[1].getText() + })); + return { + localizeCalls: localizeCalls.toArray(), + nlsExpressions: nlsExpressions.toArray() + }; + } + nls_1.analyze = analyze; + class TextModel { + constructor(contents) { + const regex = /\r\n|\r|\n/g; + let index = 0; + let match; + this.lines = []; + this.lineEndings = []; + while (match = regex.exec(contents)) { + this.lines.push(contents.substring(index, match.index)); + this.lineEndings.push(match[0]); + index = regex.lastIndex; + } + if (contents.length > 0) { + this.lines.push(contents.substring(index, contents.length)); + this.lineEndings.push(''); + } + } + get(index) { + return this.lines[index]; + } + set(index, line) { + this.lines[index] = line; + } + get lineCount() { + return this.lines.length; + } + /** + * Applies patch(es) to the model. + * Multiple patches must be ordered. + * Does not support patches spanning multiple lines. + */ + apply(patch) { + const startLineNumber = patch.span.start.line; + const endLineNumber = patch.span.end.line; + const startLine = this.lines[startLineNumber] || ''; + const endLine = this.lines[endLineNumber] || ''; + this.lines[startLineNumber] = [ + startLine.substring(0, patch.span.start.character), + patch.content, + endLine.substring(patch.span.end.character) + ].join(''); + for (let i = startLineNumber + 1; i <= endLineNumber; i++) { + this.lines[i] = ''; + } + } + toString() { + return lazy(this.lines).zip(this.lineEndings) + .flatten().toArray().join(''); + } + } + nls_1.TextModel = TextModel; + function patchJavascript(patches, contents, moduleId) { + const model = new nls.TextModel(contents); + // patch the localize calls + lazy(patches).reverse().each(p => model.apply(p)); + // patch the 'vs/nls' imports + const firstLine = model.get(0); + const patchedFirstLine = firstLine.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`); + model.set(0, patchedFirstLine); + return model.toString(); + } + nls_1.patchJavascript = patchJavascript; + function patchSourcemap(patches, rsm, smc) { + const smg = new sm.SourceMapGenerator({ + file: rsm.file, + sourceRoot: rsm.sourceRoot + }); + patches = patches.reverse(); + let currentLine = -1; + let currentLineDiff = 0; + let source = null; + smc.eachMapping(m => { + const patch = patches[patches.length - 1]; + const original = { line: m.originalLine, column: m.originalColumn }; + const generated = { line: m.generatedLine, column: m.generatedColumn }; + if (currentLine !== generated.line) { + currentLineDiff = 0; + } + currentLine = generated.line; + generated.column += currentLineDiff; + if (patch && m.generatedLine - 1 === patch.span.end.line && m.generatedColumn === patch.span.end.character) { + const originalLength = patch.span.end.character - patch.span.start.character; + const modifiedLength = patch.content.length; + const lengthDiff = modifiedLength - originalLength; + currentLineDiff += lengthDiff; + generated.column += lengthDiff; + patches.pop(); + } + source = rsm.sourceRoot ? path.relative(rsm.sourceRoot, m.source) : m.source; + source = source.replace(/\\/g, '/'); + smg.addMapping({ source, name: m.name, original, generated }); + }, null, sm.SourceMapConsumer.GENERATED_ORDER); + if (source) { + smg.setSourceContent(source, smc.sourceContentFor(source)); + } + return JSON.parse(smg.toString()); + } + nls_1.patchSourcemap = patchSourcemap; + function patch(moduleId, typescript, javascript, sourcemap) { + const { localizeCalls, nlsExpressions } = analyze(typescript); + if (localizeCalls.length === 0) { + return { javascript, sourcemap }; + } + const nlsKeys = template(localizeCalls.map(lc => lc.key)); + const nls = template(localizeCalls.map(lc => lc.value)); + const smc = new sm.SourceMapConsumer(sourcemap); + const positionFrom = mappedPositionFrom.bind(null, sourcemap.sources[0]); + let i = 0; + // build patches + const patches = lazy(localizeCalls) + .map(lc => ([ + { range: lc.keySpan, content: '' + (i++) }, + { range: lc.valueSpan, content: 'null' } + ])) + .flatten() + .map(c => { + const start = lcFrom(smc.generatedPositionFor(positionFrom(c.range.start))); + const end = lcFrom(smc.generatedPositionFor(positionFrom(c.range.end))); + return { span: { start, end }, content: c.content }; + }) + .toArray(); + javascript = patchJavascript(patches, javascript, moduleId); + // since imports are not within the sourcemap information, + // we must do this MacGyver style + if (nlsExpressions.length) { + javascript = javascript.replace(/^define\(.*$/m, line => { + return line.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`); + }); + } + sourcemap = patchSourcemap(patches, sourcemap, smc); + return { javascript, sourcemap, nlsKeys, nls }; + } + nls_1.patch = patch; + function patchFiles(javascriptFile, typescript) { + // hack? + const moduleId = javascriptFile.relative + .replace(/\.js$/, '') + .replace(/\\/g, '/'); + const { javascript, sourcemap, nlsKeys, nls } = patch(moduleId, typescript, javascriptFile.contents.toString(), javascriptFile.sourceMap); + const result = [fileFrom(javascriptFile, javascript)]; + result[0].sourceMap = sourcemap; + if (nlsKeys) { + result.push(fileFrom(javascriptFile, nlsKeys, javascriptFile.path.replace(/\.js$/, '.nls.keys.js'))); + } + if (nls) { + result.push(fileFrom(javascriptFile, nls, javascriptFile.path.replace(/\.js$/, '.nls.js'))); + } + return result; + } + nls_1.patchFiles = patchFiles; +})(nls || (nls = {})); +module.exports = nls; diff --git a/build/lib/node.js b/build/lib/node.js new file mode 100644 index 00000000000..403ae3d9657 --- /dev/null +++ b/build/lib/node.js @@ -0,0 +1,15 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const fs = require("fs"); +const root = path.dirname(path.dirname(__dirname)); +const yarnrcPath = path.join(root, 'remote', '.yarnrc'); +const yarnrc = fs.readFileSync(yarnrcPath, 'utf8'); +const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1]; +const node = process.platform === 'win32' ? 'node.exe' : 'node'; +const nodePath = path.join(root, '.build', 'node', `v${version}`, `${process.platform}-${process.arch}`, node); +console.log(nodePath); diff --git a/build/lib/optimize.js b/build/lib/optimize.js new file mode 100644 index 00000000000..9e7a9d96a8a --- /dev/null +++ b/build/lib/optimize.js @@ -0,0 +1,235 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.minifyTask = exports.optimizeTask = exports.loaderConfig = void 0; +const es = require("event-stream"); +const gulp = require("gulp"); +const concat = require("gulp-concat"); +const minifyCSS = require("gulp-cssnano"); +const filter = require("gulp-filter"); +const flatmap = require("gulp-flatmap"); +const sourcemaps = require("gulp-sourcemaps"); +const uglify = require("gulp-uglify"); +const composer = require("gulp-uglify/composer"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const path = require("path"); +const pump = require("pump"); +const terser = require("terser"); +const VinylFile = require("vinyl"); +const bundle = require("./bundle"); +const i18n_1 = require("./i18n"); +const stats_1 = require("./stats"); +const util = require("./util"); +const REPO_ROOT_PATH = path.join(__dirname, '../..'); +function log(prefix, message) { + fancyLog(ansiColors.cyan('[' + prefix + ']'), message); +} +function loaderConfig() { + const result = { + paths: { + 'vs': 'out-build/vs', + 'vscode': 'empty:' + }, + amdModulesPattern: /^vs\// + }; + result['vs/css'] = { inlineResources: true }; + return result; +} +exports.loaderConfig = loaderConfig; +const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i; +function loader(src, bundledFileHeader, bundleLoader) { + let sources = [ + `${src}/vs/loader.js` + ]; + if (bundleLoader) { + sources = sources.concat([ + `${src}/vs/css.js`, + `${src}/vs/nls.js` + ]); + } + let isFirst = true; + return (gulp + .src(sources, { base: `${src}` }) + .pipe(es.through(function (data) { + if (isFirst) { + isFirst = false; + this.emit('data', new VinylFile({ + path: 'fake', + base: '.', + contents: Buffer.from(bundledFileHeader) + })); + this.emit('data', data); + } + else { + this.emit('data', data); + } + })) + .pipe(concat('vs/loader.js'))); +} +function toConcatStream(src, bundledFileHeader, sources, dest, fileContentMapper) { + const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest); + // If a bundle ends up including in any of the sources our copyright, then + // insert a fake source at the beginning of each bundle with our copyright + let containsOurCopyright = false; + for (let i = 0, len = sources.length; i < len; i++) { + const fileContents = sources[i].contents; + if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) { + containsOurCopyright = true; + break; + } + } + if (containsOurCopyright) { + sources.unshift({ + path: null, + contents: bundledFileHeader + }); + } + const treatedSources = sources.map(function (source) { + const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : ''; + const base = source.path ? root + `/${src}` : '.'; + const path = source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake'; + const contents = source.path ? fileContentMapper(source.contents, path) : source.contents; + return new VinylFile({ + path: path, + base: base, + contents: Buffer.from(contents) + }); + }); + return es.readArray(treatedSources) + .pipe(useSourcemaps ? util.loadSourcemaps() : es.through()) + .pipe(concat(dest)) + .pipe(stats_1.createStatsStream(dest)); +} +function toBundleStream(src, bundledFileHeader, bundles, fileContentMapper) { + return es.merge(bundles.map(function (bundle) { + return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest, fileContentMapper); + })); +} +const DEFAULT_FILE_HEADER = [ + '/*!--------------------------------------------------------', + ' * Copyright (C) Microsoft Corporation. All rights reserved.', + ' *--------------------------------------------------------*/' +].join('\n'); +function optimizeTask(opts) { + const src = opts.src; + const entryPoints = opts.entryPoints; + const resources = opts.resources; + const loaderConfig = opts.loaderConfig; + const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER; + const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader); + const out = opts.out; + const fileContentMapper = opts.fileContentMapper || ((contents, _path) => contents); + return function () { + const bundlesStream = es.through(); // this stream will contain the bundled files + const resourcesStream = es.through(); // this stream will contain the resources + const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json + bundle.bundle(entryPoints, loaderConfig, function (err, result) { + if (err || !result) { + return bundlesStream.emit('error', JSON.stringify(err)); + } + toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream); + // Remove css inlined resources + const filteredResources = resources.slice(); + result.cssInlinedResources.forEach(function (resource) { + if (process.env['VSCODE_BUILD_VERBOSE']) { + log('optimizer', 'excluding inlined: ' + resource); + } + filteredResources.push('!' + resource); + }); + gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream); + const bundleInfoArray = []; + if (opts.bundleInfo) { + bundleInfoArray.push(new VinylFile({ + path: 'bundleInfo.json', + base: '.', + contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t')) + })); + } + es.readArray(bundleInfoArray).pipe(bundleInfoStream); + }); + const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, resourcesStream, bundleInfoStream); + return result + .pipe(sourcemaps.write('./', { + sourceRoot: undefined, + addComment: true, + includeContent: true + })) + .pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({ + fileHeader: bundledFileHeader, + languages: opts.languages + }) : es.through()) + .pipe(gulp.dest(out)); + }; +} +exports.optimizeTask = optimizeTask; +/** + * Wrap around uglify and allow the preserveComments function + * to have a file "context" to include our copyright only once per file. + */ +function uglifyWithCopyrights() { + const preserveComments = (f) => { + return (_node, comment) => { + const text = comment.value; + const type = comment.type; + if (/@minifier_do_not_preserve/.test(text)) { + return false; + } + const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); + if (isOurCopyright) { + if (f.__hasOurCopyright) { + return false; + } + f.__hasOurCopyright = true; + return true; + } + if ('comment2' === type) { + // check for /*!. Note that text doesn't contain leading /* + return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text); + } + else if ('comment1' === type) { + return /license|copyright/i.test(text); + } + return false; + }; + }; + const minify = composer(terser); + const input = es.through(); + const output = input + .pipe(flatmap((stream, f) => { + return stream.pipe(minify({ + output: { + comments: preserveComments(f), + max_line_len: 1024 + } + })); + })); + return es.duplex(input, output); +} +function minifyTask(src, sourceMapBaseUrl) { + const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined; + return cb => { + const jsFilter = filter('**/*.js', { restore: true }); + const cssFilter = filter('**/*.css', { restore: true }); + pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => { + if (sourcePath === 'bootstrap-fork.js') { + return 'bootstrap-fork.orig.js'; + } + return sourcePath; + }), sourcemaps.write('./', { + sourceMappingURL, + sourceRoot: undefined, + includeContent: true, + addComment: true + }), gulp.dest(src + '-min'), (err) => { + if (err instanceof uglify.GulpUglifyError) { + console.error(`Uglify error in '${err.cause && err.cause.filename}'`); + } + cb(err); + }); + }; +} +exports.minifyTask = minifyTask; diff --git a/build/lib/preLaunch.js b/build/lib/preLaunch.js new file mode 100644 index 00000000000..1aecbe19048 --- /dev/null +++ b/build/lib/preLaunch.js @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +// @ts-check +const path = require("path"); +const child_process_1 = require("child_process"); +const fs_1 = require("fs"); +const yarn = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'; +const rootDir = path.resolve(__dirname, '..', '..'); +function runProcess(command, args = []) { + return new Promise((resolve, reject) => { + const child = child_process_1.spawn(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env }); + child.on('exit', err => !err ? resolve() : process.exit(err !== null && err !== void 0 ? err : 1)); + child.on('error', reject); + }); +} +async function exists(subdir) { + try { + await fs_1.promises.stat(path.join(rootDir, subdir)); + return true; + } + catch (_a) { + return false; + } +} +async function ensureNodeModules() { + if (!(await exists('node_modules'))) { + await runProcess(yarn); + } +} +async function getElectron() { + await runProcess(yarn, ['electron']); +} +async function ensureCompiled() { + if (!(await exists('out'))) { + await runProcess(yarn, ['compile']); + } +} +async function main() { + await ensureNodeModules(); + await getElectron(); + await ensureCompiled(); + // Can't require this until after dependencies are installed + const { getBuiltInExtensions } = require('./builtInExtensions'); + await getBuiltInExtensions(); +} +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/lib/reporter.js b/build/lib/reporter.js new file mode 100644 index 00000000000..def8f24a065 --- /dev/null +++ b/build/lib/reporter.js @@ -0,0 +1,102 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createReporter = void 0; +const es = require("event-stream"); +const _ = require("underscore"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const fs = require("fs"); +const path = require("path"); +class ErrorLog { + constructor(id) { + this.id = id; + this.allErrors = []; + this.startTime = null; + this.count = 0; + } + onStart() { + if (this.count++ > 0) { + return; + } + this.startTime = new Date().getTime(); + fancyLog(`Starting ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''}...`); + } + onEnd() { + if (--this.count > 0) { + return; + } + this.log(); + } + log() { + const errors = _.flatten(this.allErrors); + const seen = new Set(); + errors.map(err => { + if (!seen.has(err)) { + seen.add(err); + fancyLog(`${ansiColors.red('Error')}: ${err}`); + } + }); + fancyLog(`Finished ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - this.startTime) + ' ms')}`); + const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/s; + const messages = errors + .map(err => regex.exec(err)) + .filter(match => !!match) + .map(x => x) + .map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message })); + try { + const logFileName = 'log' + (this.id ? `_${this.id}` : ''); + fs.writeFileSync(path.join(buildLogFolder, logFileName), JSON.stringify(messages)); + } + catch (err) { + //noop + } + } +} +const errorLogsById = new Map(); +function getErrorLog(id = '') { + let errorLog = errorLogsById.get(id); + if (!errorLog) { + errorLog = new ErrorLog(id); + errorLogsById.set(id, errorLog); + } + return errorLog; +} +const buildLogFolder = path.join(path.dirname(path.dirname(__dirname)), '.build'); +try { + fs.mkdirSync(buildLogFolder); +} +catch (err) { + // ignore +} +function createReporter(id) { + const errorLog = getErrorLog(id); + const errors = []; + errorLog.allErrors.push(errors); + const result = (err) => errors.push(err); + result.hasErrors = () => errors.length > 0; + result.end = (emitError) => { + errors.length = 0; + errorLog.onStart(); + return es.through(undefined, function () { + errorLog.onEnd(); + if (emitError && errors.length > 0) { + if (!errors.__logged__) { + errorLog.log(); + } + errors.__logged__ = true; + const err = new Error(`Found ${errors.length} errors`); + err.__reporter__ = true; + this.emit('error', err); + } + else { + this.emit('end'); + } + }); + }; + return result; +} +exports.createReporter = createReporter; diff --git a/build/lib/snapshotLoader.js b/build/lib/snapshotLoader.js new file mode 100644 index 00000000000..ee626a0f7f1 --- /dev/null +++ b/build/lib/snapshotLoader.js @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +var snaps; +(function (snaps) { + const fs = require('fs'); + const path = require('path'); + const os = require('os'); + const cp = require('child_process'); + const mksnapshot = path.join(__dirname, `../../node_modules/.bin/${process.platform === 'win32' ? 'mksnapshot.cmd' : 'mksnapshot'}`); + const product = require('../../product.json'); + const arch = (process.argv.join('').match(/--arch=(.*)/) || [])[1]; + // + let loaderFilepath; + let startupBlobFilepath; + switch (process.platform) { + case 'darwin': + loaderFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Resources/app/out/vs/loader.js`; + startupBlobFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`; + break; + case 'win32': + case 'linux': + loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`; + startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`; + break; + default: + throw new Error('Unknown platform'); + } + loaderFilepath = path.join(__dirname, '../../../', loaderFilepath); + startupBlobFilepath = path.join(__dirname, '../../../', startupBlobFilepath); + snapshotLoader(loaderFilepath, startupBlobFilepath); + function snapshotLoader(loaderFilepath, startupBlobFilepath) { + const inputFile = fs.readFileSync(loaderFilepath); + const wrappedInputFile = ` + var Monaco_Loader_Init; + (function() { + var doNotInitLoader = true; + ${inputFile.toString()}; + Monaco_Loader_Init = function() { + AMDLoader.init(); + CSSLoaderPlugin.init(); + NLSLoaderPlugin.init(); + + return { define, require }; + } + })(); + `; + const wrappedInputFilepath = path.join(os.tmpdir(), 'wrapped-loader.js'); + console.log(wrappedInputFilepath); + fs.writeFileSync(wrappedInputFilepath, wrappedInputFile); + cp.execFileSync(mksnapshot, [wrappedInputFilepath, `--startup_blob`, startupBlobFilepath]); + } +})(snaps || (snaps = {})); diff --git a/build/lib/standalone.js b/build/lib/standalone.js new file mode 100644 index 00000000000..3ae47647eaf --- /dev/null +++ b/build/lib/standalone.js @@ -0,0 +1,321 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createESMSourcesAndResources2 = exports.extractEditor = void 0; +const ts = require("typescript"); +const fs = require("fs"); +const path = require("path"); +const tss = require("./treeshaking"); +const REPO_ROOT = path.join(__dirname, '../../'); +const SRC_DIR = path.join(REPO_ROOT, 'src'); +let dirCache = {}; +function writeFile(filePath, contents) { + function ensureDirs(dirPath) { + if (dirCache[dirPath]) { + return; + } + dirCache[dirPath] = true; + ensureDirs(path.dirname(dirPath)); + if (fs.existsSync(dirPath)) { + return; + } + fs.mkdirSync(dirPath); + } + ensureDirs(path.dirname(filePath)); + fs.writeFileSync(filePath, contents); +} +function extractEditor(options) { + var _a; + const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString()); + let compilerOptions; + if (tsConfig.extends) { + compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions); + delete tsConfig.extends; + } + else { + compilerOptions = tsConfig.compilerOptions; + } + tsConfig.compilerOptions = compilerOptions; + compilerOptions.noEmit = false; + compilerOptions.noUnusedLocals = false; + compilerOptions.preserveConstEnums = false; + compilerOptions.declaration = false; + compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic; + options.compilerOptions = compilerOptions; + console.log(`Running tree shaker with shakeLevel ${tss.toStringShakeLevel(options.shakeLevel)}`); + // Take the extra included .d.ts files from `tsconfig.monaco.json` + options.typings = tsConfig.include.filter(includedFile => /\.d\.ts$/.test(includedFile)); + // Add extra .d.ts files from `node_modules/@types/` + if (Array.isArray((_a = options.compilerOptions) === null || _a === void 0 ? void 0 : _a.types)) { + options.compilerOptions.types.forEach((type) => { + options.typings.push(`../node_modules/@types/${type}/index.d.ts`); + }); + } + let result = tss.shake(options); + for (let fileName in result) { + if (result.hasOwnProperty(fileName)) { + writeFile(path.join(options.destRoot, fileName), result[fileName]); + } + } + let copied = {}; + const copyFile = (fileName) => { + if (copied[fileName]) { + return; + } + copied[fileName] = true; + const srcPath = path.join(options.sourcesRoot, fileName); + const dstPath = path.join(options.destRoot, fileName); + writeFile(dstPath, fs.readFileSync(srcPath)); + }; + const writeOutputFile = (fileName, contents) => { + writeFile(path.join(options.destRoot, fileName), contents); + }; + for (let fileName in result) { + if (result.hasOwnProperty(fileName)) { + const fileContents = result[fileName]; + const info = ts.preProcessFile(fileContents); + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFileName = info.importedFiles[i].fileName; + let importedFilePath; + if (/^vs\/css!/.test(importedFileName)) { + importedFilePath = importedFileName.substr('vs/css!'.length) + '.css'; + } + else { + importedFilePath = importedFileName; + } + if (/(^\.\/)|(^\.\.\/)/.test(importedFilePath)) { + importedFilePath = path.join(path.dirname(fileName), importedFilePath); + } + if (/\.css$/.test(importedFilePath)) { + transportCSS(importedFilePath, copyFile, writeOutputFile); + } + else { + if (fs.existsSync(path.join(options.sourcesRoot, importedFilePath + '.js'))) { + copyFile(importedFilePath + '.js'); + } + } + } + } + } + delete tsConfig.compilerOptions.moduleResolution; + writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); + [ + 'vs/css.build.js', + 'vs/css.d.ts', + 'vs/css.js', + 'vs/loader.js', + 'vs/nls.build.js', + 'vs/nls.d.ts', + 'vs/nls.js', + 'vs/nls.mock.ts', + ].forEach(copyFile); +} +exports.extractEditor = extractEditor; +function createESMSourcesAndResources2(options) { + const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder); + const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); + const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); + const getDestAbsoluteFilePath = (file) => { + let dest = options.renames[file.replace(/\\/g, '/')] || file; + if (dest === 'tsconfig.json') { + return path.join(OUT_FOLDER, `tsconfig.json`); + } + if (/\.ts$/.test(dest)) { + return path.join(OUT_FOLDER, dest); + } + return path.join(OUT_RESOURCES_FOLDER, dest); + }; + const allFiles = walkDirRecursive(SRC_FOLDER); + for (const file of allFiles) { + if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) { + continue; + } + if (file === 'tsconfig.json') { + const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); + tsConfig.compilerOptions.module = 'es6'; + tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); + continue; + } + if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file) || /\.ttf$/.test(file)) { + // Transport the files directly + write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file))); + continue; + } + if (/\.ts$/.test(file)) { + // Transform the .ts file + let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString(); + const info = ts.preProcessFile(fileContents); + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFilename = info.importedFiles[i].fileName; + const pos = info.importedFiles[i].pos; + const end = info.importedFiles[i].end; + let importedFilepath; + if (/^vs\/css!/.test(importedFilename)) { + importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; + } + else { + importedFilepath = importedFilename; + } + if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { + importedFilepath = path.join(path.dirname(file), importedFilepath); + } + let relativePath; + if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) { + relativePath = '../' + path.basename(path.dirname(file)); + } + else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) { + relativePath = '../../' + path.basename(path.dirname(path.dirname(file))); + } + else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } + relativePath = relativePath.replace(/\\/g, '/'); + if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { + relativePath = './' + relativePath; + } + fileContents = (fileContents.substring(0, pos + 1) + + relativePath + + fileContents.substring(end + 1)); + } + fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { + return `import * as ${m1} from ${m2};`; + }); + write(getDestAbsoluteFilePath(file), fileContents); + continue; + } + console.log(`UNKNOWN FILE: ${file}`); + } + function walkDirRecursive(dir) { + if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') { + dir += '/'; + } + let result = []; + _walkDirRecursive(dir, result, dir.length); + return result; + } + function _walkDirRecursive(dir, result, trimPos) { + const files = fs.readdirSync(dir); + for (let i = 0; i < files.length; i++) { + const file = path.join(dir, files[i]); + if (fs.statSync(file).isDirectory()) { + _walkDirRecursive(file, result, trimPos); + } + else { + result.push(file.substr(trimPos)); + } + } + } + function write(absoluteFilePath, contents) { + if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) { + contents = toggleComments(contents.toString()); + } + writeFile(absoluteFilePath, contents); + function toggleComments(fileContents) { + let lines = fileContents.split(/\r\n|\r|\n/); + let mode = 0; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (mode === 0) { + if (/\/\/ ESM-comment-begin/.test(line)) { + mode = 1; + continue; + } + if (/\/\/ ESM-uncomment-begin/.test(line)) { + mode = 2; + continue; + } + continue; + } + if (mode === 1) { + if (/\/\/ ESM-comment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = '// ' + line; + continue; + } + if (mode === 2) { + if (/\/\/ ESM-uncomment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) { + return indent; + }); + } + } + return lines.join('\n'); + } + } +} +exports.createESMSourcesAndResources2 = createESMSourcesAndResources2; +function transportCSS(module, enqueue, write) { + if (!/\.css/.test(module)) { + return false; + } + const filename = path.join(SRC_DIR, module); + const fileContents = fs.readFileSync(filename).toString(); + const inlineResources = 'base64'; // see https://github.com/microsoft/monaco-editor/issues/148 + const newContents = _rewriteOrInlineUrls(fileContents, inlineResources === 'base64'); + write(module, newContents); + return true; + function _rewriteOrInlineUrls(contents, forceBase64) { + return _replaceURL(contents, (url) => { + const fontMatch = url.match(/^(.*).ttf\?(.*)$/); + if (fontMatch) { + const relativeFontPath = `${fontMatch[1]}.ttf`; // trim the query parameter + const fontPath = path.join(path.dirname(module), relativeFontPath); + enqueue(fontPath); + return relativeFontPath; + } + const imagePath = path.join(path.dirname(module), url); + const fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath)); + const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png'; + let DATA = ';base64,' + fileContents.toString('base64'); + if (!forceBase64 && /\.svg$/.test(url)) { + // .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris + let newText = fileContents.toString() + .replace(/"/g, '\'') + .replace(//g, '%3E') + .replace(/&/g, '%26') + .replace(/#/g, '%23') + .replace(/\s+/g, ' '); + let encodedData = ',' + newText; + if (encodedData.length < DATA.length) { + DATA = encodedData; + } + } + return '"data:' + MIME + DATA + '"'; + }); + } + function _replaceURL(contents, replacer) { + // Use ")" as the terminator as quotes are oftentimes not used at all + return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_, ...matches) => { + let url = matches[0]; + // Eliminate starting quotes (the initial whitespace is not captured) + if (url.charAt(0) === '"' || url.charAt(0) === '\'') { + url = url.substring(1); + } + // The ending whitespace is captured + while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) { + url = url.substring(0, url.length - 1); + } + // Eliminate ending quotes + if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') { + url = url.substring(0, url.length - 1); + } + if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) { + url = replacer(url); + } + return 'url(' + url + ')'; + }); + } + function _startsWith(haystack, needle) { + return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle; + } +} diff --git a/build/lib/stats.js b/build/lib/stats.js new file mode 100644 index 00000000000..2ff02e405a6 --- /dev/null +++ b/build/lib/stats.js @@ -0,0 +1,137 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.submitAllStats = exports.createStatsStream = void 0; +const es = require("event-stream"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const appInsights = require("applicationinsights"); +class Entry { + constructor(name, totalCount, totalSize) { + this.name = name; + this.totalCount = totalCount; + this.totalSize = totalSize; + } + toString(pretty) { + if (!pretty) { + if (this.totalCount === 1) { + return `${this.name}: ${this.totalSize} bytes`; + } + else { + return `${this.name}: ${this.totalCount} files with ${this.totalSize} bytes`; + } + } + else { + if (this.totalCount === 1) { + return `Stats for '${ansiColors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`; + } + else { + const count = this.totalCount < 100 + ? ansiColors.green(this.totalCount.toString()) + : ansiColors.red(this.totalCount.toString()); + return `Stats for '${ansiColors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`; + } + } + } +} +const _entries = new Map(); +function createStatsStream(group, log) { + const entry = new Entry(group, 0, 0); + _entries.set(entry.name, entry); + return es.through(function (data) { + const file = data; + if (typeof file.path === 'string') { + entry.totalCount += 1; + if (Buffer.isBuffer(file.contents)) { + entry.totalSize += file.contents.length; + } + else if (file.stat && typeof file.stat.size === 'number') { + entry.totalSize += file.stat.size; + } + else { + // funky file... + } + } + this.emit('data', data); + }, function () { + if (log) { + if (entry.totalCount === 1) { + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`); + } + else { + const count = entry.totalCount < 100 + ? ansiColors.green(entry.totalCount.toString()) + : ansiColors.red(entry.totalCount.toString()); + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`); + } + } + this.emit('end'); + }); +} +exports.createStatsStream = createStatsStream; +function submitAllStats(productJson, commit) { + const sorted = []; + // move entries for single files to the front + _entries.forEach(value => { + if (value.totalCount === 1) { + sorted.unshift(value); + } + else { + sorted.push(value); + } + }); + // print to console + for (const entry of sorted) { + console.log(entry.toString(true)); + } + // send data as telementry event when the + // product is configured to send telemetry + if (!productJson || !productJson.aiConfig || typeof productJson.aiConfig.asimovKey !== 'string') { + return Promise.resolve(false); + } + return new Promise(resolve => { + try { + const sizes = {}; + const counts = {}; + for (const entry of sorted) { + sizes[entry.name] = entry.totalSize; + counts[entry.name] = entry.totalCount; + } + appInsights.setup(productJson.aiConfig.asimovKey) + .setAutoCollectConsole(false) + .setAutoCollectExceptions(false) + .setAutoCollectPerformance(false) + .setAutoCollectRequests(false) + .setAutoCollectDependencies(false) + .setAutoDependencyCorrelation(false) + .start(); + appInsights.defaultClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1'; + /* __GDPR__ + "monacoworkbench/packagemetrics" : { + "commit" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "size" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "count" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + } + */ + appInsights.defaultClient.trackEvent({ + name: 'monacoworkbench/packagemetrics', + properties: { commit, size: JSON.stringify(sizes), count: JSON.stringify(counts) } + }); + appInsights.defaultClient.flush({ + callback: () => { + appInsights.dispose(); + resolve(true); + } + }); + } + catch (err) { + console.error('ERROR sending build stats as telemetry event!'); + console.error(err); + resolve(false); + } + }); +} +exports.submitAllStats = submitAllStats; diff --git a/build/lib/task.js b/build/lib/task.js new file mode 100644 index 00000000000..d08ab8acde8 --- /dev/null +++ b/build/lib/task.js @@ -0,0 +1,97 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.define = exports.parallel = exports.series = void 0; +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +function _isPromise(p) { + if (typeof p.then === 'function') { + return true; + } + return false; +} +function _renderTime(time) { + return `${Math.round(time)} ms`; +} +async function _execute(task) { + const name = task.taskName || task.displayName || ``; + if (!task._tasks) { + fancyLog('Starting', ansiColors.cyan(name), '...'); + } + const startTime = process.hrtime(); + await _doExecute(task); + const elapsedArr = process.hrtime(startTime); + const elapsedNanoseconds = (elapsedArr[0] * 1e9 + elapsedArr[1]); + if (!task._tasks) { + fancyLog(`Finished`, ansiColors.cyan(name), 'after', ansiColors.magenta(_renderTime(elapsedNanoseconds / 1e6))); + } +} +async function _doExecute(task) { + // Always invoke as if it were a callback task + return new Promise((resolve, reject) => { + if (task.length === 1) { + // this is a callback task + task((err) => { + if (err) { + return reject(err); + } + resolve(); + }); + return; + } + const taskResult = task(); + if (typeof taskResult === 'undefined') { + // this is a sync task + resolve(); + return; + } + if (_isPromise(taskResult)) { + // this is a promise returning task + taskResult.then(resolve, reject); + return; + } + // this is a stream returning task + taskResult.on('end', _ => resolve()); + taskResult.on('error', err => reject(err)); + }); +} +function series(...tasks) { + const result = async () => { + for (let i = 0; i < tasks.length; i++) { + await _execute(tasks[i]); + } + }; + result._tasks = tasks; + return result; +} +exports.series = series; +function parallel(...tasks) { + const result = async () => { + await Promise.all(tasks.map(t => _execute(t))); + }; + result._tasks = tasks; + return result; +} +exports.parallel = parallel; +function define(name, task) { + if (task._tasks) { + // This is a composite task + const lastTask = task._tasks[task._tasks.length - 1]; + if (lastTask._tasks || lastTask.taskName) { + // This is a composite task without a real task function + // => generate a fake task function + return define(name, series(task, () => Promise.resolve())); + } + lastTask.taskName = name; + task.displayName = name; + return task; + } + // This is a simple task + task.taskName = name; + task.displayName = name; + return task; +} +exports.define = define; diff --git a/build/lib/test/i18n.test.js b/build/lib/test/i18n.test.js new file mode 100644 index 00000000000..3dd104259fa --- /dev/null +++ b/build/lib/test/i18n.test.js @@ -0,0 +1,40 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const assert = require("assert"); +const i18n = require("../i18n"); +suite('XLF Parser Tests', () => { + const sampleXlf = 'Key #1Key #2 &'; + const sampleTranslatedXlf = 'Key #1Кнопка #1Key #2 &Кнопка #2 &'; + const originalFilePath = 'vs/base/common/keybinding'; + const keys = ['key1', 'key2']; + const messages = ['Key #1', 'Key #2 &']; + const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' }; + test('Keys & messages to XLF conversion', () => { + const xlf = new i18n.XLF('vscode-workbench'); + xlf.addFile(originalFilePath, keys, messages); + const xlfString = xlf.toString(); + assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf); + }); + test('XLF to keys & messages conversion', () => { + i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) { + assert.deepEqual(resolvedFiles[0].messages, translatedMessages); + assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath); + }); + }); + test('JSON file source path to Transifex resource match', () => { + const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench'; + const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/contrib/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/textfile', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject }; + assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform); + assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib); + assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor); + assert.deepEqual(i18n.getResource('vs/base/common/errorMessage'), base); + assert.deepEqual(i18n.getResource('vs/code/electron-main/window'), code); + assert.deepEqual(i18n.getResource('vs/workbench/contrib/html/browser/webview'), workbenchParts); + assert.deepEqual(i18n.getResource('vs/workbench/services/textfile/node/testFileService'), workbenchServices); + assert.deepEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench); + }); +}); diff --git a/build/lib/treeshaking.js b/build/lib/treeshaking.js new file mode 100644 index 00000000000..5b1cf0591ec --- /dev/null +++ b/build/lib/treeshaking.js @@ -0,0 +1,779 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shake = exports.toStringShakeLevel = exports.ShakeLevel = void 0; +const fs = require("fs"); +const path = require("path"); +const ts = require("typescript"); +const TYPESCRIPT_LIB_FOLDER = path.dirname(require.resolve('typescript/lib/lib.d.ts')); +var ShakeLevel; +(function (ShakeLevel) { + ShakeLevel[ShakeLevel["Files"] = 0] = "Files"; + ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile"; + ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers"; +})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {})); +function toStringShakeLevel(shakeLevel) { + switch (shakeLevel) { + case 0 /* Files */: + return 'Files (0)'; + case 1 /* InnerFile */: + return 'InnerFile (1)'; + case 2 /* ClassMembers */: + return 'ClassMembers (2)'; + } +} +exports.toStringShakeLevel = toStringShakeLevel; +function printDiagnostics(options, diagnostics) { + for (const diag of diagnostics) { + let result = ''; + if (diag.file) { + result += `${path.join(options.sourcesRoot, diag.file.fileName)}`; + } + if (diag.file && diag.start) { + let location = diag.file.getLineAndCharacterOfPosition(diag.start); + result += `:${location.line + 1}:${location.character}`; + } + result += ` - ` + JSON.stringify(diag.messageText); + console.log(result); + } +} +function shake(options) { + const languageService = createTypeScriptLanguageService(options); + const program = languageService.getProgram(); + const globalDiagnostics = program.getGlobalDiagnostics(); + if (globalDiagnostics.length > 0) { + printDiagnostics(options, globalDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } + const syntacticDiagnostics = program.getSyntacticDiagnostics(); + if (syntacticDiagnostics.length > 0) { + printDiagnostics(options, syntacticDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } + const semanticDiagnostics = program.getSemanticDiagnostics(); + if (semanticDiagnostics.length > 0) { + printDiagnostics(options, semanticDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } + markNodes(languageService, options); + return generateResult(languageService, options.shakeLevel); +} +exports.shake = shake; +//#region Discovery, LanguageService & Setup +function createTypeScriptLanguageService(options) { + // Discover referenced files + const FILES = discoverAndReadFiles(options); + // Add fake usage files + options.inlineEntryPoints.forEach((inlineEntryPoint, index) => { + FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint; + }); + // Add additional typings + options.typings.forEach((typing) => { + const filePath = path.join(options.sourcesRoot, typing); + FILES[typing] = fs.readFileSync(filePath).toString(); + }); + // Resolve libs + const RESOLVED_LIBS = processLibFiles(options); + const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, options.sourcesRoot).options; + const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, compilerOptions); + return ts.createLanguageService(host); +} +/** + * Read imports and follow them until all files have been handled + */ +function discoverAndReadFiles(options) { + const FILES = {}; + const in_queue = Object.create(null); + const queue = []; + const enqueue = (moduleId) => { + if (in_queue[moduleId]) { + return; + } + in_queue[moduleId] = true; + queue.push(moduleId); + }; + options.entryPoints.forEach((entryPoint) => enqueue(entryPoint)); + while (queue.length > 0) { + const moduleId = queue.shift(); + const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts'); + if (fs.existsSync(dts_filename)) { + const dts_filecontents = fs.readFileSync(dts_filename).toString(); + FILES[`${moduleId}.d.ts`] = dts_filecontents; + continue; + } + const js_filename = path.join(options.sourcesRoot, moduleId + '.js'); + if (fs.existsSync(js_filename)) { + // This is an import for a .js file, so ignore it... + continue; + } + let ts_filename; + if (options.redirects[moduleId]) { + ts_filename = path.join(options.sourcesRoot, options.redirects[moduleId] + '.ts'); + } + else { + ts_filename = path.join(options.sourcesRoot, moduleId + '.ts'); + } + const ts_filecontents = fs.readFileSync(ts_filename).toString(); + const info = ts.preProcessFile(ts_filecontents); + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFileName = info.importedFiles[i].fileName; + if (options.importIgnorePattern.test(importedFileName)) { + // Ignore vs/css! imports + continue; + } + let importedModuleId = importedFileName; + if (/(^\.\/)|(^\.\.\/)/.test(importedModuleId)) { + importedModuleId = path.join(path.dirname(moduleId), importedModuleId); + } + enqueue(importedModuleId); + } + FILES[`${moduleId}.ts`] = ts_filecontents; + } + return FILES; +} +/** + * Read lib files and follow lib references + */ +function processLibFiles(options) { + const stack = [...options.compilerOptions.lib]; + const result = {}; + while (stack.length > 0) { + const filename = `lib.${stack.shift().toLowerCase()}.d.ts`; + const key = `defaultLib:${filename}`; + if (!result[key]) { + // add this file + const filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename); + const sourceText = fs.readFileSync(filepath).toString(); + result[key] = sourceText; + // precess dependencies and "recurse" + const info = ts.preProcessFile(sourceText); + for (let ref of info.libReferenceDirectives) { + stack.push(ref.fileName); + } + } + } + return result; +} +/** + * A TypeScript language service host + */ +class TypeScriptLanguageServiceHost { + constructor(libs, files, compilerOptions) { + this._libs = libs; + this._files = files; + this._compilerOptions = compilerOptions; + } + // --- language service host --------------- + getCompilationSettings() { + return this._compilerOptions; + } + getScriptFileNames() { + return ([] + .concat(Object.keys(this._libs)) + .concat(Object.keys(this._files))); + } + getScriptVersion(_fileName) { + return '1'; + } + getProjectVersion() { + return '1'; + } + getScriptSnapshot(fileName) { + if (this._files.hasOwnProperty(fileName)) { + return ts.ScriptSnapshot.fromString(this._files[fileName]); + } + else if (this._libs.hasOwnProperty(fileName)) { + return ts.ScriptSnapshot.fromString(this._libs[fileName]); + } + else { + return ts.ScriptSnapshot.fromString(''); + } + } + getScriptKind(_fileName) { + return ts.ScriptKind.TS; + } + getCurrentDirectory() { + return ''; + } + getDefaultLibFileName(_options) { + return 'defaultLib:lib.d.ts'; + } + isDefaultLibFileName(fileName) { + return fileName === this.getDefaultLibFileName(this._compilerOptions); + } +} +//#endregion +//#region Tree Shaking +var NodeColor; +(function (NodeColor) { + NodeColor[NodeColor["White"] = 0] = "White"; + NodeColor[NodeColor["Gray"] = 1] = "Gray"; + NodeColor[NodeColor["Black"] = 2] = "Black"; +})(NodeColor || (NodeColor = {})); +function getColor(node) { + return node.$$$color || 0 /* White */; +} +function setColor(node, color) { + node.$$$color = color; +} +function nodeOrParentIsBlack(node) { + while (node) { + const color = getColor(node); + if (color === 2 /* Black */) { + return true; + } + node = node.parent; + } + return false; +} +function nodeOrChildIsBlack(node) { + if (getColor(node) === 2 /* Black */) { + return true; + } + for (const child of node.getChildren()) { + if (nodeOrChildIsBlack(child)) { + return true; + } + } + return false; +} +function markNodes(languageService, options) { + const program = languageService.getProgram(); + if (!program) { + throw new Error('Could not get program from language service'); + } + if (options.shakeLevel === 0 /* Files */) { + // Mark all source files Black + program.getSourceFiles().forEach((sourceFile) => { + setColor(sourceFile, 2 /* Black */); + }); + return; + } + const black_queue = []; + const gray_queue = []; + const export_import_queue = []; + const sourceFilesLoaded = {}; + function enqueueTopLevelModuleStatements(sourceFile) { + sourceFile.forEachChild((node) => { + if (ts.isImportDeclaration(node)) { + if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) { + setColor(node, 2 /* Black */); + enqueueImport(node, node.moduleSpecifier.text); + } + return; + } + if (ts.isExportDeclaration(node)) { + if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) { + // export * from "foo"; + setColor(node, 2 /* Black */); + enqueueImport(node, node.moduleSpecifier.text); + } + if (node.exportClause && ts.isNamedExports(node.exportClause)) { + for (const exportSpecifier of node.exportClause.elements) { + export_import_queue.push(exportSpecifier); + } + } + return; + } + if (ts.isExpressionStatement(node) + || ts.isIfStatement(node) + || ts.isIterationStatement(node, true) + || ts.isExportAssignment(node)) { + enqueue_black(node); + } + if (ts.isImportEqualsDeclaration(node)) { + if (/export/.test(node.getFullText(sourceFile))) { + // e.g. "export import Severity = BaseSeverity;" + enqueue_black(node); + } + } + }); + } + function enqueue_gray(node) { + if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* Gray */) { + return; + } + setColor(node, 1 /* Gray */); + gray_queue.push(node); + } + function enqueue_black(node) { + const previousColor = getColor(node); + if (previousColor === 2 /* Black */) { + return; + } + if (previousColor === 1 /* Gray */) { + // remove from gray queue + gray_queue.splice(gray_queue.indexOf(node), 1); + setColor(node, 0 /* White */); + // add to black queue + enqueue_black(node); + // // move from one queue to the other + // black_queue.push(node); + // setColor(node, NodeColor.Black); + return; + } + if (nodeOrParentIsBlack(node)) { + return; + } + const fileName = node.getSourceFile().fileName; + if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) { + setColor(node, 2 /* Black */); + return; + } + const sourceFile = node.getSourceFile(); + if (!sourceFilesLoaded[sourceFile.fileName]) { + sourceFilesLoaded[sourceFile.fileName] = true; + enqueueTopLevelModuleStatements(sourceFile); + } + if (ts.isSourceFile(node)) { + return; + } + setColor(node, 2 /* Black */); + black_queue.push(node); + if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) { + const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth()); + if (references) { + for (let i = 0, len = references.length; i < len; i++) { + const reference = references[i]; + const referenceSourceFile = program.getSourceFile(reference.fileName); + if (!referenceSourceFile) { + continue; + } + const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false); + if (ts.isMethodDeclaration(referenceNode.parent) + || ts.isPropertyDeclaration(referenceNode.parent) + || ts.isGetAccessor(referenceNode.parent) + || ts.isSetAccessor(referenceNode.parent)) { + enqueue_gray(referenceNode.parent); + } + } + } + } + } + function enqueueFile(filename) { + const sourceFile = program.getSourceFile(filename); + if (!sourceFile) { + console.warn(`Cannot find source file ${filename}`); + return; + } + enqueue_black(sourceFile); + } + function enqueueImport(node, importText) { + if (options.importIgnorePattern.test(importText)) { + // this import should be ignored + return; + } + const nodeSourceFile = node.getSourceFile(); + let fullPath; + if (/(^\.\/)|(^\.\.\/)/.test(importText)) { + fullPath = path.join(path.dirname(nodeSourceFile.fileName), importText) + '.ts'; + } + else { + fullPath = importText + '.ts'; + } + enqueueFile(fullPath); + } + options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts')); + // Add fake usage files + options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`)); + let step = 0; + const checker = program.getTypeChecker(); + while (black_queue.length > 0 || gray_queue.length > 0) { + ++step; + let node; + if (step % 100 === 0) { + console.log(`Treeshaking - ${Math.floor(100 * step / (step + black_queue.length + gray_queue.length))}% - ${step}/${step + black_queue.length + gray_queue.length} (${black_queue.length}, ${gray_queue.length})`); + } + if (black_queue.length === 0) { + for (let i = 0; i < gray_queue.length; i++) { + const node = gray_queue[i]; + const nodeParent = node.parent; + if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) { + gray_queue.splice(i, 1); + black_queue.push(node); + setColor(node, 2 /* Black */); + i--; + } + } + } + if (black_queue.length > 0) { + node = black_queue.shift(); + } + else { + // only gray nodes remaining... + break; + } + const nodeSourceFile = node.getSourceFile(); + const loop = (node) => { + const [symbol, symbolImportNode] = getRealNodeSymbol(checker, node); + if (symbolImportNode) { + setColor(symbolImportNode, 2 /* Black */); + } + if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { + for (let i = 0, len = symbol.declarations.length; i < len; i++) { + const declaration = symbol.declarations[i]; + if (ts.isSourceFile(declaration)) { + // Do not enqueue full source files + // (they can be the declaration of a module import) + continue; + } + if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration)) { + enqueue_black(declaration.name); + for (let j = 0; j < declaration.members.length; j++) { + const member = declaration.members[j]; + const memberName = member.name ? member.name.getText() : null; + if (ts.isConstructorDeclaration(member) + || ts.isConstructSignatureDeclaration(member) + || ts.isIndexSignatureDeclaration(member) + || ts.isCallSignatureDeclaration(member) + || memberName === '[Symbol.iterator]' + || memberName === '[Symbol.toStringTag]' + || memberName === 'toJSON' + || memberName === 'toString' + || memberName === 'dispose' // TODO: keeping all `dispose` methods + || /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`... + ) { + enqueue_black(member); + } + } + // queue the heritage clauses + if (declaration.heritageClauses) { + for (let heritageClause of declaration.heritageClauses) { + enqueue_black(heritageClause); + } + } + } + else { + enqueue_black(declaration); + } + } + } + node.forEachChild(loop); + }; + node.forEachChild(loop); + } + while (export_import_queue.length > 0) { + const node = export_import_queue.shift(); + if (nodeOrParentIsBlack(node)) { + continue; + } + const symbol = node.symbol; + if (!symbol) { + continue; + } + const aliased = checker.getAliasedSymbol(symbol); + if (aliased.declarations && aliased.declarations.length > 0) { + if (nodeOrParentIsBlack(aliased.declarations[0]) || nodeOrChildIsBlack(aliased.declarations[0])) { + setColor(node, 2 /* Black */); + } + } + } +} +function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) { + for (let i = 0, len = symbol.declarations.length; i < len; i++) { + const declaration = symbol.declarations[i]; + const declarationSourceFile = declaration.getSourceFile(); + if (nodeSourceFile === declarationSourceFile) { + if (declaration.pos <= node.pos && node.end <= declaration.end) { + return true; + } + } + } + return false; +} +function generateResult(languageService, shakeLevel) { + const program = languageService.getProgram(); + if (!program) { + throw new Error('Could not get program from language service'); + } + let result = {}; + const writeFile = (filePath, contents) => { + result[filePath] = contents; + }; + program.getSourceFiles().forEach((sourceFile) => { + const fileName = sourceFile.fileName; + if (/^defaultLib:/.test(fileName)) { + return; + } + const destination = fileName; + if (/\.d\.ts$/.test(fileName)) { + if (nodeOrChildIsBlack(sourceFile)) { + writeFile(destination, sourceFile.text); + } + return; + } + let text = sourceFile.text; + let result = ''; + function keep(node) { + result += text.substring(node.pos, node.end); + } + function write(data) { + result += data; + } + function writeMarkedNodes(node) { + if (getColor(node) === 2 /* Black */) { + return keep(node); + } + // Always keep certain top-level statements + if (ts.isSourceFile(node.parent)) { + if (ts.isExpressionStatement(node) && ts.isStringLiteral(node.expression) && node.expression.text === 'use strict') { + return keep(node); + } + if (ts.isVariableStatement(node) && nodeOrChildIsBlack(node)) { + return keep(node); + } + } + // Keep the entire import in import * as X cases + if (ts.isImportDeclaration(node)) { + if (node.importClause && node.importClause.namedBindings) { + if (ts.isNamespaceImport(node.importClause.namedBindings)) { + if (getColor(node.importClause.namedBindings) === 2 /* Black */) { + return keep(node); + } + } + else { + let survivingImports = []; + for (const importNode of node.importClause.namedBindings.elements) { + if (getColor(importNode) === 2 /* Black */) { + survivingImports.push(importNode.getFullText(sourceFile)); + } + } + const leadingTriviaWidth = node.getLeadingTriviaWidth(); + const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth); + if (survivingImports.length > 0) { + if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) { + return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`); + } + return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`); + } + else { + if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) { + return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`); + } + } + } + } + else { + if (node.importClause && getColor(node.importClause) === 2 /* Black */) { + return keep(node); + } + } + } + if (ts.isExportDeclaration(node)) { + if (node.exportClause && node.moduleSpecifier && ts.isNamedExports(node.exportClause)) { + let survivingExports = []; + for (const exportSpecifier of node.exportClause.elements) { + if (getColor(exportSpecifier) === 2 /* Black */) { + survivingExports.push(exportSpecifier.getFullText(sourceFile)); + } + } + const leadingTriviaWidth = node.getLeadingTriviaWidth(); + const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth); + if (survivingExports.length > 0) { + return write(`${leadingTrivia}export {${survivingExports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`); + } + } + } + if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) { + let toWrite = node.getFullText(); + for (let i = node.members.length - 1; i >= 0; i--) { + const member = node.members[i]; + if (getColor(member) === 2 /* Black */ || !member.name) { + // keep method + continue; + } + let pos = member.pos - node.pos; + let end = member.end - node.pos; + toWrite = toWrite.substring(0, pos) + toWrite.substring(end); + } + return write(toWrite); + } + if (ts.isFunctionDeclaration(node)) { + // Do not go inside functions if they haven't been marked + return; + } + node.forEachChild(writeMarkedNodes); + } + if (getColor(sourceFile) !== 2 /* Black */) { + if (!nodeOrChildIsBlack(sourceFile)) { + // none of the elements are reachable => don't write this file at all! + return; + } + sourceFile.forEachChild(writeMarkedNodes); + result += sourceFile.endOfFileToken.getFullText(sourceFile); + } + else { + result = text; + } + writeFile(destination, result); + }); + return result; +} +//#endregion +//#region Utils +function isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration) { + if (!program.isSourceFileDefaultLibrary(declaration.getSourceFile()) && declaration.heritageClauses) { + for (const heritageClause of declaration.heritageClauses) { + for (const type of heritageClause.types) { + const symbol = findSymbolFromHeritageType(checker, type); + if (symbol) { + const decl = symbol.valueDeclaration || (symbol.declarations && symbol.declarations[0]); + if (decl && program.isSourceFileDefaultLibrary(decl.getSourceFile())) { + return true; + } + } + } + } + } + return false; +} +function findSymbolFromHeritageType(checker, type) { + if (ts.isExpressionWithTypeArguments(type)) { + return findSymbolFromHeritageType(checker, type.expression); + } + if (ts.isIdentifier(type)) { + return getRealNodeSymbol(checker, type)[0]; + } + if (ts.isPropertyAccessExpression(type)) { + return findSymbolFromHeritageType(checker, type.name); + } + return null; +} +/** + * Returns the node's symbol and the `import` node (if the symbol resolved from a different module) + */ +function getRealNodeSymbol(checker, node) { + const getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType; + const getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement; + const getNameFromPropertyName = ts.getNameFromPropertyName; + // Go to the original declaration for cases: + // + // (1) when the aliased symbol was declared in the location(parent). + // (2) when the aliased symbol is originating from an import. + // + function shouldSkipAlias(node, declaration) { + if (!ts.isShorthandPropertyAssignment(node) && node.kind !== ts.SyntaxKind.Identifier) { + return false; + } + if (node.parent === declaration) { + return true; + } + switch (declaration.kind) { + case ts.SyntaxKind.ImportClause: + case ts.SyntaxKind.ImportEqualsDeclaration: + return true; + case ts.SyntaxKind.ImportSpecifier: + return declaration.parent.kind === ts.SyntaxKind.NamedImports; + default: + return false; + } + } + if (!ts.isShorthandPropertyAssignment(node)) { + if (node.getChildCount() !== 0) { + return [null, null]; + } + } + const { parent } = node; + let symbol = (ts.isShorthandPropertyAssignment(node) + ? checker.getShorthandAssignmentValueSymbol(node) + : checker.getSymbolAtLocation(node)); + let importNode = null; + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. + if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { + const aliased = checker.getAliasedSymbol(symbol); + if (aliased.declarations) { + // We should mark the import as visited + importNode = symbol.declarations[0]; + symbol = aliased; + } + } + if (symbol) { + // Because name in short-hand property assignment has two different meanings: property name and property value, + // using go-to-definition at such position should go to the variable declaration of the property value rather than + // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition + // is performed at the location of property access, we would like to go to definition of the property in the short-hand + // assignment. This case and others are handled by the following code. + if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + symbol = checker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + } + // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the + // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern + // and return the property declaration for the referenced property. + // For example: + // import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo" + // + // function bar(onfulfilled: (value: T) => void) { //....} + // interface Test { + // pr/*destination*/op1: number + // } + // bar(({pr/*goto*/op1})=>{}); + if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && + (node === (parent.propertyName || parent.name))) { + const name = getNameFromPropertyName(node); + const type = checker.getTypeAtLocation(parent.parent); + if (name && type) { + if (type.isUnion()) { + const prop = type.types[0].getProperty(name); + if (prop) { + symbol = prop; + } + } + else { + const prop = type.getProperty(name); + if (prop) { + symbol = prop; + } + } + } + } + // If the current location we want to find its definition is in an object literal, try to get the contextual type for the + // object literal, lookup the property symbol in the contextual type, and use this for goto-definition. + // For example + // interface Props{ + // /*first*/prop1: number + // prop2: boolean + // } + // function Foo(arg: Props) {} + // Foo( { pr/*1*/op1: 10, prop2: false }) + const element = getContainingObjectLiteralElement(node); + if (element) { + const contextualType = element && checker.getContextualType(element.parent); + if (contextualType) { + const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false); + if (propertySymbols) { + symbol = propertySymbols[0]; + } + } + } + } + if (symbol && symbol.declarations) { + return [symbol, importNode]; + } + return [null, null]; +} +/** Get the token whose text contains the position */ +function getTokenAtPosition(sourceFile, position, allowPositionInLeadingTrivia, includeEndPosition) { + let current = sourceFile; + outer: while (true) { + // find the child that contains 'position' + for (const child of current.getChildren()) { + const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, /*includeJsDoc*/ true); + if (start > position) { + // If this child begins after position, then all subsequent children will as well. + break; + } + const end = child.getEnd(); + if (position < end || (position === end && (child.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) { + current = child; + continue outer; + } + } + return current; + } +} diff --git a/build/lib/util.js b/build/lib/util.js new file mode 100644 index 00000000000..8d0294e4ceb --- /dev/null +++ b/build/lib/util.js @@ -0,0 +1,276 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getElectronVersion = exports.streamToPromise = exports.versionStringToNumber = exports.filter = exports.rebase = exports.getVersion = exports.ensureDir = exports.rreddir = exports.rimraf = exports.rewriteSourceMappingURL = exports.stripSourceMappingURL = exports.loadSourcemaps = exports.cleanNodeModules = exports.skipDirectories = exports.toFileUri = exports.setExecutableBit = exports.fixWin32DirectoryPermissions = exports.incremental = void 0; +const es = require("event-stream"); +const debounce = require("debounce"); +const _filter = require("gulp-filter"); +const rename = require("gulp-rename"); +const path = require("path"); +const fs = require("fs"); +const _rimraf = require("rimraf"); +const git = require("./git"); +const VinylFile = require("vinyl"); +const root = path.dirname(path.dirname(__dirname)); +const NoCancellationToken = { isCancellationRequested: () => false }; +function incremental(streamProvider, initial, supportsCancellation) { + const input = es.through(); + const output = es.through(); + let state = 'idle'; + let buffer = Object.create(null); + const token = !supportsCancellation ? undefined : { isCancellationRequested: () => Object.keys(buffer).length > 0 }; + const run = (input, isCancellable) => { + state = 'running'; + const stream = !supportsCancellation ? streamProvider() : streamProvider(isCancellable ? token : NoCancellationToken); + input + .pipe(stream) + .pipe(es.through(undefined, () => { + state = 'idle'; + eventuallyRun(); + })) + .pipe(output); + }; + if (initial) { + run(initial, false); + } + const eventuallyRun = debounce(() => { + const paths = Object.keys(buffer); + if (paths.length === 0) { + return; + } + const data = paths.map(path => buffer[path]); + buffer = Object.create(null); + run(es.readArray(data), true); + }, 500); + input.on('data', (f) => { + buffer[f.path] = f; + if (state === 'idle') { + eventuallyRun(); + } + }); + return es.duplex(input, output); +} +exports.incremental = incremental; +function fixWin32DirectoryPermissions() { + if (!/win32/.test(process.platform)) { + return es.through(); + } + return es.mapSync(f => { + if (f.stat && f.stat.isDirectory && f.stat.isDirectory()) { + f.stat.mode = 16877; + } + return f; + }); +} +exports.fixWin32DirectoryPermissions = fixWin32DirectoryPermissions; +function setExecutableBit(pattern) { + const setBit = es.mapSync(f => { + if (!f.stat) { + f.stat = { isFile() { return true; } }; + } + f.stat.mode = /* 100755 */ 33261; + return f; + }); + if (!pattern) { + return setBit; + } + const input = es.through(); + const filter = _filter(pattern, { restore: true }); + const output = input + .pipe(filter) + .pipe(setBit) + .pipe(filter.restore); + return es.duplex(input, output); +} +exports.setExecutableBit = setExecutableBit; +function toFileUri(filePath) { + const match = filePath.match(/^([a-z])\:(.*)$/i); + if (match) { + filePath = '/' + match[1].toUpperCase() + ':' + match[2]; + } + return 'file://' + filePath.replace(/\\/g, '/'); +} +exports.toFileUri = toFileUri; +function skipDirectories() { + return es.mapSync(f => { + if (!f.isDirectory()) { + return f; + } + }); +} +exports.skipDirectories = skipDirectories; +function cleanNodeModules(rulePath) { + const rules = fs.readFileSync(rulePath, 'utf8') + .split(/\r?\n/g) + .map(line => line.trim()) + .filter(line => line && !/^#/.test(line)); + const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`); + const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`); + const input = es.through(); + const output = es.merge(input.pipe(_filter(['**', ...excludes])), input.pipe(_filter(includes))); + return es.duplex(input, output); +} +exports.cleanNodeModules = cleanNodeModules; +function loadSourcemaps() { + const input = es.through(); + const output = input + .pipe(es.map((f, cb) => { + if (f.sourceMap) { + cb(undefined, f); + return; + } + if (!f.contents) { + cb(undefined, f); + return; + } + const contents = f.contents.toString('utf8'); + const reg = /\/\/# sourceMappingURL=(.*)$/g; + let lastMatch = null; + let match = null; + while (match = reg.exec(contents)) { + lastMatch = match; + } + if (!lastMatch) { + f.sourceMap = { + version: '3', + names: [], + mappings: '', + sources: [f.relative], + sourcesContent: [contents] + }; + cb(undefined, f); + return; + } + f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8'); + fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', (err, contents) => { + if (err) { + return cb(err); + } + f.sourceMap = JSON.parse(contents); + cb(undefined, f); + }); + })); + return es.duplex(input, output); +} +exports.loadSourcemaps = loadSourcemaps; +function stripSourceMappingURL() { + const input = es.through(); + const output = input + .pipe(es.mapSync(f => { + const contents = f.contents.toString('utf8'); + f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8'); + return f; + })); + return es.duplex(input, output); +} +exports.stripSourceMappingURL = stripSourceMappingURL; +function rewriteSourceMappingURL(sourceMappingURLBase) { + const input = es.through(); + const output = input + .pipe(es.mapSync(f => { + const contents = f.contents.toString('utf8'); + const str = `//# sourceMappingURL=${sourceMappingURLBase}/${path.dirname(f.relative).replace(/\\/g, '/')}/$1`; + f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, str)); + return f; + })); + return es.duplex(input, output); +} +exports.rewriteSourceMappingURL = rewriteSourceMappingURL; +function rimraf(dir) { + const result = () => new Promise((c, e) => { + let retries = 0; + const retry = () => { + _rimraf(dir, { maxBusyTries: 1 }, (err) => { + if (!err) { + return c(); + } + if (err.code === 'ENOTEMPTY' && ++retries < 5) { + return setTimeout(() => retry(), 10); + } + return e(err); + }); + }; + retry(); + }); + result.taskName = `clean-${path.basename(dir).toLowerCase()}`; + return result; +} +exports.rimraf = rimraf; +function _rreaddir(dirPath, prepend, result) { + const entries = fs.readdirSync(dirPath, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory()) { + _rreaddir(path.join(dirPath, entry.name), `${prepend}/${entry.name}`, result); + } + else { + result.push(`${prepend}/${entry.name}`); + } + } +} +function rreddir(dirPath) { + let result = []; + _rreaddir(dirPath, '', result); + return result; +} +exports.rreddir = rreddir; +function ensureDir(dirPath) { + if (fs.existsSync(dirPath)) { + return; + } + ensureDir(path.dirname(dirPath)); + fs.mkdirSync(dirPath); +} +exports.ensureDir = ensureDir; +function getVersion(root) { + let version = process.env['BUILD_SOURCEVERSION']; + if (!version || !/^[0-9a-f]{40}$/i.test(version)) { + version = git.getVersion(root); + } + return version; +} +exports.getVersion = getVersion; +function rebase(count) { + return rename(f => { + const parts = f.dirname ? f.dirname.split(/[\/\\]/) : []; + f.dirname = parts.slice(count).join(path.sep); + }); +} +exports.rebase = rebase; +function filter(fn) { + const result = es.through(function (data) { + if (fn(data)) { + this.emit('data', data); + } + else { + result.restore.push(data); + } + }); + result.restore = es.through(); + return result; +} +exports.filter = filter; +function versionStringToNumber(versionStr) { + const semverRegex = /(\d+)\.(\d+)\.(\d+)/; + const match = versionStr.match(semverRegex); + if (!match) { + throw new Error('Version string is not properly formatted: ' + versionStr); + } + return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); +} +exports.versionStringToNumber = versionStringToNumber; +function streamToPromise(stream) { + return new Promise((c, e) => { + stream.on('error', err => e(err)); + stream.on('end', () => c()); + }); +} +exports.streamToPromise = streamToPromise; +function getElectronVersion() { + const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8'); + const target = /^target "(.*)"$/m.exec(yarnrc)[1]; + return target; +} +exports.getElectronVersion = getElectronVersion; diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js new file mode 100644 index 00000000000..949cb91cff0 --- /dev/null +++ b/build/lib/watch/index.js @@ -0,0 +1,9 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const watch = process.platform === 'win32' ? require('./watch-win32') : require('vscode-gulp-watch'); +module.exports = function () { + return watch.apply(null, arguments); +}; diff --git a/build/lib/watch/watch-win32.js b/build/lib/watch/watch-win32.js new file mode 100644 index 00000000000..71681c9c951 --- /dev/null +++ b/build/lib/watch/watch-win32.js @@ -0,0 +1,100 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const cp = require("child_process"); +const fs = require("fs"); +const File = require("vinyl"); +const es = require("event-stream"); +const filter = require("gulp-filter"); +const watcherPath = path.join(__dirname, 'watcher.exe'); +function toChangeType(type) { + switch (type) { + case '0': return 'change'; + case '1': return 'add'; + default: return 'unlink'; + } +} +function watch(root) { + const result = es.through(); + let child = cp.spawn(watcherPath, [root]); + child.stdout.on('data', function (data) { + const lines = data.toString('utf8').split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (line.length === 0) { + continue; + } + const changeType = line[0]; + const changePath = line.substr(2); + // filter as early as possible + if (/^\.git/.test(changePath) || /(^|\\)out($|\\)/.test(changePath)) { + continue; + } + const changePathFull = path.join(root, changePath); + const file = new File({ + path: changePathFull, + base: root + }); + file.event = toChangeType(changeType); + result.emit('data', file); + } + }); + child.stderr.on('data', function (data) { + result.emit('error', data); + }); + child.on('exit', function (code) { + result.emit('error', 'Watcher died with code ' + code); + child = null; + }); + process.once('SIGTERM', function () { process.exit(0); }); + process.once('SIGTERM', function () { process.exit(0); }); + process.once('exit', function () { if (child) { + child.kill(); + } }); + return result; +} +const cache = Object.create(null); +module.exports = function (pattern, options) { + options = options || {}; + const cwd = path.normalize(options.cwd || process.cwd()); + let watcher = cache[cwd]; + if (!watcher) { + watcher = cache[cwd] = watch(cwd); + } + const rebase = !options.base ? es.through() : es.mapSync(function (f) { + f.base = options.base; + return f; + }); + return watcher + .pipe(filter(['**', '!.git{,/**}'])) // ignore all things git + .pipe(filter(pattern)) + .pipe(es.map(function (file, cb) { + fs.stat(file.path, function (err, stat) { + if (err && err.code === 'ENOENT') { + return cb(undefined, file); + } + if (err) { + return cb(); + } + if (!stat.isFile()) { + return cb(); + } + fs.readFile(file.path, function (err, contents) { + if (err && err.code === 'ENOENT') { + return cb(undefined, file); + } + if (err) { + return cb(); + } + file.contents = contents; + file.stat = stat; + cb(undefined, file); + }); + }); + })) + .pipe(rebase); +}; From 45c7cae914d2329ab62f5d2f3e7006d333e91a33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Dec 2020 11:22:24 +0100 Subject: [PATCH 0903/1837] Bump ini from 1.3.5 to 1.3.7 in /extensions/markdown-language-features (#112275) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- extensions/markdown-language-features/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 38f3912f9a9..121018df37a 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -2237,9 +2237,9 @@ inherits@2.0.3: integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== interpret@1.2.0: version "1.2.0" From 16e715dc38e29002ccafd0ce23a82edd12edbdac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Dec 2020 11:22:41 +0100 Subject: [PATCH 0904/1837] Bump ini from 1.3.4 to 1.3.7 (#112276) Bumps [ini](https://github.com/isaacs/ini) from 1.3.4 to 1.3.7. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.4...v1.3.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index 324045e9260..8d595ec760d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4854,15 +4854,10 @@ inherits@^2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.4, ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - integrity sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4= - -ini@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== innosetup@6.0.5: version "6.0.5" From c7319db91ce9fb7cf8a94db753e0390a41c85f58 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 14 Dec 2020 11:19:41 +0100 Subject: [PATCH 0905/1837] Remove use of getActions in remote.ts --- .../remote/browser/explorerViewItems.ts | 29 ++++++++++++------- .../contrib/remote/browser/remote.ts | 20 +++---------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/explorerViewItems.ts b/src/vs/workbench/contrib/remote/browser/explorerViewItems.ts index 99604f4fa31..c0714a2271b 100644 --- a/src/vs/workbench/contrib/remote/browser/explorerViewItems.ts +++ b/src/vs/workbench/contrib/remote/browser/explorerViewItems.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { IAction, Action } from 'vs/base/common/actions'; +import { IAction } from 'vs/base/common/actions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; @@ -14,8 +14,11 @@ import { IViewDescriptor } from 'vs/workbench/common/views'; import { isStringArray } from 'vs/base/common/types'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { Action2, MenuId } from 'vs/platform/actions/common/actions'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { VIEWLET_ID } from 'vs/workbench/contrib/remote/browser/remoteExplorer'; export interface IRemoteSelectItem extends ISelectOptionItem { authority: string[]; @@ -89,19 +92,25 @@ export class SwitchRemoteViewItem extends SelectActionViewItem { } } -export class SwitchRemoteAction extends Action { +export class SwitchRemoteAction extends Action2 { public static readonly ID = 'remote.explorer.switch'; public static readonly LABEL = nls.localize('remote.explorer.switch', "Switch Remote"); - constructor( - id: string, label: string, - @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService - ) { - super(id, label); + constructor() { + super({ + id: SwitchRemoteAction.ID, + title: SwitchRemoteAction.LABEL, + menu: [{ + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), + group: 'navigation', + order: 1 + }], + }); } - public async run(item: IRemoteSelectItem): Promise { - this.remoteExplorerService.targetType = item.authority; + public async run(accessor: ServicesAccessor, args: IRemoteSelectItem): Promise { + accessor.get(IRemoteExplorerService).targetType = args.authority; } } diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 5549a5f8935..b28a9166e84 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -29,7 +29,7 @@ import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions, CATEGORIES } from 'vs/workbench/common/actions'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { registerAction2, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IProgress, IProgressStep, IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -40,7 +40,7 @@ import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; import { IDisposable } from 'vs/base/common/lifecycle'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { SwitchRemoteViewItem, SwitchRemoteAction } from 'vs/workbench/contrib/remote/browser/explorerViewItems'; -import { Action, IActionViewItem, IAction } from 'vs/base/common/actions'; +import { Action, IActionViewItem } from 'vs/base/common/actions'; import { isStringArray } from 'vs/base/common/types'; import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -468,7 +468,6 @@ class HelpPanelDescriptor implements IViewDescriptor { export class RemoteViewPaneContainer extends FilterViewPaneContainer implements IViewModel { private helpPanelDescriptor = new HelpPanelDescriptor(this); helpInformation: HelpInformation[] = []; - private actions: IAction[] | undefined; constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @@ -535,25 +534,14 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements return super.getActionViewItem(action); } - public getActions(): IAction[] { - if (!this.actions) { - this.actions = [ - this.instantiationService.createInstance(SwitchRemoteAction, SwitchRemoteAction.ID, SwitchRemoteAction.LABEL) - ]; - this.actions.forEach(a => { - this._register(a); - }); - } - return this.actions; - } - getTitle(): string { const title = nls.localize('remote.explorer', "Remote Explorer"); return title; } - } +registerAction2(SwitchRemoteAction); + Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, From 672216afdab524aa1bc1e72f426683ce74abd78c Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 11:16:24 +0100 Subject: [PATCH 0906/1837] Fix auto-generated link --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2637ae7be4..1489ba275d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -396,7 +396,7 @@ jobs: token: ${{secrets.GITHUB_TOKEN}} assignees: alexdima #${{github.actor}} labels: unit-test-failure linux - body: Running tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/runs/${{github.run_id}} + body: Running tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/actions/runs/${{github.run_id}} windows: name: Windows From 814bf82b853e54c4024ae07a3ebca521bc7399d8 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 11:24:44 +0100 Subject: [PATCH 0907/1837] Split compilation job into core compilation and extensions compilation --- .github/workflows/ci.yml | 135 ++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1489ba275d2..0f0bc254a61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check - build-compile: - name: "Build: Compile" + build-compile-core: + name: "Build: Compile Core" runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -67,31 +67,62 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Cache compiled code - id: cacheCompiledCode + - name: Cache compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} - name: Compile Core - if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} run: yarn gulp compile-build - - name: Compile Extensions - if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} - run: yarn gulp compile-extensions-build - - name: Minify VS Code - if: ${{ steps.cacheCompiledCode.outputs.cache-hit != 'true' }} + if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} run: yarn gulp minify-vscode + build-compile-extensions: + name: "Build: Compile Extensions" + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules- + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + run: yarn --frozen-lockfile + + - name: Cache compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} + + - name: Compile Extensions + if: ${{ steps.cacheCompiledExtensionsCode.outputs.cache-hit != 'true' }} + run: yarn gulp compile-extensions-build + build-linux-unit-tests: name: "Build: Linux Unit Tests" - needs: build-compile + needs: [build-compile-core, build-compile-extensions] runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -120,15 +151,21 @@ jobs: key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Restore cached compiled code - id: cacheCompiledCode + - name: Restore compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} + + - name: Restore compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-linux-x64-min-ci @@ -147,7 +184,7 @@ jobs: build-linux-integration-tests: name: "Build: Linux Integration Tests" - needs: build-compile + needs: [build-compile-core, build-compile-extensions] runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -176,15 +213,21 @@ jobs: key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- - - name: Restore cached compiled code - id: cacheCompiledCode + - name: Restore compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} + + - name: Restore compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-linux-x64-min-ci @@ -197,7 +240,7 @@ jobs: build-darwin-unit-tests: name: "Build: macOS Unit Tests" - needs: build-compile + needs: [build-compile-core, build-compile-extensions] runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -221,15 +264,21 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Restore cached compiled code - id: cacheCompiledCode + - name: Restore compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} + + - name: Restore compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci @@ -248,7 +297,7 @@ jobs: build-darwin-integration-tests: name: "Build: macOS Integration Tests" - needs: build-compile + needs: [build-compile-core, build-compile-extensions] runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -272,15 +321,21 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Restore cached compiled code - id: cacheCompiledCode + - name: Restore compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} + + - name: Restore compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci @@ -293,7 +348,7 @@ jobs: build-darwin-smoke-tests: name: "Build: macOS Smoke Tests" - needs: build-compile + needs: [build-compile-core, build-compile-extensions] runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -317,15 +372,21 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile - - name: Restore cached compiled code - id: cacheCompiledCode + - name: Restore compiled core code + id: cacheCompiledCoreCode uses: actions/cache@v2 with: path: | - .build out-build out-vscode-min - key: cacheCompiledCode-${{ github.sha }} + key: cacheCompiledCoreCode-${{ github.sha }} + + - name: Restore compiled extensions code + id: cacheCompiledExtensionsCode + uses: actions/cache@v2 + with: + path: .build + key: cacheCompiledExtensionsCode-${{ github.sha }} - name: Build VS Code run: yarn gulp vscode-darwin-x64-min-ci From 51a3943093b0ee45918fd09195547a7ad239cd85 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru Date: Mon, 14 Dec 2020 11:29:16 +0100 Subject: [PATCH 0908/1837] Delete PR workflow stub --- .github/workflows/pr.yml | 150 --------------------------------------- 1 file changed, 150 deletions(-) delete mode 100644 .github/workflows/pr.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index 7306c14035f..00000000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: PR - -on: - push: - branches: - - lszomoru/pipeline-improvements - -jobs: - # linux: - # runs-on: ubuntu-latest - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - # - run: | - # sudo apt-get update - # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - # sudo chmod +x /etc/init.d/xvfb - # sudo update-rc.d xvfb defaults - # sudo service xvfb start - # name: Setup Build Environment - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # # TODO: cache node modules - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron x64 - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: DISPLAY=:10 yarn test-browser --browser chromium - # name: Run Unit Tests (Browser) - # - run: DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" - # name: Run Integration Tests (Electron) - - # windows: - # runs-on: windows-2016 - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # - uses: actions/setup-python@v1 - # with: - # python-version: '2.x' - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: .\scripts\test.bat --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: yarn test-browser --browser chromium - # name: Run Unit Tests (Browser) - # - run: .\scripts\test-integration.bat --tfs "Integration Tests" - # name: Run Integration Tests (Electron) - - # darwin: - # runs-on: macos-latest - # env: - # CHILD_CONCURRENCY: "1" - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - uses: actions/checkout@v1 - # - uses: actions/setup-node@v1 - # with: - # node-version: 10 - # - run: yarn --frozen-lockfile - # name: Install Dependencies - # - run: yarn electron x64 - # name: Download Electron - # - run: yarn gulp hygiene - # name: Run Hygiene Checks - # - run: yarn monaco-compile-check - # name: Run Monaco Editor Checks - # - run: yarn valid-layers-check - # name: Run Valid Layers Checks - # - run: yarn compile - # name: Compile Sources - # - run: yarn download-builtin-extensions - # name: Download Built-in Extensions - # - run: ./scripts/test.sh --tfs "Unit Tests" - # name: Run Unit Tests (Electron) - # - run: yarn test-browser --browser chromium --browser webkit - # name: Run Unit Tests (Browser) - # - run: ./scripts/test-integration.sh --tfs "Integration Tests" - # name: Run Integration Tests (Electron) - - monaco: - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-node@v2-beta - with: - node-version: 12 - - - name: Compute yarn cache key - id: yarn-cache-key - run: echo "::set-output name=value::${{ hashFiles('**/yarn.lock') }}" - - - name: Cache root node modules - id: root-node-modules # use this to check for `cache-hit` (`steps.root-node-modules.outputs.cache-hit != 'true'`) - uses: actions/cache@v2 - env: - cache-name: root-node-modules - with: - path: ./node_modules - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ steps.yarn-cache-key.outputs.value }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- - - - run: yarn --frozen-lockfile - name: Install Dependencies - - - run: yarn monaco-compile-check - name: Run Monaco Editor Checks - - - run: yarn gulp editor-esm-bundle - name: Editor Distro & ESM Bundle From 4ba273fddaa3fe28868dd233cad13d52ff2525a5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 11:33:38 +0100 Subject: [PATCH 0909/1837] name marks with source when importing them --- .../services/timer/browser/timerService.ts | 21 ++++++++++--------- .../timer/electron-sandbox/timerService.ts | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index a3988e8c8e7..93ec08f681d 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -333,7 +333,7 @@ export interface ITimerService { readonly _serviceBrand: undefined; readonly startupMetrics: Promise; - submitPerformanceMarks(marks: perf.PerformanceMark[]): void; + submitPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void; } export const ITimerService = createDecorator('timerService'); @@ -341,10 +341,13 @@ export const ITimerService = createDecorator('timerService'); class PerfMarks { - private readonly _entries: perf.PerformanceMark[][] = []; + private readonly _entries = new Map(); - submitMarks(entries: perf.PerformanceMark[]): void { - this._entries.push(entries); + submitMarks(source: string, entries: perf.PerformanceMark[]): void { + if (this._entries.has(source)) { + throw new Error(`${source} EXISTS already`); + } + this._entries.set(source, entries); } getDuration(from: string, to: string): number { @@ -361,7 +364,7 @@ class PerfMarks { private _findEntry(name: string): perf.PerformanceMark | void { - for (let entries of this._entries) { + for (let entries of this._entries.values()) { for (let i = entries.length - 1; i >= 0; i--) { if (entries[i].name === name) { return entries[i]; @@ -413,25 +416,23 @@ export abstract class AbstractTimerService implements ITimerService { } private _submitNativeMarks(): void { - let timeOrigin = performance.timeOrigin; if (!timeOrigin) { // polyfill for Safari const entry = performance.timing; timeOrigin = entry.navigationStart || entry.redirectStart || entry.fetchStart; } - const marks: perf.PerformanceMark[] = performance.getEntriesByType('mark').map(entry => { return { name: entry.name, startTime: timeOrigin + entry.startTime }; }); - this.submitPerformanceMarks(marks); + this.submitPerformanceMarks('renderer', marks); } - submitPerformanceMarks(marks: perf.PerformanceMark[]): void { - this._marks.submitMarks(marks); + submitPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { + this._marks.submitMarks(source, marks); } get startupMetrics(): Promise { diff --git a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts index f3e99027475..2507df59604 100644 --- a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts +++ b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts @@ -33,7 +33,7 @@ export class TimerService extends AbstractTimerService { @ITelemetryService telemetryService: ITelemetryService, ) { super(lifecycleService, contextService, extensionService, updateService, viewletService, panelService, editorService, accessibilityService, telemetryService); - this.submitPerformanceMarks(_environmentService.configuration.perfMarks); + this.submitPerformanceMarks('main', _environmentService.configuration.perfMarks); } protected _isInitialStartup(): boolean { From 3aa342ff68e0c9a8220352645a4e81b437c73da1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 14 Dec 2020 11:38:39 +0100 Subject: [PATCH 0910/1837] Remove use of `getActions` from tunnelView.ts Part of #92038 --- .../contrib/remote/browser/tunnelView.ts | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 8ceda9778c8..8189627d024 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -10,9 +10,9 @@ import { IViewDescriptor, IEditableData, IViewsService, IViewDescriptorService } import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKeyService, IContextKey, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey, RawContextKey, ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { ICommandService, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -24,7 +24,7 @@ import { Disposable, IDisposable, toDisposable, MutableDisposable, dispose, Disp import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { ActionRunner, IAction } from 'vs/base/common/actions'; -import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction, ILocalizedString, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction, ILocalizedString, SubmenuItemAction, Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IRemoteExplorerService, TunnelModel, makeAddress, TunnelType, ITunnelItem, Tunnel, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID, parseAddress } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -637,10 +637,6 @@ export class TunnelPanel extends ViewPane { return contributedContextMenu; } - getActions(): IAction[] { - return this.titleActions; - } - shouldShowWelcome(): boolean { return (this.viewModel.forwarded.length === 0) && (this.viewModel.candidates.length === 0) && (this.viewModel.detected.length === 0) && !this.isEditing; @@ -1120,15 +1116,25 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, ({ }, when: forwardedPortsViewEnabled })); -MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({ - group: 'navigation', - order: 0, - command: { - id: ForwardPortAction.INLINE_ID, - title: ForwardPortAction.LABEL, - icon: Codicon.plus +registerAction2(class extends Action2 { + constructor() { + super({ + id: ForwardPortAction.INLINE_ID, + title: ForwardPortAction.LABEL, + icon: Codicon.plus, + menu: [{ + id: MenuId.ViewTitle, + group: 'navigation', + order: 0, + when: ContextKeyEqualsExpr.create('view', TUNNEL_VIEW_ID), + }] + }); } -})); + run(accessor: ServicesAccessor, ...args: any[]) { + return ForwardPortAction.inlineHandler()(accessor, args); + } +}); + MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({ group: '0_manage', order: 0, From c666c1d72f2cf8c7f91db4fe261507347fc7a682 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 14 Dec 2020 11:43:05 +0100 Subject: [PATCH 0911/1837] Save remote Help&Feedback enablement globally Fixes microsoft/vscode-remote-release#4165 --- src/vs/workbench/contrib/remote/browser/remote.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index b28a9166e84..b755794f5c4 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -457,7 +457,6 @@ class HelpPanelDescriptor implements IViewDescriptor { readonly ctorDescriptor: SyncDescriptor; readonly canToggleVisibility = true; readonly hideByDefault = false; - readonly workspace = true; readonly group = 'help@50'; constructor(viewModel: IViewModel) { From 4df387f5ad1a72bfb87f6de4b8915e104fe80b00 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 11:54:27 +0100 Subject: [PATCH 0912/1837] add a way to read marks with source, adopt in perf view editor --- .../performance/browser/perfviewEditor.ts | 26 ++++++++++--------- .../services/timer/browser/timerService.ts | 26 ++++++++++++------- .../timer/electron-sandbox/timerService.ts | 2 +- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index 5bf819734e5..3f84050a818 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -14,7 +14,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IModelService } from 'vs/editor/common/services/modelService'; import { ITimerService, IStartupMetrics } from 'vs/workbench/services/timer/browser/timerService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import * as perf from 'vs/base/common/performance'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { writeTransientState } from 'vs/workbench/contrib/codeEditor/browser/toggleWordWrap'; @@ -220,18 +219,21 @@ class PerfModelContentProvider implements ITextModelContentProvider { } private _addRawPerfMarks(md: MarkdownBuilder): void { - md.heading(2, 'Raw Perf Marks'); - md.value += '```\n'; - md.value += `Name\tTimestamp\tDelta\tTotal\n`; - let lastStartTime = -1; - let total = 0; - for (const { name, startTime } of perf.getMarks()) { - let delta = lastStartTime !== -1 ? startTime - lastStartTime : 0; - total += delta; - md.value += `${name}\t${startTime}\t${delta}\t${total}\n`; - lastStartTime = startTime; + + for (let [source, marks] of this._timerService.getPerformanceMarks()) { + md.heading(2, `Raw Perf Marks: ${source}`); + md.value += '```\n'; + md.value += `Name\tTimestamp\tDelta\tTotal\n`; + let lastStartTime = -1; + let total = 0; + for (const { name, startTime } of marks) { + let delta = lastStartTime !== -1 ? startTime - lastStartTime : 0; + total += delta; + md.value += `${name}\t${startTime}\t${delta}\t${total}\n`; + lastStartTime = startTime; + } + md.value += '```\n'; } - md.value += '```\n'; } private _addLoaderStats(md: MarkdownBuilder, stats: LoaderStats): void { diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 93ec08f681d..584dbf1ab43 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -333,7 +333,9 @@ export interface ITimerService { readonly _serviceBrand: undefined; readonly startupMetrics: Promise; - submitPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void; + setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void; + + getPerformanceMarks(): [source: string, marks: readonly perf.PerformanceMark[]][]; } export const ITimerService = createDecorator('timerService'); @@ -343,7 +345,7 @@ class PerfMarks { private readonly _entries = new Map(); - submitMarks(source: string, entries: perf.PerformanceMark[]): void { + setMarks(source: string, entries: perf.PerformanceMark[]): void { if (this._entries.has(source)) { throw new Error(`${source} EXISTS already`); } @@ -359,10 +361,9 @@ class PerfMarks { if (!toEntry) { return 0; } - return Math.round(toEntry.startTime - fromEntry.startTime); + return toEntry.startTime - fromEntry.startTime; } - private _findEntry(name: string): perf.PerformanceMark | void { for (let entries of this._entries.values()) { for (let i = entries.length - 1; i >= 0; i--) { @@ -372,8 +373,11 @@ class PerfMarks { } } } -} + getEntries() { + return Array.from(this._entries); + } +} export type Writeable = { -readonly [P in keyof T]: Writeable }; @@ -425,14 +429,18 @@ export abstract class AbstractTimerService implements ITimerService { const marks: perf.PerformanceMark[] = performance.getEntriesByType('mark').map(entry => { return { name: entry.name, - startTime: timeOrigin + entry.startTime + startTime: Math.round(timeOrigin + entry.startTime) }; }); - this.submitPerformanceMarks('renderer', marks); + this.setPerformanceMarks('renderer', marks); } - submitPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { - this._marks.submitMarks(source, marks); + setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { + this._marks.setMarks(source, marks); + } + + getPerformanceMarks(): [source: string, marks: readonly perf.PerformanceMark[]][] { + return this._marks.getEntries(); } get startupMetrics(): Promise { diff --git a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts index 2507df59604..5778a84e1c8 100644 --- a/src/vs/workbench/services/timer/electron-sandbox/timerService.ts +++ b/src/vs/workbench/services/timer/electron-sandbox/timerService.ts @@ -33,7 +33,7 @@ export class TimerService extends AbstractTimerService { @ITelemetryService telemetryService: ITelemetryService, ) { super(lifecycleService, contextService, extensionService, updateService, viewletService, panelService, editorService, accessibilityService, telemetryService); - this.submitPerformanceMarks('main', _environmentService.configuration.perfMarks); + this.setPerformanceMarks('main', _environmentService.configuration.perfMarks); } protected _isInitialStartup(): boolean { From 8b5984e7b8349db6602e995e7e7716a1241cde1b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 14 Dec 2020 12:02:45 +0100 Subject: [PATCH 0913/1837] Windows state deprecations. Fixes #112443 --- .../electron-main/windowsStateHandler.ts | 11 +-- .../electron-main/windowsStateHandler.test.ts | 88 ------------------- 2 files changed, 1 insertion(+), 98 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsStateHandler.ts b/src/vs/platform/windows/electron-main/windowsStateHandler.ts index 453b786f763..939178193b6 100644 --- a/src/vs/platform/windows/electron-main/windowsStateHandler.ts +++ b/src/vs/platform/windows/electron-main/windowsStateHandler.ts @@ -6,7 +6,7 @@ import { app } from 'electron'; import { Disposable } from 'vs/base/common/lifecycle'; import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; -import { URI, UriComponents } from 'vs/base/common/uri'; +import { URI } from 'vs/base/common/uri'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; @@ -43,8 +43,6 @@ interface ISerializedWindowState { readonly uiState: IWindowUIState; // deprecated - readonly folderUri?: UriComponents; - readonly folderPath?: string; readonly workspace?: { id: string; configPath: string }; } @@ -261,18 +259,11 @@ function restoreWindowState(windowState: ISerializedWindowState): IWindowState { if (windowState.folder) { result.folderUri = URI.parse(windowState.folder); - } else if (windowState.folderUri) { - result.folderUri = URI.revive(windowState.folderUri); - } else if (windowState.folderPath) { - result.folderUri = URI.file(windowState.folderPath); } if (windowState.workspaceIdentifier) { result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) }; - } else if (windowState.workspace) { - result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) }; } - return result; } diff --git a/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts b/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts index b5b38d68845..d8377b2e305 100644 --- a/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts +++ b/src/vs/platform/windows/test/electron-main/windowsStateHandler.test.ts @@ -115,94 +115,6 @@ suite('Windows State Storing', () => { assertRestoring(windowState, 'lastPluginDevelopmentHostWindow'); }); - test('open 1_31', () => { - const v1_31_workspace = `{ - "openedWindows": [], - "lastActiveWindow": { - "workspace": { - "id": "a41787288b5e9cc1a61ba2dd84cd0d80", - "configPath": "/home/user/workspaces/code-and-docs.code-workspace" - }, - "backupPath": "/home/user/.config/Code - Insiders/Backups/a41787288b5e9cc1a61ba2dd84cd0d80", - "uiState": { - "mode": 0, - "x": 0, - "y": 27, - "width": 2560, - "height": 1364 - } - } - }`; - - let windowsState = restoreWindowsState(JSON.parse(v1_31_workspace)); - let expected: IWindowsState = { - openedWindows: [], - lastActiveWindow: { - backupPath: '/home/user/.config/Code - Insiders/Backups/a41787288b5e9cc1a61ba2dd84cd0d80', - uiState: { mode: WindowMode.Maximized, x: 0, y: 27, width: 2560, height: 1364 }, - workspace: { id: 'a41787288b5e9cc1a61ba2dd84cd0d80', configPath: URI.file('/home/user/workspaces/code-and-docs.code-workspace') } - } - }; - - assertEqualWindowsState(expected, windowsState, 'v1_31_workspace'); - - const v1_31_folder = `{ - "openedWindows": [], - "lastPluginDevelopmentHostWindow": { - "folderUri": { - "$mid": 1, - "fsPath": "/home/user/workspaces/testing/customdata", - "external": "file:///home/user/workspaces/testing/customdata", - "path": "/home/user/workspaces/testing/customdata", - "scheme": "file" - }, - "uiState": { - "mode": 1, - "x": 593, - "y": 617, - "width": 1625, - "height": 595 - } - } - }`; - - windowsState = restoreWindowsState(JSON.parse(v1_31_folder)); - expected = { - openedWindows: [], - lastPluginDevelopmentHostWindow: { - uiState: { mode: WindowMode.Normal, x: 593, y: 617, width: 1625, height: 595 }, - folderUri: URI.parse('file:///home/user/workspaces/testing/customdata') - } - }; - assertEqualWindowsState(expected, windowsState, 'v1_31_folder'); - - const v1_31_empty_window = ` { - "openedWindows": [ - ], - "lastActiveWindow": { - "backupPath": "C:\\\\Users\\\\Mike\\\\AppData\\\\Roaming\\\\Code\\\\Backups\\\\1549538599815", - "uiState": { - "mode": 0, - "x": -8, - "y": -8, - "width": 2576, - "height": 1344 - } - } - }`; - - windowsState = restoreWindowsState(JSON.parse(v1_31_empty_window)); - expected = { - openedWindows: [], - lastActiveWindow: { - backupPath: 'C:\\Users\\Mike\\AppData\\Roaming\\Code\\Backups\\1549538599815', - uiState: { mode: WindowMode.Maximized, x: -8, y: -8, width: 2576, height: 1344 } - } - }; - assertEqualWindowsState(expected, windowsState, 'v1_31_empty_window'); - - }); - test('open 1_32', () => { const v1_32_workspace = `{ "openedWindows": [], From 7168a1bf157fde4d56bce0d7929e4b00f921e436 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 12:51:15 +0100 Subject: [PATCH 0914/1837] remove unused measure `ellapsedTimersToTimersComputed` --- src/vs/workbench/services/timer/browser/timerService.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 584dbf1ab43..11ce9f7cf7e 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -53,7 +53,6 @@ export interface IMemoryInfo { "timers.ellapsedPanelRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedEditorRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedWorkbench" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, - "timers.ellapsedTimersToTimersComputed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedNlsGeneration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "platform" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "release" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, @@ -311,10 +310,6 @@ export interface IStartupMetrics { * * Measured with the `renderer/started` and `didStartWorkbench` performance marks */ readonly ellapsedRenderer: number; - - // the time it took to generate this object. - // remove? - readonly ellapsedTimersToTimersComputed: number; }; readonly hasAccessibilitySupport: boolean; @@ -465,7 +460,6 @@ export abstract class AbstractTimerService implements ITimerService { } private async _computeStartupMetrics(): Promise { - const now = Date.now(); const initialStartup = this._isInitialStartup(); const startMark = initialStartup ? 'main:started' : 'main:loadWindow'; @@ -503,8 +497,7 @@ export abstract class AbstractTimerService implements ITimerService { ellapsedPanelRestore: this._marks.getDuration('willRestorePanel', 'didRestorePanel'), ellapsedWorkbench: this._marks.getDuration('willStartWorkbench', 'didStartWorkbench'), ellapsedExtensionsReady: this._marks.getDuration(startMark, 'didLoadExtensions'), - ellapsedRenderer: this._marks.getDuration('renderer/started', 'didStartWorkbench'), - ellapsedTimersToTimersComputed: Date.now() - now, + ellapsedRenderer: this._marks.getDuration('renderer/started', 'didStartWorkbench') }, // system info From 704393a57cf7827553ee243c50e772ac2d257513 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 14 Dec 2020 13:08:21 +0100 Subject: [PATCH 0915/1837] fixes #112410 --- src/vs/workbench/contrib/debug/browser/replViewer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts index da2f2d1cef7..5f6dbc2a786 100644 --- a/src/vs/workbench/contrib/debug/browser/replViewer.ts +++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts @@ -389,7 +389,8 @@ export class ReplAccessibilityProvider implements IListAccessibilityProvider 1 ? localize('occurred', ", occured {0} times", element.count) : ''); + return element.value + (element instanceof SimpleReplElement && element.count > 1 ? localize({ key: 'occurred', comment: ['Front will the the value of the debug console element. Placeholder will be replaced by a number which represents occurrance count.'] }, + ", occured {0} times", element.count) : ''); } if (element instanceof RawObjectReplElement) { return localize('replRawObjectAriaLabel', "Debug console variable {0}, value {1}", element.name, element.value); From 28776ec1a28f1267b17da74dff640d2e23b13a84 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 13:15:35 +0100 Subject: [PATCH 0916/1837] Cache yarn cache directory --- .github/workflows/ci.yml | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f0bc254a61..e28846af350 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -61,6 +72,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -103,6 +125,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -258,6 +291,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -315,6 +359,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -366,6 +421,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -428,6 +494,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -483,6 +560,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: @@ -520,6 +608,17 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules- + - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarnCacheDir- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From 90f0cf5b3131a55522a4e0227e0a3b8d42a38316 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 13:16:33 +0100 Subject: [PATCH 0917/1837] Force cacheNodeModules to fail --- .github/workflows/ci.yml | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e28846af350..7a99d4b3ba3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -70,8 +70,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -123,8 +123,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -181,8 +181,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -243,8 +243,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -289,8 +289,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -357,8 +357,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -419,8 +419,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -492,8 +492,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -558,8 +558,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -606,8 +606,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -654,8 +654,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules- + key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules2- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From 7d4c5a2c0fb76f3dc78cdf57b83c31b2430b863a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 13:28:16 +0100 Subject: [PATCH 0918/1837] Add a dedicated `Build: macOS Node Modules` job --- .github/workflows/ci.yml | 114 ++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 63 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a99d4b3ba3..f647bc51c44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -70,8 +70,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -123,8 +123,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -181,8 +181,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -243,8 +243,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -271,9 +271,8 @@ jobs: - name: Run Integration Tests (Electron) run: DISPLAY=:10 ./scripts/test-integration.sh --build - build-darwin-unit-tests: - name: "Build: macOS Unit Tests" - needs: [build-compile-core, build-compile-extensions] + build-darwin-node-modules: + name: "Build: macOS Node Modules" runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -289,8 +288,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -308,6 +307,27 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 run: yarn --frozen-lockfile + build-darwin-unit-tests: + name: "Build: macOS Unit Tests" + needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] + runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2-beta + with: + node-version: 12 + + - name: Restore cached node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- + - name: Restore compiled core code id: cacheCompiledCoreCode uses: actions/cache@v2 @@ -341,7 +361,7 @@ jobs: build-darwin-integration-tests: name: "Build: macOS Integration Tests" - needs: [build-compile-core, build-compile-extensions] + needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -352,29 +372,13 @@ jobs: with: node-version: 12 - - name: Cache node modules + - name: Restore cached node modules id: cacheNodeModules uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- - - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-yarnCacheDir- - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -403,7 +407,7 @@ jobs: build-darwin-smoke-tests: name: "Build: macOS Smoke Tests" - needs: [build-compile-core, build-compile-extensions] + needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] runs-on: macos-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -414,29 +418,13 @@ jobs: with: node-version: 12 - - name: Cache node modules + - name: Restore cached node modules id: cacheNodeModules uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- - - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-yarnCacheDir- - - name: Execute yarn - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Restore compiled core code id: cacheCompiledCoreCode @@ -492,8 +480,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -558,8 +546,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -606,8 +594,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -654,8 +642,8 @@ jobs: uses: actions/cache@v2 with: path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules2- + key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From 5f20ce95815ee7205d85482183ec48ee78c8482e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 13:41:08 +0100 Subject: [PATCH 0919/1837] Increase yarn's network timeout --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f647bc51c44..c9888dcd85d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Run Hygiene Checks run: yarn gulp hygiene @@ -87,7 +87,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Cache compiled core code id: cacheCompiledCoreCode @@ -140,7 +140,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Cache compiled extensions code id: cacheCompiledExtensionsCode @@ -305,7 +305,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 build-darwin-unit-tests: name: "Build: macOS Unit Tests" @@ -497,7 +497,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" @@ -563,7 +563,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" @@ -611,7 +611,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" @@ -648,7 +648,7 @@ jobs: if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: yarn --frozen-lockfile + run: yarn --frozen-lockfile --network-timeout 180000 - name: Run Monaco Editor Checks run: yarn monaco-compile-check From e56597ab7a654dbc2b3edd1036ef7301718d621d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 13:44:35 +0100 Subject: [PATCH 0920/1837] Save 1.5 seconds from `gulp` startup time --- build/gulpfile.vscode.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index bb8b2454a9b..91853430d7e 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -36,8 +36,6 @@ const minimist = require('minimist'); const { compileBuildTask } = require('./gulpfile.compile'); const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); -const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); - // Build const vscodeEntryPoints = _.flatten([ buildfile.entrypoint('vs/workbench/workbench.desktop.main'), @@ -202,6 +200,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path)); const root = path.resolve(path.join(__dirname, '..')); + const productionDependencies = deps.getProductionDependencies(root); const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])); const deps = gulp.src(dependenciesSrc, { base: '.', dot: true }) From ac6cadf8ee2b200c3f957d4ee493ed29af43140d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 14:01:43 +0100 Subject: [PATCH 0921/1837] Fix gulpfile --- build/gulpfile.vscode.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 91853430d7e..90fefa49562 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -29,7 +29,7 @@ const packageJson = require('../package.json'); const product = require('../product.json'); const crypto = require('crypto'); const i18n = require('./lib/i18n'); -const deps = require('./dependencies'); +const { getProductionDependencies } = require('./dependencies'); const { config } = require('./lib/electron'); const createAsar = require('./lib/asar').createAsar; const minimist = require('minimist'); @@ -200,7 +200,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path)); const root = path.resolve(path.join(__dirname, '..')); - const productionDependencies = deps.getProductionDependencies(root); + const productionDependencies = getProductionDependencies(root); const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])); const deps = gulp.src(dependenciesSrc, { base: '.', dot: true }) From c7df7d91f42ca6510298ac9d174c3a13065c3fb7 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 14:24:34 +0100 Subject: [PATCH 0922/1837] Move actual gulpfile logic to `/build/` --- build/gulpfile.js | 41 +++++++++++++++++++++++++++++++++++++++++ gulpfile.js | 39 +-------------------------------------- 2 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 build/gulpfile.js diff --git a/build/gulpfile.js b/build/gulpfile.js new file mode 100644 index 00000000000..69b37c7c667 --- /dev/null +++ b/build/gulpfile.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. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +// Increase max listeners for event emitters +require('events').EventEmitter.defaultMaxListeners = 100; + +const gulp = require('gulp'); +const util = require('./lib/util'); +const task = require('./lib/task'); +const compilation = require('./lib/compilation'); +const { monacoTypecheckTask/* , monacoTypecheckWatchTask */ } = require('./gulpfile.editor'); +const { compileExtensionsTask, watchExtensionsTask } = require('./gulpfile.extensions'); + +// Fast compile for development time +const compileClientTask = task.define('compile-client', task.series(util.rimraf('out'), compilation.compileTask('src', 'out', false))); +gulp.task(compileClientTask); + +const watchClientTask = task.define('watch-client', task.series(util.rimraf('out'), compilation.watchTask('out', false))); +gulp.task(watchClientTask); + +// All +const compileTask = task.define('compile', task.parallel(monacoTypecheckTask, compileClientTask, compileExtensionsTask)); +gulp.task(compileTask); + +gulp.task(task.define('watch', task.parallel(/* monacoTypecheckWatchTask, */ watchClientTask, watchExtensionsTask))); + +// Default +gulp.task('default', compileTask); + +process.on('unhandledRejection', (reason, p) => { + console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); + process.exit(1); +}); + +// Load all the gulpfiles only if running tasks other than the editor tasks +require('glob').sync('gulpfile.*.js', { cwd: __dirname }) + .forEach(f => require(`./${f}`)); diff --git a/gulpfile.js b/gulpfile.js index 1d13cff608c..9691ba80607 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,41 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -// Increase max listeners for event emitters -require('events').EventEmitter.defaultMaxListeners = 100; - -const gulp = require('gulp'); -const util = require('./build/lib/util'); -const task = require('./build/lib/task'); -const path = require('path'); -const compilation = require('./build/lib/compilation'); -const { monacoTypecheckTask/* , monacoTypecheckWatchTask */ } = require('./build/gulpfile.editor'); -const { compileExtensionsTask, watchExtensionsTask } = require('./build/gulpfile.extensions'); - -// Fast compile for development time -const compileClientTask = task.define('compile-client', task.series(util.rimraf('out'), compilation.compileTask('src', 'out', false))); -gulp.task(compileClientTask); - -const watchClientTask = task.define('watch-client', task.series(util.rimraf('out'), compilation.watchTask('out', false))); -gulp.task(watchClientTask); - -// All -const compileTask = task.define('compile', task.parallel(monacoTypecheckTask, compileClientTask, compileExtensionsTask)); -gulp.task(compileTask); - -gulp.task(task.define('watch', task.parallel(/* monacoTypecheckWatchTask, */ watchClientTask, watchExtensionsTask))); - -// Default -gulp.task('default', compileTask); - -process.on('unhandledRejection', (reason, p) => { - console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); - process.exit(1); -}); - -// Load all the gulpfiles only if running tasks other than the editor tasks -const build = path.join(__dirname, 'build'); -require('glob').sync('gulpfile.*.js', { cwd: build }) - .forEach(f => require(`./build/${f}`)); +require('./build/gulpfile'); From 200d60cc13cc59ec81df8e2d6d7b454670cd1c10 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 15:01:55 +0100 Subject: [PATCH 0923/1837] Do not create issue on failure --- .github/workflows/ci.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9888dcd85d..4ee616c6b30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -514,16 +514,6 @@ jobs: id: electron-integration-tests run: DISPLAY=:10 ./scripts/test-integration.sh - - name: Create Issue on Unit Test Failure - uses: nashmaniac/create-issue-action@v1.1 - if: ${{ failure() }} - with: - title: "CI: Test Failure" - token: ${{secrets.GITHUB_TOKEN}} - assignees: alexdima #${{github.actor}} - labels: unit-test-failure linux - body: Running tests failed for commit ${{github.sha}}. Please see https://github.com/microsoft/vscode/actions/runs/${{github.run_id}} - windows: name: Windows runs-on: windows-latest From b1524d6b34efa9d3b37d713494ecd2f51c879271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 11 Dec 2020 20:28:45 +0100 Subject: [PATCH 0924/1837] build: VSCODE_PUBLISH --- .../darwin/product-build-darwin.yml | 15 +++++++++++---- .../linux/product-build-alpine.yml | 1 + .../linux/product-build-linux.yml | 12 +++++++++++- build/azure-pipelines/product-build.yml | 12 ++++++------ build/azure-pipelines/product-compile.yml | 11 +++++------ .../win32/product-build-win32.yml | 16 ++++++++++++++-- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 28da2b70ee0..d76daf8788d 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -147,7 +147,7 @@ steps: yarn gulp vscode-reh-darwin-min-ci VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-reh-web-darwin-min-ci - displayName: Build reh + displayName: Build Server condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - script: | @@ -166,6 +166,7 @@ steps: security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain VSCODE_ARCH="$(VSCODE_ARCH)" DEBUG=electron-osx-sign* node build/darwin/sign.js displayName: Set Hardened Entitlements + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -245,6 +246,7 @@ steps: set -e pushd $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) && zip -r -X -y $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip * && popd displayName: Archive build + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: @@ -269,10 +271,12 @@ steps: ] SessionTimeout: 60 displayName: Codesign + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | zip -d $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip "*.pkg" - displayName: Clean Archive + displayName: Clean + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) @@ -280,6 +284,7 @@ steps: BUNDLE_IDENTIFIER=$(node -p "require(\"$APP_ROOT/$APP_NAME/Contents/Resources/app/product.json\").darwinBundleIdentifier") echo "##vso[task.setvariable variable=BundleIdentifier]$BUNDLE_IDENTIFIER" displayName: Export bundle identifier + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: @@ -304,6 +309,7 @@ steps: ] SessionTimeout: 60 displayName: Notarization + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -311,7 +317,7 @@ steps: APP_NAME="`ls $APP_ROOT | head -n 1`" "$APP_ROOT/$APP_NAME/Contents/Resources/app/bin/code" --export-default-configuration=.build displayName: Verify start after signing (export configuration) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -322,13 +328,14 @@ steps: VSCODE_ARCH="$(VSCODE_ARCH)" \ ./build/azure-pipelines/darwin/publish.sh displayName: Publish + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ VSCODE_ARCH="$(VSCODE_ARCH)" \ yarn gulp upload-vscode-configuration displayName: Upload configuration (for Bing settings search) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), ne(variables['VSCODE_PUBLISH'], 'false')) continueOnError: true - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 8108ff8193d..9998b482d59 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -129,6 +129,7 @@ steps: VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ ./build/azure-pipelines/linux/alpine/publish.sh displayName: Publish + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: "Component Detection" diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 6c9d24da74f..ef65d5fabac 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -128,11 +128,15 @@ steps: set -e VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-linux-$(VSCODE_ARCH)-min-ci + displayName: Build + + - script: | + set -e VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci - displayName: Build + displayName: Build Server - script: | set -e @@ -198,17 +202,20 @@ steps: yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-deb" yarn gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm" displayName: Build deb, rpm packages + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e yarn gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap" displayName: Prepare snap package + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) # needed for code signing - task: UseDotNet@2 displayName: "Install .NET Core SDK 2.x" inputs: version: 2.x + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: @@ -228,6 +235,7 @@ steps: ] SessionTimeout: 120 displayName: Codesign rpm + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -237,12 +245,14 @@ steps: VSCODE_ARCH="$(VSCODE_ARCH)" \ ./build/azure-pipelines/linux/publish.sh displayName: Publish + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: PublishPipelineArtifact@0 displayName: "Publish Pipeline Artifact" inputs: artifactName: "snap-$(VSCODE_ARCH)" targetPath: .build/linux/snap-tarball + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: "Component Detection" diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 2b3d87d119d..e27c8d17cd7 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -85,7 +85,7 @@ stages: - job: LinuxSnap dependsOn: - Linux - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) container: snapcraft variables: VSCODE_ARCH: x64 @@ -104,7 +104,7 @@ stages: - job: LinuxSnapArmhf dependsOn: - LinuxArmhf - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) container: snapcraft variables: VSCODE_ARCH: armhf @@ -123,7 +123,7 @@ stages: - job: LinuxSnapArm64 dependsOn: - LinuxArm64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) container: snapcraft variables: VSCODE_ARCH: arm64 @@ -136,7 +136,7 @@ stages: - template: linux/product-build-alpine.yml - job: LinuxWeb - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WEB'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) variables: VSCODE_ARCH: x64 steps: @@ -178,7 +178,7 @@ stages: - Linux - macOS - macOSARM64 - condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), ne(variables['VSCODE_PUBLISH'], 'false')) pool: vmImage: "Ubuntu-18.04" jobs: @@ -193,7 +193,7 @@ stages: - Linux - macOS - macOSARM64 - condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), ne(variables['VSCODE_PUBLISH'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) pool: vmImage: "Ubuntu-18.04" jobs: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 66baef772c8..5a851eea6f3 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -97,8 +97,7 @@ steps: displayName: Run postinstall scripts condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) - # Mixin must run before optimize, because the CSS loader will - # inline small SVGs + # Mixin must run before optimize, because the CSS loader will inline small SVGs - script: | set -e node build/azure-pipelines/mixin @@ -117,14 +116,14 @@ steps: set - ./build/azure-pipelines/common/extract-telemetry.sh displayName: Extract Telemetry - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ ./build/azure-pipelines/common/publish-webview.sh displayName: Publish Webview - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -141,7 +140,7 @@ steps: AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ node build/azure-pipelines/upload-sourcemaps displayName: Upload sourcemaps - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -149,7 +148,7 @@ steps: AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ node build/azure-pipelines/common/createBuild.js $VERSION displayName: Create build - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 5c8806401d5..ed7c526cf3f 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -107,11 +107,18 @@ steps: $ErrorActionPreference = "Stop" $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-min-ci" } - exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-code-helper" } - exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-inno-updater" } echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" displayName: Build + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-code-helper" } + exec { yarn gulp "vscode-win32-$(VSCODE_ARCH)-inno-updater" } + displayName: Prepare Package + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) + - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" @@ -236,6 +243,7 @@ steps: } ] SessionTimeout: 120 + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: NuGetCommand@2 displayName: Install ESRPClient.exe @@ -245,11 +253,13 @@ steps: nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config' externalFeedCredentials: "ESRP Nuget" restoreDirectory: packages + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: ESRPImportCertTask@1 displayName: Import ESRP Request Signing Certificate inputs: ESRP: "ESRP CodeSign" + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: PowerShell@2 inputs: @@ -257,6 +267,7 @@ steps: filePath: .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 arguments: "$(ESRP-SSL-AADAuth)" displayName: Import ESRP Auth Certificate + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - powershell: | . build/azure-pipelines/win32/exec.ps1 @@ -266,6 +277,7 @@ steps: $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" .\build\azure-pipelines\win32\publish.ps1 displayName: Publish + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: "Component Detection" From 2af62a03fe3332ea225ebd479db402ca26f28b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 11 Dec 2020 22:00:38 +0100 Subject: [PATCH 0925/1837] simplify continuous build --- build/azure-pipelines/product-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index e27c8d17cd7..efcf1903187 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -51,7 +51,7 @@ stages: - template: win32/product-build-win32.yml - job: Windows32 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) timeoutInMinutes: 90 variables: VSCODE_ARCH: ia32 @@ -59,7 +59,7 @@ stages: - template: win32/product-build-win32.yml - job: WindowsARM64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32_ARM64'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) timeoutInMinutes: 90 variables: VSCODE_ARCH: arm64 @@ -93,7 +93,7 @@ stages: - template: linux/snap-build-linux.yml - job: LinuxArmhf - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) container: vscode-armhf variables: VSCODE_ARCH: armhf @@ -112,7 +112,7 @@ stages: - template: linux/snap-build-linux.yml - job: LinuxArm64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) container: vscode-arm64 variables: VSCODE_ARCH: arm64 @@ -131,7 +131,7 @@ stages: - template: linux/snap-build-linux.yml - job: LinuxAlpine - condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) steps: - template: linux/product-build-alpine.yml @@ -165,7 +165,7 @@ stages: vmImage: macOS-latest jobs: - job: macOSARM64 - condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS_ARM64'], 'true')) + condition: and(succeeded(), eq(variables['VSCODE_BUILD_MACOS_ARM64'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) timeoutInMinutes: 90 variables: VSCODE_ARCH: arm64 From d67e33f0b0d00031c6ccb953015a2a037b73c631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Sat, 12 Dec 2020 13:45:05 +0100 Subject: [PATCH 0926/1837] split compile & hygiene --- build/azure-pipelines/product-build.yml | 21 +++++ build/azure-pipelines/product-compile.yml | 42 +-------- .../azure-pipelines/product-dependencies.yml | 92 +++++++++++++++++++ build/azure-pipelines/product-hygiene.yml | 89 ++++++++++++++++++ 4 files changed, 206 insertions(+), 38 deletions(-) create mode 100644 build/azure-pipelines/product-dependencies.yml create mode 100644 build/azure-pipelines/product-hygiene.yml diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index efcf1903187..962bde3aa97 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -24,7 +24,20 @@ resources: image: snapcore/snapcraft:stable stages: + - stage: Dependencies + jobs: + - job: Dependencies + pool: + vmImage: "Ubuntu-18.04" + container: vscode-x64 + variables: + VSCODE_ARCH: x64 + steps: + - template: product-dependencies.yml + - stage: Compile + dependsOn: + - Dependencies jobs: - job: Compile pool: @@ -34,6 +47,14 @@ stages: VSCODE_ARCH: x64 steps: - template: product-compile.yml + - job: Hygiene + pool: + vmImage: "Ubuntu-18.04" + container: vscode-x64 + variables: + VSCODE_ARCH: x64 + steps: + - template: product-hygiene.yml - stage: Windows dependsOn: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 5a851eea6f3..916e5cef3ce 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -70,25 +70,12 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + # TODO@Joao: remove - script: | set -e - export CHILD_CONCURRENCY="1" - for i in {1..3}; do # try 3 times, for Terrapin - yarn --frozen-lockfile && break - if [ $i -eq 3 ]; then - echo "Yarn failed too many times" >&2 - exit 1 - fi - echo "Yarn failed $i, trying again..." - done - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - - - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" + echo "Restore cache should not have failed" + exit 1 + displayName: Check cache restore condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - script: | @@ -104,27 +91,6 @@ steps: displayName: Mix in quality condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - script: | - set -e - yarn gulp hygiene - yarn monaco-compile-check - yarn valid-layers-check - displayName: Run hygiene, monaco compile & valid layers checks - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - - - script: | - set - - ./build/azure-pipelines/common/extract-telemetry.sh - displayName: Extract Telemetry - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - - - script: | - set -e - AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ - ./build/azure-pipelines/common/publish-webview.sh - displayName: Publish Webview - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) - - script: | set -e yarn gulp compile-build diff --git a/build/azure-pipelines/product-dependencies.yml b/build/azure-pipelines/product-dependencies.yml new file mode 100644 index 00000000000..01eb347cae5 --- /dev/null +++ b/build/azure-pipelines/product-dependencies.yml @@ -0,0 +1,92 @@ +steps: + - script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality + echo -n $ENABLE_TERRAPIN > .build/terrapin + displayName: Prepare compilation cache flag + + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + vstsFeed: "npm-vscode" + platformIndependent: true + alias: "Compilation" + dryRun: true + + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) + + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + + - script: | + set -e + export CHILD_CONCURRENCY="1" + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." + done + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml new file mode 100644 index 00000000000..aa9e3642f5e --- /dev/null +++ b/build/azure-pipelines/product-hygiene.yml @@ -0,0 +1,89 @@ +steps: + - script: | + mkdir -p .build + echo -n $ENABLE_TERRAPIN > .build/terrapin + displayName: Prepare compilation cache flag + + - task: NodeTool@0 + inputs: + versionSpec: "12.18.3" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" + + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode + + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + + - script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + + # TODO@Joao: remove + - script: | + set -e + echo "Restore cache should not have failed" + exit 1 + displayName: Check cache restore + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + + - script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + + # Mixin must run before optimize, because the CSS loader will inline small SVGs + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + + - script: | + set -e + yarn gulp hygiene + yarn monaco-compile-check + yarn valid-layers-check + displayName: Run hygiene, monaco compile & valid layers checks + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + + - script: | + set - + ./build/azure-pipelines/common/extract-telemetry.sh + displayName: Extract Telemetry + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) + + - script: | + set -e + AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ + ./build/azure-pipelines/common/publish-webview.sh + displayName: Publish Webview + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) From 2f2004f5fa8e8118b553625b347138fddb796a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Sat, 12 Dec 2020 13:58:10 +0100 Subject: [PATCH 0927/1837] faster dependencies check --- build/azure-pipelines/product-compile.yml | 5 +-- .../azure-pipelines/product-dependencies.yml | 42 +++++++------------ 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 916e5cef3ce..3b889db65be 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -4,6 +4,7 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin + echo -n $(VSCODE_ARCH) > .build/arch displayName: Prepare compilation cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -59,10 +60,6 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - script: | - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare yarn cache flags - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/product-dependencies.yml b/build/azure-pipelines/product-dependencies.yml index 01eb347cae5..3e8d3aef85d 100644 --- a/build/azure-pipelines/product-dependencies.yml +++ b/build/azure-pipelines/product-dependencies.yml @@ -1,36 +1,35 @@ steps: - script: | mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - displayName: Prepare compilation cache flag + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" - dryRun: true + alias: "Dependencies" + dryRun: true + displayName: Check dependencies cache - task: NodeTool@0 inputs: versionSpec: "12.18.3" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.x" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" inputs: azureSubscription: "vscode-builds-subscription" KeyVaultName: vscode - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - script: | set -e @@ -43,7 +42,7 @@ steps: git config user.email "vscode@microsoft.com" git config user.name "VSCode" displayName: Prepare tooling - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - script: | set -e @@ -51,24 +50,13 @@ steps: git fetch distro git merge $(node -p "require('./package.json').distro") displayName: Merge distro - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - - script: | - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare yarn cache flags - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | set -e @@ -82,11 +70,11 @@ steps: echo "Yarn failed $i, trying again..." done displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) From 064e1d19dfdb2978b4a39eb4460f82ca928f5f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Sat, 12 Dec 2020 13:58:52 +0100 Subject: [PATCH 0928/1837] fix yaml --- build/azure-pipelines/product-dependencies.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/azure-pipelines/product-dependencies.yml b/build/azure-pipelines/product-dependencies.yml index 3e8d3aef85d..133ce57bf68 100644 --- a/build/azure-pipelines/product-dependencies.yml +++ b/build/azure-pipelines/product-dependencies.yml @@ -11,7 +11,7 @@ steps: targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" alias: "Dependencies" - dryRun: true + dryRun: true displayName: Check dependencies cache - task: NodeTool@0 From 5f31a6ddc66cdb43c187918ada5282ef42b3bbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Sat, 12 Dec 2020 14:13:28 +0100 Subject: [PATCH 0929/1837] Revert "fix yaml" This reverts commit bdd7e522bfd570079f80c066dc92abcd731086c3. Revert "faster dependencies check" This reverts commit 42708cb1a59215b4a9e8b01eb9b5f89f03831ca7. --- build/azure-pipelines/product-compile.yml | 5 ++- .../azure-pipelines/product-dependencies.yml | 40 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 3b889db65be..916e5cef3ce 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -4,7 +4,6 @@ steps: echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $(VSCODE_ARCH) > .build/arch displayName: Prepare compilation cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -60,6 +59,10 @@ steps: timeoutInMinutes: 5 condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" diff --git a/build/azure-pipelines/product-dependencies.yml b/build/azure-pipelines/product-dependencies.yml index 133ce57bf68..01eb347cae5 100644 --- a/build/azure-pipelines/product-dependencies.yml +++ b/build/azure-pipelines/product-dependencies.yml @@ -1,35 +1,36 @@ steps: - script: | mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + echo -n $VSCODE_QUALITY > .build/quality echo -n $ENABLE_TERRAPIN > .build/terrapin - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare cache flags + displayName: Prepare compilation cache flag - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" + targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" vstsFeed: "npm-vscode" - alias: "Dependencies" + platformIndependent: true + alias: "Compilation" dryRun: true - displayName: Check dependencies cache - task: NodeTool@0 inputs: versionSpec: "12.18.3" - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.x" - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" inputs: azureSubscription: "vscode-builds-subscription" KeyVaultName: vscode - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -42,7 +43,7 @@ steps: git config user.email "vscode@microsoft.com" git config user.name "VSCode" displayName: Prepare tooling - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -50,13 +51,24 @@ steps: git fetch distro git merge $(node -p "require('./package.json').distro") displayName: Merge distro - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) + + - script: | + echo -n $(VSCODE_ARCH) > .build/arch + displayName: Prepare yarn cache flags + + - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -70,11 +82,11 @@ steps: echo "Yarn failed $i, trying again..." done displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Dependencies'], 'true')) + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) From f9b89066c7ac76969f370a7654eb054cd25e14fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Sat, 12 Dec 2020 14:23:11 +0100 Subject: [PATCH 0930/1837] remove dependencies stage --- build/azure-pipelines/product-build.yml | 13 --- build/azure-pipelines/product-compile.yml | 21 ++++- .../azure-pipelines/product-dependencies.yml | 92 ------------------- build/azure-pipelines/product-hygiene.yml | 14 ++- 4 files changed, 27 insertions(+), 113 deletions(-) delete mode 100644 build/azure-pipelines/product-dependencies.yml diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 962bde3aa97..0863ae0d6fc 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -24,20 +24,7 @@ resources: image: snapcore/snapcraft:stable stages: - - stage: Dependencies - jobs: - - job: Dependencies - pool: - vmImage: "Ubuntu-18.04" - container: vscode-x64 - variables: - VSCODE_ARCH: x64 - steps: - - template: product-dependencies.yml - - stage: Compile - dependsOn: - - Dependencies jobs: - job: Compile pool: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 916e5cef3ce..fb67aecafb4 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -70,12 +70,25 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - # TODO@Joao: remove - script: | set -e - echo "Restore cache should not have failed" - exit 1 - displayName: Check cache restore + export CHILD_CONCURRENCY="1" + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." + done + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + + - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" + targetfolder: "**/node_modules, !**/node_modules/**/node_modules" + vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - script: | diff --git a/build/azure-pipelines/product-dependencies.yml b/build/azure-pipelines/product-dependencies.yml deleted file mode 100644 index 01eb347cae5..00000000000 --- a/build/azure-pipelines/product-dependencies.yml +++ /dev/null @@ -1,92 +0,0 @@ -steps: - - script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - echo -n $ENABLE_TERRAPIN > .build/terrapin - displayName: Prepare compilation cache flag - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" - vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" - dryRun: true - - - task: NodeTool@0 - inputs: - versionSpec: "12.18.3" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - task: AzureKeyVault@1 - displayName: "Azure Key Vault: Get Secrets" - inputs: - azureSubscription: "vscode-builds-subscription" - KeyVaultName: vscode - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF - - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - script: | - set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") - displayName: Merge distro - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) - - - script: | - echo -n $(VSCODE_ARCH) > .build/arch - displayName: Prepare yarn cache flags - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - - - script: | - set -e - export CHILD_CONCURRENCY="1" - for i in {1..3}; do # try 3 times, for Terrapin - yarn --frozen-lockfile && break - if [ $i -eq 3 ]; then - echo "Yarn failed too many times" >&2 - exit 1 - fi - echo "Yarn failed $i, trying again..." - done - displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - - - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" - targetfolder: "**/node_modules, !**/node_modules/**/node_modules" - vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index aa9e3642f5e..1c971c7404c 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -47,12 +47,18 @@ steps: targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - # TODO@Joao: remove - script: | set -e - echo "Restore cache should not have failed" - exit 1 - displayName: Check cache restore + export CHILD_CONCURRENCY="1" + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." + done + displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | From 7381f53fd1876472b757b0f0b32bd8a1399034f3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 14 Dec 2020 15:33:23 +0100 Subject: [PATCH 0931/1837] windows - move out more state code into separate class --- .../electron-main/windowsMainService.ts | 177 +-------------- .../electron-main/windowsStateHandler.ts | 212 ++++++++++++++++-- .../electron-sandbox/actions/windowActions.ts | 16 +- 3 files changed, 205 insertions(+), 200 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 005897bc0af..e1bcd6c2063 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -12,8 +12,8 @@ import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateService } from 'vs/platform/state/node/state'; -import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; -import { screen, BrowserWindow, MessageBoxOptions, Display, WebContents } from 'electron'; +import { CodeWindow } from 'vs/code/electron-main/window'; +import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; @@ -21,7 +21,7 @@ import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder'; import { Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; -import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces'; @@ -43,10 +43,6 @@ import { CancellationToken } from 'vs/base/common/cancellation'; //#region Helper Interfaces -interface INewWindowState extends ISingleWindowState { - hasDefaultState?: boolean; -} - type RestoreWindowsSetting = 'preserve' | 'all' | 'folders' | 'one' | 'none'; interface IOpenBrowserWindowOptions { @@ -159,7 +155,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private readonly _onWindowsCountChanged = this._register(new Emitter()); readonly onWindowsCountChanged = this._onWindowsCountChanged.event; - private readonly windowsStateHandler = this._register(new WindowsStateHandler(this.stateService, this.lifecycleMainService, this, this.logService)); + private readonly windowsStateHandler = this._register(new WindowsStateHandler(this, this.stateService, this.lifecycleMainService, this.logService, this.configurationService)); constructor( private readonly machineId: string, @@ -193,10 +189,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic cli = { ...cli, remote }; } + const forceEmpty = true; const forceReuseWindow = options?.forceReuseWindow; const forceNewWindow = !forceReuseWindow; - return this.open({ ...openConfig, cli, forceEmpty: true, forceNewWindow, forceReuseWindow }); + return this.open({ ...openConfig, cli, forceEmpty, forceNewWindow, forceReuseWindow }); } open(openConfig: IOpenConfiguration): ICodeWindow[] { @@ -476,7 +473,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Open remaining ones allWorkspacesToOpen.forEach(workspaceToOpen => { - if (windowsOnWorkspace.some(win => win.openedWorkspace && win.openedWorkspace.id === workspaceToOpen.workspace.id)) { + if (windowsOnWorkspace.some(window => window.openedWorkspace && window.openedWorkspace.id === workspaceToOpen.workspace.id)) { return; // ignore folders that are already open } @@ -523,7 +520,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Open remaining ones allFoldersToOpen.forEach(folderToOpen => { - if (windowsOnFolderPath.some(win => extUriBiasedIgnorePathCase.isEqual(win.openedFolderUri, folderToOpen.folderUri))) { + if (windowsOnFolderPath.some(window => extUriBiasedIgnorePathCase.isEqual(window.openedFolderUri, folderToOpen.folderUri))) { return; // ignore folders that are already open } @@ -1262,32 +1259,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // New window if (!window) { - const windowConfig = this.configurationService.getValue('window'); - const state = this.getNewWindowState(configuration); - - // Window state is not from a previous session: only allow fullscreen if we inherit it or user wants fullscreen - let allowFullscreen: boolean; - if (state.hasDefaultState) { - allowFullscreen = !!(windowConfig?.newWindowDimensions && ['fullscreen', 'inherit', 'offset'].indexOf(windowConfig.newWindowDimensions) >= 0); - } - - // Window state is from a previous session: only allow fullscreen when we got updated or user wants to restore - else { - allowFullscreen = !!(this.lifecycleMainService.wasRestarted || windowConfig?.restoreFullscreen); - - if (allowFullscreen && isMacintosh && this.getWindows().some(win => win.isFullScreen)) { - // macOS: Electron does not allow to restore multiple windows in - // fullscreen. As such, if we already restored a window in that - // state, we cannot allow more fullscreen windows. See - // https://github.com/microsoft/vscode/issues/41691 and - // https://github.com/electron/electron/issues/13077 - allowFullscreen = false; - } - } - - if (state.mode === WindowMode.Fullscreen && !allowFullscreen) { - state.mode = WindowMode.Normal; - } + const state = this.windowsStateHandler.getNewWindowState(configuration); // Create the window const createdWindow = window = this.instantiationService.createInstance(CodeWindow, { @@ -1374,137 +1346,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic window.load(configuration); } - private getNewWindowState(configuration: INativeWindowConfiguration): INewWindowState { - const lastActive = this.getLastActiveWindow(); - - // Restore state unless we are running extension tests - if (!configuration.extensionTestsPath) { - - // extension development host Window - load from stored settings if any - if (!!configuration.extensionDevelopmentPath && this.windowsStateHandler.state.lastPluginDevelopmentHostWindow) { - return this.windowsStateHandler.state.lastPluginDevelopmentHostWindow.uiState; - } - - // Known Workspace - load from stored settings - const workspace = configuration.workspace; - if (workspace) { - const stateForWorkspace = this.windowsStateHandler.state.openedWindows.filter(o => o.workspace && o.workspace.id === workspace.id).map(o => o.uiState); - if (stateForWorkspace.length) { - return stateForWorkspace[0]; - } - } - - // Known Folder - load from stored settings - if (configuration.folderUri) { - const stateForFolder = this.windowsStateHandler.state.openedWindows.filter(o => o.folderUri && extUriBiasedIgnorePathCase.isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState); - if (stateForFolder.length) { - return stateForFolder[0]; - } - } - - // Empty windows with backups - else if (configuration.backupPath) { - const stateForEmptyWindow = this.windowsStateHandler.state.openedWindows.filter(o => o.backupPath === configuration.backupPath).map(o => o.uiState); - if (stateForEmptyWindow.length) { - return stateForEmptyWindow[0]; - } - } - - // First Window - const lastActiveState = this.windowsStateHandler.lastClosedState || this.windowsStateHandler.state.lastActiveWindow; - if (!lastActive && lastActiveState) { - return lastActiveState.uiState; - } - } - - // - // In any other case, we do not have any stored settings for the window state, so we come up with something smart - // - - // We want the new window to open on the same display that the last active one is in - let displayToUse: Display | undefined; - const displays = screen.getAllDisplays(); - - // Single Display - if (displays.length === 1) { - displayToUse = displays[0]; - } - - // Multi Display - else { - - // on mac there is 1 menu per window so we need to use the monitor where the cursor currently is - if (isMacintosh) { - const cursorPoint = screen.getCursorScreenPoint(); - displayToUse = screen.getDisplayNearestPoint(cursorPoint); - } - - // if we have a last active window, use that display for the new window - if (!displayToUse && lastActive) { - displayToUse = screen.getDisplayMatching(lastActive.getBounds()); - } - - // fallback to primary display or first display - if (!displayToUse) { - displayToUse = screen.getPrimaryDisplay() || displays[0]; - } - } - - // Compute x/y based on display bounds - // Note: important to use Math.round() because Electron does not seem to be too happy about - // display coordinates that are not absolute numbers. - let state = defaultWindowState(); - state.x = Math.round(displayToUse.bounds.x + (displayToUse.bounds.width / 2) - (state.width! / 2)); - state.y = Math.round(displayToUse.bounds.y + (displayToUse.bounds.height / 2) - (state.height! / 2)); - - // Check for newWindowDimensions setting and adjust accordingly - const windowConfig = this.configurationService.getValue('window'); - let ensureNoOverlap = true; - if (windowConfig?.newWindowDimensions) { - if (windowConfig.newWindowDimensions === 'maximized') { - state.mode = WindowMode.Maximized; - ensureNoOverlap = false; - } else if (windowConfig.newWindowDimensions === 'fullscreen') { - state.mode = WindowMode.Fullscreen; - ensureNoOverlap = false; - } else if ((windowConfig.newWindowDimensions === 'inherit' || windowConfig.newWindowDimensions === 'offset') && lastActive) { - const lastActiveState = lastActive.serializeWindowState(); - if (lastActiveState.mode === WindowMode.Fullscreen) { - state.mode = WindowMode.Fullscreen; // only take mode (fixes https://github.com/microsoft/vscode/issues/19331) - } else { - state = lastActiveState; - } - - ensureNoOverlap = state.mode !== WindowMode.Fullscreen && windowConfig.newWindowDimensions === 'offset'; - } - } - - if (ensureNoOverlap) { - state = this.ensureNoOverlap(state); - } - - (state as INewWindowState).hasDefaultState = true; // flag as default state - - return state; - } - - private ensureNoOverlap(state: ISingleWindowState): ISingleWindowState { - if (this.getWindows().length === 0) { - return state; - } - - state.x = typeof state.x === 'number' ? state.x : 0; - state.y = typeof state.y === 'number' ? state.y : 0; - - const existingWindowBounds = this.getWindows().map(win => win.getBounds()); - while (existingWindowBounds.some(b => b.x === state.x || b.y === state.y)) { - state.x += 30; - state.y += 30; - } - - return state; - } - private onWindowClosed(window: ICodeWindow): void { // Remove from our list so that Electron can clean it up diff --git a/src/vs/platform/windows/electron-main/windowsStateHandler.ts b/src/vs/platform/windows/electron-main/windowsStateHandler.ts index 939178193b6..e5867ad8195 100644 --- a/src/vs/platform/windows/electron-main/windowsStateHandler.ts +++ b/src/vs/platform/windows/electron-main/windowsStateHandler.ts @@ -3,18 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app } from 'electron'; +import { app, Display, screen } from 'electron'; import { Disposable } from 'vs/base/common/lifecycle'; +import { isMacintosh } from 'vs/base/common/platform'; import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; +import { defaultWindowState } from 'vs/code/electron-main/window'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; -import { ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows'; +import { INativeWindowConfiguration, IWindowSettings } from 'vs/platform/windows/common/windows'; +import { ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; -export type WindowsStateStorageData = object; - export interface IWindowState { workspace?: IWorkspaceIdentifier; folderUri?: URI; @@ -29,6 +31,10 @@ export interface IWindowsState { openedWindows: IWindowState[]; } +interface INewWindowState extends IWindowUIState { + hasDefaultState?: boolean; +} + interface ISerializedWindowsState { readonly lastActiveWindow?: ISerializedWindowState; readonly lastPluginDevelopmentHostWindow?: ISerializedWindowState; @@ -41,33 +47,28 @@ interface ISerializedWindowState { readonly backupPath?: string; readonly remoteAuthority?: string; readonly uiState: IWindowUIState; - - // deprecated - readonly workspace?: { id: string; configPath: string }; } export class WindowsStateHandler extends Disposable { private static readonly windowsStateStorageKey = 'windowsState'; - get state() { return this._windowsState; } - private readonly _windowsState: IWindowsState; + get state() { return this._state; } + private readonly _state = restoreWindowsState(this.stateService.getItem(WindowsStateHandler.windowsStateStorageKey)); - get lastClosedState() { return this._lastClosedState; } - private _lastClosedState?: IWindowState; + private lastClosedState: IWindowState | undefined = undefined; private shuttingDown = false; constructor( + @IWindowsMainService private readonly windowsMainService: IWindowsMainService, @IStateService private readonly stateService: IStateService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, - @IWindowsMainService private readonly windowsMainService: IWindowsMainService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(); - this._windowsState = restoreWindowsState(this.stateService.getItem(WindowsStateHandler.windowsStateStorageKey)); - this.registerListeners(); } @@ -90,7 +91,7 @@ export class WindowsStateHandler extends Disposable { // clear last closed window state when a new window opens. this helps on macOS where // otherwise closing the last window, opening a new window and then quitting would // use the state of the previously closed window when restarting. - this._lastClosedState = undefined; + this.lastClosedState = undefined; } }); @@ -144,8 +145,8 @@ export class WindowsStateHandler extends Disposable { private saveWindowsState(): void { const currentWindowsState: IWindowsState = { openedWindows: [], - lastPluginDevelopmentHostWindow: this._windowsState.lastPluginDevelopmentHostWindow, - lastActiveWindow: this._lastClosedState + lastPluginDevelopmentHostWindow: this._state.lastPluginDevelopmentHostWindow, + lastActiveWindow: this.lastClosedState }; // 1.) Find a last active window (pick any other first window otherwise) @@ -193,12 +194,12 @@ export class WindowsStateHandler extends Disposable { // On Window close, update our stored UI state of this window const state: IWindowState = this.toWindowState(window); if (window.isExtensionDevelopmentHost && !window.isExtensionTestHost) { - this._windowsState.lastPluginDevelopmentHostWindow = state; // do not let test run window state overwrite our extension development state + this._state.lastPluginDevelopmentHostWindow = state; // do not let test run window state overwrite our extension development state } // Any non extension host window with same workspace or folder else if (!window.isExtensionDevelopmentHost && (!!window.openedWorkspace || !!window.openedFolderUri)) { - this._windowsState.openedWindows.forEach(openedWindow => { + this._state.openedWindows.forEach(openedWindow => { const sameWorkspace = window.openedWorkspace && openedWindow.workspace && openedWindow.workspace.id === window.openedWorkspace.id; const sameFolder = window.openedFolderUri && openedWindow.folderUri && extUriBiasedIgnorePathCase.isEqual(openedWindow.folderUri, window.openedFolderUri); @@ -213,7 +214,7 @@ export class WindowsStateHandler extends Disposable { // On macOS we keep the last closed window state ready in case the user wants to quit right after or // wants to open another window, in which case we use this state over the persisted one. if (this.windowsMainService.getWindowCount() === 1) { - this._lastClosedState = state; + this.lastClosedState = state; } } @@ -226,11 +227,173 @@ export class WindowsStateHandler extends Disposable { uiState: window.serializeWindowState() }; } + + getNewWindowState(configuration: INativeWindowConfiguration): INewWindowState { + const state = this.doGetNewWindowState(configuration); + const windowConfig = this.configurationService.getValue('window'); + + // Window state is not from a previous session: only allow fullscreen if we inherit it or user wants fullscreen + let allowFullscreen: boolean; + if (state.hasDefaultState) { + allowFullscreen = !!(windowConfig?.newWindowDimensions && ['fullscreen', 'inherit', 'offset'].indexOf(windowConfig.newWindowDimensions) >= 0); + } + + // Window state is from a previous session: only allow fullscreen when we got updated or user wants to restore + else { + allowFullscreen = !!(this.lifecycleMainService.wasRestarted || windowConfig?.restoreFullscreen); + + if (allowFullscreen && isMacintosh && this.windowsMainService.getWindows().some(window => window.isFullScreen)) { + // macOS: Electron does not allow to restore multiple windows in + // fullscreen. As such, if we already restored a window in that + // state, we cannot allow more fullscreen windows. See + // https://github.com/microsoft/vscode/issues/41691 and + // https://github.com/electron/electron/issues/13077 + allowFullscreen = false; + } + } + + if (state.mode === WindowMode.Fullscreen && !allowFullscreen) { + state.mode = WindowMode.Normal; + } + + return state; + } + + private doGetNewWindowState(configuration: INativeWindowConfiguration): INewWindowState { + const lastActive = this.windowsMainService.getLastActiveWindow(); + + // Restore state unless we are running extension tests + if (!configuration.extensionTestsPath) { + + // extension development host Window - load from stored settings if any + if (!!configuration.extensionDevelopmentPath && this.state.lastPluginDevelopmentHostWindow) { + return this.state.lastPluginDevelopmentHostWindow.uiState; + } + + // Known Workspace - load from stored settings + const workspace = configuration.workspace; + if (workspace) { + const stateForWorkspace = this.state.openedWindows.filter(openedWindow => openedWindow.workspace && openedWindow.workspace.id === workspace.id).map(o => o.uiState); + if (stateForWorkspace.length) { + return stateForWorkspace[0]; + } + } + + // Known Folder - load from stored settings + if (configuration.folderUri) { + const stateForFolder = this.state.openedWindows.filter(openedWindow => openedWindow.folderUri && extUriBiasedIgnorePathCase.isEqual(openedWindow.folderUri, configuration.folderUri)).map(o => o.uiState); + if (stateForFolder.length) { + return stateForFolder[0]; + } + } + + // Empty windows with backups + else if (configuration.backupPath) { + const stateForEmptyWindow = this.state.openedWindows.filter(openedWindow => openedWindow.backupPath === configuration.backupPath).map(o => o.uiState); + if (stateForEmptyWindow.length) { + return stateForEmptyWindow[0]; + } + } + + // First Window + const lastActiveState = this.lastClosedState || this.state.lastActiveWindow; + if (!lastActive && lastActiveState) { + return lastActiveState.uiState; + } + } + + // + // In any other case, we do not have any stored settings for the window state, so we come up with something smart + // + + // We want the new window to open on the same display that the last active one is in + let displayToUse: Display | undefined; + const displays = screen.getAllDisplays(); + + // Single Display + if (displays.length === 1) { + displayToUse = displays[0]; + } + + // Multi Display + else { + + // on mac there is 1 menu per window so we need to use the monitor where the cursor currently is + if (isMacintosh) { + const cursorPoint = screen.getCursorScreenPoint(); + displayToUse = screen.getDisplayNearestPoint(cursorPoint); + } + + // if we have a last active window, use that display for the new window + if (!displayToUse && lastActive) { + displayToUse = screen.getDisplayMatching(lastActive.getBounds()); + } + + // fallback to primary display or first display + if (!displayToUse) { + displayToUse = screen.getPrimaryDisplay() || displays[0]; + } + } + + // Compute x/y based on display bounds + // Note: important to use Math.round() because Electron does not seem to be too happy about + // display coordinates that are not absolute numbers. + let state = defaultWindowState(); + state.x = Math.round(displayToUse.bounds.x + (displayToUse.bounds.width / 2) - (state.width! / 2)); + state.y = Math.round(displayToUse.bounds.y + (displayToUse.bounds.height / 2) - (state.height! / 2)); + + // Check for newWindowDimensions setting and adjust accordingly + const windowConfig = this.configurationService.getValue('window'); + let ensureNoOverlap = true; + if (windowConfig?.newWindowDimensions) { + if (windowConfig.newWindowDimensions === 'maximized') { + state.mode = WindowMode.Maximized; + ensureNoOverlap = false; + } else if (windowConfig.newWindowDimensions === 'fullscreen') { + state.mode = WindowMode.Fullscreen; + ensureNoOverlap = false; + } else if ((windowConfig.newWindowDimensions === 'inherit' || windowConfig.newWindowDimensions === 'offset') && lastActive) { + const lastActiveState = lastActive.serializeWindowState(); + if (lastActiveState.mode === WindowMode.Fullscreen) { + state.mode = WindowMode.Fullscreen; // only take mode (fixes https://github.com/microsoft/vscode/issues/19331) + } else { + state = lastActiveState; + } + + ensureNoOverlap = state.mode !== WindowMode.Fullscreen && windowConfig.newWindowDimensions === 'offset'; + } + } + + if (ensureNoOverlap) { + state = this.ensureNoOverlap(state); + } + + (state as INewWindowState).hasDefaultState = true; // flag as default state + + return state; + } + + private ensureNoOverlap(state: IWindowUIState): IWindowUIState { + if (this.windowsMainService.getWindows().length === 0) { + return state; + } + + state.x = typeof state.x === 'number' ? state.x : 0; + state.y = typeof state.y === 'number' ? state.y : 0; + + const existingWindowBounds = this.windowsMainService.getWindows().map(window => window.getBounds()); + while (existingWindowBounds.some(bounds => bounds.x === state.x || bounds.y === state.y)) { + state.x += 30; + state.y += 30; + } + + return state; + } } -export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState { +export function restoreWindowsState(data: ISerializedWindowsState | undefined): IWindowsState { const result: IWindowsState = { openedWindows: [] }; - const windowsState = data as ISerializedWindowsState || { openedWindows: [] }; + const windowsState = data || { openedWindows: [] }; if (windowsState.lastActiveWindow) { result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow); @@ -264,10 +427,11 @@ function restoreWindowState(windowState: ISerializedWindowState): IWindowState { if (windowState.workspaceIdentifier) { result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) }; } + return result; } -export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData { +export function getWindowsStateStoreData(windowsState: IWindowsState): IWindowsState { return { lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow), lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow), diff --git a/src/vs/workbench/electron-sandbox/actions/windowActions.ts b/src/vs/workbench/electron-sandbox/actions/windowActions.ts index 57b01d68e98..f2554bdc241 100644 --- a/src/vs/workbench/electron-sandbox/actions/windowActions.ts +++ b/src/vs/workbench/electron-sandbox/actions/windowActions.ts @@ -174,16 +174,16 @@ export abstract class BaseSwitchWindow extends Action { const windows = await this.nativeHostService.getWindows(); const placeHolder = nls.localize('switchWindowPlaceHolder', "Select a window to switch to"); - const picks = windows.map(win => { - const resource = win.filename ? URI.file(win.filename) : win.folderUri ? win.folderUri : win.workspace ? win.workspace.configPath : undefined; - const fileKind = win.filename ? FileKind.FILE : win.workspace ? FileKind.ROOT_FOLDER : win.folderUri ? FileKind.FOLDER : FileKind.FILE; + const picks = windows.map(window => { + const resource = window.filename ? URI.file(window.filename) : window.folderUri ? window.folderUri : window.workspace ? window.workspace.configPath : undefined; + const fileKind = window.filename ? FileKind.FILE : window.workspace ? FileKind.ROOT_FOLDER : window.folderUri ? FileKind.FOLDER : FileKind.FILE; return { - payload: win.id, - label: win.title, - ariaLabel: win.dirty ? nls.localize('windowDirtyAriaLabel', "{0}, dirty window", win.title) : win.title, + payload: window.id, + label: window.title, + ariaLabel: window.dirty ? nls.localize('windowDirtyAriaLabel', "{0}, dirty window", window.title) : window.title, iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind), - description: (currentWindowId === win.id) ? nls.localize('current', "Current Window") : undefined, - buttons: currentWindowId !== win.id ? win.dirty ? [this.closeDirtyWindowAction] : [this.closeWindowAction] : undefined + description: (currentWindowId === window.id) ? nls.localize('current', "Current Window") : undefined, + buttons: currentWindowId !== window.id ? window.dirty ? [this.closeDirtyWindowAction] : [this.closeWindowAction] : undefined }; }); const autoFocusIndex = (picks.indexOf(picks.filter(pick => pick.payload === currentWindowId)[0]) + 1) % picks.length; From c87c95a1a04b01107328fe1987b1865b2eb367a8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 15:49:48 +0100 Subject: [PATCH 0932/1837] prefix our performance marks with `code/`, e.g `code/didStartRenderer` etc --- src/bootstrap-window.js | 4 +- src/main.js | 8 ++-- src/vs/base/node/languagePacks.js | 8 ++-- .../code/browser/workbench/workbench-dev.html | 4 +- src/vs/code/browser/workbench/workbench.html | 4 +- .../electron-browser/workbench/workbench.js | 10 ++-- src/vs/code/electron-main/window.ts | 2 +- .../electron-sandbox/workbench/workbench.js | 6 +-- .../platform/storage/node/storageService.ts | 4 +- src/vs/workbench/browser/layout.ts | 16 +++---- src/vs/workbench/browser/web.main.ts | 6 +-- src/vs/workbench/browser/workbench.ts | 4 +- .../files/browser/views/explorerView.ts | 4 +- .../partsSplash.contribution.ts | 2 +- .../electron-browser/desktop.main.ts | 2 +- .../electron-sandbox/desktop.main.ts | 2 +- .../browser/configurationService.ts | 4 +- .../common/abstractExtensionService.ts | 10 ++-- .../lifecycle/common/lifecycleService.ts | 2 +- .../services/timer/browser/timerService.ts | 46 +++++++++---------- .../services/userData/browser/userDataInit.ts | 4 +- src/vs/workbench/workbench.web.api.ts | 2 +- 22 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 03491d0fb22..0169a669bf0 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -145,9 +145,9 @@ try { // Wait for process environment being fully resolved - performance.mark('willWaitForShellEnv'); + performance.mark('code/willWaitForShellEnv'); await whenEnvResolved; - performance.mark('didWaitForShellEnv'); + performance.mark('code/didWaitForShellEnv'); // Callback only after process environment is resolved const callbackResult = resultCallback(result, configuration); diff --git a/src/main.js b/src/main.js index b8a98c7d10f..1554b0050c3 100644 --- a/src/main.js +++ b/src/main.js @@ -7,7 +7,7 @@ 'use strict'; const perf = require('./vs/base/common/performance'); -perf.mark('main:started'); +perf.mark('code/didStartMain'); const lp = require('./vs/base/node/languagePacks'); const path = require('path'); @@ -193,14 +193,14 @@ function startup(cachedDataDir, nlsConfig) { process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || ''; // Load main in AMD - perf.mark('willLoadMainBundle'); + perf.mark('code/willLoadMainBundle'); require('./bootstrap-amd').load('vs/code/electron-main/main', () => { - perf.mark('didLoadMainBundle'); + perf.mark('code/didLoadMainBundle'); }); } async function onReady() { - perf.mark('main:appReady'); + perf.mark('code/mainAppReady'); try { const [cachedDataDir, nlsConfig] = await Promise.all([nodeCachedDataDir.ensureExists(), resolveNlsConfiguration()]); diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js index 2c64061da7b..be9ca50b1bf 100644 --- a/src/vs/base/node/languagePacks.js +++ b/src/vs/base/node/languagePacks.js @@ -186,10 +186,10 @@ function factory(nodeRequire, path, fs, perf) { const initialLocale = locale; - perf.mark('nlsGeneration:start'); + perf.mark('code/willGenerateNls'); const defaultResult = function (locale) { - perf.mark('nlsGeneration:end'); + perf.mark('code/didGenerateNls'); return Promise.resolve({ locale: locale, availableLanguages: {} }); }; try { @@ -240,7 +240,7 @@ function factory(nodeRequire, path, fs, perf) { if (fileExists) { // We don't wait for this. No big harm if we can't touch touch(coreLocation).catch(() => { }); - perf.mark('nlsGeneration:end'); + perf.mark('code/didGenerateNls'); return result; } return mkdirp(coreLocation).then(() => { @@ -279,7 +279,7 @@ function factory(nodeRequire, path, fs, perf) { writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations))); return Promise.all(writes); }).then(() => { - perf.mark('nlsGeneration:end'); + perf.mark('code/didGenerateNls'); return result; }).catch(err => { console.error('Generating translation files failed.', err); diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 20dbd370976..2df6f81256d 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -3,7 +3,7 @@ @@ -55,7 +55,7 @@ @@ -54,7 +54,7 @@ diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index e53c44eb702..aac9b404477 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -12,7 +12,7 @@ const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - performance.mark('renderer/started'); + performance.mark('code/didStartRenderer'); // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because @@ -26,7 +26,7 @@ async function (workbench, configuration) { // Mark start of workbench - performance.mark('didLoadWorkbenchMain'); + performance.mark('code/didLoadWorkbenchMain'); // @ts-ignore return require('vs/workbench/electron-browser/desktop.main').main(configuration); @@ -40,7 +40,7 @@ loaderConfig.recordStats = true; }, beforeRequire: function () { - performance.mark('willLoadWorkbenchMain'); + performance.mark('code/willLoadWorkbenchMain'); } } ); @@ -70,7 +70,7 @@ * }} configuration */ function showPartsSplash(configuration) { - performance.mark('willShowPartsSplash'); + performance.mark('code/willShowPartsSplash'); let data; if (typeof configuration.partsSplashPath === 'string') { @@ -160,7 +160,7 @@ document.body.appendChild(splash); } - performance.mark('didShowPartsSplash'); + performance.mark('code/didShowPartsSplash'); } //#endregion diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index ea7cc2f97d0..6f6660ab8f8 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -729,7 +729,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } // Load URL - perf.mark('main:loadWindow'); + perf.mark('code/willOpenNewWindow'); this._win.loadURL(this.getUrl(configuration)); // Make window visible if it did not open in N seconds because this indicates an error diff --git a/src/vs/code/electron-sandbox/workbench/workbench.js b/src/vs/code/electron-sandbox/workbench/workbench.js index e90d470d057..b4f80ac23e1 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.js +++ b/src/vs/code/electron-sandbox/workbench/workbench.js @@ -12,7 +12,7 @@ const bootstrapWindow = bootstrapWindowLib(); // Add a perf entry right from the top - performance.mark('renderer/started'); + performance.mark('code/didStartRenderer'); // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because @@ -26,7 +26,7 @@ async function (workbench, configuration) { // Mark start of workbench - performance.mark('didLoadWorkbenchMain'); + performance.mark('code/didLoadWorkbenchMain'); // @ts-ignore return require('vs/workbench/electron-sandbox/desktop.main').main(configuration); @@ -40,7 +40,7 @@ loaderConfig.recordStats = true; }, beforeRequire: function () { - performance.mark('willLoadWorkbenchMain'); + performance.mark('code/willLoadWorkbenchMain'); } } ); diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index 97cb9b161ac..b30d7c25349 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -83,7 +83,7 @@ export class NativeStorageService extends AbstractStorageService { const useInMemoryStorage = !!this.environmentService.extensionTestsLocationURI; // no storage during extension tests! // Create workspace storage and initialize - mark('willInitWorkspaceStorage'); + mark('code/willInitWorkspaceStorage'); try { const workspaceStorage = this.createWorkspaceStorage( useInMemoryStorage ? SQLiteStorageDatabase.IN_MEMORY_PATH : join(result.path, NativeStorageService.WORKSPACE_STORAGE_NAME), @@ -99,7 +99,7 @@ export class NativeStorageService extends AbstractStorageService { workspaceStorage.set(IS_NEW_KEY, false); } } finally { - mark('didInitWorkspaceStorage'); + mark('code/didInitWorkspaceStorage'); } } catch (error) { this.logService.error(`[storage] initializeWorkspaceStorage(): Unable to init workspace storage due to ${error}`); diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index bd3e2f91008..3f834c579c3 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -652,7 +652,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi // Restore editors restorePromises.push((async () => { - mark('willRestoreEditors'); + mark('code/willRestoreEditors'); // first ensure the editor part is restored await this.editorGroupService.whenRestored; @@ -669,13 +669,13 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi await this.editorService.openEditors(editors); } - mark('didRestoreEditors'); + mark('code/didRestoreEditors'); })()); // Restore default views const restoreDefaultViewsPromise = (async () => { if (this.state.views.defaults?.length) { - mark('willOpenDefaultViews'); + mark('code/willOpenDefaultViews'); let locationsRestored: { id: string; order: number }[] = []; @@ -733,7 +733,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.state.panel.panelToRestore = locationsRestored[ViewContainerLocation.Panel].id; } - mark('didOpenDefaultViews'); + mark('code/didOpenDefaultViews'); } })(); restorePromises.push(restoreDefaultViewsPromise); @@ -748,14 +748,14 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi return; } - mark('willRestoreViewlet'); + mark('code/willRestoreViewlet'); const viewlet = await this.viewletService.openViewlet(this.state.sideBar.viewletToRestore); if (!viewlet) { await this.viewletService.openViewlet(this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id); // fallback to default viewlet as needed } - mark('didRestoreViewlet'); + mark('code/didRestoreViewlet'); })()); // Restore Panel @@ -768,14 +768,14 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi return; } - mark('willRestorePanel'); + mark('code/willRestorePanel'); const panel = await this.panelService.openPanel(this.state.panel.panelToRestore!); if (!panel) { await this.panelService.openPanel(Registry.as(PanelExtensions.Panels).getDefaultPanelId()); // fallback to default panel as needed } - mark('didRestorePanel'); + mark('code/didRestorePanel'); })()); // Restore Zen Mode diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index a8a86fd763c..4a234587574 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -84,7 +84,7 @@ class BrowserMain extends Disposable { const services = await this.initServices(); await domContentLoaded(); - mark('willStartWorkbench'); + mark('code/willStartWorkbench'); // Create Workbench const workbench = new Workbench( @@ -242,7 +242,7 @@ class BrowserMain extends Disposable { serviceCollection.set(IUserDataInitializationService, userDataInitializationService); if (await userDataInitializationService.requiresInitialization()) { - mark('willInitRequiredUserData'); + mark('code/willInitRequiredUserData'); // Initialize required resources - settings & global state await userDataInitializationService.initializeRequiredResources(); @@ -251,7 +251,7 @@ class BrowserMain extends Disposable { // Reloading complete configuraiton blocks workbench until remote configuration is loaded. await configurationService.reloadLocalUserConfiguration(); - mark('didInitRequiredUserData'); + mark('code/didInitRequiredUserData'); } return { serviceCollection, configurationService, logService, storageService }; diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 2172c09448d..ef1d1ed962f 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -412,10 +412,10 @@ export class Workbench extends Layout { }, 2500); // Telemetry: startup metrics - mark('didStartWorkbench'); + mark('code/didStartWorkbench'); // Perf reporting (devtools) - performance.measure('perf: workbench create & restore', 'didLoadWorkbenchMain', 'didStartWorkbench'); + performance.measure('perf: workbench create & restore', 'code/didLoadWorkbenchMain', 'code/didStartWorkbench'); } } } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 75aa6726d94..33761289571 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -635,7 +635,7 @@ export class ExplorerView extends ViewPane { const initialInputSetup = !this.tree.getInput(); if (initialInputSetup) { - perf.mark('willResolveExplorer'); + perf.mark('code/willResolveExplorer'); } const roots = this.explorerService.roots; let input: ExplorerItem | ExplorerItem[] = roots[0]; @@ -675,7 +675,7 @@ export class ExplorerView extends ViewPane { } } if (initialInputSetup) { - perf.mark('didResolveExplorer'); + perf.mark('code/didResolveExplorer'); } }); diff --git a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts index 76c12fa6a45..db5f64070d9 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -49,7 +49,7 @@ class PartsSplash { ) { lifecycleService.when(LifecyclePhase.Restored).then(_ => { this._removePartsSplash(); - perf.mark('didRemovePartsSplash'); + perf.mark('code/didRemovePartsSplash'); }); Event.debounce(Event.any( onDidChangeFullscreen, diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index a14a1e1359c..19678d72168 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -112,7 +112,7 @@ class DesktopMain extends Disposable { const services = await this.initServices(); await domContentLoaded(); - mark('willStartWorkbench'); + mark('code/willStartWorkbench'); // Create Workbench const workbench = new Workbench(document.body, services.serviceCollection, services.logService); diff --git a/src/vs/workbench/electron-sandbox/desktop.main.ts b/src/vs/workbench/electron-sandbox/desktop.main.ts index 5d98d5ac3f7..a97b21f301b 100644 --- a/src/vs/workbench/electron-sandbox/desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/desktop.main.ts @@ -89,7 +89,7 @@ class DesktopMain extends Disposable { const services = await this.initServices(); await domContentLoaded(); - mark('willStartWorkbench'); + mark('code/willStartWorkbench'); // Create Workbench const workbench = new Workbench(document.body, services.serviceCollection, services.logService); diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 042fe365a32..66576ad7646 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -349,13 +349,13 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat } async initialize(arg: IWorkspaceInitializationPayload): Promise { - mark('willInitWorkspaceService'); + mark('code/willInitWorkspaceService'); const workspace = await this.createWorkspace(arg); await this.updateWorkspaceAndInitializeConfiguration(workspace); this.checkAndMarkWorkspaceComplete(); - mark('didInitWorkspaceService'); + mark('code/didInitWorkspaceService'); } acquireInstantiationService(instantiationService: IInstantiationService): void { diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index f9fbf7e59be..d11139dd7a0 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -407,15 +407,15 @@ export abstract class AbstractExtensionService extends Disposable implements IEx //#endregion protected async _initialize(): Promise { - perf.mark('willLoadExtensions'); + perf.mark('code/willLoadExtensions'); this._startExtensionHosts(true, []); - this.whenInstalledExtensionsRegistered().then(() => perf.mark('didLoadExtensions')); + this.whenInstalledExtensionsRegistered().then(() => perf.mark('code/didLoadExtensions')); await this._scanAndHandleExtensions(); this._releaseBarrier(); } private _releaseBarrier(): void { - perf.mark('extensionHostReady'); + perf.mark('code/extensionHostReady'); this._installedExtensionsReady.open(); this._onDidRegisterExtensions.fire(undefined); this._onDidChangeExtensionsStatus.fire(this._registry.getAllExtensionDescriptions().map(e => e.identifier)); @@ -644,11 +644,13 @@ export abstract class AbstractExtensionService extends Disposable implements IEx const messageHandler = (msg: IMessage) => this._handleExtensionPointMessage(msg); const availableExtensions = this._registry.getAllExtensionDescriptions(); const extensionPoints = ExtensionsRegistry.getExtensionPoints(); + perf.mark('code/willHandleExtensionPoints'); for (const extensionPoint of extensionPoints) { if (affectedExtensionPoints[extensionPoint.name]) { AbstractExtensionService._handleExtensionPoint(extensionPoint, availableExtensions, messageHandler); } } + perf.mark('code/didHandleExtensionPoints'); } private _handleExtensionPointMessage(msg: IMessage) { @@ -699,9 +701,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx }); } } - perf.mark(`willHandleExtensionPoint/${extensionPoint.name}`); extensionPoint.acceptUsers(users); - perf.mark(`didHandleExtensionPoint/${extensionPoint.name}`); } private _showMessageToUser(severity: Severity, msg: string): void { diff --git a/src/vs/workbench/services/lifecycle/common/lifecycleService.ts b/src/vs/workbench/services/lifecycle/common/lifecycleService.ts index a7e52e488bc..a7116f0df51 100644 --- a/src/vs/workbench/services/lifecycle/common/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/common/lifecycleService.ts @@ -49,7 +49,7 @@ export abstract class AbstractLifecycleService extends Disposable implements ILi this.logService.trace(`lifecycle: phase changed (value: ${value})`); this._phase = value; - mark(`LifecyclePhase/${LifecyclePhaseToString(value)}`); + mark(`code/LifecyclePhase/${LifecyclePhaseToString(value)}`); const barrier = this.phaseWhen.get(this._phase); if (barrier) { diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 11ce9f7cf7e..815c9159330 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -177,7 +177,7 @@ export interface IStartupMetrics { * The time it took to tell electron to open/restore a renderer (browser window). * * * Happens in the main-process - * * Measured with the `main:appReady` and `main:loadWindow` performance marks. + * * Measured with the `main:appReady` and `code/willOpenNewWindow` performance marks. * * This can be compared between insider and stable builds. * * It is our code running here and we should monitor this carefully for regressions. */ @@ -188,7 +188,7 @@ export interface IStartupMetrics { * of load the main-bundle (`workbench.desktop.main.js`). * * * Happens in the main-process *and* the renderer-process - * * Measured with the `main:loadWindow` and `willLoadWorkbenchMain` performance marks. + * * Measured with the `code/willOpenNewWindow` and `willLoadWorkbenchMain` performance marks. * * This can be compared between insider and stable builds. * * It is mostly not our code running here and we can only observe what's happening. * @@ -209,7 +209,7 @@ export interface IStartupMetrics { * and load the initial set of values. * * * Happens in the renderer-process - * * Measured with the `willInitWorkspaceStorage` and `didInitWorkspaceStorage` performance marks. + * * Measured with the `code/willInitWorkspaceStorage` and `code/didInitWorkspaceStorage` performance marks. */ readonly ellapsedWorkspaceStorageInit: number; @@ -461,13 +461,13 @@ export abstract class AbstractTimerService implements ITimerService { private async _computeStartupMetrics(): Promise { const initialStartup = this._isInitialStartup(); - const startMark = initialStartup ? 'main:started' : 'main:loadWindow'; + const startMark = initialStartup ? 'code/didStartMain' : 'code/willOpenNewWindow'; const activeViewlet = this._viewletService.getActiveViewlet(); const activePanel = this._panelService.getActivePanel(); const info: Writeable = { version: 2, - ellapsed: this._marks.getDuration(startMark, 'didStartWorkbench'), + ellapsed: this._marks.getDuration(startMark, 'code/didStartWorkbench'), // reflections isLatestVersion: Boolean(await this._updateService.isLatestVersion()), @@ -480,24 +480,24 @@ export abstract class AbstractTimerService implements ITimerService { // timers timers: { - ellapsedAppReady: initialStartup ? this._marks.getDuration('main:started', 'main:appReady') : undefined, - ellapsedNlsGeneration: initialStartup ? this._marks.getDuration('nlsGeneration:start', 'nlsGeneration:end') : undefined, - ellapsedLoadMainBundle: initialStartup ? this._marks.getDuration('willLoadMainBundle', 'didLoadMainBundle') : undefined, - ellapsedWindowLoad: initialStartup ? this._marks.getDuration('main:appReady', 'main:loadWindow') : undefined, - ellapsedWindowLoadToRequire: this._marks.getDuration('main:loadWindow', 'willLoadWorkbenchMain'), - ellapsedRequire: this._marks.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain'), - ellapsedWaitForShellEnv: this._marks.getDuration('willWaitForShellEnv', 'didWaitForShellEnv'), - ellapsedWorkspaceStorageInit: this._marks.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage'), - ellapsedWorkspaceServiceInit: this._marks.getDuration('willInitWorkspaceService', 'didInitWorkspaceService'), - ellapsedRequiredUserDataInit: this._marks.getDuration('willInitRequiredUserData', 'didInitRequiredUserData'), - ellapsedOtherUserDataInit: this._marks.getDuration('willInitOtherUserData', 'didInitOtherUserData'), - ellapsedExtensions: this._marks.getDuration('willLoadExtensions', 'didLoadExtensions'), - ellapsedEditorRestore: this._marks.getDuration('willRestoreEditors', 'didRestoreEditors'), - ellapsedViewletRestore: this._marks.getDuration('willRestoreViewlet', 'didRestoreViewlet'), - ellapsedPanelRestore: this._marks.getDuration('willRestorePanel', 'didRestorePanel'), - ellapsedWorkbench: this._marks.getDuration('willStartWorkbench', 'didStartWorkbench'), - ellapsedExtensionsReady: this._marks.getDuration(startMark, 'didLoadExtensions'), - ellapsedRenderer: this._marks.getDuration('renderer/started', 'didStartWorkbench') + ellapsedAppReady: initialStartup ? this._marks.getDuration('code/didStartMain', 'code/mainAppReady') : undefined, + ellapsedNlsGeneration: initialStartup ? this._marks.getDuration('code/willGenerateNls', 'code/didGenerateNls') : undefined, + ellapsedLoadMainBundle: initialStartup ? this._marks.getDuration('code/willLoadMainBundle', 'code/didLoadMainBundle') : undefined, + ellapsedWindowLoad: initialStartup ? this._marks.getDuration('code/mainAppReady', 'code/willOpenNewWindow') : undefined, + ellapsedWindowLoadToRequire: this._marks.getDuration('code/willOpenNewWindow', 'code/willLoadWorkbenchMain'), + ellapsedRequire: this._marks.getDuration('code/willLoadWorkbenchMain', 'code/didLoadWorkbenchMain'), + ellapsedWaitForShellEnv: this._marks.getDuration('code/willWaitForShellEnv', 'code/didWaitForShellEnv'), + ellapsedWorkspaceStorageInit: this._marks.getDuration('code/willInitWorkspaceStorage', 'code/didInitWorkspaceStorage'), + ellapsedWorkspaceServiceInit: this._marks.getDuration('code/willInitWorkspaceService', 'code/didInitWorkspaceService'), + ellapsedRequiredUserDataInit: this._marks.getDuration('code/willInitRequiredUserData', 'code/didInitRequiredUserData'), + ellapsedOtherUserDataInit: this._marks.getDuration('code/willInitOtherUserData', 'code/didInitOtherUserData'), + ellapsedExtensions: this._marks.getDuration('code/willLoadExtensions', 'code/didLoadExtensions'), + ellapsedEditorRestore: this._marks.getDuration('code/willRestoreEditors', 'code/didRestoreEditors'), + ellapsedViewletRestore: this._marks.getDuration('code/willRestoreViewlet', 'code/didRestoreViewlet'), + ellapsedPanelRestore: this._marks.getDuration('code/willRestorePanel', 'code/didRestorePanel'), + ellapsedWorkbench: this._marks.getDuration('code/willStartWorkbench', 'code/didStartWorkbench'), + ellapsedExtensionsReady: this._marks.getDuration(startMark, 'code/didLoadExtensions'), + ellapsedRenderer: this._marks.getDuration('code/didStartRenderer', 'code/didStartWorkbench') }, // system info diff --git a/src/vs/workbench/services/userData/browser/userDataInit.ts b/src/vs/workbench/services/userData/browser/userDataInit.ts index 23e3b451a92..4673d41229f 100644 --- a/src/vs/workbench/services/userData/browser/userDataInit.ts +++ b/src/vs/workbench/services/userData/browser/userDataInit.ts @@ -234,9 +234,9 @@ class InitializeOtherResourcesContribution implements IWorkbenchContribution { private async initializeOtherResource(userDataInitializeService: IUserDataInitializationService, instantiationService: IInstantiationService): Promise { if (await userDataInitializeService.requiresInitialization()) { - mark('willInitOtherUserData'); + mark('code/willInitOtherUserData'); await userDataInitializeService.initializeOtherResources(instantiationService); - mark('didInitOtherUserData'); + mark('code/didInitOtherUserData'); } } } diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index 0ccee7fa3e4..e4409b3bc16 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -461,7 +461,7 @@ const workbenchPromise = new Promise(resolve => workbenchPromiseReso function create(domElement: HTMLElement, options: IWorkbenchConstructionOptions): IDisposable { // Mark start of workbench - mark('didLoadWorkbenchMain'); + mark('code/didLoadWorkbenchMain'); // Assert that the workbench is not created more than once. We currently // do not support this and require a full context switch to clean-up. From 43017777275f8f0c29b75c38c4ecc4c4b9928d72 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 14 Dec 2020 15:50:05 +0100 Subject: [PATCH 0933/1837] Update grammars --- extensions/cpp/cgmanifest.json | 4 +- extensions/cpp/syntaxes/c.tmLanguage.json | 8 +- .../cpp.embedded.macro.tmLanguage.json | 8 +- extensions/cpp/syntaxes/cpp.tmLanguage.json | 8 +- extensions/fsharp/cgmanifest.json | 2 +- extensions/fsharp/package.json | 2 +- .../fsharp/syntaxes/fsharp.tmLanguage.json | 9 +- .../syntaxes/JavaScript.tmLanguage.json | 235 +++++--- .../syntaxes/JavaScriptReact.tmLanguage.json | 235 +++++--- extensions/log/cgmanifest.json | 4 +- extensions/log/syntaxes/log.tmLanguage.json | 6 +- extensions/markdown-basics/cgmanifest.json | 6 +- .../syntaxes/markdown.tmLanguage.json | 4 +- extensions/php/cgmanifest.json | 4 +- extensions/php/syntaxes/php.tmLanguage.json | 512 +++++++++++------- extensions/rust/cgmanifest.json | 4 +- extensions/rust/syntaxes/rust.tmLanguage.json | 51 +- .../test/colorize-results/test-6611_rs.json | 96 ++-- .../rust/test/colorize-results/test_rs.json | 24 +- .../swift/syntaxes/swift.tmLanguage.json | 23 +- extensions/typescript-basics/cgmanifest.json | 2 +- .../syntaxes/TypeScript.tmLanguage.json | 235 +++++--- .../syntaxes/TypeScriptReact.tmLanguage.json | 235 +++++--- 23 files changed, 1146 insertions(+), 571 deletions(-) diff --git a/extensions/cpp/cgmanifest.json b/extensions/cpp/cgmanifest.json index 05938de60d9..a483664d1c5 100644 --- a/extensions/cpp/cgmanifest.json +++ b/extensions/cpp/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "jeff-hykin/cpp-textmate-grammar", "repositoryUrl": "https://github.com/jeff-hykin/cpp-textmate-grammar", - "commitHash": "ad9f1541fd376740c30a7257614c9cb5ed25005d" + "commitHash": "f074a48ae0b7ba313af3faf3d8bfda8537864bd1" } }, "license": "MIT", - "version": "1.15.3", + "version": "1.15.5", "description": "The files syntaxes/c.json and syntaxes/c++.json were derived from https://github.com/atom/language-c which was originally converted from the C TextMate bundle https://github.com/textmate/c.tmbundle." }, { diff --git a/extensions/cpp/syntaxes/c.tmLanguage.json b/extensions/cpp/syntaxes/c.tmLanguage.json index 952730f5a0e..7ce64b81de7 100644 --- a/extensions/cpp/syntaxes/c.tmLanguage.json +++ b/extensions/cpp/syntaxes/c.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/jeff-hykin/cpp-textmate-grammar/commit/afa42b3f5529833714ae354fbc638ece8f253074", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/f074a48ae0b7ba313af3faf3d8bfda8537864bd1", "name": "C", "scopeName": "source.c", "patterns": [ @@ -2939,9 +2939,6 @@ } } }, - { - "include": "#comments_context" - }, { "include": "#comments" }, @@ -3104,9 +3101,6 @@ "match": ":", "name": "punctuation.separator.delimiter.colon.assembly.c" }, - { - "include": "#comments_context" - }, { "include": "#comments" } diff --git a/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json b/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json index 151cad6feb2..23f35fd5658 100644 --- a/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json +++ b/extensions/cpp/syntaxes/cpp.embedded.macro.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/jeff-hykin/cpp-textmate-grammar/commit/ad9f1541fd376740c30a7257614c9cb5ed25005d", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/f074a48ae0b7ba313af3faf3d8bfda8537864bd1", "name": "C++", "scopeName": "source.cpp.embedded.macro", "patterns": [ @@ -298,9 +298,6 @@ } } }, - { - "include": "#comments_context" - }, { "include": "#comments" }, @@ -463,9 +460,6 @@ "match": ":", "name": "punctuation.separator.delimiter.colon.assembly.cpp" }, - { - "include": "#comments_context" - }, { "include": "#comments" } diff --git a/extensions/cpp/syntaxes/cpp.tmLanguage.json b/extensions/cpp/syntaxes/cpp.tmLanguage.json index 43ce952624a..ecd7d3db266 100644 --- a/extensions/cpp/syntaxes/cpp.tmLanguage.json +++ b/extensions/cpp/syntaxes/cpp.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/jeff-hykin/cpp-textmate-grammar/commit/dc9c3ed759c84e0b168cc2140e6869ca97abbd14", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/f074a48ae0b7ba313af3faf3d8bfda8537864bd1", "name": "C++", "scopeName": "source.cpp", "patterns": [ @@ -344,9 +344,6 @@ } } }, - { - "include": "#comments_context" - }, { "include": "#comments" }, @@ -509,9 +506,6 @@ "match": ":", "name": "punctuation.separator.delimiter.colon.assembly.cpp" }, - { - "include": "#comments_context" - }, { "include": "#comments" } diff --git a/extensions/fsharp/cgmanifest.json b/extensions/fsharp/cgmanifest.json index d1f7e2324e7..b898a38669c 100644 --- a/extensions/fsharp/cgmanifest.json +++ b/extensions/fsharp/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "ionide/ionide-fsgrammar", "repositoryUrl": "https://github.com/ionide/ionide-fsgrammar", - "commitHash": "af037b23ca4c61b02799957a61cbd05b44355caf" + "commitHash": "fc4cac6d9bc1787f54ce48bbc77bcbb1de8160ff" } }, "license": "MIT", diff --git a/extensions/fsharp/package.json b/extensions/fsharp/package.json index 4341fdc30c2..fb67e704c2c 100644 --- a/extensions/fsharp/package.json +++ b/extensions/fsharp/package.json @@ -7,7 +7,7 @@ "license": "MIT", "engines": { "vscode": "*" }, "scripts": { - "update-grammar": "node ../../build/npm/update-grammar.js ionide/ionide-fsgrammar grammar/fsharp.json ./syntaxes/fsharp.tmLanguage.json" + "update-grammar": "node ../../build/npm/update-grammar.js ionide/ionide-fsgrammar grammars/fsharp.json ./syntaxes/fsharp.tmLanguage.json" }, "contributes": { "languages": [{ diff --git a/extensions/fsharp/syntaxes/fsharp.tmLanguage.json b/extensions/fsharp/syntaxes/fsharp.tmLanguage.json index 419feb7f7bb..ca06a19c2c2 100644 --- a/extensions/fsharp/syntaxes/fsharp.tmLanguage.json +++ b/extensions/fsharp/syntaxes/fsharp.tmLanguage.json @@ -1,10 +1,10 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/ionide/ionide-fsgrammar/blob/master/grammar/fsharp.json", + "This file has been converted from https://github.com/ionide/ionide-fsgrammar/blob/master/grammars/fsharp.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/ionide/ionide-fsgrammar/commit/af037b23ca4c61b02799957a61cbd05b44355caf", + "version": "https://github.com/ionide/ionide-fsgrammar/commit/fc4cac6d9bc1787f54ce48bbc77bcbb1de8160ff", "name": "fsharp", "scopeName": "source.fsharp", "patterns": [ @@ -560,6 +560,11 @@ } }, "patterns": [ + { + "comments": "Capture // when inside of (* *) like that the rule which capture comments starting by // is not trigger. See https://github.com/ionide/ionide-fsgrammar/issues/155", + "name": "fast-capture.comment.line.double-slash.fsharp", + "match": "//" + }, { "include": "#comments" } diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index c729c8ff9c6..974f90673e1 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/59b62cbc624e3a01368e5432d85af0c99a27d49d", + "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/a755c6bad619daa8349fb23149eeeff220a06603", "name": "JavaScript (with React support)", "scopeName": "source.js", "patterns": [ @@ -439,7 +439,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js entity.name.function.js" @@ -497,7 +497,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js variable.other.constant.js entity.name.function.js" @@ -881,7 +881,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -1121,7 +1121,7 @@ "include": "#comment" }, { - "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.js entity.name.function.js" @@ -1304,7 +1304,7 @@ }, { "name": "meta.method.declaration.js", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js" @@ -1334,7 +1334,7 @@ }, { "name": "meta.method.declaration.js", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js" @@ -1366,7 +1366,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.js", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1387,7 +1387,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1447,7 +1447,7 @@ }, { "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1557,6 +1557,14 @@ } }, "patterns": [ + { + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js" @@ -2732,7 +2757,7 @@ "end": "(?=,|\\})", "patterns": [ { - "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -2765,7 +2790,7 @@ ] }, { - "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -2801,7 +2826,7 @@ ] }, { - "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "meta.brace.round.js" @@ -2854,13 +2879,13 @@ "function-call": { "patterns": [ { - "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", - "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "name": "meta.function-call.js", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "include": "#function-call-target" @@ -2989,7 +3014,7 @@ "paren-expression-possibly-arrow": { "patterns": [ { - "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -3003,7 +3028,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -3073,7 +3098,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -3328,8 +3353,18 @@ ] }, "typeof-operator": { - "name": "keyword.operator.expression.typeof.js", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", + "match": "(?x) (?:(\\.)|(\\?\\.(?!\\s*[[:digit:]]))) \\s* (?:\n (?:(constructor|length|prototype|__proto__)\\b(?!\\$|\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.js" @@ -3641,7 +3676,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js" @@ -3964,7 +3999,7 @@ "include": "#comment" }, { - "include": "#string" + "include": "#type-string" }, { "include": "#numeric-literal" @@ -4172,7 +4207,7 @@ }, "patterns": [ { - "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", + "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", "captures": { "1": { "name": "storage.modifier.js" @@ -4577,42 +4612,7 @@ "template": { "patterns": [ { - "name": "string.template.js", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "end": "(?=`)", - "patterns": [ - { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.tagged-template.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.js" - } - }, - "end": "(?=`)", - "patterns": [ - { - "include": "#type-arguments" - } - ] + "include": "#template-call" }, { "name": "string.template.js", @@ -4642,6 +4642,48 @@ } ] }, + "template-call": { + "patterns": [ + { + "name": "string.template.js", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, + { + "name": "string.template.js", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.js" + } + }, + "end": "(?=`)", + "patterns": [ + { + "include": "#type-arguments" + } + ] + } + ] + }, "template-substitution-element": { "name": "meta.template.expression.js", "begin": "\\$\\{", @@ -4663,6 +4705,73 @@ ], "contentName": "meta.embedded.line.js" }, + "type-string": { + "patterns": [ + { + "include": "#qstring-single" + }, + { + "include": "#qstring-double" + }, + { + "include": "#template-type" + } + ] + }, + "template-type": { + "patterns": [ + { + "include": "#template-call" + }, + { + "name": "string.template.js", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?(`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.js" + }, + "2": { + "name": "punctuation.definition.string.template.begin.js" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.template.end.js" + } + }, + "patterns": [ + { + "include": "#template-type-substitution-element" + }, + { + "include": "#string-character-escape" + } + ] + } + ] + }, + "template-type-substitution-element": { + "name": "meta.template.expression.js", + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.template-expression.begin.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.template-expression.end.js" + } + }, + "patterns": [ + { + "include": "#type" + } + ], + "contentName": "meta.embedded.line.js" + }, "regex": { "patterns": [ { diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index 6cf2346d97a..3d9f9bf7bcd 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/59b62cbc624e3a01368e5432d85af0c99a27d49d", + "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/a755c6bad619daa8349fb23149eeeff220a06603", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "patterns": [ @@ -439,7 +439,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js.jsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx entity.name.function.js.jsx" @@ -497,7 +497,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js.jsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx variable.other.constant.js.jsx entity.name.function.js.jsx" @@ -881,7 +881,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -1121,7 +1121,7 @@ "include": "#comment" }, { - "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.js.jsx entity.name.function.js.jsx" @@ -1304,7 +1304,7 @@ }, { "name": "meta.method.declaration.js.jsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js.jsx" @@ -1334,7 +1334,7 @@ }, { "name": "meta.method.declaration.js.jsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js.jsx" @@ -1366,7 +1366,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.js.jsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1387,7 +1387,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1447,7 +1447,7 @@ }, { "name": "meta.arrow.js.jsx", - "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1557,6 +1557,14 @@ } }, "patterns": [ + { + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js.jsx" @@ -2732,7 +2757,7 @@ "end": "(?=,|\\})", "patterns": [ { - "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -2765,7 +2790,7 @@ ] }, { - "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -2801,7 +2826,7 @@ ] }, { - "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "meta.brace.round.js.jsx" @@ -2854,13 +2879,13 @@ "function-call": { "patterns": [ { - "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", - "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "name": "meta.function-call.js.jsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "include": "#function-call-target" @@ -2989,7 +3014,7 @@ "paren-expression-possibly-arrow": { "patterns": [ { - "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -3003,7 +3028,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -3073,7 +3098,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -3328,8 +3353,18 @@ ] }, "typeof-operator": { - "name": "keyword.operator.expression.typeof.js.jsx", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", + "match": "(?x) (?:(\\.)|(\\?\\.(?!\\s*[[:digit:]]))) \\s* (?:\n (?:(constructor|length|prototype|__proto__)\\b(?!\\$|\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.js.jsx" @@ -3641,7 +3676,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js.jsx" @@ -3964,7 +3999,7 @@ "include": "#comment" }, { - "include": "#string" + "include": "#type-string" }, { "include": "#numeric-literal" @@ -4172,7 +4207,7 @@ }, "patterns": [ { - "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", + "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -4577,42 +4612,7 @@ "template": { "patterns": [ { - "name": "string.template.js.jsx", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "end": "(?=`)", - "patterns": [ - { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.tagged-template.js.jsx", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.js.jsx", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.js.jsx" - } - }, - "end": "(?=`)", - "patterns": [ - { - "include": "#type-arguments" - } - ] + "include": "#template-call" }, { "name": "string.template.js.jsx", @@ -4642,6 +4642,48 @@ } ] }, + "template-call": { + "patterns": [ + { + "name": "string.template.js.jsx", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.js.jsx", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, + { + "name": "string.template.js.jsx", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.js.jsx" + } + }, + "end": "(?=`)", + "patterns": [ + { + "include": "#type-arguments" + } + ] + } + ] + }, "template-substitution-element": { "name": "meta.template.expression.js.jsx", "begin": "\\$\\{", @@ -4663,6 +4705,73 @@ ], "contentName": "meta.embedded.line.js.jsx" }, + "type-string": { + "patterns": [ + { + "include": "#qstring-single" + }, + { + "include": "#qstring-double" + }, + { + "include": "#template-type" + } + ] + }, + "template-type": { + "patterns": [ + { + "include": "#template-call" + }, + { + "name": "string.template.js.jsx", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?(`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.js.jsx" + }, + "2": { + "name": "punctuation.definition.string.template.begin.js.jsx" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.template.end.js.jsx" + } + }, + "patterns": [ + { + "include": "#template-type-substitution-element" + }, + { + "include": "#string-character-escape" + } + ] + } + ] + }, + "template-type-substitution-element": { + "name": "meta.template.expression.js.jsx", + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.template-expression.begin.js.jsx" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.template-expression.end.js.jsx" + } + }, + "patterns": [ + { + "include": "#type" + } + ], + "contentName": "meta.embedded.line.js.jsx" + }, "regex": { "patterns": [ { diff --git a/extensions/log/cgmanifest.json b/extensions/log/cgmanifest.json index 0fe21e5c2c4..be1411f8187 100644 --- a/extensions/log/cgmanifest.json +++ b/extensions/log/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "vscode-logfile-highlighter", "repositoryUrl": "https://github.com/emilast/vscode-logfile-highlighter", - "commitHash": "5dcab1c304110b605041824cde3810c6ef305477" + "commitHash": "6f6eecc097509c6ee8f4141a7bd6a1f243461d68" } }, "license": "MIT", - "version": "2.8.0" + "version": "2.9.0" } ], "version": 1 diff --git a/extensions/log/syntaxes/log.tmLanguage.json b/extensions/log/syntaxes/log.tmLanguage.json index 4882a761e6f..1306563834a 100644 --- a/extensions/log/syntaxes/log.tmLanguage.json +++ b/extensions/log/syntaxes/log.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/emilast/vscode-logfile-highlighter/commit/5dcab1c304110b605041824cde3810c6ef305477", + "version": "https://github.com/emilast/vscode-logfile-highlighter/commit/6f6eecc097509c6ee8f4141a7bd6a1f243461d68", "name": "Log file", "scopeName": "text.log", "patterns": [ @@ -73,7 +73,7 @@ "name": "comment log.date" }, { - "match": "\\b\\d{2}[^\\w\\s]\\d{2}[^\\w\\s]\\d{4}\\b", + "match": "(?<=(^|\\s))\\d{2}[^\\w\\s]\\d{2}[^\\w\\s]\\d{4}\\b", "name": "comment log.date" }, { @@ -114,7 +114,7 @@ "name": "string.key, emphasis log.exception" }, { - "match": "\\b(http|https|ftp|file)://\\S+\\b/?", + "match": "\\b[a-z]+://\\S+\\b/?", "name": "constant.language log.constant" }, { diff --git a/extensions/markdown-basics/cgmanifest.json b/extensions/markdown-basics/cgmanifest.json index 5606dcc7cdd..92288d403b9 100644 --- a/extensions/markdown-basics/cgmanifest.json +++ b/extensions/markdown-basics/cgmanifest.json @@ -33,12 +33,12 @@ "git": { "name": "microsoft/vscode-markdown-tm-grammar", "repositoryUrl": "https://github.com/microsoft/vscode-markdown-tm-grammar", - "commitHash": "11cf764606cb2cde54badb5d0e5a0758a8871c4b" + "commitHash": "7019b191c3ee38b6c345f3a2a843f223eb92ca1e" } }, "license": "MIT", - "version": "0.0.0" + "version": "1.0.0" } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index 13ee6f3604b..a61af0d0c06 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/f051a36bd9713dd722cbe1bdde9c8240d12f00b4", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/7019b191c3ee38b6c345f3a2a843f223eb92ca1e", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -2574,7 +2574,7 @@ "name": "punctuation.definition.link.markdown" } }, - "match": "(<)((?:mailto:)?[-.\\w]+@[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+)(>)", + "match": "(<)((?:mailto:)?[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)(>)", "name": "meta.link.email.lt-gt.markdown" }, "link-inet": { diff --git a/extensions/php/cgmanifest.json b/extensions/php/cgmanifest.json index 3c5b9b9ffd3..4326e0a5e59 100644 --- a/extensions/php/cgmanifest.json +++ b/extensions/php/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "language-php", "repositoryUrl": "https://github.com/atom/language-php", - "commitHash": "6c0da475f86b45ea990638525f68be7658986546" + "commitHash": "e2637e1c522c932459eb2d5cf1651c5cc38058a1" } }, "license": "MIT", - "version": "0.44.5" + "version": "0.44.7" } ], "version": 1 diff --git a/extensions/php/syntaxes/php.tmLanguage.json b/extensions/php/syntaxes/php.tmLanguage.json index 54fbd4b7869..27a13e74c1b 100644 --- a/extensions/php/syntaxes/php.tmLanguage.json +++ b/extensions/php/syntaxes/php.tmLanguage.json @@ -4,9 +4,12 @@ "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/atom/language-php/commit/6c0da475f86b45ea990638525f68be7658986546", + "version": "https://github.com/atom/language-php/commit/e2637e1c522c932459eb2d5cf1651c5cc38058a1", "scopeName": "source.php", "patterns": [ + { + "include": "#attribute" + }, { "include": "#comments" }, @@ -230,7 +233,7 @@ ] }, { - "begin": "(?ix)\n(?:\n (?:^|(?<=}))\\s*(?:(abstract|final)\\s+)?(class)\\s+([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\n |\\b(new)\\s+(class)\\b # anonymous class\n)", + "begin": "(?ix)\n(?:\n \\b(?:(abstract|final)\\s+)?(class)\\s+([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\n |\\b(new)\\b\\s*(\\#\\[.*\\])?\\s*\\b(class)\\b # anonymous class\n)", "beginCaptures": { "1": { "name": "storage.modifier.${1:/downcase}.php" @@ -245,6 +248,13 @@ "name": "keyword.other.new.php" }, "5": { + "patterns": [ + { + "include": "#attribute" + } + ] + }, + "6": { "name": "storage.type.class.php" } }, @@ -410,30 +420,34 @@ "name": "meta.catch.php", "patterns": [ { - "include": "#namespace" - }, - { - "match": "(?xi)\n([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Exception class\n((?:\\s*\\|\\s*[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)*) # Optional additional exception classes\n\\s*\n((\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable", + "match": "(?xi)\n([a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)*) # union or single exception class\n\\s*\n((\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)? # Variable", "captures": { "1": { - "name": "support.class.exception.php" - }, - "2": { "patterns": [ - { - "match": "(?i)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*", - "name": "support.class.exception.php" - }, { "match": "\\|", "name": "punctuation.separator.delimiter.php" + }, + { + "begin": "(?i)(?=[\\\\a-z_\\x{7f}-\\x{7fffffff}])", + "end": "(?xi)\n( [a-z_\\x{7f}-\\x{7fffffff}] [a-z0-9_\\x{7f}-\\x{7fffffff}]* )\n(?![a-z0-9_\\x{7f}-\\x{7fffffff}\\\\])", + "endCaptures": { + "1": { + "name": "support.class.exception.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] } ] }, - "3": { + "2": { "name": "variable.other.php" }, - "4": { + "3": { "name": "punctuation.definition.variable.php" } } @@ -496,7 +510,12 @@ "name": "punctuation.definition.parameters.end.bracket.round.php" } }, + "name": "meta.function.closure.use.php", "patterns": [ + { + "match": ",", + "name": "punctuation.separator.delimiter.php" + }, { "captures": { "1": { @@ -509,22 +528,22 @@ "name": "punctuation.definition.variable.php" } }, - "match": "(?i)((&)?\\s*(\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\\s*(?=,|\\))", - "name": "meta.function.closure.use.php" + "match": "(?i)((?:(&)\\s*)?(\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\\s*(?=,|\\))" } ] }, { - "match": "(:)\\s*(\\?)?\\s*((?:\\\\?[a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*)+)", + "match": "(?xi)\n(:)\\s*\n(\n (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type\n [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type\n)\n(?=\\s*(?:{|/[/*]|\\#|$))", "captures": { "1": { "name": "keyword.operator.return-value.php" }, "2": { - "name": "keyword.operator.nullable-type.php" - }, - "3": { - "name": "storage.type.php" + "patterns": [ + { + "include": "#php-types" + } + ] } } } @@ -546,7 +565,7 @@ "name": "meta.function.closure.php", "patterns": [ { - "begin": "(&)?\\s*(\\()", + "begin": "(?:(&)\\s*)?(\\()", "beginCaptures": { "1": { "name": "storage.modifier.reference.php" @@ -569,21 +588,109 @@ ] }, { - "match": "(:)\\s*(\\?)?\\s*((?:\\\\?[a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*)+)\\s*", + "match": "(?xi)\n(:)\\s*\n(\n (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type\n [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type\n)\n(?=\\s*(?:=>|/[/*]|\\#|$))", "captures": { "1": { "name": "keyword.operator.return-value.php" }, "2": { - "name": "keyword.operator.nullable-type.php" - }, - "3": { - "name": "storage.type.php" + "patterns": [ + { + "include": "#php-types" + } + ] } } } ] }, + { + "begin": "(?x)\n((?:(?:final|abstract|public|private|protected)\\s+)*)\n(function)\\s+(__construct)\n\\s*(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "final|abstract|public|private|protected", + "name": "storage.modifier.php" + } + ] + }, + "2": { + "name": "storage.type.function.php" + }, + "3": { + "name": "support.function.constructor.php" + }, + "4": { + "name": "punctuation.definition.parameters.begin.bracket.round.php" + } + }, + "contentName": "meta.function.parameters.php", + "end": "(?xi)\n(\\)) \\s* ( : \\s*\n (?:\\?\\s*)? (?!\\s) [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\\\s\\|]+ (?[^\\[\\]]+|\\[\\g<8>\\])*)(\\])\n |((?:\\S*?\\(\\))|(?:\\S*?))\n )\n)?\n\\s*(?=,|\\)|/[/*]|\\#|$) # A closing parentheses (end of argument list) or a comma or a comment", - "name": "meta.function.parameter.array.php", + "match": "(?xi)\n(?: (\n (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type\n [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type\n) \\s+ )?\n((?:(&)\\s*)?(\\.\\.\\.)(\\$)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference\n(?=\\s*(?:,|\\)|/[/*]|\\#|$)) # A closing parentheses (end of argument list) or a comma or a comment", "captures": { "1": { - "name": "keyword.operator.nullable-type.php" - }, - "2": { - "name": "storage.type.php" - }, - "3": { - "name": "variable.other.php" - }, - "4": { - "name": "storage.modifier.reference.php" - }, - "5": { - "name": "punctuation.definition.variable.php" - }, - "6": { - "name": "keyword.operator.assignment.php" - }, - "7": { - "name": "constant.language.php" - }, - "8": { - "name": "punctuation.section.array.begin.php" - }, - "9": { "patterns": [ { - "include": "#parameter-default-types" + "include": "#php-types" } ] }, - "10": { - "name": "punctuation.section.array.end.php" - }, - "11": { - "name": "invalid.illegal.non-null-typehinted.php" - } - } - }, - { - "begin": "(?xi)\n(?:(\\?)\\s*)?\n(\\\\?(?:[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*\\\\)*) # Optional namespace\n([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Typehinted class name\n\\s+((&)?\\s*(\\.\\.\\.)?(\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference", - "beginCaptures": { - "1": { - "name": "keyword.operator.nullable-type.php" - }, "2": { - "name": "support.other.namespace.php", - "patterns": [ - { - "match": "(?i)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*", - "name": "storage.type.php" - }, - { - "match": "\\\\", - "name": "punctuation.separator.inheritance.php" - } - ] - }, - "3": { - "name": "storage.type.php" - }, - "4": { "name": "variable.other.php" }, - "5": { + "3": { "name": "storage.modifier.reference.php" }, - "6": { + "4": { "name": "keyword.operator.variadic.php" }, - "7": { + "5": { "name": "punctuation.definition.variable.php" } }, - "end": "(?=,|\\)|/[/*]|\\#)", + "name": "meta.function.parameter.variadic.php" + }, + { + "begin": "(?xi)\n(\n (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type\n [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type\n)\n\\s+ ((?:(&)\\s*)?(\\$)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#php-types" + } + ] + }, + "2": { + "name": "variable.other.php" + }, + "3": { + "name": "storage.modifier.reference.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + } + }, + "end": "(?=\\s*(?:,|\\)|/[/*]|\\#))", "name": "meta.function.parameter.typehinted.php", "patterns": [ { @@ -1260,16 +1363,17 @@ "name": "keyword.operator.assignment.php" } }, - "end": "(?=,|\\)|/[/*]|\\#)", + "end": "(?=\\s*(?:,|\\)|/[/*]|\\#))", "patterns": [ { - "include": "$self" + "include": "#parameter-default-types" } ] } ] }, { + "match": "(?xi)\n((?:(&)\\s*)?(\\$)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference\n(?=\\s*(?:,|\\)|/[/*]|\\#|$)) # A closing parentheses (end of argument list) or a comma or a comment", "captures": { "1": { "name": "variable.other.php" @@ -1278,17 +1382,13 @@ "name": "storage.modifier.reference.php" }, "3": { - "name": "keyword.operator.variadic.php" - }, - "4": { "name": "punctuation.definition.variable.php" } }, - "match": "(?xi)\n((&)?\\s*(\\.\\.\\.)?(\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference\n\\s*(?=,|\\)|/[/*]|\\#|$) # A closing parentheses (end of argument list) or a comma or a comment", "name": "meta.function.parameter.no-default.php" }, { - "begin": "(?xi)\n((&)?\\s*(\\.\\.\\.)?(\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference\n\\s*(=)\\s*\n(?:(\\[)((?>[^\\[\\]]+|\\[\\g<6>\\])*)(\\]))? # Optional default type", + "begin": "(?xi)\n((?:(&)\\s*)?(\\$)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*) # Variable name with possible reference\n\\s*(=)\\s*", "beginCaptures": { "1": { "name": "variable.other.php" @@ -1297,29 +1397,13 @@ "name": "storage.modifier.reference.php" }, "3": { - "name": "keyword.operator.variadic.php" - }, - "4": { "name": "punctuation.definition.variable.php" }, - "5": { + "4": { "name": "keyword.operator.assignment.php" - }, - "6": { - "name": "punctuation.section.array.begin.php" - }, - "7": { - "patterns": [ - { - "include": "#parameter-default-types" - } - ] - }, - "8": { - "name": "punctuation.section.array.end.php" } }, - "end": "(?=,|\\)|/[/*]|\\#)", + "end": "(?=\\s*(?:,|\\)|/[/*]|\\#))", "name": "meta.function.parameter.default.php", "patterns": [ { @@ -2154,13 +2238,13 @@ "invoke-call": { "captures": { "1": { - "name": "punctuation.definition.variable.php" + "name": "variable.other.php" }, "2": { - "name": "variable.other.php" + "name": "punctuation.definition.variable.php" } }, - "match": "(?i)(\\$+)([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)(?=\\s*\\()", + "match": "(?i)((\\$+)[a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)(?=\\s*\\()", "name": "meta.function-call.invoke.php" }, "namespace": { @@ -2283,6 +2367,29 @@ } ] }, + "php-types": { + "patterns": [ + { + "match": "\\?", + "name": "keyword.operator.nullable-type.php" + }, + { + "match": "\\|", + "name": "punctuation.separator.delimiter.php" + }, + { + "match": "(?i)\\b(null|int|float|bool|string|array|object|callable|iterable|false|mixed)\\b", + "name": "storage.type.php" + }, + { + "match": "(?i)\\b(parent|self)\\b", + "name": "storage.type.php" + }, + { + "include": "#class-name" + } + ] + }, "parameter-default-types": { "patterns": [ { @@ -2332,6 +2439,25 @@ } ] }, + { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "punctuation.section.array.begin.php" + } + }, + "end": "\\]|(?=\\?>)", + "endCaptures": { + "0": { + "name": "punctuation.section.array.end.php" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, { "include": "#instantiation" }, @@ -2430,7 +2556,7 @@ "0": { "patterns": [ { - "match": "(?x)\\b\n(string|integer|int|boolean|bool|float|double|object|mixed\n|array|resource|void|null|callback|false|true|self)\\b", + "match": "(?x)\\b\n(string|integer|int|boolean|bool|float|double|object|mixed\n|array|resource|void|null|callback|false|true|self|static)\\b", "name": "keyword.other.type.php" }, { diff --git a/extensions/rust/cgmanifest.json b/extensions/rust/cgmanifest.json index 932a3926f12..676e6a18390 100644 --- a/extensions/rust/cgmanifest.json +++ b/extensions/rust/cgmanifest.json @@ -6,12 +6,12 @@ "git": { "name": "rust-syntax", "repositoryUrl": "https://github.com/dustypomerleau/rust-syntax", - "commitHash": "19f9aa86c0850b98db175754f019a2e79413353e" + "commitHash": "f202e7c2b0e962d78d82477b97c25a6234210c78" } }, "license": "MIT", "description": "A TextMate-style grammar for Rust.", - "version": "0.2.13" + "version": "0.4.2" } ], "version": 1 diff --git a/extensions/rust/syntaxes/rust.tmLanguage.json b/extensions/rust/syntaxes/rust.tmLanguage.json index fdced07972b..ffcbbfdbede 100644 --- a/extensions/rust/syntaxes/rust.tmLanguage.json +++ b/extensions/rust/syntaxes/rust.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dustypomerleau/rust-syntax/commit/19f9aa86c0850b98db175754f019a2e79413353e", + "version": "https://github.com/dustypomerleau/rust-syntax/commit/f202e7c2b0e962d78d82477b97c25a6234210c78", "name": "Rust", "scopeName": "source.rust", "patterns": [ @@ -52,7 +52,7 @@ { "comment": "macro type metavariables", "name": "meta.macro.metavariable.type.rust", - "match": "(\\$)((crate)|([A-Z][A-Za-z0-9_]*))((:)(block|expr|ident|item|lifetime|literal|meta|pat|path|stmt|tt|ty|vis))?", + "match": "(\\$)((crate)|([A-Z][A-Za-z0-9_]*))((:)(block|expr|ident|item|lifetime|literal|meta|path?|stmt|tt|ty|vis))?", "captures": { "1": { "name": "keyword.operator.macro.dollar.rust" @@ -79,7 +79,7 @@ { "comment": "macro metavariables", "name": "meta.macro.metavariable.rust", - "match": "(\\$)([a-z][A-Za-z0-9_]*)((:)(block|expr|ident|item|lifetime|literal|meta|pat|path|stmt|tt|ty|vis))?", + "match": "(\\$)([a-z][A-Za-z0-9_]*)((:)(block|expr|ident|item|lifetime|literal|meta|path?|stmt|tt|ty|vis))?", "captures": { "1": { "name": "keyword.operator.macro.dollar.rust" @@ -169,7 +169,7 @@ "match": "(mod)\\s+((?:r#(?!crate|[Ss]elf|super))?[a-z][A-Za-z0-9_]*)", "captures": { "1": { - "name": "keyword.control.rust" + "name": "storage.type.rust" }, "2": { "name": "entity.name.module.rust" @@ -182,7 +182,7 @@ "begin": "\\b(extern)\\s+(crate)", "beginCaptures": { "1": { - "name": "keyword.control.rust" + "name": "storage.type.rust" }, "2": { "name": "keyword.other.crate.rust" @@ -215,7 +215,7 @@ "begin": "\\b(use)\\s", "beginCaptures": { "1": { - "name": "keyword.control.rust" + "name": "keyword.other.rust" } }, "end": ";", @@ -309,9 +309,14 @@ "block-comments": { "patterns": [ { - "comment": "block comments", + "comment": "empty block comments", "name": "comment.block.rust", - "begin": "/\\*(?!\\*)", + "match": "/\\*\\*/" + }, + { + "comment": "block documentation comments", + "name": "comment.block.documentation.rust", + "begin": "/\\*\\*", "end": "\\*/", "patterns": [ { @@ -320,9 +325,9 @@ ] }, { - "comment": "block documentation comments", - "name": "comment.block.documentation.rust", - "begin": "/\\*\\*", + "comment": "block comments", + "name": "comment.block.rust", + "begin": "/\\*(?!\\*)", "end": "\\*/", "patterns": [ { @@ -344,7 +349,7 @@ "match": "\\b(const)\\s+([A-Z][A-Za-z0-9_]*)\\b", "captures": { "1": { - "name": "keyword.control.rust" + "name": "storage.type.rust" }, "2": { "name": "constant.other.caps.rust" @@ -406,7 +411,7 @@ { "comment": "booleans", "name": "constant.language.bool.rust", - "match": "\\btrue|false\\b" + "match": "\\b(true|false)\\b" } ] }, @@ -452,7 +457,7 @@ "begin": "\\b(fn)\\s+((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)((\\()|(<))", "beginCaptures": { "1": { - "name": "keyword.control.fn.rust" + "name": "keyword.other.fn.rust" }, "2": { "name": "entity.name.function.rust" @@ -645,7 +650,7 @@ { "comment": "control flow keywords", "name": "keyword.control.rust", - "match": "\\b(async|await|break|continue|do|else|for|if|loop|match|move|return|try|where|while|yield)\\b" + "match": "\\b(await|break|continue|do|else|for|if|loop|match|return|try|while|yield)\\b" }, { "comment": "storage keywords", @@ -660,7 +665,7 @@ { "comment": "other keywords", "name": "keyword.other.rust", - "match": "\\b(as|become|box|dyn|final|impl|in|override|priv|pub|ref|typeof|union|unsafe|unsized|use|virtual)\\b" + "match": "\\b(as|async|become|box|dyn|move|final|impl|in|override|priv|pub|ref|typeof|union|unsafe|unsized|use|virtual|where)\\b" }, { "comment": "fn", @@ -677,11 +682,6 @@ "name": "storage.modifier.mut.rust", "match": "\\bmut\\b" }, - { - "comment": "math operators", - "name": "keyword.operator.math.rust", - "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))" - }, { "comment": "logical operators", "name": "keyword.operator.logical.rust", @@ -695,7 +695,7 @@ { "comment": "assignment operators", "name": "keyword.operator.assignment.rust", - "match": "(-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)" + "match": "(\\+=|-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)" }, { "comment": "single equal", @@ -707,6 +707,11 @@ "name": "keyword.operator.comparison.rust", "match": "(=(=)?(?!>)|!=|<=|(?=)" }, + { + "comment": "math operators", + "name": "keyword.operator.math.rust", + "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))" + }, { "comment": "less than, greater than (special case)", "match": "(?:\\b|(?:(\\))|(\\])|(\\})))[ \\t]+([<>])[ \\t]+(?:\\b|(?:(\\()|(\\[)|(\\{)))", @@ -1129,7 +1134,7 @@ { "comment": "variables", "name": "variable.other.rust", - "match": "\\b(?`?)[\\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.other.declaration-specifier.swift" + } + }, + "end": "(?=$|[={])", + "patterns": [ + { + "include": "#available-types" + } + ] + }, "types-precedencegroup": { "patterns": [ { diff --git a/extensions/typescript-basics/cgmanifest.json b/extensions/typescript-basics/cgmanifest.json index 0a81ee864e0..d8f149a1517 100644 --- a/extensions/typescript-basics/cgmanifest.json +++ b/extensions/typescript-basics/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "TypeScript-TmLanguage", "repositoryUrl": "https://github.com/microsoft/TypeScript-TmLanguage", - "commitHash": "59b62cbc624e3a01368e5432d85af0c99a27d49d" + "commitHash": "a755c6bad619daa8349fb23149eeeff220a06603" } }, "license": "MIT", diff --git a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json index 4f7b3c715e0..3c707e69977 100644 --- a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/59b62cbc624e3a01368e5432d85af0c99a27d49d", + "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/a755c6bad619daa8349fb23149eeeff220a06603", "name": "TypeScript", "scopeName": "source.ts", "patterns": [ @@ -436,7 +436,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.ts", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts entity.name.function.ts" @@ -494,7 +494,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.ts", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts variable.other.constant.ts entity.name.function.ts" @@ -878,7 +878,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -1118,7 +1118,7 @@ "include": "#comment" }, { - "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.ts entity.name.function.ts" @@ -1301,7 +1301,7 @@ }, { "name": "meta.method.declaration.ts", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.ts" @@ -1331,7 +1331,7 @@ }, { "name": "meta.method.declaration.ts", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.ts" @@ -1363,7 +1363,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.ts", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1384,7 +1384,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1444,7 +1444,7 @@ }, { "name": "meta.arrow.ts", - "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1554,6 +1554,14 @@ } }, "patterns": [ + { + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.ts" @@ -2729,7 +2754,7 @@ "end": "(?=,|\\})", "patterns": [ { - "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -2762,7 +2787,7 @@ ] }, { - "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -2798,7 +2823,7 @@ ] }, { - "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "meta.brace.round.ts" @@ -2851,13 +2876,13 @@ "function-call": { "patterns": [ { - "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", - "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "name": "meta.function-call.ts", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "include": "#function-call-target" @@ -2986,7 +3011,7 @@ "paren-expression-possibly-arrow": { "patterns": [ { - "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -3000,7 +3025,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -3070,7 +3095,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -3377,8 +3402,18 @@ ] }, "typeof-operator": { - "name": "keyword.operator.expression.typeof.ts", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", + "match": "(?x) (?:(\\.)|(\\?\\.(?!\\s*[[:digit:]]))) \\s* (?:\n (?:(constructor|length|prototype|__proto__)\\b(?!\\$|\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -3690,7 +3725,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -4013,7 +4048,7 @@ "include": "#comment" }, { - "include": "#string" + "include": "#type-string" }, { "include": "#numeric-literal" @@ -4221,7 +4256,7 @@ }, "patterns": [ { - "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", + "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", "captures": { "1": { "name": "storage.modifier.ts" @@ -4626,42 +4661,7 @@ "template": { "patterns": [ { - "name": "string.template.ts", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "end": "(?=`)", - "patterns": [ - { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.tagged-template.ts", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.ts", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.ts" - } - }, - "end": "(?=`)", - "patterns": [ - { - "include": "#type-arguments" - } - ] + "include": "#template-call" }, { "name": "string.template.ts", @@ -4691,6 +4691,48 @@ } ] }, + "template-call": { + "patterns": [ + { + "name": "string.template.ts", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.ts", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, + { + "name": "string.template.ts", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.ts" + } + }, + "end": "(?=`)", + "patterns": [ + { + "include": "#type-arguments" + } + ] + } + ] + }, "template-substitution-element": { "name": "meta.template.expression.ts", "begin": "\\$\\{", @@ -4712,6 +4754,73 @@ ], "contentName": "meta.embedded.line.ts" }, + "type-string": { + "patterns": [ + { + "include": "#qstring-single" + }, + { + "include": "#qstring-double" + }, + { + "include": "#template-type" + } + ] + }, + "template-type": { + "patterns": [ + { + "include": "#template-call" + }, + { + "name": "string.template.ts", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?(`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.ts" + }, + "2": { + "name": "punctuation.definition.string.template.begin.ts" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.template.end.ts" + } + }, + "patterns": [ + { + "include": "#template-type-substitution-element" + }, + { + "include": "#string-character-escape" + } + ] + } + ] + }, + "template-type-substitution-element": { + "name": "meta.template.expression.ts", + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.template-expression.begin.ts" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.template-expression.end.ts" + } + }, + "patterns": [ + { + "include": "#type" + } + ], + "contentName": "meta.embedded.line.ts" + }, "regex": { "patterns": [ { diff --git a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json index e655d8ab0b4..323199d95d3 100644 --- a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/59b62cbc624e3a01368e5432d85af0c99a27d49d", + "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/a755c6bad619daa8349fb23149eeeff220a06603", "name": "TypeScriptReact", "scopeName": "source.tsx", "patterns": [ @@ -439,7 +439,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.tsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx entity.name.function.tsx" @@ -497,7 +497,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.tsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx variable.other.constant.tsx entity.name.function.tsx" @@ -881,7 +881,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -1121,7 +1121,7 @@ "include": "#comment" }, { - "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(\\#?[_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.tsx entity.name.function.tsx" @@ -1304,7 +1304,7 @@ }, { "name": "meta.method.declaration.tsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.tsx" @@ -1334,7 +1334,7 @@ }, { "name": "meta.method.declaration.tsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.tsx" @@ -1366,7 +1366,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.tsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1387,7 +1387,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", + "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1447,7 +1447,7 @@ }, { "name": "meta.arrow.tsx", - "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1557,6 +1557,14 @@ } }, "patterns": [ + { + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.tsx" @@ -2732,7 +2757,7 @@ "end": "(?=,|\\})", "patterns": [ { - "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -2765,7 +2790,7 @@ ] }, { - "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -2801,7 +2826,7 @@ ] }, { - "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "meta.brace.round.tsx" @@ -2854,13 +2879,13 @@ "function-call": { "patterns": [ { - "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", - "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "name": "meta.function-call.tsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", + "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?((<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\())", "patterns": [ { "include": "#function-call-target" @@ -2989,7 +3014,7 @@ "paren-expression-possibly-arrow": { "patterns": [ { - "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -3003,7 +3028,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -3073,7 +3098,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -3328,8 +3353,18 @@ ] }, "typeof-operator": { - "name": "keyword.operator.expression.typeof.tsx", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", + "match": "(?x) (?:(\\.)|(\\?\\.(?!\\s*[[:digit:]]))) \\s* (?:\n (?:(constructor|length|prototype|__proto__)\\b(?!\\$|\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -3641,7 +3676,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\'\\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -3964,7 +3999,7 @@ "include": "#comment" }, { - "include": "#string" + "include": "#type-string" }, { "include": "#numeric-literal" @@ -4172,7 +4207,7 @@ }, "patterns": [ { - "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", + "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*(?\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -4577,42 +4612,7 @@ "template": { "patterns": [ { - "name": "string.template.tsx", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "end": "(?=`)", - "patterns": [ - { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.tagged-template.tsx", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.tsx", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.tsx" - } - }, - "end": "(?=`)", - "patterns": [ - { - "include": "#type-arguments" - } - ] + "include": "#template-call" }, { "name": "string.template.tsx", @@ -4642,6 +4642,48 @@ } ] }, + "template-call": { + "patterns": [ + { + "name": "string.template.tsx", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.tsx", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, + { + "name": "string.template.tsx", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?\\s*(?=(<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|awaited|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.tsx" + } + }, + "end": "(?=`)", + "patterns": [ + { + "include": "#type-arguments" + } + ] + } + ] + }, "template-substitution-element": { "name": "meta.template.expression.tsx", "begin": "\\$\\{", @@ -4663,6 +4705,73 @@ ], "contentName": "meta.embedded.line.tsx" }, + "type-string": { + "patterns": [ + { + "include": "#qstring-single" + }, + { + "include": "#qstring-double" + }, + { + "include": "#template-type" + } + ] + }, + "template-type": { + "patterns": [ + { + "include": "#template-call" + }, + { + "name": "string.template.tsx", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)?(`)", + "beginCaptures": { + "1": { + "name": "entity.name.function.tagged-template.tsx" + }, + "2": { + "name": "punctuation.definition.string.template.begin.tsx" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.template.end.tsx" + } + }, + "patterns": [ + { + "include": "#template-type-substitution-element" + }, + { + "include": "#string-character-escape" + } + ] + } + ] + }, + "template-type-substitution-element": { + "name": "meta.template.expression.tsx", + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.template-expression.begin.tsx" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.template-expression.end.tsx" + } + }, + "patterns": [ + { + "include": "#type" + } + ], + "contentName": "meta.embedded.line.tsx" + }, "regex": { "patterns": [ { From a6f2524e4a8178ecfca17816acf259ee002cd342 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 16:09:49 +0100 Subject: [PATCH 0934/1837] - introduce panel title menu id - move view container menu acitons --- src/vs/platform/actions/common/actions.ts | 2 + src/vs/workbench/browser/menuActions.ts | 99 +++++++++++++++ src/vs/workbench/browser/panecomposite.ts | 36 +----- src/vs/workbench/browser/panel.ts | 56 ++++++++- .../browser/parts/panel/panelActions.ts | 9 +- .../browser/parts/panel/panelPart.ts | 4 +- .../browser/parts/views/viewMenuActions.ts | 116 ++---------------- .../workbench/browser/parts/views/viewPane.ts | 2 +- .../browser/parts/views/viewPaneContainer.ts | 46 +++++-- 9 files changed, 208 insertions(+), 162 deletions(-) create mode 100644 src/vs/workbench/browser/menuActions.ts diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index dcc37228225..0bd63c41c03 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -133,6 +133,8 @@ export class MenuId { static readonly TimelineTitle = new MenuId('TimelineTitle'); static readonly TimelineTitleContext = new MenuId('TimelineTitleContext'); static readonly AccountsContext = new MenuId('AccountsContext'); + static readonly PanelTitle = new MenuId('PanelTitle'); + static readonly PanelTitleContext = new MenuId('PanelTitleContext'); readonly id: number; readonly _debugName: string; diff --git a/src/vs/workbench/browser/menuActions.ts b/src/vs/workbench/browser/menuActions.ts new file mode 100644 index 00000000000..3cc2d827b0b --- /dev/null +++ b/src/vs/workbench/browser/menuActions.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IAction } from 'vs/base/common/actions'; +import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { Emitter, Event } from 'vs/base/common/event'; +import { MenuId, IMenuService, IMenu, SubmenuItemAction, IMenuActionOptions } from 'vs/platform/actions/common/actions'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; + +class MenuActions extends Disposable { + + private readonly menu: IMenu; + + private _primaryActions: IAction[] = []; + get primaryActions() { return this._primaryActions; } + + private _secondaryActions: IAction[] = []; + get secondaryActions() { return this._secondaryActions; } + + private readonly _onDidChange = new Emitter(); + readonly onDidChange = this._onDidChange.event; + + private disposables = this._register(new DisposableStore()); + + constructor( + menuId: MenuId, + private readonly options: IMenuActionOptions | undefined, + private readonly menuService: IMenuService, + private readonly contextKeyService: IContextKeyService + ) { + super(); + this.menu = this._register(menuService.createMenu(menuId, contextKeyService)); + this._register(this.menu.onDidChange(() => this.updateActions())); + this.updateActions(); + } + + private updateActions(): void { + this.disposables.clear(); + this._primaryActions = []; + this._secondaryActions = []; + this.disposables.add(createAndFillInActionBarActions(this.menu, this.options, { primary: this._primaryActions, secondary: this._secondaryActions })); + this.disposables.add(this.updateSubmenus([...this._primaryActions, ...this._secondaryActions], {})); + this._onDidChange.fire(); + } + + private updateSubmenus(actions: IAction[], submenus: { [id: number]: IMenu }): IDisposable { + const disposables = new DisposableStore(); + for (const action of actions) { + if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) { + const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService)); + disposables.add(menu.onDidChange(() => this.updateActions())); + disposables.add(this.updateSubmenus(action.actions, submenus)); + } + } + return disposables; + } +} + +export class CompositeMenuActions extends Disposable { + + private readonly menuActions: MenuActions; + private readonly contextMenuActionsDisposable = this._register(new MutableDisposable()); + + private _onDidChange = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; + + constructor( + menuId: MenuId, + private readonly contextMenuId: MenuId, + private readonly options: IMenuActionOptions | undefined, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IMenuService private readonly menuService: IMenuService, + ) { + super(); + this.menuActions = this._register(new MenuActions(menuId, this.options, menuService, contextKeyService)); + this._register(this.menuActions.onDidChange(() => this._onDidChange.fire())); + } + + getPrimaryActions(): IAction[] { + return this.menuActions.primaryActions; + } + + getSecondaryActions(): IAction[] { + return this.menuActions.secondaryActions; + } + + getContextMenuActions(): IAction[] { + const actions: IAction[] = []; + const menu = this.menuService.createMenu(this.contextMenuId, this.contextKeyService); + this.contextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, this.options, { primary: [], secondary: actions }); + menu.dispose(); + return actions; + } + +} + diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts index b1e83500c44..ac9a44260da 100644 --- a/src/vs/workbench/browser/panecomposite.ts +++ b/src/vs/workbench/browser/panecomposite.ts @@ -15,15 +15,12 @@ import { Composite } from 'vs/workbench/browser/composite'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ViewPaneContainer } from './parts/views/viewPaneContainer'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; -import { IAction, IActionViewItem, Separator } from 'vs/base/common/actions'; -import { ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; -import { MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { IAction, IActionViewItem } from 'vs/base/common/actions'; +import { MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; export class PaneComposite extends Composite implements IPaneComposite { - private menuActions: ViewContainerMenuActions; - constructor( id: string, protected readonly viewPaneContainer: ViewPaneContainer, @@ -36,9 +33,6 @@ export class PaneComposite extends Composite implements IPaneComposite { @IWorkspaceContextService protected contextService: IWorkspaceContextService ) { super(id, telemetryService, themeService, storageService); - - this.menuActions = this._register(this.instantiationService.createInstance(ViewContainerMenuActions, viewPaneContainer.viewContainer, MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext)); - this._register(this.menuActions.onDidChangeTitle(() => this.updateTitleArea())); this._register(this.viewPaneContainer.onTitleAreaUpdate(() => this.updateTitleArea())); } @@ -72,35 +66,15 @@ export class PaneComposite extends Composite implements IPaneComposite { } getContextMenuActions(): ReadonlyArray { - const result = []; - result.push(...this.menuActions.getContextMenuActions()); - - if (result.length) { - result.push(new Separator()); - } - - result.push(...this.viewPaneContainer.getContextMenuActions()); - return result; + return this.viewPaneContainer.getContextMenuActions(); } getActions(): ReadonlyArray { - const result = []; - result.push(...this.viewPaneContainer.getActions()); - result.push(...this.menuActions.getPrimaryActions()); - return result; + return this.viewPaneContainer.getActions(); } getSecondaryActions(): ReadonlyArray { - const menuActions = this.menuActions.getSecondaryActions(); - const viewPaneContainerActions = this.viewPaneContainer.getSecondaryActions(); - if (menuActions.length && viewPaneContainerActions.length) { - return [ - ...menuActions, - new Separator(), - ...viewPaneContainerActions - ]; - } - return menuActions.length ? menuActions : viewPaneContainerActions; + return this.viewPaneContainer.getSecondaryActions(); } getActionViewItem(action: IAction): IActionViewItem | undefined { diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index b2b2a18b46f..435c034cbfe 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -6,11 +6,63 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IPanel } from 'vs/workbench/common/panel'; import { CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite'; -import { IConstructorSignature0, BrandedService } from 'vs/platform/instantiation/common/instantiation'; +import { IConstructorSignature0, BrandedService, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { assertIsDefined } from 'vs/base/common/types'; import { PaneComposite } from 'vs/workbench/browser/panecomposite'; +import { IAction, Separator } from 'vs/base/common/actions'; +import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { MenuId } from 'vs/platform/actions/common/actions'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -export abstract class Panel extends PaneComposite implements IPanel { } +export abstract class Panel extends PaneComposite implements IPanel { + + private readonly panelActions: CompositeMenuActions; + + constructor(id: string, + viewPaneContainer: ViewPaneContainer, + @ITelemetryService telemetryService: ITelemetryService, + @IStorageService storageService: IStorageService, + @IInstantiationService instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + ) { + super(id, viewPaneContainer, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService); + this.panelActions = this._register(this.instantiationService.createInstance(CompositeMenuActions, MenuId.PanelTitle, MenuId.PanelTitleContext, undefined)); + this._register(this.panelActions.onDidChange(() => this.updateTitleArea())); + } + + getActions(): ReadonlyArray { + return [...super.getActions(), ...this.panelActions.getPrimaryActions()]; + } + + getSecondaryActions(): ReadonlyArray { + return this.mergeSecondaryActions(super.getSecondaryActions(), this.panelActions.getSecondaryActions()); + } + + getContextMenuActions(): ReadonlyArray { + return this.mergeSecondaryActions(super.getContextMenuActions(), this.panelActions.getContextMenuActions()); + } + + private mergeSecondaryActions(actions: ReadonlyArray, panelActions: IAction[]): ReadonlyArray { + if (panelActions.length && actions.length) { + return [ + ...actions, + new Separator(), + ...panelActions, + ]; + } + return panelActions.length ? panelActions : actions; + } + +} /** * A panel descriptor is a leightweight descriptor of a panel in the workbench. diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 9fa815919e7..2d9264928d7 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -15,10 +15,9 @@ import { IWorkbenchLayoutService, Parts, Position, positionToString } from 'vs/w import { ActivityAction, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositeBarActions'; import { IActivity } from 'vs/workbench/common/activity'; import { ActivePanelContext, PanelMaximizedContext, PanelPositionContext, PanelVisibleContext } from 'vs/workbench/common/panel'; -import { ContextKeyEqualsExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -import { ViewContainerLocation, ViewContainerLocationToString } from 'vs/workbench/common/views'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; const maximizeIcon = registerIcon('panel-maximize', Codicon.chevronUp, nls.localize('maximizeIcon', 'Icon to maximize a panel.')); @@ -242,8 +241,7 @@ registerAction2(class extends Action2 { icon: maximizeIcon, toggled: { condition: PanelMaximizedContext, icon: restoreIcon, tooltip: { value: nls.localize('minimizePanel', "Restore Panel Size"), original: 'Restore Panel Size' } }, menu: [{ - id: MenuId.ViewContainerTitle, - when: ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Panel)), + id: MenuId.PanelTitle, group: 'navigation', order: 1 }] @@ -275,8 +273,7 @@ registerAction2(class extends Action2 { id: MenuId.CommandPalette, when: PanelVisibleContext, }, { - id: MenuId.ViewContainerTitle, - when: ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Panel)), + id: MenuId.PanelTitle, group: 'navigation', order: 2 }] diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 8a7c5c62f4a..c6cd4744d24 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -34,11 +34,11 @@ import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ViewContainer, IViewDescriptorService, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views'; -import { MenuId } from 'vs/platform/actions/common/actions'; import { ViewMenuActions, ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { Before2D, CompositeDragAndDropObserver, ICompositeDragAndDrop, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; +import { MenuId } from 'vs/platform/actions/common/actions'; interface ICachedPanel { id: string; @@ -195,7 +195,7 @@ export class PanelPart extends CompositePart implements IPanelService { viewMenuActions.dispose(); } - const viewContainerMenuActions = this.instantiationService.createInstance(ViewContainerMenuActions, container, MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext); + const viewContainerMenuActions = this.instantiationService.createInstance(ViewContainerMenuActions, container); result.push(...viewContainerMenuActions.getContextMenuActions()); viewContainerMenuActions.dispose(); } diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts index 37e0ce2237c..c9536c59615 100644 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ b/src/vs/workbench/browser/parts/views/viewMenuActions.ts @@ -3,101 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IAction } from 'vs/base/common/actions'; -import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; -import { Emitter, Event } from 'vs/base/common/event'; -import { MenuId, IMenuService, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { MenuId, IMenuService } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IViewDescriptorService, ViewContainer, ViewContainerLocationToString } from 'vs/workbench/common/views'; - -class MenuActions extends Disposable { - - private readonly menu: IMenu; - - private _primaryActions: IAction[] = []; - get primaryActions() { return this._primaryActions; } - - private _secondaryActions: IAction[] = []; - get secondaryActions() { return this._secondaryActions; } - - private readonly _onDidChange = new Emitter(); - readonly onDidChange = this._onDidChange.event; - - private disposables = this._register(new DisposableStore()); - - constructor( - menuId: MenuId, - private readonly menuService: IMenuService, - private readonly contextKeyService: IContextKeyService - ) { - super(); - this.menu = this._register(menuService.createMenu(menuId, contextKeyService)); - this._register(this.menu.onDidChange(() => this.updateActions())); - this.updateActions(); - } - - private updateActions(): void { - this.disposables.clear(); - this._primaryActions = []; - this._secondaryActions = []; - this.disposables.add(createAndFillInActionBarActions(this.menu, { shouldForwardArgs: true }, { primary: this._primaryActions, secondary: this._secondaryActions })); - this.disposables.add(this.updateSubmenus([...this._primaryActions, ...this._secondaryActions], {})); - this._onDidChange.fire(); - } - - private updateSubmenus(actions: IAction[], submenus: { [id: number]: IMenu }): IDisposable { - const disposables = new DisposableStore(); - for (const action of actions) { - if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) { - const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService)); - disposables.add(menu.onDidChange(() => this.updateActions())); - disposables.add(this.updateSubmenus(action.actions, submenus)); - } - } - return disposables; - } -} - -export abstract class AbstractViewMenuActions extends Disposable { - - private readonly menuActions: MenuActions; - private readonly contextMenuActionsDisposable = this._register(new MutableDisposable()); - - private _onDidChangeTitle = this._register(new Emitter()); - readonly onDidChangeTitle: Event = this._onDidChangeTitle.event; - - constructor( - menuId: MenuId, - private readonly contextMenuId: MenuId, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IMenuService private readonly menuService: IMenuService, - ) { - super(); - this.menuActions = this._register(new MenuActions(menuId, menuService, contextKeyService)); - this._register(this.menuActions.onDidChange(() => this._onDidChangeTitle.fire())); - } - - getPrimaryActions(): IAction[] { - return this.menuActions.primaryActions; - } - - getSecondaryActions(): IAction[] { - return this.menuActions.secondaryActions; - } - - getContextMenuActions(): IAction[] { - const actions: IAction[] = []; - const menu = this.menuService.createMenu(this.contextMenuId, this.contextKeyService); - this.contextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, { primary: [], secondary: actions }); - menu.dispose(); - return actions; - } - -} - -export class ViewMenuActions extends AbstractViewMenuActions { +import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { ViewContainer } from 'vs/workbench/common/views'; +export class ViewMenuActions extends CompositeMenuActions { constructor( viewId: string, menuId: MenuId, @@ -107,34 +18,21 @@ export class ViewMenuActions extends AbstractViewMenuActions { ) { const scopedContextKeyService = contextKeyService.createScoped(); scopedContextKeyService.createKey('view', viewId); - super(menuId, contextMenuId, scopedContextKeyService, menuService); + super(menuId, contextMenuId, { shouldForwardArgs: true }, scopedContextKeyService, menuService); this._register(scopedContextKeyService); } } -export class ViewContainerMenuActions extends AbstractViewMenuActions { - +export class ViewContainerMenuActions extends CompositeMenuActions { constructor( viewContainer: ViewContainer, - menuId: MenuId, - contextMenuId: MenuId, @IContextKeyService contextKeyService: IContextKeyService, - @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IMenuService menuService: IMenuService, ) { const scopedContextKeyService = contextKeyService.createScoped(); scopedContextKeyService.createKey('viewContainer', viewContainer.id); - const updateViewContainerLocationContext = () => { - const viewContainerLocation = viewDescriptorService.getViewContainerLocation(viewContainer); - if (viewContainerLocation !== null) { - scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewContainerLocation)); - } - }; - updateViewContainerLocationContext(); - super(menuId, contextMenuId, scopedContextKeyService, menuService); + super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true }, scopedContextKeyService, menuService); this._register(scopedContextKeyService); - this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(updateViewContainerLocationContext)); } - } diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts index c4026faa203..30ab4d2a700 100644 --- a/src/vs/workbench/browser/parts/views/viewPane.ts +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -212,7 +212,7 @@ export abstract class ViewPane extends Pane implements IView { this.focusedViewContextKey = FocusedViewContext.bindTo(contextKeyService); this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext)); - this._register(this.menuActions.onDidChangeTitle(() => this.updateActions())); + this._register(this.menuActions.onDidChange(() => this.updateActions())); this.viewWelcomeController = new ViewWelcomeController(this.id, contextKeyService); } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 9f28f536afc..be781f69e09 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -35,6 +35,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; +import { ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; @@ -333,6 +334,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { return this.paneItems.length; } + private readonly menuActions: ViewContainerMenuActions; + constructor( id: string, private options: IViewPaneContainerOptions, @@ -345,7 +348,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { @IThemeService protected themeService: IThemeService, @IStorageService protected storageService: IStorageService, @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IViewDescriptorService protected viewDescriptorService: IViewDescriptorService + @IViewDescriptorService protected viewDescriptorService: IViewDescriptorService, ) { super(id, themeService, storageService); @@ -361,6 +364,9 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { this.visibleViewsCountFromCache = this.storageService.getNumber(this.visibleViewsStorageId, StorageScope.WORKSPACE, undefined); this._register(toDisposable(() => this.viewDisposables = dispose(this.viewDisposables))); this.viewContainerModel = this.viewDescriptorService.getViewContainerModel(container); + + this.menuActions = this._register(instantiationService.createInstance(ViewContainerMenuActions, container)); + this._register(this.menuActions.onDidChange(() => this.updateTitleArea())); } create(parent: HTMLElement): void { @@ -533,11 +539,23 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { let anchor: { x: number, y: number; } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ getAnchor: () => anchor, - getActions: () => this.getContextMenuActions() + getActions: () => [...this.getContextMenuActions()] }); } - getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] { + getContextMenuActions(): ReadonlyArray { + const result = []; + result.push(...this.menuActions.getContextMenuActions()); + + if (result.length) { + result.push(new Separator()); + } + + result.push(...this._getContextMenuActions()); + return result; + } + + private _getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] { const result: IAction[] = []; let showHide = true; @@ -572,19 +590,25 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } getActions(): IAction[] { + const result = []; if (this.isViewMergedWithContainer()) { - return this.paneItems[0].pane.getActions(); + result.push(...this.paneItems[0].pane.getActions()); } - - return []; + result.push(...this.menuActions.getPrimaryActions()); + return result; } getSecondaryActions(): IAction[] { - if (this.isViewMergedWithContainer()) { - return this.paneItems[0].pane.getSecondaryActions(); + const menuActions = this.menuActions.getSecondaryActions(); + const viewPaneContainerActions = this.isViewMergedWithContainer() ? this.paneItems[0].pane.getSecondaryActions() : []; + if (menuActions.length && viewPaneContainerActions.length) { + return [ + ...menuActions, + new Separator(), + ...viewPaneContainerActions + ]; } - - return []; + return menuActions.length ? menuActions : viewPaneContainerActions; } getActionsContext(): unknown { @@ -748,7 +772,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { event.stopPropagation(); event.preventDefault(); - const actions: IAction[] = this.getContextMenuActions(viewDescriptor); + const actions: IAction[] = this._getContextMenuActions(viewDescriptor); let anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ From 9ac0fc879023b9b4162516295a2d89b7376f930e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 16:12:26 +0100 Subject: [PATCH 0935/1837] remove unused/duplicated perf.mark --- .../services/extensions/common/abstractExtensionService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index d11139dd7a0..9f687b71840 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -415,7 +415,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } private _releaseBarrier(): void { - perf.mark('code/extensionHostReady'); this._installedExtensionsReady.open(); this._onDidRegisterExtensions.fire(undefined); this._onDidChangeExtensionsStatus.fire(this._registry.getAllExtensionDescriptions().map(e => e.identifier)); From 72e82ba7b25c6cb4bd5a3bdf3161aa0692771d2f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 14 Dec 2020 16:31:12 +0100 Subject: [PATCH 0936/1837] Make simple file dialog more predictable for screen readers Fixes #109722 --- .../services/dialogs/browser/simpleFileDialog.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index e0eca9ebe37..ba20c4d6d90 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -34,6 +34,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { normalizeDriveLetter } from 'vs/base/common/labels'; import { SaveReason } from 'vs/workbench/common/editor'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export namespace OpenLocalFileCommand { export const ID = 'workbench.action.files.openLocalFile'; @@ -138,6 +139,7 @@ export class SimpleFileDialog { @IPathService protected readonly pathService: IPathService, @IKeybindingService private readonly keybindingService: IKeybindingService, @IContextKeyService contextKeyService: IContextKeyService, + @IAccessibilityService private readonly accessibilityService: IAccessibilityService ) { this.remoteAuthority = this.environmentService.remoteAuthority; this.contextKey = RemoteFileDialogContext.bindTo(contextKeyService); @@ -642,12 +644,16 @@ export class SimpleFileDialog { return true; } else if (force && (!equalsIgnoreCase(this.basenameWithTrailingSlash(quickPickItem.uri), (this.userEnteredPathSegment + this.autoCompletePathSegment)))) { this.userEnteredPathSegment = ''; - this.autoCompletePathSegment = this.trimTrailingSlash(itemBasename); + if (!this.accessibilityService.isScreenReaderOptimized()) { + this.autoCompletePathSegment = this.trimTrailingSlash(itemBasename); + } this.activeItem = quickPickItem; - this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder, true).length, this.filePickBox.value.length]; - // use insert text to preserve undo buffer - this.insertText(this.pathAppend(this.currentFolder, this.autoCompletePathSegment), this.autoCompletePathSegment); - this.filePickBox.valueSelection = [this.filePickBox.value.length - this.autoCompletePathSegment.length, this.filePickBox.value.length]; + if (!this.accessibilityService.isScreenReaderOptimized()) { + this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder, true).length, this.filePickBox.value.length]; + // use insert text to preserve undo buffer + this.insertText(this.pathAppend(this.currentFolder, this.autoCompletePathSegment), this.autoCompletePathSegment); + this.filePickBox.valueSelection = [this.filePickBox.value.length - this.autoCompletePathSegment.length, this.filePickBox.value.length]; + } return true; } else { this.userEnteredPathSegment = startingBasename; From 5b2015c9a001bd855f365153d5792f5ebf38fad9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 16:34:40 +0100 Subject: [PATCH 0937/1837] telemetry for raw timer marks --- .../services/timer/browser/timerService.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 815c9159330..31dd63a4d6d 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -453,10 +453,21 @@ export abstract class AbstractTimerService implements ITimerService { */ this._telemetryService.publicLog('startupTimeVaried', metrics); - // report raw timers as telemetry - type Durations = { entries: perf.PerformanceMark[]; }; - type DurationsClassification = { entries: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; - this._telemetryService.publicLog2('startup.timers.raw', { entries: perf.getMarks() }); + + // report raw timers as telemetry. each mark is send a separate telemetry + // event and it is "normalized" to a relative timestamp where the first mark + // defines the start + for (const [source, marks] of this.getPerformanceMarks()) { + type Mark = { source: string; name: string; relativeStartTime: number; }; + type MarkClassification = { [K in keyof Mark]: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; + + let lastMark: perf.PerformanceMark = marks[0]; + for (const mark of marks) { + let delta = mark.startTime - lastMark.startTime; + this._telemetryService.publicLog2('startup.timer.mark', { source, name: mark.name, relativeStartTime: delta }); + lastMark = mark; + } + } } private async _computeStartupMetrics(): Promise { From 8876c6debbab4c7999dc410251cfa2aba8a948e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 14 Dec 2020 17:08:54 +0100 Subject: [PATCH 0938/1837] enable master ci for production build --- build/azure-pipelines/product-build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 0863ae0d6fc..98b8a1ba11e 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -1,4 +1,8 @@ -trigger: none +trigger: + branches: + include: + - master + pr: none schedules: @@ -8,6 +12,10 @@ schedules: include: - master +variables: + ${{ if and(eq(variables['VSCODE_PUBLISH'], ''), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'BatchedCI'))) }}: + VSCODE_PUBLISH: 'false' + resources: containers: - container: vscode-x64 From f7d9fe9b720dd5a3d55f85a6a845b7486e2a7b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 14 Dec 2020 17:11:57 +0100 Subject: [PATCH 0939/1837] no trigger specification --- build/azure-pipelines/product-build.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 98b8a1ba11e..a99e40b8509 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -1,8 +1,3 @@ -trigger: - branches: - include: - - master - pr: none schedules: From d766e6baa8d9299bc2e3dfd26cb5b1ca21c708eb Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 14 Dec 2020 17:31:13 +0100 Subject: [PATCH 0940/1837] =revert changes to themes.contribution.ts --- .../contrib/themes/browser/themes.contribution.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index b9eb30ddbf1..ca1165af6ad 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -23,7 +23,6 @@ import { IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/commo import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { DEFAULT_PRODUCT_ICON_THEME_ID } from 'vs/workbench/services/themes/browser/productIconThemeData'; import { IGettingStartedService } from 'vs/workbench/services/gettingStarted/common/gettingStartedService'; -import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; export class SelectColorThemeAction extends Action { @@ -298,20 +297,11 @@ class GenerateColorThemeAction extends Action { label: string, @IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService, @IEditorService private readonly editorService: IEditorService, - @IProgressService readonly progressService: IProgressService ) { super(id, label); } - async run(): Promise { - await this.progressService.withProgress({ location: ProgressLocation.Dialog }, async (r) => { - r.report({ message: 'ssdf', total: 30 }); - return new Promise((s, e) => { - setTimeout(() => s(), 5000); - }); - }); - - + run(): Promise { let theme = this.themeService.getColorTheme(); let colors = Registry.as(ColorRegistryExtensions.ColorContribution).getColors(); let colorIds = colors.map(c => c.id).sort(); From 29edd0d2a909a8508bec3abc8aa413c31f3c6a17 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 17:35:11 +0100 Subject: [PATCH 0941/1837] Use panel title context menu for contextMenu actions --- .../browser/parts/panel/panelPart.ts | 27 ++++++------- .../browser/parts/views/viewMenuActions.ts | 38 ------------------- .../workbench/browser/parts/views/viewPane.ts | 20 +++++++++- .../browser/parts/views/viewPaneContainer.ts | 17 ++++++++- .../views/browser/viewDescriptorService.ts | 8 ++++ 5 files changed, 52 insertions(+), 58 deletions(-) delete mode 100644 src/vs/workbench/browser/parts/views/viewMenuActions.ts diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index c6cd4744d24..c24cf278f8c 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -28,17 +28,17 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Dimension, trackFocus, EventHelper } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; -import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ViewContainer, IViewDescriptorService, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views'; -import { ViewMenuActions, ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { Before2D, CompositeDragAndDropObserver, ICompositeDragAndDrop, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; -import { MenuId } from 'vs/platform/actions/common/actions'; +import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; interface ICachedPanel { id: string; @@ -117,6 +117,7 @@ export class PanelPart extends CompositePart implements IPanelService { @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IExtensionService private readonly extensionService: IExtensionService, + @IMenuService private readonly menuService: IMenuService, ) { super( notificationService, @@ -184,21 +185,15 @@ export class PanelPart extends CompositePart implements IPanelService { this.onDidRegisterPanels([...this.getPanels()]); } + private readonly panelContextMenuActionsDisposable = this._register(new MutableDisposable()); private getContextMenuActionsForComposite(compositeId: string): readonly IAction[] { const result: IAction[] = []; - const container = this.getViewContainer(compositeId); - if (container) { - const viewContainerModel = this.viewDescriptorService.getViewContainerModel(container); - if (viewContainerModel.allViewDescriptors.length === 1) { - const viewMenuActions = this.instantiationService.createInstance(ViewMenuActions, viewContainerModel.allViewDescriptors[0].id, MenuId.ViewTitle, MenuId.ViewTitleContext); - result.push(...viewMenuActions.getContextMenuActions()); - viewMenuActions.dispose(); - } - - const viewContainerMenuActions = this.instantiationService.createInstance(ViewContainerMenuActions, container); - result.push(...viewContainerMenuActions.getContextMenuActions()); - viewContainerMenuActions.dispose(); - } + const scopedContextKeyService = this.contextKeyService.createScoped(); + scopedContextKeyService.createKey('viewContainer', compositeId); + const menu = this.menuService.createMenu(MenuId.PanelTitleContext, scopedContextKeyService); + this.panelContextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, undefined, { primary: [], secondary: result }); + scopedContextKeyService.dispose(); + menu.dispose(); return result; } diff --git a/src/vs/workbench/browser/parts/views/viewMenuActions.ts b/src/vs/workbench/browser/parts/views/viewMenuActions.ts deleted file mode 100644 index c9536c59615..00000000000 --- a/src/vs/workbench/browser/parts/views/viewMenuActions.ts +++ /dev/null @@ -1,38 +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 { MenuId, IMenuService } from 'vs/platform/actions/common/actions'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; -import { ViewContainer } from 'vs/workbench/common/views'; - -export class ViewMenuActions extends CompositeMenuActions { - constructor( - viewId: string, - menuId: MenuId, - contextMenuId: MenuId, - @IContextKeyService contextKeyService: IContextKeyService, - @IMenuService menuService: IMenuService, - ) { - const scopedContextKeyService = contextKeyService.createScoped(); - scopedContextKeyService.createKey('view', viewId); - super(menuId, contextMenuId, { shouldForwardArgs: true }, scopedContextKeyService, menuService); - this._register(scopedContextKeyService); - } - -} - -export class ViewContainerMenuActions extends CompositeMenuActions { - constructor( - viewContainer: ViewContainer, - @IContextKeyService contextKeyService: IContextKeyService, - @IMenuService menuService: IMenuService, - ) { - const scopedContextKeyService = contextKeyService.createScoped(); - scopedContextKeyService.createKey('viewContainer', viewContainer.id); - super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true }, scopedContextKeyService, menuService); - this._register(scopedContextKeyService); - } -} diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts index 30ab4d2a700..82c5b7ce19f 100644 --- a/src/vs/workbench/browser/parts/views/viewPane.ts +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -25,9 +25,8 @@ import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IView import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined } from 'vs/base/common/types'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { MenuId, MenuItemAction, Action2, IAction2Options, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { MenuId, MenuItemAction, Action2, IAction2Options, SubmenuItemAction, IMenuService } from 'vs/platform/actions/common/actions'; import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; import { parseLinkedText } from 'vs/base/common/linkedText'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { Button } from 'vs/base/browser/ui/button/button'; @@ -41,6 +40,7 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { URI } from 'vs/base/common/uri'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { Codicon } from 'vs/base/common/codicons'; +import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; export interface IViewPaneOptions extends IPaneOptions { id: string; @@ -140,6 +140,22 @@ class ViewWelcomeController { } } +class ViewMenuActions extends CompositeMenuActions { + constructor( + viewId: string, + menuId: MenuId, + contextMenuId: MenuId, + @IContextKeyService contextKeyService: IContextKeyService, + @IMenuService menuService: IMenuService, + ) { + const scopedContextKeyService = contextKeyService.createScoped(); + scopedContextKeyService.createKey('view', viewId); + super(menuId, contextMenuId, { shouldForwardArgs: true }, scopedContextKeyService, menuService); + this._register(scopedContextKeyService); + } + +} + export abstract class ViewPane extends Pane implements IView { private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions'; diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index be781f69e09..b382c97a177 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -28,14 +28,14 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Component } from 'vs/workbench/common/component'; -import { registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions'; +import { registerAction2, Action2, IAction2Options, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { CompositeDragAndDropObserver, DragAndDropObserver, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; import { RunOnceScheduler } from 'vs/base/common/async'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; -import { ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; +import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; @@ -284,6 +284,19 @@ class ViewPaneDropOverlay extends Themable { } } +class ViewContainerMenuActions extends CompositeMenuActions { + constructor( + viewContainer: ViewContainer, + @IContextKeyService contextKeyService: IContextKeyService, + @IMenuService menuService: IMenuService, + ) { + const scopedContextKeyService = contextKeyService.createScoped(); + scopedContextKeyService.createKey('viewContainer', viewContainer.id); + super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true }, scopedContextKeyService, menuService); + this._register(scopedContextKeyService); + } +} + export class ViewPaneContainer extends Component implements IViewPaneContainer { readonly viewContainer: ViewContainer; diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index 78f04269f6a..39a0859fc86 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -736,6 +736,14 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor ContextKeyExpr.equals(`${viewContainer.id}.defaultViewContainerLocation`, false) ) ) + }, { + id: MenuId.PanelTitleContext, + when: ContextKeyExpr.or( + ContextKeyExpr.and( + ContextKeyExpr.equals('viewContainer', viewContainer.id), + ContextKeyExpr.equals(`${viewContainer.id}.defaultViewContainerLocation`, false) + ) + ) }], }); } From e2ba0809426fe6a9efb7d81926f305ccad10d94c Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 14 Dec 2020 08:49:09 -0800 Subject: [PATCH 0942/1837] fix typo per #112437 --- .../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 ed21243bfae..759e7c2eb96 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -262,7 +262,7 @@ export const terminalConfiguration: IConfigurationNode = { default: true }, 'terminal.integrated.allowMnemonics': { - markdownDescription: localize('terminal.integrated.allowMnemonics', "Whether to allow menubar mnemonics (eg. alt+f) to trigger the open the menubar. Note that this will cause all alt keystrokes will skip the shell when true. This does nothing on macOS."), + markdownDescription: localize('terminal.integrated.allowMnemonics', "Whether to allow menubar mnemonics (eg. alt+f) to trigger the open the menubar. Note that this will cause all alt keystrokes to skip the shell when true. This does nothing on macOS."), type: 'boolean', default: false }, From 17c777b111991f9ee03f9f21987c137116ddeeb6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 17:50:44 +0100 Subject: [PATCH 0943/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d9da490d1f..97c44a78c64 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "25d6e2bec6a5bf41f26c0f1c164b8e75f441a057", + "distro": "380942b0d321602ed8362c03ea855d7827431f4e", "author": { "name": "Microsoft Corporation" }, From c2a8940127bc293ca61f860af1605b8ddb846dbd Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 14 Dec 2020 18:15:09 +0100 Subject: [PATCH 0944/1837] simpler perf mark for didLoadExtensions --- .../services/extensions/common/abstractExtensionService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 9f687b71840..612584c3a4e 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -409,9 +409,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx protected async _initialize(): Promise { perf.mark('code/willLoadExtensions'); this._startExtensionHosts(true, []); - this.whenInstalledExtensionsRegistered().then(() => perf.mark('code/didLoadExtensions')); await this._scanAndHandleExtensions(); this._releaseBarrier(); + perf.mark('code/didLoadExtensions'); } private _releaseBarrier(): void { From a22b5d54ad424f0559ad6a27f65e9d264287d05d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 14 Dec 2020 18:18:51 +0100 Subject: [PATCH 0945/1837] [json/css/html] adopt lsp 316 --- .../client/src/requests.ts | 6 +- extensions/css-language-features/package.json | 2 +- .../css-language-features/server/package.json | 8 +- .../server/src/requests.ts | 6 +- .../server/src/utils/runner.ts | 4 +- .../css-language-features/server/yarn.lock | 48 +++++----- extensions/css-language-features/yarn.lock | 63 ++++++++----- .../client/src/htmlClient.ts | 34 +++---- .../client/src/requests.ts | 6 +- .../html-language-features/package.json | 2 +- .../server/package.json | 10 +-- .../server/src/htmlServer.ts | 25 +++--- .../server/src/modes/semanticTokens.ts | 8 +- .../server/src/requests.ts | 6 +- .../server/src/utils/runner.ts | 4 +- .../html-language-features/server/yarn.lock | 58 ++++++------ extensions/html-language-features/yarn.lock | 88 ++++++++++++++----- .../client/src/jsonClient.ts | 19 ++-- .../json-language-features/package.json | 14 +-- .../server/package.json | 4 +- .../server/src/jsonServer.ts | 10 +-- .../server/src/utils/runner.ts | 4 +- .../json-language-features/server/yarn.lock | 48 +++++----- extensions/json-language-features/yarn.lock | 88 ++++++++++++++----- 24 files changed, 326 insertions(+), 239 deletions(-) diff --git a/extensions/css-language-features/client/src/requests.ts b/extensions/css-language-features/client/src/requests.ts index 1b1e70b2d88..47378dc43db 100644 --- a/extensions/css-language-features/client/src/requests.ts +++ b/extensions/css-language-features/client/src/requests.ts @@ -8,14 +8,14 @@ import { RequestType, CommonLanguageClient } from 'vscode-languageclient'; import { Runtime } from './cssClient'; export namespace FsContentRequest { - export const type: RequestType<{ uri: string; encoding?: string; }, string, any, any> = new RequestType('fs/content'); + export const type: RequestType<{ uri: string; encoding?: string; }, string, any> = new RequestType('fs/content'); } export namespace FsStatRequest { - export const type: RequestType = new RequestType('fs/stat'); + export const type: RequestType = new RequestType('fs/stat'); } export namespace FsReadDirRequest { - export const type: RequestType = new RequestType('fs/readDir'); + export const type: RequestType = new RequestType('fs/readDir'); } export function serveFileSystemRequests(client: CommonLanguageClient, runtime: Runtime) { diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 29f056e4137..d6b9e41699a 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -807,7 +807,7 @@ ] }, "dependencies": { - "vscode-languageclient": "7.0.0-next.5.1", + "vscode-languageclient": "^7.0.0", "vscode-nls": "^4.1.2" }, "devDependencies": { diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 5a2cd56cf59..713f12207a0 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -10,8 +10,8 @@ "main": "./out/node/cssServerMain", "browser": "./dist/browser/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^4.4.0", - "vscode-languageserver": "7.0.0-next.3", + "vscode-css-languageservice": "^5.0.0", + "vscode-languageserver": "^7.0.0", "vscode-uri": "^2.1.2" }, "devDependencies": { @@ -26,9 +26,9 @@ "compile": "gulp compile-extension:css-language-features-server", "watch": "gulp watch-extension:css-language-features-server", "install-service-next": "yarn add vscode-css-languageservice@next", - "install-service-local": "npm install ../../../../vscode-css-languageservice -f", + "install-service-local": "yarn link vscode-css-languageservice", "install-server-next": "yarn add vscode-languageserver@next", - "install-server-local": "npm install ../../../../vscode-languageserver-node/server -f", + "install-server-local": "yarn link vscode-languageserver", "test": "node ./test/index.js" } } diff --git a/extensions/css-language-features/server/src/requests.ts b/extensions/css-language-features/server/src/requests.ts index 79f166c2d40..4b91fbd2a41 100644 --- a/extensions/css-language-features/server/src/requests.ts +++ b/extensions/css-language-features/server/src/requests.ts @@ -8,14 +8,14 @@ import { RequestType, Connection } from 'vscode-languageserver'; import { RuntimeEnvironment } from './cssServer'; export namespace FsContentRequest { - export const type: RequestType<{ uri: string; encoding?: string; }, string, any, any> = new RequestType('fs/content'); + export const type: RequestType<{ uri: string; encoding?: string; }, string, any> = new RequestType('fs/content'); } export namespace FsStatRequest { - export const type: RequestType = new RequestType('fs/stat'); + export const type: RequestType = new RequestType('fs/stat'); } export namespace FsReadDirRequest { - export const type: RequestType = new RequestType('fs/readDir'); + export const type: RequestType = new RequestType('fs/readDir'); } export enum FileType { diff --git a/extensions/css-language-features/server/src/utils/runner.ts b/extensions/css-language-features/server/src/utils/runner.ts index ad1d779e211..9b82baf5482 100644 --- a/extensions/css-language-features/server/src/utils/runner.ts +++ b/extensions/css-language-features/server/src/utils/runner.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ResponseError, ErrorCodes, CancellationToken } from 'vscode-languageserver'; +import { ResponseError, CancellationToken, LSPErrorCodes } from 'vscode-languageserver'; export function formatError(message: string, err: any): string { if (err instanceof Error) { @@ -39,5 +39,5 @@ export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessa } function cancelValue() { - return new ResponseError(ErrorCodes.RequestCancelled, 'Request cancelled'); + return new ResponseError(LSPErrorCodes.RequestCancelled, 'Request cancelled'); } diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index af0eddbb95a..fc5118c50f3 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -696,45 +696,45 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -vscode-css-languageservice@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.4.0.tgz#a7c5edf3057e707601ca18fa3728784a298513b4" - integrity sha512-jWi+297PJUUWTHwlcrZz0zIuEXuHOBJIQMapXmEzbosWGv/gMnNSAMV4hTKnl5wzxvZKZzV6j+WFdrSlKQ5qnw== +vscode-css-languageservice@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.0.tgz#04fd899e25407a2fccd8f59a5896e2f020269bda" + integrity sha512-DTMa8QbVmujFPvD3NxoC5jjIXCyCG+cvn3hNzwQRhvhsk8LblNymBZBwzfcDdgEtqsi4O/2AB5HnMIRzxhzEzg== dependencies: vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" + vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" vscode-uri "^2.1.2" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" vscode-languageserver-textdocument@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== -vscode-languageserver@7.0.0-next.3: - version "7.0.0-next.3" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0-next.3.tgz#3833bd09259a4a085baeba90783f1e4d06d81095" - integrity sha512-qSt8eb546iFuoFIN+9MPl4Avru6Iz2/JP0UmS/3djf40ICa31Np/yJ7anX2j0Az5rCzb0fak8oeKwDioGeVOYg== +vscode-languageserver@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0" + integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw== dependencies: - vscode-languageserver-protocol "3.16.0-next.4" + vscode-languageserver-protocol "3.16.0" vscode-nls@^5.0.0: version "5.0.0" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 241dd5e9437..7cc1fd33297 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -384,6 +384,13 @@ log-symbols@2.2.0: dependencies: chalk "^2.0.1" +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" + minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -547,10 +554,12 @@ semver@^5.7.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.4: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" set-blocking@^2.0.0: version "2.0.0" @@ -635,31 +644,32 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageclient@7.0.0-next.5.1: - version "7.0.0-next.5.1" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0-next.5.1.tgz#ed93f14e4c2cdccedf15002c7bf8ef9cb638f36c" - integrity sha512-OONvbk3IFpubwF8/Y5uPQaq5J5CEskpeET3SfK4iGlv5OUK+44JawH/SEW5wXuEPpfdMLEMZLuGLU5v5d7N7PQ== +vscode-languageclient@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz#b505c22c21ffcf96e167799757fca07a6bad0fb2" + integrity sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg== dependencies: - semver "^6.3.0" - vscode-languageserver-protocol "3.16.0-next.4" + minimatch "^3.0.4" + semver "^7.3.4" + vscode-languageserver-protocol "3.16.0" -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== vscode-nls@^4.1.2: version "4.1.2" @@ -704,6 +714,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +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== + yargs-parser@13.1.1, yargs-parser@^13.1.1: version "13.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" diff --git a/extensions/html-language-features/client/src/htmlClient.ts b/extensions/html-language-features/client/src/htmlClient.ts index 494b935a7ca..5600979935e 100644 --- a/extensions/html-language-features/client/src/htmlClient.ts +++ b/extensions/html-language-features/client/src/htmlClient.ts @@ -25,22 +25,18 @@ namespace CustomDataChangedNotification { } namespace TagCloseRequest { - export const type: RequestType = new RequestType('html/tag'); + export const type: RequestType = new RequestType('html/tag'); } -namespace LinkedEditingRequest { - export const type: RequestType = new RequestType('html/linkedEditing'); -} - // experimental: semantic tokens interface SemanticTokenParams { textDocument: TextDocumentIdentifier; ranges?: LspRange[]; } namespace SemanticTokenRequest { - export const type: RequestType = new RequestType('html/semanticTokens'); + export const type: RequestType = new RequestType('html/semanticTokens'); } namespace SemanticTokenLegendRequest { - export const type: RequestType0<{ types: string[]; modifiers: string[] } | null, any, any> = new RequestType0('html/semanticTokenLegend'); + export const type: RequestType0<{ types: string[]; modifiers: string[] } | null, any> = new RequestType0('html/semanticTokenLegend'); } namespace SettingIds { @@ -168,22 +164,6 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua toDispose.push(languages.registerDocumentSemanticTokensProvider(documentSelector, provider, new SemanticTokensLegend(legend.types, legend.modifiers))); } }); - - disposable = languages.registerLinkedEditingRangeProvider(documentSelector, { - async provideLinkedEditingRanges(document, position) { - const param = client.code2ProtocolConverter.asTextDocumentPositionParams(document, position); - return client.sendRequest(LinkedEditingRequest.type, param).then(response => { - if (response) { - return { - ranges: response.map(r => client.protocol2CodeConverter.asRange(r)) - }; - } - return undefined; - }); - } - }); - toDispose.push(disposable); - }); function updateFormatterRegistration() { @@ -194,10 +174,16 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua } else if (formatEnabled && !rangeFormatting) { rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, { provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult { + const filesConfig = workspace.getConfiguration('files', document); + const fileFormattingOptions = { + trimTrailingWhitespace: filesConfig.get('trimTrailingWhitespace'), + trimFinalNewlines: filesConfig.get('trimFinalNewlines'), + insertFinalNewline: filesConfig.get('insertFinalNewline'), + }; let params: DocumentRangeFormattingParams = { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), range: client.code2ProtocolConverter.asRange(range), - options: client.code2ProtocolConverter.asFormattingOptions(options) + options: client.code2ProtocolConverter.asFormattingOptions(options, fileFormattingOptions) }; return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then( client.protocol2CodeConverter.asTextEdits, diff --git a/extensions/html-language-features/client/src/requests.ts b/extensions/html-language-features/client/src/requests.ts index ac966636314..f127c88562f 100644 --- a/extensions/html-language-features/client/src/requests.ts +++ b/extensions/html-language-features/client/src/requests.ts @@ -8,14 +8,14 @@ import { RequestType, CommonLanguageClient } from 'vscode-languageclient'; import { Runtime } from './htmlClient'; export namespace FsContentRequest { - export const type: RequestType<{ uri: string; encoding?: string; }, string, any, any> = new RequestType('fs/content'); + export const type: RequestType<{ uri: string; encoding?: string; }, string, any> = new RequestType('fs/content'); } export namespace FsStatRequest { - export const type: RequestType = new RequestType('fs/stat'); + export const type: RequestType = new RequestType('fs/stat'); } export namespace FsReadDirRequest { - export const type: RequestType = new RequestType('fs/readDir'); + export const type: RequestType = new RequestType('fs/readDir'); } export function serveFileSystemRequests(client: CommonLanguageClient, runtime: Runtime) { diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index c2c211ccbaa..4d39f2a5e8f 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -240,7 +240,7 @@ }, "dependencies": { "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "7.0.0-next.5.1", + "vscode-languageclient": "^7.0.0", "vscode-nls": "^5.0.0" }, "devDependencies": { diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index 65ce7cc7ed9..55b7d93a824 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,9 +9,9 @@ }, "main": "./out/node/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^4.4.0", - "vscode-html-languageservice": "^3.2.0", - "vscode-languageserver": "7.0.0-next.3", + "vscode-css-languageservice": "^5.0.0", + "vscode-html-languageservice": "^4.0.0", + "vscode-languageserver": "^7.0.0", "vscode-nls": "^5.0.0", "vscode-uri": "^2.1.2" }, @@ -27,9 +27,9 @@ "compile": "npx gulp compile-extension:html-language-features-server", "watch": "npx gulp watch-extension:html-language-features-server", "install-service-next": "yarn add vscode-css-languageservice@next && yarn add vscode-html-languageservice@next", - "install-service-local": "npm install ../../../../vscode-css-languageservice -f && npm install ../../../../vscode-html-languageservice -f", + "install-service-local": "yarn link vscode-css-languageservice && yarn link vscode-html-languageservice", "install-server-next": "yarn add vscode-languageserver@next", - "install-server-local": "npm install ../../../../vscode-languageserver-node/server -f", + "install-server-local": "yarn link vscode-languageserver", "test": "npm run compile && node ./test/index.js" } } diff --git a/extensions/html-language-features/server/src/htmlServer.ts b/extensions/html-language-features/server/src/htmlServer.ts index f1aeebb34d2..7bc6a444bea 100644 --- a/extensions/html-language-features/server/src/htmlServer.ts +++ b/extensions/html-language-features/server/src/htmlServer.ts @@ -7,7 +7,7 @@ import { Connection, TextDocuments, InitializeParams, InitializeResult, RequestType, DocumentRangeFormattingRequest, Disposable, DocumentSelector, TextDocumentPositionParams, ServerCapabilities, ConfigurationRequest, ConfigurationParams, DidChangeWorkspaceFoldersNotification, - DocumentColorRequest, ColorPresentationRequest, TextDocumentSyncKind, NotificationType + DocumentColorRequest, ColorPresentationRequest, TextDocumentSyncKind, NotificationType, RequestType0 } from 'vscode-languageserver'; import { getLanguageModes, LanguageModes, Settings, TextDocument, Position, Diagnostic, WorkspaceFolder, ColorInformation, @@ -31,10 +31,7 @@ namespace CustomDataChangedNotification { } namespace TagCloseRequest { - export const type: RequestType = new RequestType('html/tag'); -} -namespace LinkedEditingRequest { - export const type: RequestType = new RequestType('html/linkedEditing'); + export const type: RequestType = new RequestType('html/tag'); } // experimental: semantic tokens @@ -43,10 +40,10 @@ interface SemanticTokenParams { ranges?: Range[]; } namespace SemanticTokenRequest { - export const type: RequestType = new RequestType('html/semanticTokens'); + export const type: RequestType = new RequestType('html/semanticTokens'); } namespace SemanticTokenLegendRequest { - export const type: RequestType = new RequestType('html/semanticTokenLegend'); + export const type: RequestType0<{ types: string[]; modifiers: string[] } | null, any> = new RequestType0('html/semanticTokenLegend'); } export interface RuntimeEnvironment { @@ -164,7 +161,8 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) colorProvider: {}, foldingRangeProvider: true, selectionRangeProvider: true, - renameProvider: true + renameProvider: true, + linkedEditingRangeProvider: true }; return { capabilities }; }); @@ -511,15 +509,18 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) }, null, `Error while computing rename for ${params.textDocument.uri}`, token); }); - connection.onRequest(LinkedEditingRequest.type, (params, token) => { - return runSafe(async () => { + connection.languages.onLinkedEditingRange((params, token) => { + return /* todo remove when microsoft/vscode-languageserver-node#700 fixed */ runSafe(async () => { const document = documents.get(params.textDocument.uri); if (document) { const pos = params.position; if (pos.character > 0) { const mode = languageModes.getModeAtPosition(document, Position.create(pos.line, pos.character - 1)); if (mode && mode.doLinkedEditing) { - return mode.doLinkedEditing(document, pos); + const ranges = await mode.doLinkedEditing(document, pos); + if (ranges) { + return { ranges }; + } } } } @@ -545,7 +546,7 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) }, null, `Error while computing semantic tokens for ${params.textDocument.uri}`, token); }); - connection.onRequest(SemanticTokenLegendRequest.type, (_params, token) => { + connection.onRequest(SemanticTokenLegendRequest.type, token => { return runSafe(async () => { return getSemanticTokenProvider().legend; }, null, `Error while computing semantic tokens legend`, token); diff --git a/extensions/html-language-features/server/src/modes/semanticTokens.ts b/extensions/html-language-features/server/src/modes/semanticTokens.ts index 33f17a70b54..f386a0daba6 100644 --- a/extensions/html-language-features/server/src/modes/semanticTokens.ts +++ b/extensions/html-language-features/server/src/modes/semanticTokens.ts @@ -45,7 +45,7 @@ export function newSemanticTokenProvider(languageModes: LanguageModes): Semantic } } } - return encodeTokens(allTokens, ranges); + return encodeTokens(allTokens, ranges, document); } }; } @@ -94,15 +94,13 @@ function applyModifiersMapping(tokens: SemanticTokenData[], modifiersMapping: nu } } -const fullRange = [Range.create(Position.create(0, 0), Position.create(Number.MAX_VALUE, 0))]; - -function encodeTokens(tokens: SemanticTokenData[], ranges?: Range[]): number[] { +function encodeTokens(tokens: SemanticTokenData[], ranges: Range[] | undefined, document: TextDocument): number[] { const resultTokens = tokens.sort((d1, d2) => d1.start.line - d2.start.line || d1.start.character - d2.start.character); if (ranges) { ranges = ranges.sort((d1, d2) => d1.start.line - d2.start.line || d1.start.character - d2.start.character); } else { - ranges = fullRange; + ranges = [Range.create(Position.create(0, 0), Position.create(document.lineCount, 0))]; } let rangeIndex = 0; diff --git a/extensions/html-language-features/server/src/requests.ts b/extensions/html-language-features/server/src/requests.ts index 45b2ef2048e..8d741faebf3 100644 --- a/extensions/html-language-features/server/src/requests.ts +++ b/extensions/html-language-features/server/src/requests.ts @@ -8,14 +8,14 @@ import { RequestType, Connection } from 'vscode-languageserver'; import { RuntimeEnvironment } from './htmlServer'; export namespace FsContentRequest { - export const type: RequestType<{ uri: string; encoding?: string; }, string, any, any> = new RequestType('fs/content'); + export const type: RequestType<{ uri: string; encoding?: string; }, string, any> = new RequestType('fs/content'); } export namespace FsStatRequest { - export const type: RequestType = new RequestType('fs/stat'); + export const type: RequestType = new RequestType('fs/stat'); } export namespace FsReadDirRequest { - export const type: RequestType = new RequestType('fs/readDir'); + export const type: RequestType = new RequestType('fs/readDir'); } export enum FileType { diff --git a/extensions/html-language-features/server/src/utils/runner.ts b/extensions/html-language-features/server/src/utils/runner.ts index 6bf8a88d0c6..7889b6a4216 100644 --- a/extensions/html-language-features/server/src/utils/runner.ts +++ b/extensions/html-language-features/server/src/utils/runner.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ResponseError, ErrorCodes, CancellationToken } from 'vscode-languageserver'; +import { ResponseError, CancellationToken, LSPErrorCodes } from 'vscode-languageserver'; export function formatError(message: string, err: any): string { if (err instanceof Error) { @@ -41,5 +41,5 @@ export function runSafe(func: () => Thenable, errorVal: T, errorMessage: s function cancelValue() { - return new ResponseError(ErrorCodes.RequestCancelled, 'Request cancelled'); + return new ResponseError(LSPErrorCodes.RequestCancelled, 'Request cancelled'); } diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index 6d17972d5f2..f6d5001a838 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -880,55 +880,55 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -vscode-css-languageservice@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.4.0.tgz#a7c5edf3057e707601ca18fa3728784a298513b4" - integrity sha512-jWi+297PJUUWTHwlcrZz0zIuEXuHOBJIQMapXmEzbosWGv/gMnNSAMV4hTKnl5wzxvZKZzV6j+WFdrSlKQ5qnw== +vscode-css-languageservice@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.0.tgz#04fd899e25407a2fccd8f59a5896e2f020269bda" + integrity sha512-DTMa8QbVmujFPvD3NxoC5jjIXCyCG+cvn3hNzwQRhvhsk8LblNymBZBwzfcDdgEtqsi4O/2AB5HnMIRzxhzEzg== dependencies: vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" + vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" vscode-uri "^2.1.2" -vscode-html-languageservice@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.2.0.tgz#e92269a04097d87bd23431e3a4e491a27b5447b9" - integrity sha512-aLWIoWkvb5HYTVE0kI9/u3P0ZAJGrYOSAAE6L0wqB9radKRtbJNrF9+BjSUFyCgBdNBE/GFExo35LoknQDJrfw== +vscode-html-languageservice@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-4.0.0.tgz#a562cb1dfe7e40a9d1f50dbd8c4ec2d02f393f01" + integrity sha512-UmC+GS0IqBeZnOAmdtQvaDzoH1c5/un+b7qALUziu/Y4SOPXso5dF+YkJeTqsde6YU2pLm78RtMDzl9BParwbw== dependencies: vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" + vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" vscode-uri "^2.1.2" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" vscode-languageserver-textdocument@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== -vscode-languageserver@7.0.0-next.3: - version "7.0.0-next.3" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0-next.3.tgz#3833bd09259a4a085baeba90783f1e4d06d81095" - integrity sha512-qSt8eb546iFuoFIN+9MPl4Avru6Iz2/JP0UmS/3djf40ICa31Np/yJ7anX2j0Az5rCzb0fak8oeKwDioGeVOYg== +vscode-languageserver@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0" + integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw== dependencies: - vscode-languageserver-protocol "3.16.0-next.4" + vscode-languageserver-protocol "3.16.0" vscode-nls@^5.0.0: version "5.0.0" diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index 7d639c7b400..716146e2034 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -16,6 +16,24 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -28,15 +46,31 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" +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" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + semver@^5.3.0: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.4: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" vscode-extension-telemetry@0.1.1: version "0.1.1" @@ -45,37 +79,43 @@ vscode-extension-telemetry@0.1.1: dependencies: applicationinsights "1.0.8" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageclient@7.0.0-next.5.1: - version "7.0.0-next.5.1" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0-next.5.1.tgz#ed93f14e4c2cdccedf15002c7bf8ef9cb638f36c" - integrity sha512-OONvbk3IFpubwF8/Y5uPQaq5J5CEskpeET3SfK4iGlv5OUK+44JawH/SEW5wXuEPpfdMLEMZLuGLU5v5d7N7PQ== +vscode-languageclient@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz#b505c22c21ffcf96e167799757fca07a6bad0fb2" + integrity sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg== dependencies: - semver "^6.3.0" - vscode-languageserver-protocol "3.16.0-next.4" + minimatch "^3.0.4" + semver "^7.3.4" + vscode-languageserver-protocol "3.16.0" -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== 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== +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== + zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/json-language-features/client/src/jsonClient.ts b/extensions/json-language-features/client/src/jsonClient.ts index 068fe11cbf1..c925a9181f6 100644 --- a/extensions/json-language-features/client/src/jsonClient.ts +++ b/extensions/json-language-features/client/src/jsonClient.ts @@ -21,15 +21,15 @@ import { hash } from './utils/hash'; import { RequestService, joinPath } from './requests'; namespace VSCodeContentRequest { - export const type: RequestType = new RequestType('vscode/content'); + export const type: RequestType = new RequestType('vscode/content'); } namespace SchemaContentChangeNotification { - export const type: NotificationType = new NotificationType('json/schemaContent'); + export const type: NotificationType = new NotificationType('json/schemaContent'); } namespace ForceValidateRequest { - export const type: RequestType = new RequestType('json/validate'); + export const type: RequestType = new RequestType('json/validate'); } export interface ISchemaAssociations { @@ -42,11 +42,11 @@ export interface ISchemaAssociation { } namespace SchemaAssociationNotification { - export const type: NotificationType = new NotificationType('json/schemaAssociations'); + export const type: NotificationType = new NotificationType('json/schemaAssociations'); } namespace ResultLimitReachedNotification { - export const type: NotificationType = new NotificationType('json/resultLimitReached'); + export const type: NotificationType = new NotificationType('json/resultLimitReached'); } interface Settings { @@ -325,12 +325,17 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua } else if (formatEnabled && !rangeFormatting) { rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, { provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult { + const filesConfig = workspace.getConfiguration('files', document); + const fileFormattingOptions = { + trimTrailingWhitespace: filesConfig.get('trimTrailingWhitespace'), + trimFinalNewlines: filesConfig.get('trimFinalNewlines'), + insertFinalNewline: filesConfig.get('insertFinalNewline'), + }; const params: DocumentRangeFormattingParams = { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), range: client.code2ProtocolConverter.asRange(range), - options: client.code2ProtocolConverter.asFormattingOptions(options) + options: client.code2ProtocolConverter.asFormattingOptions(options, fileFormattingOptions) }; - params.options.insertFinalNewline = workspace.getConfiguration('files', document).get('insertFinalNewline'); return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then( client.protocol2CodeConverter.asTextEdits, diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index a8e3231a93a..ddfad88efe8 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -98,11 +98,13 @@ "description": "%json.maxItemsComputed.desc%" }, "json.schemaDownload.enable": { - "type": "boolean", - "default": true, - "description": "%json.enableSchemaDownload.desc%", - "tags": ["usesOnlineServices"] - } + "type": "boolean", + "default": true, + "description": "%json.enableSchemaDownload.desc%", + "tags": [ + "usesOnlineServices" + ] + } } }, "configurationDefaults": { @@ -129,7 +131,7 @@ "dependencies": { "request-light": "^0.4.0", "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "7.0.0-next.5.1", + "vscode-languageclient": "^7.0.0", "vscode-nls": "^5.0.0" }, "devDependencies": { diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 86df32285a1..6be6c7c96ba 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -14,8 +14,8 @@ "dependencies": { "jsonc-parser": "^3.0.0", "request-light": "^0.4.0", - "vscode-json-languageservice": "^3.11.0", - "vscode-languageserver": "7.0.0-next.3", + "vscode-json-languageservice": "^4.0.0", + "vscode-languageserver": "^7.0.0", "vscode-uri": "^2.1.2" }, "devDependencies": { diff --git a/extensions/json-language-features/server/src/jsonServer.ts b/extensions/json-language-features/server/src/jsonServer.ts index e7d2526f1e5..0266d536c26 100644 --- a/extensions/json-language-features/server/src/jsonServer.ts +++ b/extensions/json-language-features/server/src/jsonServer.ts @@ -17,23 +17,23 @@ import { RequestService, basename, resolvePath } from './requests'; type ISchemaAssociations = Record; namespace SchemaAssociationNotification { - export const type: NotificationType = new NotificationType('json/schemaAssociations'); + export const type: NotificationType = new NotificationType('json/schemaAssociations'); } namespace VSCodeContentRequest { - export const type: RequestType = new RequestType('vscode/content'); + export const type: RequestType = new RequestType('vscode/content'); } namespace SchemaContentChangeNotification { - export const type: NotificationType = new NotificationType('json/schemaContent'); + export const type: NotificationType = new NotificationType('json/schemaContent'); } namespace ResultLimitReachedNotification { - export const type: NotificationType = new NotificationType('json/resultLimitReached'); + export const type: NotificationType = new NotificationType('json/resultLimitReached'); } namespace ForceValidateRequest { - export const type: RequestType = new RequestType('json/validate'); + export const type: RequestType = new RequestType('json/validate'); } diff --git a/extensions/json-language-features/server/src/utils/runner.ts b/extensions/json-language-features/server/src/utils/runner.ts index 3efbc6bbe69..968df7987ad 100644 --- a/extensions/json-language-features/server/src/utils/runner.ts +++ b/extensions/json-language-features/server/src/utils/runner.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CancellationToken, ResponseError, ErrorCodes } from 'vscode-languageserver'; +import { CancellationToken, ResponseError, LSPErrorCodes } from 'vscode-languageserver'; export function formatError(message: string, err: any): string { if (err instanceof Error) { @@ -64,5 +64,5 @@ export function runSafe(func: () => T, errorVal: T, errorMessage: string, function cancelValue() { console.log('cancelled'); - return new ResponseError(ErrorCodes.RequestCancelled, 'Request cancelled'); + return new ResponseError(LSPErrorCodes.RequestCancelled, 'Request cancelled'); } diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index ec82f87b584..d38ac210239 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -80,46 +80,46 @@ request-light@^0.4.0: https-proxy-agent "^2.2.4" vscode-nls "^4.1.2" -vscode-json-languageservice@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.11.0.tgz#ad574b36c4346bd7830f1d34b5a5213d3af8d232" - integrity sha512-QxI+qV97uD7HHOCjh3MrM1TfbdwmTXrMckri5Tus1/FQiG3baDZb2C9Y0y8QThs7PwHYBIQXcAc59ZveCRZKPA== +vscode-json-languageservice@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.0.0.tgz#b4b81be7e49ee36b0227bb800131a0a5abbcdd13" + integrity sha512-5Px31Pj+Rrw9/S9SvPs2+Zh0wrnsG/N3MMrYs7zV495RdC0hev5Y1rtBVRivnucQohLgetUQ0jN9M/ScT60Oyg== dependencies: jsonc-parser "^3.0.0" vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" + vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" vscode-uri "^2.1.2" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" vscode-languageserver-textdocument@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== -vscode-languageserver@7.0.0-next.3: - version "7.0.0-next.3" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0-next.3.tgz#3833bd09259a4a085baeba90783f1e4d06d81095" - integrity sha512-qSt8eb546iFuoFIN+9MPl4Avru6Iz2/JP0UmS/3djf40ICa31Np/yJ7anX2j0Az5rCzb0fak8oeKwDioGeVOYg== +vscode-languageserver@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0" + integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw== dependencies: - vscode-languageserver-protocol "3.16.0-next.4" + vscode-languageserver-protocol "3.16.0" vscode-nls@^4.1.2: version "4.1.2" diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index a1e87bdbced..2f93800d4ea 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -30,6 +30,24 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -84,6 +102,20 @@ https-proxy-agent@^2.2.4: agent-base "^4.3.0" debug "^3.1.0" +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" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -108,10 +140,12 @@ semver@^5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.4: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" vscode-extension-telemetry@0.1.1: version "0.1.1" @@ -120,31 +154,32 @@ vscode-extension-telemetry@0.1.1: dependencies: applicationinsights "1.0.8" -vscode-jsonrpc@6.0.0-next.2: - version "6.0.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.2.tgz#3d73f86d812304cb91b9fb1efee40ec60b09ed7f" - integrity sha512-dKQXRYNUY6BHALQJBJlyZyv9oWlYpbJ2vVoQNNVNPLAYQ3hzNp4zy+iSo7zGx1BPXByArJQDWTKLQh8dz3dnNw== +vscode-jsonrpc@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== -vscode-languageclient@7.0.0-next.5.1: - version "7.0.0-next.5.1" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0-next.5.1.tgz#ed93f14e4c2cdccedf15002c7bf8ef9cb638f36c" - integrity sha512-OONvbk3IFpubwF8/Y5uPQaq5J5CEskpeET3SfK4iGlv5OUK+44JawH/SEW5wXuEPpfdMLEMZLuGLU5v5d7N7PQ== +vscode-languageclient@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz#b505c22c21ffcf96e167799757fca07a6bad0fb2" + integrity sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg== dependencies: - semver "^6.3.0" - vscode-languageserver-protocol "3.16.0-next.4" + minimatch "^3.0.4" + semver "^7.3.4" + vscode-languageserver-protocol "3.16.0" -vscode-languageserver-protocol@3.16.0-next.4: - version "3.16.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.4.tgz#8f8b1b831d4dfd9b26aa1ba3d2a32c427a91c99f" - integrity sha512-6GmPUp2MhJy2H1CTWp2B40Pa9BeC9glrXWmQWVG6A/0V9UbcAjVC9m56znm2GL32iyLDIprTBe8gBvvvcjbpaQ== +vscode-languageserver-protocol@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== dependencies: - vscode-jsonrpc "6.0.0-next.2" - vscode-languageserver-types "3.16.0-next.2" + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== +vscode-languageserver-types@3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== vscode-nls@^4.1.2: version "4.1.2" @@ -156,6 +191,11 @@ vscode-nls@^5.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== +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== + zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" From 3ee9eb9be4a78b668130a5e613706f68ddf6569e Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 14 Dec 2020 18:22:41 +0100 Subject: [PATCH 0946/1837] fixes #112417 --- .../workbench/contrib/files/browser/fileActions.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 23079af7ec8..328c400d057 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -1308,15 +1308,19 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { if (pasteShouldMove) { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target)); const options = { - progressLabel: sourceTargetPairs.length > 1 ? nls.localize('movingBulkEdit', "Moving {0} files", sourceTargetPairs.length) : nls.localize('movingFileBulkEdit', "Moving {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), - undoLabel: sourceTargetPairs.length > 1 ? nls.localize('moveBulkEdit', "Move {0} files", sourceTargetPairs.length) : nls.localize('moveFileBulkEdit', "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + progressLabel: sourceTargetPairs.length > 1 ? nls.localize({ key: 'movingBulkEdit', comment: ['Placeholder will be replaced by the number of files being moved'] }, "Moving {0} files", sourceTargetPairs.length) + : nls.localize({ key: 'movingFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file moved.'] }, "Moving {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize({ key: 'moveBulkEdit', comment: ['Placeholder will be replaced by the number of files being moved'] }, "Move {0} files", sourceTargetPairs.length) + : nls.localize({ key: 'moveFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file moved.'] }, "Move {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) }; await explorerService.applyBulkEdit(resourceFileEdits, options); } else { const resourceFileEdits = sourceTargetPairs.map(pair => new ResourceFileEdit(pair.source, pair.target, { copy: true })); const options = { - progressLabel: sourceTargetPairs.length > 1 ? nls.localize('copyingBulkEdit', "Copying {0} files", sourceTargetPairs.length) : nls.localize('copyingFileBulkEdit', "Copying {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), - undoLabel: sourceTargetPairs.length > 1 ? nls.localize('copyBulkEdit', "Copy {0} files", sourceTargetPairs.length) : nls.localize('copyFileBulkEdit', "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) + progressLabel: sourceTargetPairs.length > 1 ? nls.localize({ key: 'copyingBulkEdit', comment: ['Placeholder will be replaced by the number of files being copied'] }, "Copying {0} files", sourceTargetPairs.length) + : nls.localize({ key: 'copyingFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file copied.'] }, "Copying {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)), + undoLabel: sourceTargetPairs.length > 1 ? nls.localize({ key: 'copyBulkEdit', comment: ['Placeholder will be replaced by the number of files being copied'] }, "Copy {0} files", sourceTargetPairs.length) + : nls.localize({ key: 'copyFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file copied.'] }, "Copy {0}", resources.basenameOrAuthority(sourceTargetPairs[0].target)) }; await explorerService.applyBulkEdit(resourceFileEdits, options); } From 8fbaf86e4b15b8a86aea270a9f801bd24116378e Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 14 Dec 2020 18:32:39 +0100 Subject: [PATCH 0947/1837] fixes #112413 --- src/vs/workbench/contrib/debug/browser/debugHover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugHover.ts b/src/vs/workbench/contrib/debug/browser/debugHover.ts index d828f5bf41c..3bbddfa9593 100644 --- a/src/vs/workbench/contrib/debug/browser/debugHover.ts +++ b/src/vs/workbench/contrib/debug/browser/debugHover.ts @@ -105,7 +105,7 @@ export class DebugHoverWidget implements IContentWidget { this.treeContainer = dom.append(this.complexValueContainer, $('.debug-hover-tree')); this.treeContainer.setAttribute('role', 'tree'); const tip = dom.append(this.complexValueContainer, $('.tip')); - tip.textContent = nls.localize('quickTip', 'Hold {0} key to switch to editor language hover', isMacintosh ? 'Option' : 'Alt'); + tip.textContent = nls.localize({ key: 'quickTip', comment: ['"switch to editor language hover" means to show the programming language hover widget instead of the debug hover'] }, 'Hold {0} key to switch to editor language hover', isMacintosh ? 'Option' : 'Alt'); const dataSource = new DebugHoverDataSource(); this.tree = >this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'DebugHover', this.treeContainer, new DebugHoverDelegate(), [this.instantiationService.createInstance(VariablesRenderer)], From dce22cf74b5a3fffada3e609cc366b1b8325f519 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 13 Dec 2020 19:25:10 -0800 Subject: [PATCH 0948/1837] Fall back on node API when $SHELL is not set, for user shell and shell environment discovery See github/codespaces#1639 --- src/vs/base/node/shell.ts | 70 +++++++++++++++++++ src/vs/code/node/shellEnv.ts | 6 +- .../api/node/extHostTerminalService.ts | 3 +- .../electron-browser/terminal.contribution.ts | 2 +- .../terminalInstanceService.ts | 2 +- .../contrib/terminal/node/terminal.ts | 51 -------------- 6 files changed, 78 insertions(+), 56 deletions(-) create mode 100644 src/vs/base/node/shell.ts diff --git a/src/vs/base/node/shell.ts b/src/vs/base/node/shell.ts new file mode 100644 index 00000000000..0ae5fe92ac6 --- /dev/null +++ b/src/vs/base/node/shell.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as os from 'os'; +import * as platform from 'vs/base/common/platform'; +import * as processes from 'vs/base/node/processes'; + +/** + * Gets the detected default shell for the _system_, not to be confused with VS Code's _default_ + * shell that the terminal uses by default. + * @param p The platform to detect the shell of. + */ +export function getSystemShell(p: platform.Platform, environment: platform.IProcessEnvironment = process.env as platform.IProcessEnvironment): string { + if (p === platform.Platform.Windows) { + if (platform.isWindows) { + return getSystemShellWindows(environment); + } + // Don't detect Windows shell when not on Windows + return processes.getWindowsShell(environment); + } + // Only use $SHELL for the current OS + if (platform.isLinux && p === platform.Platform.Mac || platform.isMacintosh && p === platform.Platform.Linux) { + return '/bin/bash'; + } + return getSystemShellUnixLike(environment); +} + +let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null; +function getSystemShellUnixLike(environment: platform.IProcessEnvironment): string { + if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) { + let unixLikeTerminal: string; + if (platform.isWindows) { + unixLikeTerminal = '/bin/bash'; // for WSL + } else { + unixLikeTerminal = environment.SHELL; + + if (!unixLikeTerminal) { + try { + // It's possible for $SHELL to be unset, this API reads /etc/passwd. See https://github.com/github/codespaces/issues/1639 + // Node docs: "Throws a SystemError if a user has no username or homedir." + unixLikeTerminal = os.userInfo().shell; + } catch (err) { } + } + + if (!unixLikeTerminal) { + unixLikeTerminal = 'sh'; + } + + // Some systems have $SHELL set to /bin/false which breaks the terminal + if (unixLikeTerminal === '/bin/false') { + unixLikeTerminal = '/bin/bash'; + } + } + _TERMINAL_DEFAULT_SHELL_UNIX_LIKE = unixLikeTerminal; + } + return _TERMINAL_DEFAULT_SHELL_UNIX_LIKE; +} + +let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null; +function getSystemShellWindows(environment: platform.IProcessEnvironment): string { + if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) { + const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10; + const is32ProcessOn64Windows = environment.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + const powerShellPath = `${environment.windir}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; + _TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(environment); + } + return _TERMINAL_DEFAULT_SHELL_WINDOWS; +} diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 29ef8c143b3..2ea93f9c5af 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -5,11 +5,12 @@ import { spawn } from 'child_process'; import { generateUuid } from 'vs/base/common/uuid'; -import { isWindows } from 'vs/base/common/platform'; +import { isWindows, platform } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { getSystemShell } from 'vs/base/node/shell'; /** * We need to get the environment from a user's shell. @@ -78,7 +79,8 @@ async function doResolveUnixShellEnv(logService: ILogService): Promise= 10; - const is32ProcessOn64Windows = environment.hasOwnProperty('PROCESSOR_ARCHITEW6432'); - const powerShellPath = `${environment.windir}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; - _TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(environment); - } - return _TERMINAL_DEFAULT_SHELL_WINDOWS; -} - let detectedDistro = LinuxDistro.Unknown; if (platform.isLinux) { const file = '/etc/os-release'; From 287137afbcf2f74a366dc63207eef31c9a2a52f6 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 14 Dec 2020 18:50:55 +0100 Subject: [PATCH 0949/1837] fixes #112415 --- src/vs/workbench/contrib/files/browser/fileActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 328c400d057..8e3c6d86c76 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -225,8 +225,8 @@ async function deleteFiles(explorerService: IExplorerService, workingCopyFileSer try { const resourceFileEdits = distinctElements.map(e => new ResourceFileEdit(e.resource, undefined, { recursive: true, folder: e.isDirectory, skipTrashBin: !useTrash, maxSize: MAX_UNDO_FILE_SIZE })); const options = { - undoLabel: distinctElements.length > 1 ? nls.localize('deleteBulkEdit', "Delete {0} files", distinctElements.length) : nls.localize('deleteFileBulkEdit', "Delete {0}", distinctElements[0].name), - progressLabel: distinctElements.length > 1 ? nls.localize('deletingBulkEdit', "Deleting {0} files", distinctElements.length) : nls.localize('deletingFileBulkEdit', "Deleting {0}", distinctElements[0].name), + undoLabel: distinctElements.length > 1 ? nls.localize({ key: 'deleteBulkEdit', comment: ['Placeholder will be replaced by the number of files deleted'] }, "Delete {0} files", distinctElements.length) : nls.localize({ key: 'deleteFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file deleted'] }, "Delete {0}", distinctElements[0].name), + progressLabel: distinctElements.length > 1 ? nls.localize({ key: 'deletingBulkEdit', comment: ['Placeholder will be replaced by the number of files deleted'] }, "Deleting {0} files", distinctElements.length) : nls.localize({ key: 'deletingFileBulkEdit', comment: ['Placeholder will be replaced by the name of the file deleted'] }, "Deleting {0}", distinctElements[0].name), }; await explorerService.applyBulkEdit(resourceFileEdits, options); } catch (error) { From 5431ddb506f5769d3398c35d3dc9ba8fb6f9d550 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 14 Dec 2020 10:17:20 -0800 Subject: [PATCH 0950/1837] Bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97c44a78c64..e0e17b4031c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "380942b0d321602ed8362c03ea855d7827431f4e", + "distro": "e856403a200fb74359bbc46af1b5a2a59f36d2ef", "author": { "name": "Microsoft Corporation" }, From 42e31e92e293616e8b87748c858610a54c663fad Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 10:27:24 -0800 Subject: [PATCH 0951/1837] cursor and user select update for output --- .../contrib/notebook/browser/diff/notebookDiff.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index 5866ea2c558..95afc16af1f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -126,9 +126,12 @@ -.monaco-workbench .notebook-text-diff-editor .cell-body .output-view-container .output-inner-container { - /* overflow-x: scroll; */ +.monaco-workbench .notebook-text-diff-editor .cell-body .output-view-container { + user-select: text; + -webkit-user-select: text; + -ms-user-select: text; white-space: initial; + cursor: auto; } .monaco-workbench .notebook-text-diff-editor .cell-body.left .output-view-container .output-inner-container, From 0f33afa9f9682b42044413badea9ef7bca892b01 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 14 Dec 2020 10:30:18 -0800 Subject: [PATCH 0952/1837] fix #112217 by replacing look behinds --- .../src/features/smartSelect.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/extensions/markdown-language-features/src/features/smartSelect.ts b/extensions/markdown-language-features/src/features/smartSelect.ts index 12b2bdd78b3..53c0bb8d850 100644 --- a/extensions/markdown-language-features/src/features/smartSelect.ts +++ b/extensions/markdown-language-features/src/features/smartSelect.ts @@ -162,9 +162,9 @@ function createFencedRange(token: Token, cursorLine: number, document: vscode.Te } function createBoldRange(lineText: string, cursorChar: number, cursorLine: number, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined { - const regex = /(?:^|(?<=\s))(?:\*\*\s*([^*]+)(?:\*\s*([^*]+)\s*?\*)*([^*]+)\s*?\*\*)/g; + const regex = /(?:\*\*([^*]+)(?:\*([^*]+)([^*]+)\*)*([^*]+)\*\*)/g; const matches = [...lineText.matchAll(regex)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar); - if (matches.length > 0) { + if (matches.length) { // should only be one match, so select first and index 0 contains the entire match const bold = matches[0][0]; const startIndex = lineText.indexOf(bold); @@ -177,11 +177,20 @@ function createBoldRange(lineText: string, cursorChar: number, cursorLine: numbe } function createOtherInlineRange(lineText: string, cursorChar: number, cursorLine: number, isItalic: boolean, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined { - const regex = isItalic ? /(?:^|(?<=\s))(?:\*\s*([^*]+)(?:\*\*\s*([^*]+)\s*?\*\*)*([^*]+)\s*?\*)/g : /\`[^\`]*\`/g; - const matches = [...lineText.matchAll(regex)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar); - if (matches.length > 0) { - // should only be one match, so select first and index 0 contains the entire match - const match = matches[0][0]; + const italicRegexes = [/(?:[^*]+)(\*([^*]+)(?:\*\*[^*]*\*\*)*([^*]+)\*)(?:[^*]+)/g, /^(?:[^*]*)(\*([^*]+)(?:\*\*[^*]*\*\*)*([^*]+)\*)(?:[^*]*)$/g]; + let matches = []; + if (isItalic) { + matches = [...lineText.matchAll(italicRegexes[0])].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar); + if (!matches.length) { + matches = [...lineText.matchAll(italicRegexes[1])].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar); + } + } else { + matches = [...lineText.matchAll(/\`[^\`]*\`/g)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar); + } + if (matches.length) { + // should only be one match, so select first and select group 1 for italics because that contains just the italic section + // doesn't include the leading and trailing characters which are guaranteed to not be * so as not to be confused with bold + const match = isItalic ? matches[0][1] : matches[0][0]; const startIndex = lineText.indexOf(match); const cursorOnType = cursorChar === startIndex || cursorChar === startIndex + match.length; const contentAndType = new vscode.SelectionRange(new vscode.Range(cursorLine, startIndex, cursorLine, startIndex + match.length), parent); @@ -195,7 +204,7 @@ function createLinkRange(lineText: string, cursorChar: number, cursorLine: numbe const regex = /(\[[^\(\)]*\])(\([^\[\]]*\))/g; const matches = [...lineText.matchAll(regex)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length > cursorChar); - if (matches.length > 0) { + if (matches.length) { // should only be one match, so select first and index 0 contains the entire match, so match = [text](url) const link = matches[0][0]; const linkRange = new vscode.SelectionRange(new vscode.Range(cursorLine, lineText.indexOf(link), cursorLine, lineText.indexOf(link) + link.length), parent); From d583e26cd09deef6e15dbed5f647b40aadf0de69 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 19:36:48 +0100 Subject: [PATCH 0953/1837] fix show view submenu in debug --- src/vs/workbench/browser/panecomposite.ts | 28 ++++++++++++-- .../browser/parts/views/viewPaneContainer.ts | 38 ++++++++----------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts index ac9a44260da..78c58259648 100644 --- a/src/vs/workbench/browser/panecomposite.ts +++ b/src/vs/workbench/browser/panecomposite.ts @@ -15,7 +15,7 @@ import { Composite } from 'vs/workbench/browser/composite'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ViewPaneContainer } from './parts/views/viewPaneContainer'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; -import { IAction, IActionViewItem } from 'vs/base/common/actions'; +import { IAction, IActionViewItem, Separator } from 'vs/base/common/actions'; import { MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; @@ -66,15 +66,35 @@ export class PaneComposite extends Composite implements IPaneComposite { } getContextMenuActions(): ReadonlyArray { - return this.viewPaneContainer.getContextMenuActions(); + const result = []; + result.push(...this.viewPaneContainer.getContextMenuActions2()); + + if (result.length) { + result.push(new Separator()); + } + + result.push(...this.viewPaneContainer.getContextMenuActions()); + return result; } getActions(): ReadonlyArray { - return this.viewPaneContainer.getActions(); + const result = []; + result.push(...this.viewPaneContainer.getActions2()); + result.push(...this.viewPaneContainer.getActions()); + return result; } getSecondaryActions(): ReadonlyArray { - return this.viewPaneContainer.getSecondaryActions(); + const menuActions = this.viewPaneContainer.getSecondaryActions2(); + const viewPaneContainerActions = this.viewPaneContainer.getSecondaryActions(); + if (menuActions.length && viewPaneContainerActions.length) { + return [ + ...menuActions, + new Separator(), + ...viewPaneContainerActions + ]; + } + return menuActions.length ? menuActions : viewPaneContainerActions; } getActionViewItem(action: IAction): IActionViewItem | undefined { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index b382c97a177..768e6d0f5ee 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -556,19 +556,11 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { }); } - getContextMenuActions(): ReadonlyArray { - const result = []; - result.push(...this.menuActions.getContextMenuActions()); - - if (result.length) { - result.push(new Separator()); - } - - result.push(...this._getContextMenuActions()); - return result; + getContextMenuActions2(): ReadonlyArray { + return this.menuActions.getContextMenuActions(); } - private _getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] { + getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] { const result: IAction[] = []; let showHide = true; @@ -602,26 +594,28 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { return result; } + getActions2(): IAction[] { + return this.menuActions.getPrimaryActions(); + } + getActions(): IAction[] { const result = []; if (this.isViewMergedWithContainer()) { result.push(...this.paneItems[0].pane.getActions()); } - result.push(...this.menuActions.getPrimaryActions()); return result; } + getSecondaryActions2(): IAction[] { + return this.menuActions.getSecondaryActions(); + } + getSecondaryActions(): IAction[] { - const menuActions = this.menuActions.getSecondaryActions(); - const viewPaneContainerActions = this.isViewMergedWithContainer() ? this.paneItems[0].pane.getSecondaryActions() : []; - if (menuActions.length && viewPaneContainerActions.length) { - return [ - ...menuActions, - new Separator(), - ...viewPaneContainerActions - ]; + const result = []; + if (this.isViewMergedWithContainer()) { + result.push(...this.paneItems[0].pane.getSecondaryActions()); } - return menuActions.length ? menuActions : viewPaneContainerActions; + return result; } getActionsContext(): unknown { @@ -785,7 +779,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { event.stopPropagation(); event.preventDefault(); - const actions: IAction[] = this._getContextMenuActions(viewDescriptor); + const actions: IAction[] = this.getContextMenuActions(viewDescriptor); let anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ From 3ba967fd7eb97621b0e2a4fb0267b70323ffcf5f Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 14 Dec 2020 10:39:10 -0800 Subject: [PATCH 0954/1837] ext: log errors running contributed commands to the console for debugger vis --- src/vs/workbench/api/common/extHostCommands.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index 649612e38f4..228d60c37fc 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -194,7 +194,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { } } - private _executeContributedCommand(id: string, args: any[]): Promise { + private async _executeContributedCommand(id: string, args: any[]): Promise { const command = this._commands.get(id); if (!command) { throw new Error('Unknown command'); @@ -205,17 +205,17 @@ export class ExtHostCommands implements ExtHostCommandsShape { try { validateConstraint(args[i], description.args[i].constraint); } catch (err) { - return Promise.reject(new Error(`Running the contributed command: '${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`)); + throw new Error(`Running the contributed command: '${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`); } } } try { - const result = callback.apply(thisArg, args); - return Promise.resolve(result); + return await callback.apply(thisArg, args); } catch (err) { + console.error(err); // so that it shows up in any attached debugger this._logService.error(err, id); - return Promise.reject(new Error(`Running the contributed command: '${id}' failed.`)); + throw new Error(`Running the contributed command: '${id}' failed.`); } } From d6e0a5424f2b5e0b6c0468687f1e09e35cfc6e19 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 20:02:37 +0100 Subject: [PATCH 0955/1837] Use directly `yarn compile` --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ee616c6b30..b5aa9082ee2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -500,7 +500,7 @@ jobs: run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download - run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - name: Run Unit Tests (Electron) id: electron-unit-tests @@ -556,7 +556,7 @@ jobs: run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download - run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" - name: Run Unit Tests (Electron) run: .\scripts\test.bat From 428008f3a560f5913fb3da237c0c4e23f8826046 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 20:06:18 +0100 Subject: [PATCH 0956/1837] Align versions across `package.json` files --- build/gulpfile.hygiene.js | 15 ++++-- build/lib/watch/watch-win32.ts | 4 +- build/package.json | 8 +-- build/yarn.lock | 96 ++++++++++++++++++++++++++-------- package.json | 2 +- yarn.lock | 88 ++++++++++++++++++++++++++++--- 6 files changed, 173 insertions(+), 40 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 7f890e86098..bcaecb73509 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -35,10 +35,10 @@ gulp.task('eslint', () => { function checkPackageJSON(actualPath) { const actual = require(path.join(__dirname, '..', actualPath)); const rootPackageJSON = require('../package.json'); - - for (let depName in actual.dependencies) { - const depVersion = actual.dependencies[depName]; - const rootDepVersion = rootPackageJSON.dependencies[depName]; + const checkIncluded = (set1, set2) => { + for (let depName in set1) { + const depVersion = set1[depName]; + const rootDepVersion = set2[depName]; if (!rootDepVersion) { // missing in root is allowed continue; @@ -49,7 +49,11 @@ function checkPackageJSON(actualPath) { `The dependency ${depName} in '${actualPath}' (${depVersion}) is different than in the root package.json (${rootDepVersion})` ); } - } + } + }; + + checkIncluded(actual.dependencies, rootPackageJSON.dependencies); + checkIncluded(actual.devDependencies, rootPackageJSON.devDependencies); } const checkPackageJSONTask = task.define('check-package-json', () => { @@ -57,6 +61,7 @@ const checkPackageJSONTask = task.define('check-package-json', () => { es.through(function () { checkPackageJSON.call(this, 'remote/package.json'); checkPackageJSON.call(this, 'remote/web/package.json'); + checkPackageJSON.call(this, 'build/package.json'); }) ); }); diff --git a/build/lib/watch/watch-win32.ts b/build/lib/watch/watch-win32.ts index 4ed37277123..833c8d9c672 100644 --- a/build/lib/watch/watch-win32.ts +++ b/build/lib/watch/watch-win32.ts @@ -25,7 +25,7 @@ function watch(root: string): Stream { const result = es.through(); let child: cp.ChildProcess | null = cp.spawn(watcherPath, [root]); - child.stdout.on('data', function (data) { + child.stdout!.on('data', function (data) { const lines: string[] = data.toString('utf8').split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); @@ -52,7 +52,7 @@ function watch(root: string): Stream { } }); - child.stderr.on('data', function (data) { + child.stderr!.on('data', function (data) { result.emit('error', data); }); diff --git a/build/package.json b/build/package.json index bde784395a5..007a62890d4 100644 --- a/build/package.json +++ b/build/package.json @@ -21,7 +21,7 @@ "@types/minimatch": "^3.0.3", "@types/minimist": "^1.2.0", "@types/mocha": "2.2.39", - "@types/node": "^10.14.8", + "@types/node": "^12.11.7", "@types/pump": "^1.0.1", "@types/request": "^2.47.0", "@types/rimraf": "^2.0.2", @@ -31,7 +31,7 @@ "@types/underscore": "^1.8.9", "@types/xml2js": "0.0.33", "@typescript-eslint/experimental-utils": "~2.13.0", - "@typescript-eslint/parser": "^2.12.0", + "@typescript-eslint/parser": "^3.3.0", "applicationinsights": "1.0.8", "azure-storage": "^2.1.0", "electron-osx-sign": "^0.4.16", @@ -43,8 +43,8 @@ "gulp-uglify": "^3.0.0", "iconv-lite-umd": "0.6.8", "jsonc-parser": "^2.3.0", - "mime": "^1.3.4", - "minimatch": "3.0.4", + "mime": "^1.4.1", + "minimatch": "^3.0.4", "minimist": "^1.2.3", "request": "^2.85.0", "terser": "4.3.8", diff --git a/build/yarn.lock b/build/yarn.lock index 1253206c77c..3f865daf638 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -240,10 +240,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@^10.14.8": - version "10.14.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" - integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== +"@types/node@^12.11.7": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/pump@^1.0.1": version "1.0.1" @@ -343,14 +343,16 @@ resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de" integrity sha1-IMXdZGAkUoTWSlVpABW5XkCft94= -"@typescript-eslint/experimental-utils@2.14.0": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.14.0.tgz#e9179fa3c44e00b3106b85d7b69342901fb43e3b" - integrity sha512-KcyKS7G6IWnIgl3ZpyxyBCxhkBPV+0a5Jjy2g5HxlrbG2ZLQNFeneIBVXdaBCYOVjvGmGGFKom1kgiAY75SDeQ== +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.14.0" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-scope "^5.0.0" + eslint-utils "^2.0.0" "@typescript-eslint/experimental-utils@~2.13.0": version "2.13.0" @@ -361,16 +363,22 @@ "@typescript-eslint/typescript-estree" "2.13.0" eslint-scope "^5.0.0" -"@typescript-eslint/parser@^2.12.0": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.14.0.tgz#30fa0523d86d74172a5e32274558404ba4262cd6" - integrity sha512-haS+8D35fUydIs+zdSf4BxpOartb/DjrZ2IxQ5sR8zyGfd77uT9ZJZYF8+I0WPhzqHmfafUBx8MYpcp8pfaoSA== +"@typescript-eslint/parser@^3.3.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.14.0" - "@typescript-eslint/typescript-estree" "2.14.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-visitor-keys "^1.1.0" +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== + "@typescript-eslint/typescript-estree@2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.13.0.tgz#a2e746867da772c857c13853219fced10d2566bc" @@ -384,19 +392,27 @@ semver "^6.3.0" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@2.14.0": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.14.0.tgz#c67698acdc14547f095eeefe908958d93e1a648d" - integrity sha512-pnLpUcMNG7GfFFfNQbEX6f1aPa5fMnH2G9By+A1yovYI4VIOK2DzkaRuUlIkbagpAcrxQHLqovI1YWqEcXyRnA== +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== dependencies: + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" glob "^7.1.6" is-glob "^4.0.1" - lodash.unescape "4.0.1" - semver "^6.3.0" + lodash "^4.17.15" + semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== + dependencies: + eslint-visitor-keys "^1.1.0" + acorn@4.X: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -1208,6 +1224,13 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-utils@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" @@ -2188,6 +2211,18 @@ lodash@^4.15.0, lodash@^4.17.10: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +lodash@^4.17.15: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +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" + make-error-cause@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" @@ -2283,6 +2318,11 @@ mime@^1.3.4: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== +mime@^1.4.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -2905,6 +2945,13 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.2: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + 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" @@ -3577,6 +3624,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +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== + yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" diff --git a/package.json b/package.json index e0e17b4031c..2ee117cb329 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "glob": "^5.0.13", "gulp": "^4.0.0", "gulp-atom-electron": "^1.22.0", - "gulp-azure-storage": "^0.10.0", + "gulp-azure-storage": "^0.11.1", "gulp-buffer": "0.0.2", "gulp-concat": "^2.6.1", "gulp-cssnano": "^2.1.3", diff --git a/yarn.lock b/yarn.lock index 8d595ec760d..1e156cabbc1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1865,6 +1865,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + cliui@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3" @@ -3633,6 +3642,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" @@ -4263,21 +4280,21 @@ gulp-atom-electron@^1.22.0: vinyl "^2.2.0" vinyl-fs "^3.0.3" -gulp-azure-storage@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/gulp-azure-storage/-/gulp-azure-storage-0.10.0.tgz#7c3669b62c0e84002fd7539b231fba76bd8c1cf1" - integrity sha512-rrAUz3gpjgpiKanz+ahFIjVWoKTcjFQFqSHosI+RLkZUCh6WBS68g7Uj0hU92mk26xV1e7zC6ZcePpNUlShT3w== +gulp-azure-storage@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/gulp-azure-storage/-/gulp-azure-storage-0.11.1.tgz#0e5f5d0f789da11206f1e5a9311a6cf7107877d7" + integrity sha512-csOwItwZV1P9GLsORVQy+CFwjYDdHNrBol89JlHdlhGx0fTgJBc1COTRZbjGRyRjgdUuVguo3YLl4ToJ10/SIQ== dependencies: azure-storage "^2.10.2" delayed-stream "0.0.6" event-stream "3.3.4" mime "^1.3.4" - optimist "^0.6.1" progress "^1.1.8" queue "^3.0.10" streamifier "^0.1.1" vinyl "^2.2.0" vinyl-fs "^3.0.3" + yargs "^15.3.0" gulp-buffer@0.0.2: version "0.0.2" @@ -5742,6 +5759,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6939,6 +6963,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -6953,6 +6984,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -7090,6 +7128,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -9520,7 +9563,6 @@ tsec@googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1: resolved "https://codeload.github.com/googleinterns/tsec/tar.gz/7bf4ab23686500522341b977b3e2cc04b1f720b1" dependencies: "@types/node" "^13.13.5" - typescript "^4.1.2" tslib@^1.8.1, tslib@^1.9.0: version "1.9.3" @@ -10306,6 +10348,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -10471,6 +10522,14 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^20.0.0: version "20.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.0.0.tgz#c65a1daaa977ad63cebdd52159147b789a4e19a9" @@ -10516,6 +10575,23 @@ yargs@^13.3.0, yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" +yargs@^15.3.0: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yargs@^16.0.0: version "16.0.3" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c" From 7989b98326e7234ce88fca09d22f8eb8d5b1aa50 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 11:55:20 -0800 Subject: [PATCH 0957/1837] separate side by side and single side viewmodel --- .../notebook/browser/diff/cellComponents.ts | 94 +++++++++---------- .../browser/diff/celllDiffViewModel.ts | 81 ++++++++++++---- .../contrib/notebook/browser/diff/common.ts | 6 +- .../browser/diff/notebookDiffActions.ts | 8 +- .../browser/diff/notebookTextDiffEditor.ts | 28 +++--- .../browser/diff/notebookTextDiffList.ts | 30 +++--- 6 files changed, 148 insertions(+), 99 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 6a5be0bdd4d..29e062d6156 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellDiffViewModel, getFormatedMetadataJSON, PropertyFoldingState } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModelBase, getFormatedMetadataJSON, PropertyFoldingState, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; @@ -83,14 +83,14 @@ class PropertyHeader extends Disposable { protected _menu!: IMenu; constructor( - readonly cell: CellDiffViewModel, + readonly cell: CellDiffViewModelBase, readonly propertyHeaderContainer: HTMLElement, readonly notebookEditor: INotebookTextDiffEditor, readonly accessor: { updateInfoRendering: () => void; - checkIfModified: (cell: CellDiffViewModel) => boolean; - getFoldingState: (cell: CellDiffViewModel) => PropertyFoldingState; - updateFoldingState: (cell: CellDiffViewModel, newState: PropertyFoldingState) => void; + checkIfModified: (cell: CellDiffViewModelBase) => boolean; + getFoldingState: (cell: CellDiffViewModelBase) => PropertyFoldingState; + updateFoldingState: (cell: CellDiffViewModelBase, newState: PropertyFoldingState) => void; unChangedLabel: string; changedLabel: string; prefix: string; @@ -239,7 +239,7 @@ abstract class AbstractCellRenderer extends Disposable { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModel, + readonly cell: CellDiffViewModelBase, readonly templateData: CellDiffSingleSideRenderTemplate | CellDiffSideBySideRenderTemplate, readonly style: 'left' | 'right' | 'full', protected readonly instantiationService: IInstantiationService, @@ -399,7 +399,7 @@ abstract class AbstractCellRenderer extends Disposable { } private _buildMetadataEditor() { - if (this.cell.type === 'modified' || this.cell.type === 'unchanged') { + if (this.cell instanceof SideBySideCellDiffViewModel) { const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.original?.metadata || {}, this.cell.original?.language); const modifiedMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.modified?.metadata || {}, this.cell.modified?.language); this._metadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._metadataEditorContainer!, { @@ -457,43 +457,43 @@ abstract class AbstractCellRenderer extends Disposable { })); return; + } else { + this._metadataEditor = this.instantiationService.createInstance(CodeEditorWidget, this._metadataEditorContainer!, { + ...fixedEditorOptions, + dimension: { + width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), + height: 0 + }, + overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), + readOnly: false + }, {}); + this._register(this._metadataEditor); + + const mode = this.modeService.create('jsonc'); + const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, + this.cell.type === 'insert' + ? this.cell.modified!.metadata || {} + : this.cell.original!.metadata || {}); + const uri = this.cell.type === 'insert' + ? this.cell.modified!.uri + : this.cell.original!.uri; + const handle = this.cell.type === 'insert' + ? this.cell.modified!.handle + : this.cell.original!.handle; + + const modelUri = CellUri.generateCellMetadataUri(uri, handle); + const metadataModel = this.modelService.createModel(originalMetadataSource, mode, modelUri, false); + this._metadataEditor.setModel(metadataModel); + this._register(metadataModel); + + this.cell.metadataHeight = this._metadataEditor.getContentHeight(); + + this._register(this._metadataEditor.onDidContentSizeChange((e) => { + if (e.contentHeightChanged && this.cell.metadataFoldingState === PropertyFoldingState.Expanded) { + this.cell.metadataHeight = e.contentHeight; + } + })); } - - this._metadataEditor = this.instantiationService.createInstance(CodeEditorWidget, this._metadataEditorContainer!, { - ...fixedEditorOptions, - dimension: { - width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), - height: 0 - }, - overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(), - readOnly: false - }, {}); - this._register(this._metadataEditor); - - const mode = this.modeService.create('jsonc'); - const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, - this.cell.type === 'insert' - ? this.cell.modified!.metadata || {} - : this.cell.original!.metadata || {}); - const uri = this.cell.type === 'insert' - ? this.cell.modified!.uri - : this.cell.original!.uri; - const handle = this.cell.type === 'insert' - ? this.cell.modified!.handle - : this.cell.original!.handle; - - const modelUri = CellUri.generateCellMetadataUri(uri, handle); - const metadataModel = this.modelService.createModel(originalMetadataSource, mode, modelUri, false); - this._metadataEditor.setModel(metadataModel); - this._register(metadataModel); - - this.cell.metadataHeight = this._metadataEditor.getContentHeight(); - - this._register(this._metadataEditor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this.cell.metadataFoldingState === PropertyFoldingState.Expanded) { - this.cell.metadataHeight = e.contentHeight; - } - })); } private _getFormatedOutputJSON(outputs: any[]) { @@ -600,7 +600,7 @@ abstract class AbstractCellRenderer extends Disposable { abstract class SingleSideCell extends AbstractCellRenderer { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModel, + readonly cell: SingleSideCellDiffViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, readonly style: 'left' | 'right' | 'full', protected readonly instantiationService: IInstantiationService, @@ -723,7 +723,7 @@ export class DeletedCell extends SingleSideCell { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModel, + readonly cell: SingleSideCellDiffViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, @IModeService readonly modeService: IModeService, @IModelService readonly modelService: IModelService, @@ -818,7 +818,7 @@ export class InsertCell extends SingleSideCell { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModel, + readonly cell: SingleSideCellDiffViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, @@ -924,7 +924,7 @@ export class ModifiedCell extends AbstractCellRenderer { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModel, + readonly cell: SideBySideCellDiffViewModel, readonly templateData: CellDiffSideBySideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index 8eed8eff932..a6df242c3fc 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -15,16 +15,17 @@ import { hash } from 'vs/base/common/hash'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; export enum PropertyFoldingState { Expanded, Collapsed } -export class CellDiffViewModel extends Disposable { +export abstract class CellDiffViewModelBase extends Disposable { public metadataFoldingState: PropertyFoldingState; public outputFoldingState: PropertyFoldingState; - private _layoutInfoEmitter = new Emitter(); + protected _layoutInfoEmitter = new Emitter(); onDidLayoutChange = this._layoutInfoEmitter.event; protected _layoutInfo!: { @@ -37,6 +38,9 @@ export class CellDiffViewModel extends Disposable { bodyMargin: number; }; + protected _outputCollection: number[] = []; + protected _outputsTop: PrefixSumComputer | null = null; + set outputHeight(height: number) { this._layoutInfo.outputHeight = height; this._fireLayoutChangeEvent({ outputEditor: true, outputView: true }); @@ -114,17 +118,10 @@ export class CellDiffViewModel extends Disposable { bodyMargin: 32 }; + this.metadataFoldingState = PropertyFoldingState.Collapsed; this.outputFoldingState = PropertyFoldingState.Collapsed; - if (this.checkMetadataIfModified()) { - this.metadataFoldingState = PropertyFoldingState.Expanded; - } - - if (this.checkIfOutputsModified()) { - this.outputFoldingState = PropertyFoldingState.Expanded; - } - this._register(this.editorEventDispatcher.onDidChangeLayout(e => { this._layoutInfoEmitter.fire({ outerWidth: true }); })); @@ -134,13 +131,9 @@ export class CellDiffViewModel extends Disposable { this._layoutInfoEmitter.fire(state); } - checkIfOutputsModified() { - return this.type !== 'delete' && this.type !== 'insert' && !this.documentTextModel.transientOptions.transientOutputs && this.type === 'modified' && hash(this.original?.outputs ?? []) !== hash(this.modified?.outputs ?? []); - } + abstract checkIfOutputsModified(): boolean; + abstract checkMetadataIfModified(): boolean; - checkMetadataIfModified() { - return this.type !== 'delete' && this.type !== 'insert' && hash(getFormatedMetadataJSON(this.documentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.documentTextModel, this.modified?.metadata ?? {}, this.modified?.language)); - } getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -151,6 +144,62 @@ export class CellDiffViewModel extends Disposable { } } +export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { + constructor( + readonly documentTextModel: NotebookTextModel, + readonly original: NotebookCellTextModel | undefined, + readonly modified: NotebookCellTextModel | undefined, + readonly type: 'unchanged' | 'modified', + readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher + ) { + super( + documentTextModel, + original, + modified, + type, + editorEventDispatcher); + + this.metadataFoldingState = PropertyFoldingState.Collapsed; + this.outputFoldingState = PropertyFoldingState.Collapsed; + + if (this.checkMetadataIfModified()) { + this.metadataFoldingState = PropertyFoldingState.Expanded; + } + + if (this.checkIfOutputsModified()) { + this.outputFoldingState = PropertyFoldingState.Expanded; + } + } + + checkIfOutputsModified() { + return !this.documentTextModel.transientOptions.transientOutputs && this.type === 'modified' && hash(this.original?.outputs ?? []) !== hash(this.modified?.outputs ?? []); + } + + checkMetadataIfModified(): boolean { + return hash(getFormatedMetadataJSON(this.documentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.documentTextModel, this.modified?.metadata ?? {}, this.modified?.language)); + } +} + +export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { + constructor( + readonly documentTextModel: NotebookTextModel, + readonly original: NotebookCellTextModel | undefined, + readonly modified: NotebookCellTextModel | undefined, + readonly type: 'insert' | 'delete', + readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher + ) { + super(documentTextModel, original, modified, type, editorEventDispatcher); + } + + checkIfOutputsModified(): boolean { + return false; + } + + checkMetadataIfModified(): boolean { + return false; + } +} + export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, metadata: NotebookCellMetadata, language?: string) { let filteredMetadata: { [key: string]: any } = {}; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index a08dce346a1..40fe1571f42 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -16,10 +16,10 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; - onMouseUp: Event<{ readonly event: MouseEvent; readonly target: CellDiffViewModel; }>; + onMouseUp: Event<{ readonly event: MouseEvent; readonly target: CellDiffViewModelBase; }>; getOverflowContainerDomNode(): HTMLElement; getLayoutInfo(): NotebookLayoutInfo; - layoutNotebookCell(cell: CellDiffViewModel, height: number): void; + layoutNotebookCell(cell: CellDiffViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index cb8709d167d..3983cfcc4bb 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ActiveEditorContext, viewColumnToEditorGroup } from 'vs/workbench/common/editor'; -import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; import { openAsTextIcon, revertIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; @@ -65,7 +65,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModel }) { + run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { if (!context) { return; } @@ -95,7 +95,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModel }) { + run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { if (!context) { return; } @@ -125,7 +125,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModel }) { + run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { if (!context) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 1f838eecf76..dd1a285d7e3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -14,7 +14,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe import { NotebookDiffEditorInput } from '../notebookDiffEditorInput'; import { CancellationToken } from 'vs/base/common/cancellation'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; -import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffSideBySideRenderer, CellDiffSingleSideRenderer, NotebookCellTextDiffListDelegate, NotebookTextDiffList } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -47,10 +47,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _rootElement!: HTMLElement; private _overflowContainer!: HTMLElement; private _dimension: DOM.Dimension | null = null; - private _list!: WorkbenchList; + private _list!: WorkbenchList; private _fontInfo: BareFontInfo | undefined; - private readonly _onMouseUp = this._register(new Emitter<{ readonly event: MouseEvent; readonly target: CellDiffViewModel; }>()); + private readonly _onMouseUp = this._register(new Emitter<{ readonly event: MouseEvent; readonly target: CellDiffViewModelBase; }>()); public readonly onMouseUp = this._onMouseUp.event; private _eventDispatcher: NotebookDiffEditorEventDispatcher | undefined; protected _scopeContextKeyService!: IContextKeyService; @@ -227,7 +227,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const diffResult = await this.notebookEditorWorkerService.computeDiff(this._model.original.resource, this._model.modified.resource); const cellChanges = diffResult.cellsDiff.changes; - const cellDiffViewModels: CellDiffViewModel[] = []; + const cellDiffViewModels: CellDiffViewModelBase[] = []; const originalModel = this._model.original.notebook; const modifiedModel = this._model.modified.notebook; let originalCellIndex = 0; @@ -243,7 +243,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const originalCell = originalModel.cells[originalCellIndex + j]; const modifiedCell = modifiedModel.cells[modifiedCellIndex + j]; if (originalCell.getHashValue() === modifiedCell.getHashValue()) { - cellDiffViewModels.push(new CellDiffViewModel( + cellDiffViewModels.push(new SideBySideCellDiffViewModel( this._model.modified.notebook, originalCell, modifiedCell, @@ -255,7 +255,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD firstChangeIndex = cellDiffViewModels.length; } - cellDiffViewModels.push(new CellDiffViewModel( + cellDiffViewModels.push(new SideBySideCellDiffViewModel( this._model.modified.notebook, originalCell, modifiedCell, @@ -276,7 +276,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } for (let i = originalCellIndex; i < originalModel.cells.length; i++) { - cellDiffViewModels.push(new CellDiffViewModel( + cellDiffViewModels.push(new SideBySideCellDiffViewModel( this._model.modified.notebook, originalModel.cells[i], modifiedModel.cells[i - originalCellIndex + modifiedCellIndex], @@ -295,12 +295,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } private _computeModifiedLCS(change: IDiffChange, originalModel: NotebookTextModel, modifiedModel: NotebookTextModel) { - const result: CellDiffViewModel[] = []; + const result: CellDiffViewModelBase[] = []; // modified cells const modifiedLen = Math.min(change.originalLength, change.modifiedLength); for (let j = 0; j < modifiedLen; j++) { - result.push(new CellDiffViewModel( + result.push(new SideBySideCellDiffViewModel( modifiedModel, originalModel.cells[change.originalStart + j], modifiedModel.cells[change.modifiedStart + j], @@ -311,7 +311,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.originalLength; j++) { // deletion - result.push(new CellDiffViewModel( + result.push(new SingleSideCellDiffViewModel( originalModel, originalModel.cells[change.originalStart + j], undefined, @@ -322,7 +322,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.modifiedLength; j++) { // insertion - result.push(new CellDiffViewModel( + result.push(new SingleSideCellDiffViewModel( modifiedModel, undefined, modifiedModel.cells[change.modifiedStart + j], @@ -334,11 +334,11 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return result; } - private pendingLayouts = new WeakMap(); + private pendingLayouts = new WeakMap(); - layoutNotebookCell(cell: CellDiffViewModel, height: number) { - const relayout = (cell: CellDiffViewModel, height: number) => { + layoutNotebookCell(cell: CellDiffViewModelBase, height: number) { + const relayout = (cell: CellDiffViewModelBase, height: number) => { const viewIndex = this._list.indexOf(cell); this._list?.updateElementHeight(viewIndex, height); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index f4bc58255c3..beacd76156e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -14,7 +14,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/list/browser/listService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { CellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { isMacintosh } from 'vs/base/common/platform'; import { DeletedCell, InsertCell, ModifiedCell } from 'vs/workbench/contrib/notebook/browser/diff/cellComponents'; @@ -88,7 +88,7 @@ export function getOptimizedNestedCodeEditorWidgetOptions(): ICodeEditorWidgetOp }; } -export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { +export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { // private readonly lineHeight: number; constructor( @@ -98,15 +98,15 @@ export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { +export class CellDiffSingleSideRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'cell_diff_single'; constructor( @@ -177,7 +177,7 @@ export class CellDiffSingleSideRenderer implements IListRenderer { +export class CellDiffSideBySideRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'cell_diff_side_by_side'; constructor( @@ -286,7 +286,7 @@ export class CellDiffSideBySideRenderer implements IListRenderer implements IDisposable, IStyleController { +export class NotebookTextDiffList extends WorkbenchList implements IDisposable, IStyleController { private styleElement?: HTMLStyleElement; constructor( listUser: string, container: HTMLElement, - delegate: IListVirtualDelegate, - renderers: IListRenderer[], + delegate: IListVirtualDelegate, + renderers: IListRenderer[], contextKeyService: IContextKeyService, - options: IWorkbenchListOptions, + options: IWorkbenchListOptions, @IListService listService: IListService, @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, From 387f4f4b1125930530169dca9cbb15521ce633b9 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 21:33:41 +0100 Subject: [PATCH 0958/1837] Skip electron binary download --- .github/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5aa9082ee2..217911223bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,7 @@ jobs: 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: Run Hygiene Checks @@ -87,6 +88,7 @@ jobs: 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: Cache compiled core code @@ -140,6 +142,7 @@ jobs: 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: Cache compiled extensions code @@ -305,6 +308,7 @@ jobs: 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 build-darwin-unit-tests: @@ -497,6 +501,7 @@ jobs: 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: Compile and Download @@ -553,6 +558,7 @@ jobs: 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: Compile and Download @@ -601,6 +607,7 @@ jobs: 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: Compile and Download @@ -638,6 +645,7 @@ jobs: 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: Run Monaco Editor Checks From b44750d551debee69710fd3e641e735f69d0b61d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 21:48:06 +0100 Subject: [PATCH 0959/1837] use menu registry for views visibility actions --- .../browser/parts/views/viewPaneContainer.ts | 115 ++++++++---------- .../browser/parts/views/viewsViewlet.ts | 16 --- src/vs/workbench/browser/viewlet.ts | 20 +-- src/vs/workbench/common/views.ts | 5 +- .../views/browser/viewDescriptorService.ts | 115 +++++++++++++++++- .../views/common/viewContainerModel.ts | 10 +- 6 files changed, 173 insertions(+), 108 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 768e6d0f5ee..fc324cfe1f4 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -9,9 +9,9 @@ import { Event, Emitter } from 'vs/base/common/event'; import { ColorIdentifier, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler'; import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme'; -import { EventType, isAncestor, Dimension, addDisposableListener } from 'vs/base/browser/dom'; +import { EventType, Dimension, addDisposableListener, isAncestor } from 'vs/base/browser/dom'; import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions'; +import { IAction, IActionViewItem, Separator } from 'vs/base/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; @@ -19,16 +19,16 @@ import { PaneView, IPaneViewOptions } from 'vs/base/browser/ui/splitview/panevie import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, IViewsService } from 'vs/workbench/common/views'; +import { IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, IViewsService, ViewContainerLocationToString } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined } from 'vs/base/common/types'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Component } from 'vs/workbench/common/component'; -import { registerAction2, Action2, IAction2Options, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { registerAction2, Action2, IAction2Options, IMenuService, MenuId, MenuRegistry, ISubmenuItem, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { CompositeDragAndDropObserver, DragAndDropObserver, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -37,6 +37,14 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +export const ViewsSubMenu = new MenuId('Views'); +MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { + submenu: ViewsSubMenu, + title: nls.localize('views', "Views"), + order: 1, + when: ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar)), +}); + export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; headerForeground?: ColorIdentifier; @@ -287,13 +295,16 @@ class ViewPaneDropOverlay extends Themable { class ViewContainerMenuActions extends CompositeMenuActions { constructor( viewContainer: ViewContainer, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IContextKeyService contextKeyService: IContextKeyService, @IMenuService menuService: IMenuService, ) { const scopedContextKeyService = contextKeyService.createScoped(); scopedContextKeyService.createKey('viewContainer', viewContainer.id); + const viewContainerLocationKey = scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!)); super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true }, scopedContextKeyService, menuService); this._register(scopedContextKeyService); + this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(() => viewContainerLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!)))); } } @@ -552,7 +563,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { let anchor: { x: number, y: number; } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ getAnchor: () => anchor, - getActions: () => [...this.getContextMenuActions()] + getActions: () => [...this.getContextMenuActions2()] }); } @@ -561,77 +572,55 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] { - const result: IAction[] = []; - - let showHide = true; - if (!viewDescriptor && this.isViewMergedWithContainer()) { - viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.panes[0].id) || undefined; - showHide = false; - } - - if (viewDescriptor) { - if (showHide) { - result.push({ - id: `${viewDescriptor.id}.removeView`, - label: nls.localize('hideView', "Hide"), - enabled: viewDescriptor.canToggleVisibility, - run: () => this.toggleViewVisibility(viewDescriptor!.id) - }); - } - const view = this.getView(viewDescriptor.id); - if (view) { - result.push(...view.getContextMenuActions()); - } - } - - const viewToggleActions = this.getViewsVisibilityActions(); - if (result.length && viewToggleActions.length) { - result.push(new Separator()); - } - - result.push(...viewToggleActions); - - return result; + return []; } getActions2(): IAction[] { - return this.menuActions.getPrimaryActions(); - } - - getActions(): IAction[] { const result = []; + result.push(...this.menuActions.getPrimaryActions()); if (this.isViewMergedWithContainer()) { result.push(...this.paneItems[0].pane.getActions()); } return result; } + getActions(): IAction[] { + return []; + } + getSecondaryActions2(): IAction[] { - return this.menuActions.getSecondaryActions(); + let menuActions = this.menuActions.getSecondaryActions(); + const isViewsSubMenuAction = (action: IAction) => action instanceof SubmenuItemAction && action.item.submenu === ViewsSubMenu; + const index = menuActions.findIndex(a => isViewsSubMenuAction(a)); + if (index !== -1) { + if (index !== 0) { + menuActions = [menuActions[index], ...menuActions.slice(0, index), ...menuActions.slice(index + 1)]; + } + if (menuActions.length === 1) { + menuActions = (menuActions[0]).actions; + } + } + + const viewPaneContainerActions = this.isViewMergedWithContainer() ? this.paneItems[0].pane.getSecondaryActions() : []; + if (menuActions.length && viewPaneContainerActions.length) { + return [ + ...menuActions, + new Separator(), + ...viewPaneContainerActions + ]; + } + + return menuActions.length ? menuActions : viewPaneContainerActions; } getSecondaryActions(): IAction[] { - const result = []; - if (this.isViewMergedWithContainer()) { - result.push(...this.paneItems[0].pane.getSecondaryActions()); - } - return result; + return []; } getActionsContext(): unknown { return undefined; } - getViewsVisibilityActions(): IAction[] { - return this.viewContainerModel.activeViewDescriptors.map(viewDescriptor => ({ - id: `${viewDescriptor.id}.toggleVisibility`, - label: viewDescriptor.name, - checked: this.viewContainerModel.isVisible(viewDescriptor.id), - enabled: viewDescriptor.canToggleVisibility && (!this.viewContainerModel.isVisible(viewDescriptor.id) || this.viewContainerModel.visibleViewDescriptors.length > 1), - run: () => this.toggleViewVisibility(viewDescriptor.id) - })); - } - getActionViewItem(action: IAction): IActionViewItem | undefined { if (this.isViewMergedWithContainer()) { return this.paneItems[0].pane.getActionViewItem(action); @@ -775,11 +764,11 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { this.storageService.store(this.visibleViewsStorageId, this.length, StorageScope.WORKSPACE, StorageTarget.USER); } - private onContextMenu(event: StandardMouseEvent, viewDescriptor: IViewDescriptor): void { + private onContextMenu(event: StandardMouseEvent, viewPane: ViewPane): void { event.stopPropagation(); event.preventDefault(); - const actions: IAction[] = this.getContextMenuActions(viewDescriptor); + const actions: IAction[] = viewPane.getContextMenuActions(); let anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ @@ -818,7 +807,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { const contextMenuDisposable = addDisposableListener(pane.draggableElement, 'contextmenu', e => { e.stopPropagation(); e.preventDefault(); - this.onContextMenu(new StandardMouseEvent(e), viewDescriptor); + this.onContextMenu(new StandardMouseEvent(e), pane); }); const collapseDisposable = Event.latch(Event.map(pane.onDidChange, () => !pane.isExpanded()))(collapsed => { @@ -855,7 +844,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } } - protected toggleViewVisibility(viewId: string): void { + toggleViewVisibility(viewId: string): void { // Check if view is active if (this.viewContainerModel.activeViewDescriptors.some(viewDescriptor => viewDescriptor.id === viewId)) { const visible = !this.viewContainerModel.isVisible(viewId); @@ -1127,11 +1116,11 @@ export abstract class ViewPaneContainerAction exte run(accessor: ServicesAccessor, ...args: any[]) { const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(this.desc.viewPaneContainerId); if (viewPaneContainer) { - return this.runInView(accessor, viewPaneContainer, ...args); + return this.runInViewPaneContainer(accessor, viewPaneContainer, ...args); } } - abstract runInView(accessor: ServicesAccessor, view: T, ...args: any[]): any; + abstract runInViewPaneContainer(accessor: ServicesAccessor, viewPaneContainer: T, ...args: any[]): any; } class MoveViewPosition extends Action2 { diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 9df0fa0263e..d6a6f07e6ad 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IAction } from 'vs/base/common/actions'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IViewDescriptor, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views'; @@ -82,18 +81,6 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer { this.getViewsForTarget(newFilterValue).forEach(item => this.viewContainerModel.setVisible(item.id, true)); } - getContextMenuActions(): IAction[] { - const result: IAction[] = Array.from(this.constantViewDescriptors.values()).map(viewDescriptor => ({ - id: `${viewDescriptor.id}.toggleVisibility`, - label: viewDescriptor.name, - checked: this.viewContainerModel.isVisible(viewDescriptor.id), - enabled: viewDescriptor.canToggleVisibility, - run: () => this.toggleViewVisibility(viewDescriptor.id) - })); - - return result; - } - private getViewsForTarget(target: string[]): IViewDescriptor[] { const views: IViewDescriptor[] = []; for (let i = 0; i < target.length; i++) { @@ -141,7 +128,4 @@ export abstract class FilterViewPaneContainer extends ViewPaneContainer { abstract getTitle(): string; - getViewsVisibilityActions(): IAction[] { - return []; - } } diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index febbc772fdd..83a658a2016 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import * as DOM from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite'; @@ -68,24 +68,6 @@ export abstract class Viewlet extends PaneComposite implements IViewlet { run: () => this.layoutService.setSideBarHidden(true) }]; } - - getSecondaryActions(): ReadonlyArray { - const secondaryActions = super.getSecondaryActions(); - const viewVisibilityActions = this.viewPaneContainer.getViewsVisibilityActions(); - if (viewVisibilityActions.length <= 1 || viewVisibilityActions.every(({ enabled }) => !enabled)) { - return secondaryActions; - } - - if (secondaryActions.length === 0) { - return viewVisibilityActions; - } - - return [ - new SubmenuAction('workbench.views', nls.localize('views', "Views"), viewVisibilityActions), - new Separator(), - ...secondaryActions - ]; - } } /** diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 5fa948c8f85..e5105b8a09c 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -263,6 +263,8 @@ export interface IAddedViewDescriptorState { export interface IViewContainerModel { + readonly viewContainer: ViewContainer; + readonly title: string; readonly icon: ThemeIcon | URI | undefined; readonly onDidChangeContainerInfo: Event<{ title?: boolean, icon?: boolean }>; @@ -512,7 +514,7 @@ export interface IViewsService { * View Contexts */ export const FocusedViewContext = new RawContextKey('focusedView', ''); -export function getVisbileViewContextKey(viewId: string): string { return `${viewId}.visible`; } +export function getVisbileViewContextKey(viewId: string): string { return `view.${viewId}.visible`; } export const IViewDescriptorService = createDecorator('viewDescriptorService'); @@ -763,5 +765,6 @@ export interface IViewPaneContainer { getActionViewItem(action: IAction): IActionViewItem | undefined; getActionsContext(): unknown; getView(viewId: string): IView | undefined; + toggleViewVisibility(viewId: string): void; saveState(): void; } diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index 39a0859fc86..dc12e9bfb90 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -3,19 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState, defaultViewIcon } from 'vs/workbench/common/views'; -import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState, defaultViewIcon, ViewContainerLocationToString } from 'vs/workbench/common/views'; +import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr, ContextKeyEqualsExpr, ContextKeyFalseExpr, ContextKeyOrExpr, ContextKeyTrueExpr, ContextKeyAndExpr, ContextKeyDefinedExpr } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { Registry } from 'vs/platform/registry/common/platform'; import { toDisposable, DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPaneContainer, ViewPaneContainerAction, ViewsSubMenu } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Event, Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { generateUuid } from 'vs/base/common/uuid'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { getViewsStateStorageId, ViewContainerModel } from 'vs/workbench/services/views/common/viewContainerModel'; import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions'; import { localize } from 'vs/nls'; @@ -44,6 +44,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor readonly onDidChangeContainerLocation: Event<{ viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation }> = this._onDidChangeContainerLocation.event; private readonly viewContainerModels: Map; + private readonly viewsVisibilityActionDisposables: Map; private readonly activeViewContextKeys: Map>; private readonly movableViewContextKeys: Map>; private readonly defaultViewLocationContextKeys: Map>; @@ -101,6 +102,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor super(); this.viewContainerModels = new Map(); + this.viewsVisibilityActionDisposables = new Map(); this.activeViewContextKeys = new Map>(); this.movableViewContextKeys = new Map>(); this.defaultViewLocationContextKeys = new Map>(); @@ -133,6 +135,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor this._register(toDisposable(() => { this.viewContainerModels.forEach(({ disposable }) => disposable.dispose()); this.viewContainerModels.clear(); + this.viewsVisibilityActionDisposables.forEach(disposables => disposables.dispose()); + this.viewsVisibilityActionDisposables.clear(); })); this._register(this.storageService.onDidChangeValue((e) => { this.onDidStorageChange(e); })); @@ -681,6 +685,22 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor this.onDidChangeActiveViews({ added: viewContainerModel.activeViewDescriptors, removed: [] }); viewContainerModel.onDidChangeActiveViewDescriptors(changed => this.onDidChangeActiveViews(changed), this, disposables); + this.onDidChangeVisibleViews({ added: [...viewContainerModel.visibleViewDescriptors], removed: [] }); + viewContainerModel.onDidAddVisibleViewDescriptors(added => this.onDidChangeVisibleViews({ added: added.map(({ viewDescriptor }) => viewDescriptor), removed: [] }), this, disposables); + viewContainerModel.onDidRemoveVisibleViewDescriptors(removed => this.onDidChangeVisibleViews({ added: [], removed: removed.map(({ viewDescriptor }) => viewDescriptor) }), this, disposables); + + this.registerViewsVisibilityActions(viewContainerModel); + disposables.add(Event.any( + viewContainerModel.onDidChangeActiveViewDescriptors, + viewContainerModel.onDidAddVisibleViewDescriptors, + viewContainerModel.onDidRemoveVisibleViewDescriptors, + viewContainerModel.onDidMoveVisibleViewDescriptors + )(e => this.registerViewsVisibilityActions(viewContainerModel!))); + disposables.add(toDisposable(() => { + this.viewsVisibilityActionDisposables.get(viewContainer)?.dispose(); + this.viewsVisibilityActionDisposables.delete(viewContainer); + })); + disposables.add(this.registerResetViewContainerAction(viewContainer)); this.viewContainerModels.set(viewContainer, { viewContainerModel: viewContainerModel, disposable: disposables }); @@ -718,6 +738,83 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor }); } + private onDidChangeVisibleViews({ added, removed }: { added: IViewDescriptor[], removed: IViewDescriptor[]; }): void { + this.contextKeyService.bufferChangeEvents(() => { + added.forEach(viewDescriptor => this.getOrCreateVisibleViewContextKey(viewDescriptor).set(true)); + removed.forEach(viewDescriptor => this.getOrCreateVisibleViewContextKey(viewDescriptor).set(false)); + }); + } + + private registerViewsVisibilityActions(viewContainerModel: ViewContainerModel): void { + let disposables = this.viewsVisibilityActionDisposables.get(viewContainerModel.viewContainer); + if (!disposables) { + disposables = new DisposableStore(); + this.viewsVisibilityActionDisposables.set(viewContainerModel.viewContainer, disposables); + } + disposables.clear(); + viewContainerModel.activeViewDescriptors.forEach((viewDescriptor, index) => { + if (!viewDescriptor.remoteAuthority) { + disposables?.add(registerAction2(class extends ViewPaneContainerAction { + constructor() { + super({ + id: `${viewDescriptor.id}.toggleVisibility`, + viewPaneContainerId: viewContainerModel.viewContainer.id, + precondition: viewDescriptor.canToggleVisibility && (!viewContainerModel.isVisible(viewDescriptor.id) || viewContainerModel.visibleViewDescriptors.length > 1) ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE, + toggled: ContextKeyDefinedExpr.create(`${viewDescriptor.id}.visible`), + title: viewDescriptor.name, + menu: [{ + id: ViewsSubMenu, + when: ContextKeyAndExpr.create([ + ContextKeyEqualsExpr.create('viewContainer', viewContainerModel.viewContainer.id), + ContextKeyEqualsExpr.create('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar)), + ]), + order: index, + }, { + id: MenuId.ViewContainerTitleContext, + when: ContextKeyAndExpr.create([ + ContextKeyEqualsExpr.create('viewContainer', viewContainerModel.viewContainer.id), + ]), + order: index, + group: '1_toggleVisibility' + }, { + id: MenuId.ViewTitleContext, + when: ContextKeyAndExpr.create([ + viewContainerModel.visibleViewDescriptors.length > 1 ? ContextKeyOrExpr.create(viewContainerModel.visibleViewDescriptors.map(v => ContextKeyEqualsExpr.create('view', v.id))) : ContextKeyFalseExpr.INSTANCE + ]), + order: index, + group: '2_toggleVisibility' + }] + }); + } + async runInViewPaneContainer(serviceAccessor: ServicesAccessor, viewPaneContainer: ViewPaneContainer): Promise { + viewPaneContainer.toggleViewVisibility(viewDescriptor.id); + } + })); + disposables?.add(registerAction2(class extends ViewPaneContainerAction { + constructor() { + super({ + id: `${viewDescriptor.id}.removeView`, + viewPaneContainerId: viewContainerModel.viewContainer.id, + title: localize('hideView', "Hide"), + precondition: viewDescriptor.canToggleVisibility && (!viewContainerModel.isVisible(viewDescriptor.id) || viewContainerModel.visibleViewDescriptors.length > 1) ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE, + menu: [{ + id: MenuId.ViewTitleContext, + when: ContextKeyAndExpr.create([ + ContextKeyEqualsExpr.create('view', viewDescriptor.id), + ContextKeyDefinedExpr.create(`${viewDescriptor.id}.visible`), + ]), + group: '1_hide' + }] + }); + } + async runInViewPaneContainer(serviceAccessor: ServicesAccessor, viewPaneContainer: ViewPaneContainer): Promise { + viewPaneContainer.toggleViewVisibility(viewDescriptor.id); + } + })); + } + }); + } + private registerResetViewContainerAction(viewContainer: ViewContainer): IDisposable { const that = this; return registerAction2(class ResetViewLocationAction extends Action2 { @@ -791,6 +888,16 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor return contextKey; } + private getOrCreateVisibleViewContextKey(viewDescriptor: IViewDescriptor): IContextKey { + const activeContextKeyId = `${viewDescriptor.id}.visible`; + let contextKey = this.activeViewContextKeys.get(activeContextKeyId); + if (!contextKey) { + contextKey = new RawContextKey(activeContextKeyId, false).bindTo(this.contextKeyService); + this.activeViewContextKeys.set(activeContextKeyId, contextKey); + } + return contextKey; + } + private getOrCreateMovableViewContextKey(viewDescriptor: IViewDescriptor): IContextKey { const movableViewContextKeyId = `${viewDescriptor.id}.canMove`; let contextKey = this.movableViewContextKeys.get(movableViewContextKeyId); diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 811fd8dbc30..2d1e65712ef 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -316,14 +316,14 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode readonly onDidMoveVisibleViewDescriptors: Event<{ from: IViewDescriptorRef; to: IViewDescriptorRef; }> = this._onDidMoveVisibleViewDescriptors.event; constructor( - private readonly container: ViewContainer, + readonly viewContainer: ViewContainer, @IInstantiationService instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, ) { super(); this._register(Event.filter(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys))(() => this.onDidChangeContext())); - this.viewDescriptorsState = this._register(instantiationService.createInstance(ViewDescriptorsState, container.storageId || `${container.id}.state`)); + this.viewDescriptorsState = this._register(instantiationService.createInstance(ViewDescriptorsState, viewContainer.storageId || `${viewContainer.id}.state`)); this._register(this.viewDescriptorsState.onDidChangeStoredState(items => this.updateVisibility(items))); this._register(Event.any( @@ -340,15 +340,15 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode private updateContainerInfo(): void { /* Use default container info if one of the visible view descriptors belongs to the current container by default */ - const useDefaultContainerInfo = this.container.alwaysUseContainerInfo || this.visibleViewDescriptors.length === 0 || this.visibleViewDescriptors.some(v => Registry.as(ViewExtensions.ViewsRegistry).getViewContainer(v.id) === this.container); - const title = useDefaultContainerInfo ? this.container.name : this.visibleViewDescriptors[0]?.containerTitle || this.visibleViewDescriptors[0]?.name || ''; + const useDefaultContainerInfo = this.viewContainer.alwaysUseContainerInfo || this.visibleViewDescriptors.length === 0 || this.visibleViewDescriptors.some(v => Registry.as(ViewExtensions.ViewsRegistry).getViewContainer(v.id) === this.viewContainer); + const title = useDefaultContainerInfo ? this.viewContainer.name : this.visibleViewDescriptors[0]?.containerTitle || this.visibleViewDescriptors[0]?.name || ''; let titleChanged: boolean = false; if (this._title !== title) { this._title = title; titleChanged = true; } - const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || defaultViewIcon; + const icon = useDefaultContainerInfo ? this.viewContainer.icon : this.visibleViewDescriptors[0]?.containerIcon || defaultViewIcon; let iconChanged: boolean = false; if (!this.isEqualIcon(icon)) { this._icon = icon; From 9565cf54c632d3c563b3b8c3de3c080283a03d41 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 14 Dec 2020 13:13:44 -0800 Subject: [PATCH 0960/1837] chore: bump electron@11.0.5 --- .yarnrc | 2 +- cgmanifest.json | 8 ++++---- package.json | 4 ++-- yarn.lock | 13 ++++--------- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/.yarnrc b/.yarnrc index 7b0e7edfcbf..e93e4570cfb 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://electronjs.org/headers" -target "11.0.3" +target "11.0.5" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index 5575cb4b04c..fffd667ab0a 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "0387c513f0319231a8ca6dd0a265102af3d4455e" + "commitHash": "dcfd8d6023038d7a33f7baf393dcd6b1dc93f3b5" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "87.0.4280.67" + "version": "87.0.4280.88" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "b0862a6e63173c4c919bd5ed27d257235bbfe7d2" + "commitHash": "296cba563ea41277fd2b8b5a3b246acb9888befa" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "11.0.3" + "version": "11.0.5" }, { "component": { diff --git a/package.json b/package.json index 2ee117cb329..66ee8a569bc 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "compile-web": "gulp compile-web --max_old_space_size=4095", "watch-web": "gulp watch-web --max_old_space_size=4095", "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", - "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.3" + "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.5" }, "dependencies": { "applicationinsights": "1.0.8", @@ -112,7 +112,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "11.0.3", + "electron": "11.0.5", "electron-rebuild": "2.0.3", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", diff --git a/yarn.lock b/yarn.lock index 1e156cabbc1..7a328eec3e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2866,10 +2866,10 @@ electron-to-chromium@^1.2.7: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@11.0.3: - version "11.0.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-11.0.3.tgz#c29eaacda38ce561890e59906ca5f507c72b3ec4" - integrity sha512-nNfbLi7Q1xfJXOEO2adck5TS6asY4Jxc332E4Te8XfQ9hcaC3GiCdeEqk9FndNCwxhJA5Lr9jfSGRTwWebFa/w== +electron@11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.0.5.tgz#ca83cc294fecef08755a528e4a18f8a5534d220f" + integrity sha512-gGMnlDk2nrI/r9gtxDMtOmGPhI9OOTWxABI0K/zQ3QyiAIdtYM4/AkPAcZ6ZZ1cJ4LShaCrFTHqia8ZL3i9zCg== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -9646,11 +9646,6 @@ typescript@^2.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q= -typescript@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" - integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== - uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" From 79a42e72217df42fa3e59cfe859f0f335e152bcf Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Dec 2020 22:29:22 +0100 Subject: [PATCH 0961/1837] use menu registry for sidebar actions --- .../browser/actions/layoutActions.ts | 92 ++++++++++++++----- src/vs/workbench/browser/panecomposite.ts | 17 +--- .../browser/parts/views/viewPaneContainer.ts | 11 ++- src/vs/workbench/browser/viewlet.ts | 19 +--- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index cdd2cdfc3c9..784dc905a15 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -203,7 +203,42 @@ export class ToggleSidebarPositionAction extends Action { } } -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSidebarPositionAction), 'View: Toggle Side Bar Position', CATEGORIES.View.value); +registerAction2(class extends Action2 { + constructor() { + super({ + id: ToggleSidebarPositionAction.ID, + title: { value: nls.localize('toggleSidebarPosition', "Toggle Side Bar Position"), original: 'Toggle Side Bar Position' }, + category: CATEGORIES.View, + f1: true + }); + } + run(accessor: ServicesAccessor) { + accessor.get(IInstantiationService).createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL).run(); + } +}); +MenuRegistry.appendMenuItems([{ + id: MenuId.ViewContainerTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: ToggleSidebarPositionAction.ID, + title: nls.localize('move sidebar right', "Move Side Bar Right") + }, + when: ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), + order: 1 + } +}, { + id: MenuId.ViewContainerTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: ToggleSidebarPositionAction.ID, + title: nls.localize('move sidebar left', "Move Side Bar Left") + }, + when: ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), + order: 1 + } +}]); MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { group: '3_workbench_layout_move', @@ -256,27 +291,6 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { order: 5 }); -export class ToggleSidebarVisibilityAction extends Action { - - static readonly ID = 'workbench.action.toggleSidebarVisibility'; - static readonly LABEL = nls.localize('toggleSidebar', "Toggle Side Bar Visibility"); - - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService - ) { - super(id, label); - } - - async run(): Promise { - const hideSidebar = this.layoutService.isVisible(Parts.SIDEBAR_PART); - this.layoutService.setSideBarHidden(hideSidebar); - } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSidebarVisibilityAction, { primary: KeyMod.CtrlCmd | KeyCode.KEY_B }), 'View: Toggle Side Bar Visibility', CATEGORIES.View.value); - MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { group: '2_appearance', title: nls.localize({ key: 'miAppearance', comment: ['&& denotes a mnemonic'] }, "&&Appearance"), @@ -284,10 +298,42 @@ MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { order: 1 }); +export const TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID = 'workbench.action.toggleSidebarVisibility'; +registerAction2(class extends Action2 { + constructor() { + super({ + id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + title: { value: nls.localize('toggleSidebar', "Toggle Side Bar Visibility"), original: 'Toggle Side Bar Visibility' }, + category: CATEGORIES.View, + f1: true, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyMod.CtrlCmd | KeyCode.KEY_B + } + }); + } + run(accessor: ServicesAccessor) { + const layoutService = accessor.get(IWorkbenchLayoutService); + layoutService.setSideBarHidden(layoutService.isVisible(Parts.SIDEBAR_PART)); + } +}); +MenuRegistry.appendMenuItems([{ + id: MenuId.ViewContainerTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + title: nls.localize('compositePart.hideSideBarLabel', "Hide Side Bar"), + }, + when: SideBarVisibleContext, + order: 2 + } +}]); + MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { group: '2_workbench_layout', command: { - id: ToggleSidebarVisibilityAction.ID, + id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, title: nls.localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"), toggled: SideBarVisibleContext }, diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts index 78c58259648..1f00c9ec5b3 100644 --- a/src/vs/workbench/browser/panecomposite.ts +++ b/src/vs/workbench/browser/panecomposite.ts @@ -16,8 +16,6 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { ViewPaneContainer } from './parts/views/viewPaneContainer'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IAction, IActionViewItem, Separator } from 'vs/base/common/actions'; -import { MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; -import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; export class PaneComposite extends Composite implements IPaneComposite { @@ -98,20 +96,7 @@ export class PaneComposite extends Composite implements IPaneComposite { } getActionViewItem(action: IAction): IActionViewItem | undefined { - const actionViewItem = this.viewPaneContainer.getActionViewItem(action); - if (actionViewItem) { - return actionViewItem; - } - - if (action instanceof MenuItemAction) { - return this.instantiationService.createInstance(MenuEntryActionViewItem, action); - } - - if (action instanceof SubmenuItemAction) { - return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action); - } - - return undefined; + return this.viewPaneContainer.getActionViewItem(action); } getTitle(): string { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index fc324cfe1f4..c02ca3dfcc3 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -28,7 +28,7 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Component } from 'vs/workbench/common/component'; -import { registerAction2, Action2, IAction2Options, IMenuService, MenuId, MenuRegistry, ISubmenuItem, SubmenuItemAction } from 'vs/platform/actions/common/actions'; +import { registerAction2, Action2, IAction2Options, IMenuService, MenuId, MenuRegistry, ISubmenuItem, SubmenuItemAction, MenuItemAction } from 'vs/platform/actions/common/actions'; import { CompositeDragAndDropObserver, DragAndDropObserver, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -36,6 +36,7 @@ import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; export const ViewsSubMenu = new MenuId('Views'); MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { @@ -626,6 +627,14 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { return this.paneItems[0].pane.getActionViewItem(action); } + if (action instanceof MenuItemAction) { + return this.instantiationService.createInstance(MenuEntryActionViewItem, action); + } + + if (action instanceof SubmenuItemAction) { + return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action); + } + return undefined; } diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 83a658a2016..0bc5ee5814e 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -6,12 +6,11 @@ import * as nls from 'vs/nls'; import * as DOM from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { Action } from 'vs/base/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite'; import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation'; -import { ToggleSidebarVisibilityAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -52,22 +51,6 @@ export abstract class Viewlet extends PaneComposite implements IViewlet { })); } } - - getContextMenuActions(): IAction[] { - const parentActions = [...super.getContextMenuActions()]; - if (parentActions.length) { - parentActions.push(new Separator()); - } - - const toggleSidebarPositionAction = new ToggleSidebarPositionAction(ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService), this.layoutService, this.configurationService); - return [...parentActions, toggleSidebarPositionAction, - { - id: ToggleSidebarVisibilityAction.ID, - label: nls.localize('compositePart.hideSideBarLabel', "Hide Side Bar"), - enabled: true, - run: () => this.layoutService.setSideBarHidden(true) - }]; - } } /** From f76b1c25e7e67595c39b5a0627b9abb998920c5a Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Mon, 14 Dec 2020 22:03:51 +0000 Subject: [PATCH 0962/1837] remove quotes since we don't spawn shell --- extensions/git/src/git.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 34eb1ab677a..aec131a03db 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1694,7 +1694,7 @@ export class Repository { args.push(name); } - args.splice(0, 0, '-c', `http.userAgent="${this.git.userAgent}"`); + args.splice(0, 0, '-c', `http.userAgent=${this.git.userAgent}`); try { await this.run(args); From 4d0195152faa2bfcbb5a018f23a63e5b19a28008 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 14 Dec 2020 23:09:19 +0100 Subject: [PATCH 0963/1837] Add a slice to fix compilation --- src/vs/workbench/browser/parts/sidebar/sidebarPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index f6504de93c1..f42d5779d17 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -288,7 +288,7 @@ export class SidebarPart extends CompositePart implements IViewletServi const anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ getAnchor: () => anchor, - getActions: () => contextMenuActions, + getActions: () => contextMenuActions.slice(), getActionViewItem: action => this.actionViewItemProvider(action as Action), actionRunner: activeViewlet.getActionRunner() }); From 239c211326d5ff9d0ca2ee0070489e915059316d Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 14:10:32 -0800 Subject: [PATCH 0964/1837] positioning for dynamic height output --- .../notebook/browser/diff/cellComponents.ts | 15 +- .../notebook/browser/diff/cellOutputs.ts | 104 +++++++++---- .../browser/diff/celllDiffViewModel.ts | 145 +++++++++++++++++- .../notebook/browser/diff/notebookDiff.css | 4 +- .../browser/viewModel/codeCellViewModel.ts | 2 +- 5 files changed, 226 insertions(+), 44 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 29e062d6156..f4e30a7c966 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -872,14 +872,13 @@ export class InsertCell extends SingleSideCell { } _buildOutputContainer() { - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputViewContainer!); + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputViewContainer!); this._outputLeftView.render(); - this.cell.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; + this.cell.outputHeight = this.cell.getOutputTotalHeight(); } _updateOutputContainerHeight(): void { - // throw new Error('Method not implemented.'); - this.cell.outputHeight = (this._outputViewContainer!.childNodes[0] as HTMLElement).clientHeight; + this.cell.outputHeight = this.cell.getOutputTotalHeight(); } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { @@ -1037,17 +1036,17 @@ export class ModifiedCell extends AbstractCellRenderer { this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left')); this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right')); // We should use the original text model here - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.original!, this._outputLeftContainer!); + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, false, this._outputLeftContainer!); this._outputLeftView.render(); - this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputRightContainer!); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputRightContainer!); this._outputRightView.render(); - this.cell.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); + this.cell.outputHeight = this.cell.getOutputTotalHeight(); } _updateOutputContainerHeight(): void { - this.cell.outputHeight = Math.max((this._outputLeftContainer!.childNodes[0] as HTMLElement).clientHeight, (this._outputRightContainer!.childNodes[0] as HTMLElement).clientHeight); + this.cell.outputHeight = this.cell.getOutputTotalHeight(); } updateSourceEditor(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts index 6ba1e204d3a..6bf10590626 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts @@ -6,8 +6,10 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -24,6 +26,9 @@ export class OutputElement extends Disposable { private notebookEditor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, private notebookService: INotebookService, + private cellViewModel: CellDiffViewModelBase, + private modified: boolean, + // private viewCell: CodeCellViewModel, private outputContainer: HTMLElement, readonly output: ICellOutputViewModel @@ -31,7 +36,7 @@ export class OutputElement extends Disposable { super(); } - render(beforeElement?: HTMLElement) { + render(index: number, beforeElement?: HTMLElement) { const outputItemDiv = document.createElement('div'); let result: IRenderOutput | undefined = undefined; @@ -84,41 +89,69 @@ export class OutputElement extends Disposable { if (outputHasDynamicHeight(result)) { // this.viewCell.selfSizeMonitoring = true; - - // const clientHeight = outputItemDiv.clientHeight; + const clientHeight = outputItemDiv.clientHeight; + // TODO, set an inital dimension to avoid force reflow // const dimension = { - // width: this.viewCell.layoutInfo.editorWidth, + // width: this.cellViewModel., // height: clientHeight // }; - // const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { - // if (this.outputContainer && document.body.contains(this.outputContainer)) { - // const height = Math.ceil(elementSizeObserver.getHeight()); - // if (clientHeight === height) { - // return; - // } + const elementSizeObserver = getResizesObserver(outputItemDiv, undefined, () => { + if (this.outputContainer && document.body.contains(this.outputContainer)) { + const height = Math.ceil(elementSizeObserver.getHeight()); - // const currIndex = this.viewCell.outputsViewModels.indexOf(this.output); - // if (currIndex < 0) { - // return; - // } + if (clientHeight === height) { + return; + } - // this.viewCell.updateOutputHeight(currIndex, height); - // this.relayoutCell(); - // } - // }); - // elementSizeObserver.startObserving(); - // this.resizeListener.add(elementSizeObserver); + const currIndex = this.getCellOutputCurrentIndex(); + if (currIndex < 0) { + return; + } + + this.updateHeight(currIndex, height); + } + }); + elementSizeObserver.startObserving(); + this.resizeListener.add(elementSizeObserver); // this.viewCell.updateOutputHeight(index, clientHeight); + this.updateHeight(index, clientHeight); } else if (result.type === RenderOutputType.None) { // no-op if it's a webview - // const clientHeight = Math.ceil(outputItemDiv.clientHeight); - // this.viewCell.updateOutputHeight(index, clientHeight); + const clientHeight = Math.ceil(outputItemDiv.clientHeight); + this.updateHeight(index, clientHeight); - // const top = this.viewCell.getOutputOffsetInContainer(index); - // outputItemDiv.style.top = `${top}px`; + const top = this.getOffset(index); + outputItemDiv.style.top = `${top}px`; } } + getCellOutputCurrentIndex() { + if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.modified) { + return this.cellViewModel.modified.outputs.indexOf(this.output.model); + } else { + return this.cellViewModel.original.outputs.indexOf(this.output.model); + } + } else { + return (this.cellViewModel as SingleSideCellDiffViewModel).cellTextModel!.outputs.indexOf(this.output.model); + } + } + + updateHeight(index: number, height: number) { + if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + this.cellViewModel.updateOutputHeight(!this.modified, index, height); + } else { + (this.cellViewModel as SingleSideCellDiffViewModel).updateOutputHeight(index, height); + } + } + + getOffset(index: number) { + if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + return this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); + } else { + return (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInContainer(index); + } + } } export class OutputContainer extends Disposable { @@ -127,7 +160,9 @@ export class OutputContainer extends Disposable { constructor( private _editor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, + private cellViewModel: CellDiffViewModelBase, cell: NotebookCellTextModel, + private modified: boolean, private outputContainer: HTMLElement, @INotebookService private notebookService: INotebookService, // @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -142,6 +177,21 @@ export class OutputContainer extends Disposable { // viewCell.onDidChangeLayout // say the height of the cell editor changes + + this._register(this.cellViewModel.onDidLayoutChange(() => { + this.outputEntries.forEach((value, key) => { + const index = cell.outputs.indexOf(key.model); + if (index >= 0) { + if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + const top = this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); + value.domNode.style.top = `${top}px`; + } else { + const top = (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInContainer(index); + value.domNode.style.top = `${top}px`; + } + } + }); + })); } render() { @@ -156,10 +206,10 @@ export class OutputContainer extends Disposable { private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this.outputEntries.has(currOutput)) { - this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.outputContainer, currOutput)); + this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.cellViewModel, this.modified, this.outputContainer, currOutput)); } - this.outputEntries.get(currOutput)!.render(beforeElement); - + const renderElement = this.outputEntries.get(currOutput)!; + renderElement.render(index, beforeElement); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index a6df242c3fc..59774828baf 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -29,6 +29,7 @@ export abstract class CellDiffViewModelBase extends Disposable { onDidLayoutChange = this._layoutInfoEmitter.event; protected _layoutInfo!: { + width: number; editorHeight: number; editorMargin: number; metadataStatusHeight: number; @@ -38,9 +39,6 @@ export abstract class CellDiffViewModelBase extends Disposable { bodyMargin: number; }; - protected _outputCollection: number[] = []; - protected _outputsTop: PrefixSumComputer | null = null; - set outputHeight(height: number) { this._layoutInfo.outputHeight = height; this._fireLayoutChangeEvent({ outputEditor: true, outputView: true }); @@ -109,6 +107,7 @@ export abstract class CellDiffViewModelBase extends Disposable { ) { super(); this._layoutInfo = { + width: 0, editorHeight: 0, editorMargin: 0, metadataHeight: 0, @@ -133,7 +132,7 @@ export abstract class CellDiffViewModelBase extends Disposable { abstract checkIfOutputsModified(): boolean; abstract checkMetadataIfModified(): boolean; - + abstract ensureOutputsTop(): void; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -145,10 +144,15 @@ export abstract class CellDiffViewModelBase extends Disposable { } export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { + protected _originalOutputCollection: number[] = []; + protected _originalOutputsTop: PrefixSumComputer | null = null; + protected _modifiedOutputCollection: number[] = []; + protected _modifiedOutputsTop: PrefixSumComputer | null = null; + constructor( readonly documentTextModel: NotebookTextModel, - readonly original: NotebookCellTextModel | undefined, - readonly modified: NotebookCellTextModel | undefined, + readonly original: NotebookCellTextModel, + readonly modified: NotebookCellTextModel, readonly type: 'unchanged' | 'modified', readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { @@ -169,6 +173,9 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { if (this.checkIfOutputsModified()) { this.outputFoldingState = PropertyFoldingState.Expanded; } + + this._originalOutputCollection = new Array(this.original.outputs.length); + this._modifiedOutputCollection = new Array(this.modified.outputs.length); } checkIfOutputsModified() { @@ -178,9 +185,95 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { checkMetadataIfModified(): boolean { return hash(getFormatedMetadataJSON(this.documentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.documentTextModel, this.modified?.metadata ?? {}, this.modified?.language)); } + + updateOutputHeight(original: boolean, index: number, height: number) { + if (original) { + if (index >= this._originalOutputCollection.length) { + throw new Error('Output index out of range!'); + } + + this.ensureOriginalOutputsTop(); + this.ensureModifiedOutputsTop(); + this._originalOutputCollection[index] = height; + + if (this._originalOutputsTop!.changeValue(index, height)) { + this.outputHeight = Math.max(this._originalOutputsTop!.getTotalValue(), this._modifiedOutputsTop!.getTotalValue()); + } + } else { + if (index >= this._modifiedOutputCollection.length) { + throw new Error('Output index out of range!'); + } + + this.ensureOriginalOutputsTop(); + this.ensureModifiedOutputsTop(); + this._modifiedOutputCollection[index] = height; + + if (this._modifiedOutputsTop!.changeValue(index, height)) { + this.outputHeight = Math.max(this._originalOutputsTop!.getTotalValue(), this._modifiedOutputsTop!.getTotalValue()); + } + } + } + + ensureOriginalOutputsTop() { + if (!this._originalOutputsTop) { + const values = new Uint32Array(this._originalOutputCollection.length); + for (let i = 0; i < this._originalOutputCollection.length; i++) { + values[i] = this._originalOutputCollection[i]; + } + + this._originalOutputsTop = new PrefixSumComputer(values); + } + } + + ensureModifiedOutputsTop() { + if (!this._modifiedOutputsTop) { + const values = new Uint32Array(this._modifiedOutputCollection.length); + for (let i = 0; i < this._modifiedOutputCollection.length; i++) { + values[i] = this._modifiedOutputCollection[i]; + } + + this._modifiedOutputsTop = new PrefixSumComputer(values); + } + } + + getOutputOffsetInContainer(original: boolean, index: number) { + this.ensureOutputsTop(); + + if (original) { + if (index >= this._originalOutputCollection.length) { + throw new Error('Output index out of range!'); + } + + return this._originalOutputsTop!.getAccumulatedValue(index - 1); + } else { + if (index >= this._modifiedOutputCollection.length) { + throw new Error('Output index out of range!'); + } + + return this._modifiedOutputsTop!.getAccumulatedValue(index - 1); + } + } + + getOutputTotalHeight() { + this.ensureOutputsTop(); + + return Math.max(this._originalOutputsTop?.getTotalValue() ?? 0, this._modifiedOutputsTop?.getTotalValue() ?? 0); + } + + ensureOutputsTop() { + this.ensureOriginalOutputsTop(); + this.ensureModifiedOutputsTop(); + } } export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { + protected _outputCollection: number[] = []; + protected _outputsTop: PrefixSumComputer | null = null; + + get cellTextModel() { + return this.type === 'insert' ? this.modified : this.original; + } + constructor( readonly documentTextModel: NotebookTextModel, readonly original: NotebookCellTextModel | undefined, @@ -189,6 +282,7 @@ export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { super(documentTextModel, original, modified, type, editorEventDispatcher); + this._outputCollection = new Array(this.original ? this.original.outputs.length : this.modified!.outputs.length); } checkIfOutputsModified(): boolean { @@ -198,6 +292,45 @@ export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { checkMetadataIfModified(): boolean { return false; } + + updateOutputHeight(index: number, height: number) { + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + this.ensureOutputsTop(); + this._outputCollection[index] = height; + if (this._outputsTop!.changeValue(index, height)) { + this.outputHeight = this._outputsTop!.getTotalValue(); + } + } + + ensureOutputsTop() { + if (!this._outputsTop) { + const values = new Uint32Array(this._outputCollection.length); + for (let i = 0; i < this._outputCollection.length; i++) { + values[i] = this._outputCollection[i]; + } + + this._outputsTop = new PrefixSumComputer(values); + } + } + + getOutputOffsetInContainer(index: number) { + this.ensureOutputsTop(); + + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + return this._outputsTop!.getAccumulatedValue(index - 1); + } + + getOutputTotalHeight() { + this.ensureOutputsTop(); + + return this._outputsTop?.getTotalValue() ?? 0; + } } export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, metadata: NotebookCellMetadata, language?: string) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index 95afc16af1f..22266135923 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -125,18 +125,18 @@ } - .monaco-workbench .notebook-text-diff-editor .cell-body .output-view-container { user-select: text; -webkit-user-select: text; -ms-user-select: text; white-space: initial; cursor: auto; + position: relative; } .monaco-workbench .notebook-text-diff-editor .cell-body.left .output-view-container .output-inner-container, .monaco-workbench .notebook-text-diff-editor .cell-body.right .output-view-container .output-inner-container { - width: calc(50% - 16px); + width: 100%; padding: 4px 8px; box-sizing: border-box; } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 74f6cf9385a..497b93760da 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -270,8 +270,8 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod throw new Error('Output index out of range!'); } - this._outputCollection[index] = height; this._ensureOutputsTop(); + this._outputCollection[index] = height; if (this._outputsTop!.changeValue(index, height)) { this.layoutChange({ outputHeight: true }); } From dcda9032e78bdd7f7dfaa194932153a8257b5bff Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 14:18:47 -0800 Subject: [PATCH 0965/1837] output height calculation in view model by reading folding state. --- .../notebook/browser/diff/cellComponents.ts | 2 +- .../browser/diff/celllDiffViewModel.ts | 45 +++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index f4e30a7c966..48f13b6a406 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -310,7 +310,7 @@ abstract class AbstractCellRenderer extends Disposable { } else { this._outputInfoContainer.style.display = 'none'; this._outputEditorDisposeStore.clear(); - this.cell.outputHeight = 0; + this.cell.layoutChange(); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index 59774828baf..d7c30ce18d1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -125,7 +125,6 @@ export abstract class CellDiffViewModelBase extends Disposable { this._layoutInfoEmitter.fire({ outerWidth: true }); })); } - private _fireLayoutChangeEvent(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { this._layoutInfoEmitter.fire(state); } @@ -133,6 +132,7 @@ export abstract class CellDiffViewModelBase extends Disposable { abstract checkIfOutputsModified(): boolean; abstract checkMetadataIfModified(): boolean; abstract ensureOutputsTop(): void; + abstract layoutChange(): void; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -178,6 +178,24 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { this._modifiedOutputCollection = new Array(this.modified.outputs.length); } + layoutChange() { + this.ensureOutputsTop(); + + let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); + this._layoutInfo = { + width: this._layoutInfo.width, + editorHeight: this._layoutInfo.editorHeight, + editorMargin: this._layoutInfo.editorMargin, + metadataHeight: this._layoutInfo.metadataHeight, + metadataStatusHeight: this._layoutInfo.metadataStatusHeight, + outputHeight: outputHeight, + outputStatusHeight: this._layoutInfo.outputStatusHeight, + bodyMargin: this._layoutInfo.bodyMargin + }; + + this._layoutInfoEmitter.fire({}); + } + checkIfOutputsModified() { return !this.documentTextModel.transientOptions.transientOutputs && this.type === 'modified' && hash(this.original?.outputs ?? []) !== hash(this.modified?.outputs ?? []); } @@ -197,7 +215,7 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { this._originalOutputCollection[index] = height; if (this._originalOutputsTop!.changeValue(index, height)) { - this.outputHeight = Math.max(this._originalOutputsTop!.getTotalValue(), this._modifiedOutputsTop!.getTotalValue()); + this.layoutChange(); } } else { if (index >= this._modifiedOutputCollection.length) { @@ -209,7 +227,7 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { this._modifiedOutputCollection[index] = height; if (this._modifiedOutputsTop!.changeValue(index, height)) { - this.outputHeight = Math.max(this._originalOutputsTop!.getTotalValue(), this._modifiedOutputsTop!.getTotalValue()); + this.layoutChange(); } } } @@ -285,6 +303,25 @@ export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { this._outputCollection = new Array(this.original ? this.original.outputs.length : this.modified!.outputs.length); } + layoutChange() { + this.ensureOutputsTop(); + + let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); + this._layoutInfo = { + width: this._layoutInfo.width, + editorHeight: this._layoutInfo.editorHeight, + editorMargin: this._layoutInfo.editorMargin, + metadataHeight: this._layoutInfo.metadataHeight, + metadataStatusHeight: this._layoutInfo.metadataStatusHeight, + outputHeight: outputHeight, + outputStatusHeight: this._layoutInfo.outputStatusHeight, + bodyMargin: this._layoutInfo.bodyMargin + }; + + this._layoutInfoEmitter.fire({}); + } + + checkIfOutputsModified(): boolean { return false; } @@ -301,7 +338,7 @@ export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { this.ensureOutputsTop(); this._outputCollection[index] = height; if (this._outputsTop!.changeValue(index, height)) { - this.outputHeight = this._outputsTop!.getTotalValue(); + this.layoutChange(); } } From 14b7df48c3943f556f9d35c471eadeadb5ad4b26 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 14 Dec 2020 23:50:39 +0100 Subject: [PATCH 0966/1837] do not restore default theme --- .../themes/browser/workbenchThemeService.ts | 4 ++-- .../services/themes/common/colorThemeData.ts | 16 +++++++++++----- .../services/themes/common/themeConfiguration.ts | 5 +++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index a19c6fb877c..1a74be71986 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -139,7 +139,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // In order to avoid paint flashing for tokens, because // themes are loaded asynchronously, we need to initialize // a color theme document with good defaults until the theme is loaded - let themeData: ColorThemeData | undefined = ColorThemeData.fromStorageData(this.storageService); + let themeData: ColorThemeData | undefined = ColorThemeData.fromStorageData(this.storageService, isWeb); // the preferred color scheme (high contrast, light, dark) has changed since the last start const preferredColorScheme = this.getPreferredColorScheme(); @@ -496,7 +496,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // remember theme data for a quick restore if (newTheme.isLoaded) { - newTheme.toStorage(this.storageService); + newTheme.toStorage(this.storageService, this.settings.isDefaultColorTheme(newTheme)); } return this.settings.setColorTheme(this.currentColorTheme, settingsTarget); diff --git a/src/vs/workbench/services/themes/common/colorThemeData.ts b/src/vs/workbench/services/themes/common/colorThemeData.ts index 0cd5d178a91..a6fb53721dc 100644 --- a/src/vs/workbench/services/themes/common/colorThemeData.ts +++ b/src/vs/workbench/services/themes/common/colorThemeData.ts @@ -505,7 +505,7 @@ export class ColorThemeData implements IWorkbenchColorTheme { this.customTokenScopeMatchers = undefined; } - toStorage(storageService: IStorageService) { + toStorage(storageService: IStorageService, isDefaultTheme: boolean) { let colorMapData: { [key: string]: string } = {}; for (let key in this.colorMap) { colorMapData[key] = Color.Format.CSS.formatHexA(this.colorMap[key], true); @@ -515,12 +515,13 @@ export class ColorThemeData implements IWorkbenchColorTheme { id: this.id, label: this.label, settingsId: this.settingsId, - themeTokenColors: this.themeTokenColors.map(tc => ({ settings: tc.settings, scope: tc.scope })), // don't pesist names + themeTokenColors: this.themeTokenColors.map(tc => ({ settings: tc.settings, scope: tc.scope })), // don't persist names semanticTokenRules: this.semanticTokenRules.map(SemanticTokenRule.toJSONObject), extensionData: ExtensionData.toJSONObject(this.extensionData), themeSemanticHighlighting: this.themeSemanticHighlighting, colorMap: colorMapData, - watch: this.watch + watch: this.watch, + isDefaultTheme }); // roam persisted color theme colors. Don't enable for icons as they contain references to fonts and images. @@ -570,12 +571,14 @@ export class ColorThemeData implements IWorkbenchColorTheme { return themeData; } - static fromStorageData(storageService: IStorageService): ColorThemeData | undefined { + static fromStorageData(storageService: IStorageService, doNotRestoreDefaultTheme: boolean): ColorThemeData | undefined { const input = storageService.get(ColorThemeData.STORAGE_KEY, StorageScope.GLOBAL); if (!input) { return undefined; } try { + let isDefaultTheme = false; + let data = JSON.parse(input); let theme = new ColorThemeData('', '', ''); for (let key in data) { @@ -607,9 +610,12 @@ export class ColorThemeData implements IWorkbenchColorTheme { case 'extensionData': theme.extensionData = ExtensionData.fromJSONObject(data.extensionData); break; + case 'isDefaultTheme': + isDefaultTheme = data.isDefaultTheme; + break; } } - if (!theme.id || !theme.settingsId) { + if (!theme.id || !theme.settingsId || doNotRestoreDefaultTheme && isDefaultTheme) { return undefined; } return theme; diff --git a/src/vs/workbench/services/themes/common/themeConfiguration.ts b/src/vs/workbench/services/themes/common/themeConfiguration.ts index 461ce1b6a79..090ec9ac24c 100644 --- a/src/vs/workbench/services/themes/common/themeConfiguration.ts +++ b/src/vs/workbench/services/themes/common/themeConfiguration.ts @@ -308,6 +308,11 @@ export class ThemeConfiguration { return theme; } + public isDefaultColorTheme(theme: IWorkbenchColorTheme): boolean { + let settings = this.configurationService.inspect(ThemeSettings.COLOR_THEME); + return settings && settings.default?.value === theme.settingsId; + } + public findAutoConfigurationTarget(key: string) { let settings = this.configurationService.inspect(key); if (!types.isUndefined(settings.workspaceFolderValue)) { From f656636cc387422959bc1fef8acf95d51a131dfc Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 18:29:30 -0800 Subject: [PATCH 0967/1837] :lipstick: --- .../notebook/browser/diff/cellComponents.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 48f13b6a406..854e2d2ad80 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -294,7 +294,7 @@ abstract class AbstractCellRenderer extends Disposable { this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); this._buildOutputContainer(); } else { - this._updateOutputContainerHeight(); + this.cell.layoutChange(); } } else { this._outputInfoContainer.style.display = 'block'; @@ -315,7 +315,6 @@ abstract class AbstractCellRenderer extends Disposable { } abstract _buildOutputContainer(): void; - abstract _updateOutputContainerHeight(): void; private _applySanitizedMetadataChanges(currentMetadata: NotebookCellMetadata, newMetadata: any) { let result: { [key: string]: any } = {}; @@ -808,10 +807,6 @@ export class DeletedCell extends SingleSideCell { // this._outputView.render(); // this.layout({ outputView: true }); } - - _updateOutputContainerHeight(): void { - // throw new Error('Method not implemented.'); - } } export class InsertCell extends SingleSideCell { @@ -874,11 +869,7 @@ export class InsertCell extends SingleSideCell { _buildOutputContainer() { this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputViewContainer!); this._outputLeftView.render(); - this.cell.outputHeight = this.cell.getOutputTotalHeight(); - } - - _updateOutputContainerHeight(): void { - this.cell.outputHeight = this.cell.getOutputTotalHeight(); + this.cell.layoutChange(); } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { @@ -1041,14 +1032,10 @@ export class ModifiedCell extends AbstractCellRenderer { this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputRightContainer!); this._outputRightView.render(); - this.cell.outputHeight = this.cell.getOutputTotalHeight(); + this.cell.layoutChange(); } - _updateOutputContainerHeight(): void { - this.cell.outputHeight = this.cell.getOutputTotalHeight(); - } - updateSourceEditor(): void { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textBuffer.getLineCount(); From ca4601deba4fbb522b6572619a6d263c8482ad4d Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 18:52:05 -0800 Subject: [PATCH 0968/1837] no unnecessary as any --- .../contrib/notebook/browser/view/renderers/cellOutput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index 6f17a156f95..b0b486cf541 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -127,7 +127,7 @@ export class OutputElement extends Disposable { if (result.type !== RenderOutputType.None) { this.viewCell.selfSizeMonitoring = true; - this.notebookEditor.createInset(this.viewCell, result as any, this.viewCell.getOutputOffset(index)); + this.notebookEditor.createInset(this.viewCell, result, this.viewCell.getOutputOffset(index)); } else { outputItemDiv.classList.add('foreground', 'output-element'); outputItemDiv.style.position = 'absolute'; From cf242ccaa83c564bee910bf1423d33960480ba46 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 18:57:59 -0800 Subject: [PATCH 0969/1837] prep for webview renderers --- .../notebook/browser/diff/cellOutputs.ts | 29 ++++++++++++++----- .../browser/diff/celllDiffViewModel.ts | 24 +++++++++++++++ .../contrib/notebook/browser/diff/common.ts | 4 ++- .../browser/diff/notebookTextDiffEditor.ts | 17 ++++++++++- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts index 6bf10590626..2641b731f03 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts @@ -29,7 +29,7 @@ export class OutputElement extends Disposable { private cellViewModel: CellDiffViewModelBase, private modified: boolean, - // private viewCell: CodeCellViewModel, + private cell: NotebookCellTextModel, private outputContainer: HTMLElement, readonly output: ICellOutputViewModel ) { @@ -81,7 +81,15 @@ export class OutputElement extends Disposable { if (result.type !== RenderOutputType.None) { // this.viewCell.selfSizeMonitoring = true; - // this.notebookEditor.createInset(this.viewCell, result as any, this.viewCell.getOutputOffset(index)); + this.notebookEditor.createInset( + this.cellViewModel, + this.cell, + result, + this.getOutputOffsetInContainer(index), + this.cellViewModel instanceof SideBySideCellDiffViewModel + ? this.modified + : this.cellViewModel.type === 'insert' + ); } else { outputItemDiv.classList.add('foreground', 'output-element'); outputItemDiv.style.position = 'absolute'; @@ -114,13 +122,12 @@ export class OutputElement extends Disposable { }); elementSizeObserver.startObserving(); this.resizeListener.add(elementSizeObserver); - // this.viewCell.updateOutputHeight(index, clientHeight); this.updateHeight(index, clientHeight); } else if (result.type === RenderOutputType.None) { // no-op if it's a webview const clientHeight = Math.ceil(outputItemDiv.clientHeight); this.updateHeight(index, clientHeight); - const top = this.getOffset(index); + const top = this.getOutputOffsetInContainer(index); outputItemDiv.style.top = `${top}px`; } } @@ -145,13 +152,21 @@ export class OutputElement extends Disposable { } } - getOffset(index: number) { + getOutputOffsetInContainer(index: number) { if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { return this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); } else { return (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInContainer(index); } } + + getOutputOffsetInCell(index: number) { + if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + return this.cellViewModel.getOutputOffsetInCell(!this.modified, index); + } else { + return (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInCell(index); + } + } } export class OutputContainer extends Disposable { @@ -161,7 +176,7 @@ export class OutputContainer extends Disposable { private _editor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, private cellViewModel: CellDiffViewModelBase, - cell: NotebookCellTextModel, + private cell: NotebookCellTextModel, private modified: boolean, private outputContainer: HTMLElement, @INotebookService private notebookService: INotebookService, @@ -206,7 +221,7 @@ export class OutputContainer extends Disposable { private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this.outputEntries.has(currOutput)) { - this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.cellViewModel, this.modified, this.outputContainer, currOutput)); + this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.cellViewModel, this.modified, this.cell, this.outputContainer, currOutput)); } const renderElement = this.outputEntries.get(currOutput)!; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts index d7c30ce18d1..09eba7ca261 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts @@ -272,6 +272,18 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { } } + getOutputOffsetInCell(original: boolean, index: number) { + const offsetInOutputsContainer = this.getOutputOffsetInContainer(original, index); + + return this._layoutInfo.editorHeight + + this._layoutInfo.editorMargin + + this._layoutInfo.metadataHeight + + this._layoutInfo.metadataStatusHeight + + this._layoutInfo.outputStatusHeight + + this._layoutInfo.bodyMargin / 2 + + offsetInOutputsContainer; + } + getOutputTotalHeight() { this.ensureOutputsTop(); @@ -363,6 +375,18 @@ export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { return this._outputsTop!.getAccumulatedValue(index - 1); } + getOutputOffsetInCell(index: number) { + const offsetInOutputsContainer = this.getOutputOffsetInContainer(index); + + return this._layoutInfo.editorHeight + + this._layoutInfo.editorMargin + + this._layoutInfo.metadataHeight + + this._layoutInfo.metadataStatusHeight + + this._layoutInfo.outputStatusHeight + + this._layoutInfo.bodyMargin / 2 + + offsetInOutputsContainer; + } + getOutputTotalHeight() { this.ensureOutputsTop(); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 40fe1571f42..8db7afd6bcb 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellDiffViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; @@ -13,6 +13,7 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -21,6 +22,7 @@ export interface INotebookTextDiffEditor { getLayoutInfo(): NotebookLayoutInfo; layoutNotebookCell(cell: CellDiffViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; + createInset(cellDiffViewModel: CellDiffViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; } export interface CellDiffSingleSideRenderTemplate { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index dd1a285d7e3..a040aa520b6 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -24,7 +24,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; -import { INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -38,6 +38,8 @@ import { Schemas } from 'vs/base/common/network'; import { IDiffChange } from 'vs/base/common/diff/diff'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { SequencerByKey } from 'vs/base/common/async'; export const IN_NOTEBOOK_TEXT_DIFF_EDITOR = new RawContextKey('isInNotebookTextDiffEditor', false); @@ -63,6 +65,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } private _revealFirst: boolean; + private readonly _insetModifyQueueByOutputId = new SequencerByKey(); constructor( @IInstantiationService readonly instantiationService: IInstantiationService, @@ -364,6 +367,18 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return new Promise(resolve => { r = resolve; }); } + + createInset(cellDiffViewModel: CellDiffViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { + this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { + }); + } + + // private async _resolveWebview(rightEditor: boolean): Promise { + // if (rightEditor) { + + // } + // } + getDomNode() { return this._rootElement; } From b2c0291c254b4bb279ed4dde73c37e84881f9d7c Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 19:00:08 -0800 Subject: [PATCH 0970/1837] expose notebook text diff editor list row container --- .../contrib/notebook/browser/diff/notebookTextDiffList.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index beacd76156e..da0ad650d44 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -313,6 +313,10 @@ export class CellDiffSideBySideRenderer implements IListRenderer implements IDisposable, IStyleController { private styleElement?: HTMLStyleElement; + get rowsContainer(): HTMLElement { + return this.view.containerDomNode; + } + constructor( listUser: string, container: HTMLElement, From 6361cfab60c4b0d1fea51db80143c7a70f913082 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 14 Dec 2020 19:30:43 -0800 Subject: [PATCH 0971/1837] Add scrolling to getting started page (#112500) * Scrolling via native scroll, ideally this would be Monaco's scroll * Non-working attemot at using domscrollabelelement * Add example usage * Working native scrol implementation * Native scroll with built nodes (rather tahn template) * Wrap with DomScrollableElement (non-working) * Use custom scrolling. * Tweak padding Co-authored-by: Alexandru Dima --- .../gettingStarted/browser/gettingStarted.css | 10 +++++-- .../gettingStarted/browser/gettingStarted.ts | 26 +++++++++++++++---- .../browser/vs_code_editor_getting_started.ts | 6 +++-- .../walkThrough/browser/walkThroughInput.ts | 6 +++++ .../walkThrough/browser/walkThroughPart.ts | 4 +++ 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index bc419a929cb..7eebbcbb7c7 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -20,10 +20,11 @@ height: calc(100% - 50px); display: flex; flex-direction: column; + overflow: hidden; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .gap { - flex: 150px 0 1 + flex: 150px 0 1000 } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories .header { @@ -59,6 +60,11 @@ margin: 32px auto; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories #getting-started-categories-scrolling-container { + overflow: scroll; + height: 100%; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide .getting-started-category { width: 330px; min-height: 80px; @@ -252,7 +258,7 @@ text-align: center; bottom: 0; width: calc(100% - 40px); - margin-bottom: 20px; + margin-bottom: 10px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.next { diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index e17a22d02b0..ef84c8a3b0d 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -14,7 +14,7 @@ import { IEditorInputFactory } from 'vs/workbench/common/editor'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { assertIsDefined } from 'vs/base/common/types'; -import { $, addDisposableListener } from 'vs/base/browser/dom'; +import { $, addDisposableListener, Dimension } from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IProductService } from 'vs/platform/product/common/productService'; import { IGettingStartedCategoryWithProgress, IGettingStartedService } from 'vs/workbench/services/gettingStarted/common/gettingStartedService'; @@ -24,6 +24,7 @@ import { activeContrastBorder, buttonBackground, buttonForeground, buttonHoverBa import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; export const gettingStartedInputTypeId = 'workbench.editors.gettingStartedInput'; const telemetryFrom = 'gettingStartedPage'; @@ -44,6 +45,8 @@ export class GettingStartedPage extends Disposable { private gettingStartedCategories: IGettingStartedCategoryWithProgress[]; private currentCategory: IGettingStartedCategoryWithProgress | undefined; + private scrollbar: DomScrollableElement | undefined; + constructor( initialState: { selectedCategory?: string, selectedTask?: string }, @IEditorService private readonly editorService: IEditorService, @@ -68,7 +71,8 @@ export class GettingStartedPage extends Disposable { name: localize('editorGettingStarted.title', "Getting Started"), resource, telemetryFrom, - onReady: (container: HTMLElement) => this.onReady(container) + onReady: (container: HTMLElement) => this.onReady(container), + layout: () => this.layout(), }); this.editorInput.selectedCategory = initialState.selectedCategory; @@ -205,21 +209,29 @@ export class GettingStartedPage extends Disposable { $('.codicon.codicon-' + category.codicon, {}), categoryDescriptionElement); }); + const categoriesSlide = assertIsDefined(document.getElementById('gettingStartedSlideCategory')); + const tasksSlide = assertIsDefined(document.getElementById('gettingStartedSlideDetails')); + const rightColumn = assertIsDefined(container.querySelector('#getting-started-detail-right')); rightColumn.appendChild($('img#getting-started-media')); - const categoriesContainer = assertIsDefined(document.getElementById('getting-started-categories-container')); + const categoryScrollContainer = $('#getting-started-categories-scrolling-container'); + const categoriesContainer = $('#getting-started-categories-container'); categoryElements.forEach(element => { categoriesContainer.appendChild(element); }); + categoryScrollContainer.appendChild(categoriesContainer); + this.scrollbar = this._register(new DomScrollableElement(categoryScrollContainer, {})); + categoriesSlide.appendChild(this.scrollbar.getDomNode()); + categoriesSlide.appendChild($('.gap')); + this.scrollbar.scanDomNode(); + this.updateCategoryProgress(); assertIsDefined(document.getElementById('product-name')).textContent = this.productService.nameLong; this.registerDispatchListeners(container); - const categoriesSlide = assertIsDefined(document.getElementById('gettingStartedSlideCategory')); - const tasksSlide = assertIsDefined(document.getElementById('gettingStartedSlideDetails')); if (this.editorInput.selectedCategory) { this.currentCategory = this.gettingStartedCategories.find(category => category.id === this.editorInput.selectedCategory); @@ -233,6 +245,10 @@ export class GettingStartedPage extends Disposable { } } + private layout() { + this.scrollbar?.scanDomNode(); + } + private updateCategoryProgress() { document.querySelectorAll('.category-progress').forEach(element => { const categoryID = element.getAttribute('x-data-category-id'); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index dc50482806e..6bb3e6fd883 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -15,8 +15,6 @@ export default () => `

${escape(localize('gettingStarted.vscode', "Visual Studio Code"))}

${escape(localize({ key: 'gettingStarted.editingRedefined', comment: ['Shown as subtitle on the Welcome page.'] }, "Code editing. Redefined"))}

-
-
`.replace(/\|/g, '`'); + + +//
+//
diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts index a491c1577f2..288b01233e5 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts @@ -11,6 +11,7 @@ import * as marked from 'vs/base/common/marked/marked'; import { Schemas } from 'vs/base/common/network'; import { isEqual } from 'vs/base/common/resources'; import { requireToContent } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughContentProvider'; +import { Dimension } from 'vs/base/browser/dom'; export class WalkThroughModel extends EditorModel { @@ -42,6 +43,7 @@ export interface WalkThroughInputOptions { readonly resource: URI; readonly telemetryFrom: string; readonly onReady?: (container: HTMLElement) => void; + readonly layout?: (dimension: Dimension) => void; } export class WalkThroughInput extends EditorInput { @@ -91,6 +93,10 @@ export class WalkThroughInput extends EditorInput { return this.options.onReady; } + get layout() { + return this.options.layout; + } + resolve(): Promise { if (!this.promise) { this.promise = requireToContent(this.options.resource) diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts index 2d7de16e85d..a3474fb4fe6 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts @@ -210,6 +210,10 @@ export class WalkThroughPart extends EditorPane { disposable.layout(); } }); + const walkthroughInput = this.input instanceof WalkThroughInput && this.input; + if (walkthroughInput && walkthroughInput.layout) { + walkthroughInput.layout(dimension); + } this.scrollbar.scanDomNode(); } From a9c5d7cc3c652f3a32d4643a3a0f691f5b52d304 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 14 Dec 2020 20:07:44 -0800 Subject: [PATCH 0972/1837] chore: fix CXX export --- build/.cachesalt | 2 +- build/azure-pipelines/linux/product-build-linux.yml | 2 +- build/azure-pipelines/product-compile.yml | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/build/.cachesalt b/build/.cachesalt index 661e359818e..909042d161e 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-12-05T15:02:48.675Z +2020-12-15T04:06:58.201Z diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index ef65d5fabac..797d4db8884 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -78,7 +78,7 @@ steps: - script: | set -e - if [ -z "$CC" || -z "$CXX" ] + if [ -z "$CC" ] || [ -z "$CXX" ] then export CC=$(which gcc-5) export CXX=$(which g++-5) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index fb67aecafb4..8dc27649502 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -72,6 +72,11 @@ steps: - script: | set -e + if [ -z "$CC" ] || [ -z "$CXX" ] + then + export CC=$(which gcc-5) + export CXX=$(which g++-5) + fi export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break From cbf9234d4fde1a73ff8479477bf08f69dc0924bc Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 20:23:29 -0800 Subject: [PATCH 0973/1837] hook modified webview --- .../browser/diff/backLayerWebview2.ts | 890 ++++++++++++++++++ .../browser/diff/notebookTextDiffEditor.ts | 52 +- .../browser/diff/notebookTextDiffList.ts | 10 + 3 files changed, 950 insertions(+), 2 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts new file mode 100644 index 00000000000..0af765801a5 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -0,0 +1,890 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as DOM from 'vs/base/browser/dom'; +import { Emitter, Event } from 'vs/base/common/event'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { isWeb } from 'vs/base/common/platform'; +import { URI } from 'vs/base/common/uri'; +import * as UUID from 'vs/base/common/uuid'; +import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; +import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; +import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; +import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; +import { dirname, joinPath } from 'vs/base/common/resources'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; +import { FileAccess, Schemas } from 'vs/base/common/network'; +import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IFileService } from 'vs/platform/files/common/files'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { getExtensionForMimeType } from 'vs/base/common/mime'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; + +export interface WebviewIntialized { + __vscode_notebook_message: boolean; + type: 'initialized' +} + +export interface IDimensionMessage { + __vscode_notebook_message: boolean; + type: 'dimension'; + id: string; + data: DOM.Dimension; +} + +export interface IMouseEnterMessage { + __vscode_notebook_message: boolean; + type: 'mouseenter'; + id: string; +} + +export interface IMouseLeaveMessage { + __vscode_notebook_message: boolean; + type: 'mouseleave'; + id: string; +} + +export interface IWheelMessage { + __vscode_notebook_message: boolean; + type: 'did-scroll-wheel'; + payload: any; +} + + +export interface IScrollAckMessage { + __vscode_notebook_message: boolean; + type: 'scroll-ack'; + data: { top: number }; + version: number; +} + +export interface IBlurOutputMessage { + __vscode_notebook_message: boolean; + type: 'focus-editor'; + id: string; + focusNext?: boolean; +} + +export interface IClickedDataUrlMessage { + __vscode_notebook_message: boolean; + type: 'clicked-data-url'; + data: string; + downloadName?: string; +} + +export interface IClearMessage { + type: 'clear'; +} + +export interface ICreationRequestMessage { + type: 'html'; + content: + | { type: RenderOutputType.Html; htmlContent: string } + | { type: RenderOutputType.Extension; output: IDisplayOutput; mimeType: string }; + cellId: string; + outputId: string; + top: number; + left: number; + requiredPreloads: ReadonlyArray; + initiallyHidden?: boolean; + apiNamespace?: string | undefined; +} + +export interface IContentWidgetTopRequest { + id: string; + top: number; + left: number; +} + +export interface IViewScrollTopRequestMessage { + type: 'view-scroll'; + top?: number; + forceDisplay: boolean; + widgets: IContentWidgetTopRequest[]; + version: number; +} + +export interface IScrollRequestMessage { + type: 'scroll'; + id: string; + top: number; + widgetTop?: number; + version: number; +} + +export interface IClearOutputRequestMessage { + type: 'clearOutput'; + cellId: string; + outputId: string; + cellUri: string; + apiNamespace: string | undefined; +} + +export interface IHideOutputMessage { + type: 'hideOutput'; + outputId: string; + cellId: string; +} + +export interface IShowOutputMessage { + type: 'showOutput'; + cellId: string; + outputId: string; + top: number; +} + +export interface IFocusOutputMessage { + type: 'focus-output'; + cellId: string; +} + +export interface IPreloadResource { + originalUri: string; + uri: string; +} + +export interface IUpdatePreloadResourceMessage { + type: 'preload'; + resources: IPreloadResource[]; + source: 'renderer' | 'kernel'; +} + +export interface IUpdateDecorationsMessage { + type: 'decorations'; + cellId: string; + addedClassNames: string[]; + removedClassNames: string[]; +} + +export interface ICustomRendererMessage { + __vscode_notebook_message: boolean; + type: 'customRendererMessage'; + rendererId: string; + message: unknown; +} + +export type FromWebviewMessage = + | WebviewIntialized + | IDimensionMessage + | IMouseEnterMessage + | IMouseLeaveMessage + | IWheelMessage + | IScrollAckMessage + | IBlurOutputMessage + | ICustomRendererMessage + | IClickedDataUrlMessage; + +export type ToWebviewMessage = + | IClearMessage + | IFocusOutputMessage + | ICreationRequestMessage + | IViewScrollTopRequestMessage + | IScrollRequestMessage + | IClearOutputRequestMessage + | IHideOutputMessage + | IShowOutputMessage + | IUpdatePreloadResourceMessage + | IUpdateDecorationsMessage + | ICustomRendererMessage; + +export type AnyMessage = FromWebviewMessage | ToWebviewMessage; + +interface ICachedInset { + outputId: string; + cell: CodeCellViewModel; + renderer?: INotebookRendererInfo; + cachedCreation: ICreationRequestMessage; +} + +function html(strings: TemplateStringsArray, ...values: any[]): string { + let str = ''; + strings.forEach((string, i) => { + str += string + (values[i] || ''); + }); + return str; +} + +export interface INotebookWebviewMessage { + message: unknown; + forRenderer?: string; +} + +let version = 0; +export class BackLayerWebView extends Disposable { + element: HTMLElement; + webview: WebviewElement | undefined = undefined; + insetMapping: Map = new Map(); + hiddenInsetMapping: Set = new Set(); + reversedInsetMapping: Map = new Map(); + localResourceRootsCache: URI[] | undefined = undefined; + rendererRootsCache: URI[] = []; + kernelRootsCache: URI[] = []; + private readonly _onMessage = this._register(new Emitter()); + private readonly _preloadsCache = new Set(); + public readonly onMessage: Event = this._onMessage.event; + private _loaded!: Promise; + private _initalized?: Promise; + private _disposed = false; + + constructor( + public notebookEditor: INotebookTextDiffEditor, + public id: string, + public documentUri: URI, + @IWebviewService readonly webviewService: IWebviewService, + @IOpenerService readonly openerService: IOpenerService, + @INotebookService private readonly notebookService: INotebookService, + @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, + @IFileDialogService private readonly fileDialogService: IFileDialogService, + @IFileService private readonly fileService: IFileService, + ) { + super(); + + this.element = document.createElement('div'); + + this.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; + this.element.style.height = '1400px'; + this.element.style.position = 'absolute'; + // this.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; + } + generateContent(outputNodePadding: number, coreDependencies: string, baseUrl: string) { + return html` + + + + + + + + + ${coreDependencies} +
+ + + `; + } + + postRendererMessage(rendererId: string, message: any) { + this._sendMessageToWebview({ + __vscode_notebook_message: true, + type: 'customRendererMessage', + message, + rendererId + }); + } + + private resolveOutputId(id: string): { cell: CodeCellViewModel, output: IDisplayOutputViewModel } | undefined { + const output = this.reversedInsetMapping.get(id); + if (!output) { + return; + } + + const cell = this.insetMapping.get(output)!.cell; + + // const currCell = this.notebookEditor.viewModel?.viewCells.find(vc => vc.handle === cell.handle); + // if (currCell !== cell && currCell !== undefined) { + // this.insetMapping.get(output)!.cell = currCell as CodeCellViewModel; + // } + + return { cell: this.insetMapping.get(output)!.cell, output }; + } + + async createWebview(): Promise { + let coreDependencies = ''; + let resolveFunc: () => void; + + this._initalized = new Promise((resolve, reject) => { + resolveFunc = resolve; + }); + + const baseUrl = asWebviewUri(this.environmentService, this.id, dirname(this.documentUri)); + + if (!isWeb) { + const loaderUri = FileAccess.asFileUri('vs/loader.js', require); + const loader = asWebviewUri(this.environmentService, this.id, loaderUri); + + coreDependencies = ``; + const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); + this._initialize(htmlContent); + resolveFunc!(); + } else { + const loaderUri = FileAccess.asBrowserUri('vs/loader.js', require); + + fetch(loaderUri.toString(true)).then(async response => { + if (response.status !== 200) { + throw new Error(response.statusText); + } + + const loaderJs = await response.text(); + + coreDependencies = ` + + +`; + + const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); + this._initialize(htmlContent); + resolveFunc!(); + }); + } + + await this._initalized; + } + + private async _initialize(content: string) { + if (!document.body.contains(this.element)) { + throw new Error('Element is already detached from the DOM tree'); + } + + this.webview = this._createInset(this.webviewService, content); + this.webview.mountTo(this.element); + this._register(this.webview); + + this._register(this.webview.onDidClickLink(link => { + if (this._disposed) { + return; + } + + if (!link) { + return; + } + + if (matchesScheme(link, Schemas.http) || matchesScheme(link, Schemas.https) || matchesScheme(link, Schemas.mailto) + || matchesScheme(link, Schemas.command)) { + this.openerService.open(link, { fromUserGesture: true }); + } + })); + + this._register(this.webview.onDidReload(() => { + if (this._disposed) { + return; + } + + let renderers = new Set(); + for (const inset of this.insetMapping.values()) { + if (inset.renderer) { + renderers.add(inset.renderer); + } + } + + this._preloadsCache.clear(); + this.updateRendererPreloads(renderers); + + for (const [output, inset] of this.insetMapping.entries()) { + this._sendMessageToWebview({ ...inset.cachedCreation, initiallyHidden: this.hiddenInsetMapping.has(output) }); + } + })); + + this._register(this.webview.onMessage((data: FromWebviewMessage) => { + if (this._disposed) { + return; + } + + // if (data.__vscode_notebook_message) { + // if (data.type === 'dimension') { + // const height = data.data.height; + // const outputHeight = height; + + // const info = this.resolveOutputId(data.id); + // if (info) { + // const { cell, output } = info; + // const outputIndex = cell.outputsViewModels.indexOf(output); + // cell.updateOutputHeight(outputIndex, outputHeight); + // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); + // } + // } else if (data.type === 'mouseenter') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // const { cell } = info; + // cell.outputIsHovered = true; + // } + // } else if (data.type === 'mouseleave') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // const { cell } = info; + // cell.outputIsHovered = false; + // } + // } else if (data.type === '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()); + // } else if (data.type === 'did-scroll-wheel') { + // this.notebookEditor.triggerScroll({ + // ...data.payload, + // preventDefault: () => { }, + // stopPropagation: () => { } + // }); + // } else if (data.type === 'focus-editor') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // if (data.focusNext) { + // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); + // if (typeof idx !== 'number') { + // return; + // } + + // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; + // if (!newCell) { + // return; + // } + + // this.notebookEditor.focusNotebookCell(newCell, 'editor'); + // } else { + // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); + // } + // } + // } else if (data.type === 'clicked-data-url') { + // this._onDidClickDataLink(data); + // } else if (data.type === 'customRendererMessage') { + // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); + // } + // return; + // } + + this._onMessage.fire({ message: data }); + })); + } + + private async _onDidClickDataLink(event: IClickedDataUrlMessage): Promise { + const [splitStart, splitData] = event.data.split(';base64,'); + if (!splitData || !splitStart) { + return; + } + + const defaultDir = dirname(this.documentUri); + let defaultName: string; + if (event.downloadName) { + defaultName = event.downloadName; + } else { + const mimeType = splitStart.replace(/^data:/, ''); + const candidateExtension = mimeType && getExtensionForMimeType(mimeType); + defaultName = candidateExtension ? `download${candidateExtension}` : 'download'; + } + + const defaultUri = joinPath(defaultDir, defaultName); + const newFileUri = await this.fileDialogService.showSaveDialog({ + defaultUri + }); + if (!newFileUri) { + return; + } + + const decoded = atob(splitData); + const typedArray = new Uint8Array(decoded.length); + for (let i = 0; i < decoded.length; i++) { + typedArray[i] = decoded.charCodeAt(i); + } + + const buff = VSBuffer.wrap(typedArray); + await this.fileService.writeFile(newFileUri, buff); + await this.openerService.open(newFileUri); + } + + private _createInset(webviewService: IWebviewService, content: string) { + const rootPath = isWeb ? FileAccess.asBrowserUri('', require) : FileAccess.asFileUri('', require); + + const workspaceFolders = this.contextService.getWorkspace().folders.map(x => x.uri); + + this.localResourceRootsCache = [...this.notebookService.getNotebookProviderResourceRoots(), ...workspaceFolders, rootPath]; + + const webview = webviewService.createWebviewElement(this.id, { + purpose: WebviewContentPurpose.NotebookRenderer, + enableFindWidget: false, + }, { + allowMultipleAPIAcquire: true, + allowScripts: true, + localResourceRoots: this.localResourceRootsCache + }, undefined); + + let resolveFunc: () => void; + this._loaded = new Promise((resolve, reject) => { + resolveFunc = resolve; + }); + + const dispose = webview.onMessage((data: FromWebviewMessage) => { + if (data.__vscode_notebook_message && data.type === 'initialized') { + resolveFunc(); + dispose.dispose(); + } + }); + + webview.html = content; + return webview; + } + + shouldUpdateInset(cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { + if (this._disposed) { + return; + } + + if (cell.metadata?.outputCollapsed) { + return false; + } + + const outputCache = this.insetMapping.get(output)!; + const outputIndex = cell.outputsViewModels.indexOf(output); + const outputOffset = cellTop + cell.getOutputOffset(outputIndex); + + if (this.hiddenInsetMapping.has(output)) { + return true; + } + + if (outputOffset === outputCache.cachedCreation.top) { + return false; + } + + return true; + } + + updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { + if (this._disposed) { + return; + } + + const widgets: IContentWidgetTopRequest[] = items.map(item => { + const outputCache = this.insetMapping.get(item.output)!; + const id = outputCache.outputId; + const outputIndex = item.cell.outputsViewModels.indexOf(item.output); + + const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); + outputCache.cachedCreation.top = outputOffset; + this.hiddenInsetMapping.delete(item.output); + + return { + id: id, + top: outputOffset, + left: 0 + }; + }); + + this._sendMessageToWebview({ + top, + type: 'view-scroll', + version: version++, + forceDisplay, + widgets: widgets + }); + } + + async createInset(cell: NotebookCellTextModel, content: IInsetRenderOutput, cellTop: number, offset: number) { + if (this._disposed) { + return; + } + + const initialTop = cellTop + offset; + + if (this.insetMapping.has(content.source)) { + const outputCache = this.insetMapping.get(content.source); + + if (outputCache) { + this.hiddenInsetMapping.delete(content.source); + this._sendMessageToWebview({ + type: 'showOutput', + cellId: outputCache.cell.id, + outputId: outputCache.outputId, + top: initialTop + }); + return; + } + } + + const messageBase = { + type: 'html', + cellId: cell.id, + top: initialTop, + left: 0, + requiredPreloads: [], + } as const; + + let message: ICreationRequestMessage; + let renderer: INotebookRendererInfo | undefined; + if (content.type === RenderOutputType.Extension) { + const output = content.source.model; + renderer = content.renderer; + message = { + ...messageBase, + outputId: output.outputId, + apiNamespace: content.renderer.id, + requiredPreloads: await this.updateRendererPreloads([content.renderer]), + content: { + type: RenderOutputType.Extension, + mimeType: content.mimeType, + output: { + outputKind: CellOutputKind.Rich, + metadata: output.metadata, + data: output.data, + }, + }, + }; + } else { + message = { + ...messageBase, + outputId: UUID.generateUuid(), + content: { + type: content.type, + htmlContent: content.htmlContent, + } + }; + } + + this._sendMessageToWebview(message); + this.insetMapping.set(content.source, { outputId: message.outputId, cell, renderer, cachedCreation: message }); + this.hiddenInsetMapping.delete(content.source); + this.reversedInsetMapping.set(message.outputId, content.source); + } + + removeInset(output: IDisplayOutputViewModel) { + if (this._disposed) { + return; + } + + const outputCache = this.insetMapping.get(output); + if (!outputCache) { + return; + } + + const id = outputCache.outputId; + + this._sendMessageToWebview({ + type: 'clearOutput', + apiNamespace: outputCache.cachedCreation.apiNamespace, + cellUri: outputCache.cell.uri.toString(), + outputId: id, + cellId: outputCache.cell.id + }); + this.insetMapping.delete(output); + this.reversedInsetMapping.delete(id); + } + + hideInset(output: IDisplayOutputViewModel) { + if (this._disposed) { + return; + } + + const outputCache = this.insetMapping.get(output); + if (!outputCache) { + return; + } + + this.hiddenInsetMapping.add(output); + + this._sendMessageToWebview({ + type: 'hideOutput', + outputId: outputCache.outputId, + cellId: outputCache.cell.id, + }); + } + + clearInsets() { + if (this._disposed) { + return; + } + + this._sendMessageToWebview({ + type: 'clear' + }); + + this.insetMapping = new Map(); + this.reversedInsetMapping = new Map(); + } + + focusWebview() { + if (this._disposed) { + return; + } + + this.webview?.focus(); + } + + focusOutput(cellId: string) { + if (this._disposed) { + return; + } + + this.webview?.focus(); + setTimeout(() => { // Need this, or focus decoration is not shown. No clue. + this._sendMessageToWebview({ + type: 'focus-output', + cellId, + }); + }, 50); + } + + deltaCellOutputContainerClassNames(cellId: string, added: string[], removed: string[]) { + this._sendMessageToWebview({ + type: 'decorations', + cellId, + addedClassNames: added, + removedClassNames: removed + }); + + } + + async updateKernelPreloads(extensionLocations: URI[], preloads: URI[]) { + if (this._disposed) { + return; + } + + await this._loaded; + + const resources: IPreloadResource[] = []; + for (const preload of preloads) { + const uri = this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https') + ? preload : asWebviewUri(this.environmentService, this.id, preload); + + if (!this._preloadsCache.has(uri.toString())) { + resources.push({ uri: uri.toString(), originalUri: preload.toString() }); + this._preloadsCache.add(uri.toString()); + } + } + + if (!resources.length) { + return; + } + + this.kernelRootsCache = [...extensionLocations, ...this.kernelRootsCache]; + this._updatePreloads(resources, 'kernel'); + } + + async updateRendererPreloads(renderers: Iterable) { + if (this._disposed) { + return []; + } + + await this._loaded; + + const requiredPreloads: IPreloadResource[] = []; + const resources: IPreloadResource[] = []; + const extensionLocations: URI[] = []; + for (const rendererInfo of renderers) { + extensionLocations.push(rendererInfo.extensionLocation); + for (const preload of [rendererInfo.entrypoint, ...rendererInfo.preloads]) { + const uri = asWebviewUri(this.environmentService, this.id, preload); + const resource: IPreloadResource = { uri: uri.toString(), originalUri: preload.toString() }; + requiredPreloads.push(resource); + + if (!this._preloadsCache.has(uri.toString())) { + resources.push(resource); + this._preloadsCache.add(uri.toString()); + } + } + } + + if (!resources.length) { + return requiredPreloads; + } + + this.rendererRootsCache = extensionLocations; + this._updatePreloads(resources, 'renderer'); + return requiredPreloads; + } + + private _updatePreloads(resources: IPreloadResource[], source: 'renderer' | 'kernel') { + if (!this.webview) { + return; + } + + const mixedResourceRoots = [...(this.localResourceRootsCache || []), ...this.rendererRootsCache, ...this.kernelRootsCache]; + + this.webview.localResourcesRoot = mixedResourceRoots; + + this._sendMessageToWebview({ + type: 'preload', + resources: resources, + source: source + }); + } + + private _sendMessageToWebview(message: ToWebviewMessage) { + if (this._disposed) { + return; + } + + this.webview?.postMessage(message); + } + + clearPreloadsCache() { + this._preloadsCache.clear(); + } + + dispose() { + this._disposed = true; + this.webview?.dispose(); + super.dispose(); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index a040aa520b6..e06081697ec 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -13,7 +13,6 @@ import { notebookCellBorder, NotebookEditorWidget } from 'vs/workbench/contrib/n import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { NotebookDiffEditorInput } from '../notebookDiffEditorInput'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffSideBySideRenderer, CellDiffSingleSideRenderer, NotebookCellTextDiffListDelegate, NotebookTextDiffList } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList'; @@ -40,6 +39,11 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { SequencerByKey } from 'vs/base/common/async'; +import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/backLayerWebview2'; +import { generateUuid } from 'vs/base/common/uuid'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; + +const $ = DOM.$; export const IN_NOTEBOOK_TEXT_DIFF_EDITOR = new RawContextKey('isInNotebookTextDiffEditor', false); @@ -49,7 +53,9 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _rootElement!: HTMLElement; private _overflowContainer!: HTMLElement; private _dimension: DOM.Dimension | null = null; - private _list!: WorkbenchList; + private _list!: NotebookTextDiffList; + private _modifiedWebview: BackLayerWebView | null = null; + private _webviewTransparentCover: HTMLElement | null = null; private _fontInfo: BareFontInfo | undefined; private readonly _onMouseUp = this._register(new Emitter<{ readonly event: MouseEvent; readonly target: CellDiffViewModelBase; }>()); @@ -148,11 +154,30 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } ); + this._register(this._list); + this._register(this._list.onMouseUp(e => { if (e.element) { this._onMouseUp.fire({ event: e.browserEvent, target: e.element }); } })); + + // transparent cover + this._webviewTransparentCover = DOM.append(this._list.rowsContainer, $('.webview-cover')); + this._webviewTransparentCover.style.display = 'none'; + + this._register(DOM.addStandardDisposableGenericMouseDownListner(this._overflowContainer, (e: StandardMouseEvent) => { + if (e.target.classList.contains('slider') && this._webviewTransparentCover) { + this._webviewTransparentCover.style.display = 'block'; + } + })); + + this._register(DOM.addStandardDisposableGenericMouseUpListner(this._overflowContainer, () => { + if (this._webviewTransparentCover) { + // no matter when + this._webviewTransparentCover.style.display = 'none'; + } + })); } async setInput(input: NotebookDiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { @@ -204,11 +229,20 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } })); + await this._createModifiedWebview(generateUuid(), this._model.modified.resource); this._eventDispatcher = new NotebookDiffEditorEventDispatcher(); await this.updateLayout(); } + private async _createModifiedWebview(id: string, resource: URI): Promise { + this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource); + // attach the webview container to the DOM tree first + this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); + await this._modifiedWebview.createWebview(); + this._modifiedWebview.element.style.left = `calc(50%)`; + } + private async _resolveStats(resource: URI) { if (resource.scheme === Schemas.untitled) { return undefined; @@ -370,6 +404,13 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD createInset(cellDiffViewModel: CellDiffViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { + if (rightEditor) { + if (!this._modifiedWebview!.insetMapping.has(output.source)) { + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + await this._modifiedWebview?.createInset(cellTextModel, output, cellTop, offset); + + } + } }); } @@ -429,6 +470,13 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._rootElement.style.height = `${dimension.height}px`; this._list?.layout(this._dimension.height, this._dimension.width); + + + if (this._modifiedWebview) { + this._modifiedWebview.element.style.width = `${this._dimension.width / 2}px`; + this._modifiedWebview.element.style.left = `calc(50%)`; + } + this._eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index da0ad650d44..cd4ac5ef433 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -331,6 +331,16 @@ export class NotebookTextDiffList extends WorkbenchList i super(listUser, container, delegate, renderers, options, contextKeyService, listService, themeService, configurationService, keybindingService); } + getAbsoluteTopOfElement(element: CellDiffViewModelBase): number { + const index = this.indexOf(element); + // if (index === undefined || index < 0 || index >= this.length) { + // this._getViewIndexUpperBound(element); + // throw new ListError(this.listUser, `Invalid index ${index}`); + // } + + return this.view.elementTop(index); + } + style(styles: IListStyles) { const selectorSuffix = this.view.domId; if (!this.styleElement) { From 9ca7b4ed4df3d0c2110b4a27e3db95c22baaf73e Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 20:27:13 -0800 Subject: [PATCH 0974/1837] DiffElement --- .../contrib/notebook/browser/diff/common.ts | 8 ++-- .../{cellComponents.ts => diffComponents.ts} | 36 ++++++++-------- .../{cellOutputs.ts => diffElementOutputs.ts} | 28 ++++++------- ...ffViewModel.ts => diffElementViewModel.ts} | 6 +-- .../browser/diff/notebookDiffActions.ts | 8 ++-- .../browser/diff/notebookTextDiffEditor.ts | 36 ++++++++-------- .../browser/diff/notebookTextDiffList.ts | 42 +++++++++---------- 7 files changed, 81 insertions(+), 83 deletions(-) rename src/vs/workbench/contrib/notebook/browser/diff/{cellComponents.ts => diffComponents.ts} (97%) rename src/vs/workbench/contrib/notebook/browser/diff/{cellOutputs.ts => diffElementOutputs.ts} (86%) rename src/vs/workbench/contrib/notebook/browser/diff/{celllDiffViewModel.ts => diffElementViewModel.ts} (98%) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 8db7afd6bcb..46abd5d8d2f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CellDiffViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -17,12 +17,12 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; - onMouseUp: Event<{ readonly event: MouseEvent; readonly target: CellDiffViewModelBase; }>; + onMouseUp: Event<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>; getOverflowContainerDomNode(): HTMLElement; getLayoutInfo(): NotebookLayoutInfo; - layoutNotebookCell(cell: CellDiffViewModelBase, height: number): void; + layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; - createInset(cellDiffViewModel: CellDiffViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; + createInset(cellDiffViewModel: DiffElementViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; } export interface CellDiffSingleSideRenderTemplate { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts similarity index 97% rename from src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts rename to src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 854e2d2ad80..2bf42f22011 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellDiffViewModelBase, getFormatedMetadataJSON, PropertyFoldingState, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase, getFormatedMetadataJSON, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; @@ -31,7 +31,7 @@ import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/noteb import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { renderCodicons } from 'vs/base/browser/codicons'; -import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/cellOutputs'; +import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/diffElementOutputs'; const RENDER_RICH_OUTPUT = true; @@ -74,8 +74,6 @@ const fixedDiffEditorOptions: IDiffEditorOptions = { isInEmbeddedEditor: true, }; - - class PropertyHeader extends Disposable { protected _foldingIndicator!: HTMLElement; protected _statusSpan!: HTMLElement; @@ -83,14 +81,14 @@ class PropertyHeader extends Disposable { protected _menu!: IMenu; constructor( - readonly cell: CellDiffViewModelBase, + readonly cell: DiffElementViewModelBase, readonly propertyHeaderContainer: HTMLElement, readonly notebookEditor: INotebookTextDiffEditor, readonly accessor: { updateInfoRendering: () => void; - checkIfModified: (cell: CellDiffViewModelBase) => boolean; - getFoldingState: (cell: CellDiffViewModelBase) => PropertyFoldingState; - updateFoldingState: (cell: CellDiffViewModelBase, newState: PropertyFoldingState) => void; + checkIfModified: (cell: DiffElementViewModelBase) => boolean; + getFoldingState: (cell: DiffElementViewModelBase) => PropertyFoldingState; + updateFoldingState: (cell: DiffElementViewModelBase, newState: PropertyFoldingState) => void; unChangedLabel: string; changedLabel: string; prefix: string; @@ -212,7 +210,7 @@ class PropertyHeader extends Disposable { } } -abstract class AbstractCellRenderer extends Disposable { +abstract class AbstractElementRenderer extends Disposable { protected _metadataHeaderContainer!: HTMLElement; protected _metadataHeader!: PropertyHeader; protected _metadataInfoContainer!: HTMLElement; @@ -239,7 +237,7 @@ abstract class AbstractCellRenderer extends Disposable { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: CellDiffViewModelBase, + readonly cell: DiffElementViewModelBase, readonly templateData: CellDiffSingleSideRenderTemplate | CellDiffSideBySideRenderTemplate, readonly style: 'left' | 'right' | 'full', protected readonly instantiationService: IInstantiationService, @@ -398,7 +396,7 @@ abstract class AbstractCellRenderer extends Disposable { } private _buildMetadataEditor() { - if (this.cell instanceof SideBySideCellDiffViewModel) { + if (this.cell instanceof SideBySideDiffElementViewModel) { const originalMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.original?.metadata || {}, this.cell.original?.language); const modifiedMetadataSource = getFormatedMetadataJSON(this.notebookEditor.textModel!, this.cell.modified?.metadata || {}, this.cell.modified?.language); this._metadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._metadataEditorContainer!, { @@ -596,10 +594,10 @@ abstract class AbstractCellRenderer extends Disposable { abstract layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }): void; } -abstract class SingleSideCell extends AbstractCellRenderer { +abstract class SingleSideDiffElement extends AbstractElementRenderer { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: SingleSideCellDiffViewModel, + readonly cell: SingleSideDiffElementViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, readonly style: 'left' | 'right' | 'full', protected readonly instantiationService: IInstantiationService, @@ -718,11 +716,11 @@ abstract class SingleSideCell extends AbstractCellRenderer { this._outputHeader.buildHeader(); } } -export class DeletedCell extends SingleSideCell { +export class DeletedElement extends SingleSideDiffElement { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: SingleSideCellDiffViewModel, + readonly cell: SingleSideDiffElementViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, @IModeService readonly modeService: IModeService, @IModelService readonly modelService: IModelService, @@ -809,11 +807,11 @@ export class DeletedCell extends SingleSideCell { } } -export class InsertCell extends SingleSideCell { +export class InsertElement extends SingleSideDiffElement { private _editor!: CodeEditorWidget; constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: SingleSideCellDiffViewModel, + readonly cell: SingleSideDiffElementViewModel, readonly templateData: CellDiffSingleSideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, @@ -905,7 +903,7 @@ export class InsertCell extends SingleSideCell { } } -export class ModifiedCell extends AbstractCellRenderer { +export class ModifiedElement extends AbstractElementRenderer { private _editor?: DiffEditorWidget; private _editorContainer!: HTMLElement; private _inputToolbarContainer!: HTMLElement; @@ -914,7 +912,7 @@ export class ModifiedCell extends AbstractCellRenderer { constructor( readonly notebookEditor: INotebookTextDiffEditor, - readonly cell: SideBySideCellDiffViewModel, + readonly cell: SideBySideDiffElementViewModel, readonly templateData: CellDiffSideBySideRenderTemplate, @IInstantiationService protected readonly instantiationService: IInstantiationService, @IModeService readonly modeService: IModeService, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts similarity index 86% rename from src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts rename to src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 2641b731f03..7a90e32bdae 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -6,7 +6,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; @@ -26,7 +26,7 @@ export class OutputElement extends Disposable { private notebookEditor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, private notebookService: INotebookService, - private cellViewModel: CellDiffViewModelBase, + private cellViewModel: DiffElementViewModelBase, private modified: boolean, private cell: NotebookCellTextModel, @@ -86,7 +86,7 @@ export class OutputElement extends Disposable { this.cell, result, this.getOutputOffsetInContainer(index), - this.cellViewModel instanceof SideBySideCellDiffViewModel + this.cellViewModel instanceof SideBySideDiffElementViewModel ? this.modified : this.cellViewModel.type === 'insert' ); @@ -133,38 +133,38 @@ export class OutputElement extends Disposable { } getCellOutputCurrentIndex() { - if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { if (this.modified) { return this.cellViewModel.modified.outputs.indexOf(this.output.model); } else { return this.cellViewModel.original.outputs.indexOf(this.output.model); } } else { - return (this.cellViewModel as SingleSideCellDiffViewModel).cellTextModel!.outputs.indexOf(this.output.model); + return (this.cellViewModel as SingleSideDiffElementViewModel).cellTextModel!.outputs.indexOf(this.output.model); } } updateHeight(index: number, height: number) { - if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { this.cellViewModel.updateOutputHeight(!this.modified, index, height); } else { - (this.cellViewModel as SingleSideCellDiffViewModel).updateOutputHeight(index, height); + (this.cellViewModel as SingleSideDiffElementViewModel).updateOutputHeight(index, height); } } getOutputOffsetInContainer(index: number) { - if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { return this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); } else { - return (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInContainer(index); + return (this.cellViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); } } getOutputOffsetInCell(index: number) { - if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { return this.cellViewModel.getOutputOffsetInCell(!this.modified, index); } else { - return (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInCell(index); + return (this.cellViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(index); } } } @@ -175,7 +175,7 @@ export class OutputContainer extends Disposable { constructor( private _editor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, - private cellViewModel: CellDiffViewModelBase, + private cellViewModel: DiffElementViewModelBase, private cell: NotebookCellTextModel, private modified: boolean, private outputContainer: HTMLElement, @@ -197,11 +197,11 @@ export class OutputContainer extends Disposable { this.outputEntries.forEach((value, key) => { const index = cell.outputs.indexOf(key.model); if (index >= 0) { - if (this.cellViewModel instanceof SideBySideCellDiffViewModel) { + if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { const top = this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); value.domNode.style.top = `${top}px`; } else { - const top = (this.cellViewModel as SingleSideCellDiffViewModel).getOutputOffsetInContainer(index); + const top = (this.cellViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); value.domNode.style.top = `${top}px`; } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts similarity index 98% rename from src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts rename to src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 09eba7ca261..ed66e8523ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -22,7 +22,7 @@ export enum PropertyFoldingState { Collapsed } -export abstract class CellDiffViewModelBase extends Disposable { +export abstract class DiffElementViewModelBase extends Disposable { public metadataFoldingState: PropertyFoldingState; public outputFoldingState: PropertyFoldingState; protected _layoutInfoEmitter = new Emitter(); @@ -143,7 +143,7 @@ export abstract class CellDiffViewModelBase extends Disposable { } } -export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { +export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { protected _originalOutputCollection: number[] = []; protected _originalOutputsTop: PrefixSumComputer | null = null; protected _modifiedOutputCollection: number[] = []; @@ -296,7 +296,7 @@ export class SideBySideCellDiffViewModel extends CellDiffViewModelBase { } } -export class SingleSideCellDiffViewModel extends CellDiffViewModelBase { +export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { protected _outputCollection: number[] = []; protected _outputsTop: PrefixSumComputer | null = null; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index 3983cfcc4bb..1f2dcffe0e3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ActiveEditorContext, viewColumnToEditorGroup } from 'vs/workbench/common/editor'; -import { CellDiffViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; import { openAsTextIcon, revertIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; @@ -65,7 +65,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { + run(accessor: ServicesAccessor, context?: { cell: DiffElementViewModelBase }) { if (!context) { return; } @@ -95,7 +95,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { + run(accessor: ServicesAccessor, context?: { cell: DiffElementViewModelBase }) { if (!context) { return; } @@ -125,7 +125,7 @@ registerAction2(class extends Action2 { } ); } - run(accessor: ServicesAccessor, context?: { cell: CellDiffViewModelBase }) { + run(accessor: ServicesAccessor, context?: { cell: DiffElementViewModelBase }) { if (!context) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index e06081697ec..07861ff1596 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -13,7 +13,7 @@ import { notebookCellBorder, NotebookEditorWidget } from 'vs/workbench/contrib/n import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { NotebookDiffEditorInput } from '../notebookDiffEditorInput'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellDiffSideBySideRenderer, CellDiffSingleSideRenderer, NotebookCellTextDiffListDelegate, NotebookTextDiffList } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -58,7 +58,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _webviewTransparentCover: HTMLElement | null = null; private _fontInfo: BareFontInfo | undefined; - private readonly _onMouseUp = this._register(new Emitter<{ readonly event: MouseEvent; readonly target: CellDiffViewModelBase; }>()); + private readonly _onMouseUp = this._register(new Emitter<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>()); public readonly onMouseUp = this._onMouseUp.event; private _eventDispatcher: NotebookDiffEditorEventDispatcher | undefined; protected _scopeContextKeyService!: IContextKeyService; @@ -264,7 +264,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const diffResult = await this.notebookEditorWorkerService.computeDiff(this._model.original.resource, this._model.modified.resource); const cellChanges = diffResult.cellsDiff.changes; - const cellDiffViewModels: CellDiffViewModelBase[] = []; + const diffElementViewModels: DiffElementViewModelBase[] = []; const originalModel = this._model.original.notebook; const modifiedModel = this._model.modified.notebook; let originalCellIndex = 0; @@ -280,7 +280,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const originalCell = originalModel.cells[originalCellIndex + j]; const modifiedCell = modifiedModel.cells[modifiedCellIndex + j]; if (originalCell.getHashValue() === modifiedCell.getHashValue()) { - cellDiffViewModels.push(new SideBySideCellDiffViewModel( + diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, originalCell, modifiedCell, @@ -289,10 +289,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD )); } else { if (firstChangeIndex === -1) { - firstChangeIndex = cellDiffViewModels.length; + firstChangeIndex = diffElementViewModels.length; } - cellDiffViewModels.push(new SideBySideCellDiffViewModel( + diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, originalCell, modifiedCell, @@ -304,16 +304,16 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const modifiedLCS = this._computeModifiedLCS(change, originalModel, modifiedModel); if (modifiedLCS.length && firstChangeIndex === -1) { - firstChangeIndex = cellDiffViewModels.length; + firstChangeIndex = diffElementViewModels.length; } - cellDiffViewModels.push(...modifiedLCS); + diffElementViewModels.push(...modifiedLCS); originalCellIndex = change.originalStart + change.originalLength; modifiedCellIndex = change.modifiedStart + change.modifiedLength; } for (let i = originalCellIndex; i < originalModel.cells.length; i++) { - cellDiffViewModels.push(new SideBySideCellDiffViewModel( + diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, originalModel.cells[i], modifiedModel.cells[i - originalCellIndex + modifiedCellIndex], @@ -322,7 +322,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD )); } - this._list.splice(0, this._list.length, cellDiffViewModels); + this._list.splice(0, this._list.length, diffElementViewModels); if (this._revealFirst && firstChangeIndex !== -1) { this._revealFirst = false; @@ -332,12 +332,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } private _computeModifiedLCS(change: IDiffChange, originalModel: NotebookTextModel, modifiedModel: NotebookTextModel) { - const result: CellDiffViewModelBase[] = []; + const result: DiffElementViewModelBase[] = []; // modified cells const modifiedLen = Math.min(change.originalLength, change.modifiedLength); for (let j = 0; j < modifiedLen; j++) { - result.push(new SideBySideCellDiffViewModel( + result.push(new SideBySideDiffElementViewModel( modifiedModel, originalModel.cells[change.originalStart + j], modifiedModel.cells[change.modifiedStart + j], @@ -348,7 +348,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.originalLength; j++) { // deletion - result.push(new SingleSideCellDiffViewModel( + result.push(new SingleSideDiffElementViewModel( originalModel, originalModel.cells[change.originalStart + j], undefined, @@ -359,7 +359,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = modifiedLen; j < change.modifiedLength; j++) { // insertion - result.push(new SingleSideCellDiffViewModel( + result.push(new SingleSideDiffElementViewModel( modifiedModel, undefined, modifiedModel.cells[change.modifiedStart + j], @@ -371,11 +371,11 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return result; } - private pendingLayouts = new WeakMap(); + private pendingLayouts = new WeakMap(); - layoutNotebookCell(cell: CellDiffViewModelBase, height: number) { - const relayout = (cell: CellDiffViewModelBase, height: number) => { + layoutNotebookCell(cell: DiffElementViewModelBase, height: number) { + const relayout = (cell: DiffElementViewModelBase, height: number) => { const viewIndex = this._list.indexOf(cell); this._list?.updateElementHeight(viewIndex, height); @@ -402,7 +402,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } - createInset(cellDiffViewModel: CellDiffViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { + createInset(cellDiffViewModel: DiffElementViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { if (rightEditor) { if (!this._modifiedWebview!.insetMapping.has(output.source)) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index cd4ac5ef433..2c3c565a7d4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -14,10 +14,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/list/browser/listService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { CellDiffViewModelBase, SideBySideCellDiffViewModel, SingleSideCellDiffViewModel } from 'vs/workbench/contrib/notebook/browser/diff/celllDiffViewModel'; +import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { isMacintosh } from 'vs/base/common/platform'; -import { DeletedCell, InsertCell, ModifiedCell } from 'vs/workbench/contrib/notebook/browser/diff/cellComponents'; +import { DeletedElement, InsertElement, ModifiedElement } from 'vs/workbench/contrib/notebook/browser/diff/diffComponents'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -88,7 +88,7 @@ export function getOptimizedNestedCodeEditorWidgetOptions(): ICodeEditorWidgetOp }; } -export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { +export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { // private readonly lineHeight: number; constructor( @@ -98,15 +98,15 @@ export class NotebookCellTextDiffListDelegate implements IListVirtualDelegate { +export class CellDiffSingleSideRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'cell_diff_single'; constructor( @@ -177,13 +177,13 @@ export class CellDiffSingleSideRenderer implements IListRenderer { +export class CellDiffSideBySideRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'cell_diff_side_by_side'; constructor( @@ -286,13 +286,13 @@ export class CellDiffSideBySideRenderer implements IListRenderer implements IDisposable, IStyleController { +export class NotebookTextDiffList extends WorkbenchList implements IDisposable, IStyleController { private styleElement?: HTMLStyleElement; get rowsContainer(): HTMLElement { @@ -320,10 +320,10 @@ export class NotebookTextDiffList extends WorkbenchList i constructor( listUser: string, container: HTMLElement, - delegate: IListVirtualDelegate, - renderers: IListRenderer[], + delegate: IListVirtualDelegate, + renderers: IListRenderer[], contextKeyService: IContextKeyService, - options: IWorkbenchListOptions, + options: IWorkbenchListOptions, @IListService listService: IListService, @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, @@ -331,7 +331,7 @@ export class NotebookTextDiffList extends WorkbenchList i super(listUser, container, delegate, renderers, options, contextKeyService, listService, themeService, configurationService, keybindingService); } - getAbsoluteTopOfElement(element: CellDiffViewModelBase): number { + getAbsoluteTopOfElement(element: DiffElementViewModelBase): number { const index = this.indexOf(element); // if (index === undefined || index < 0 || index >= this.length) { // this._getViewIndexUpperBound(element); From 89fd7be7fbd58cc1e54dc8fcdba6ae665a2b9f19 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 14 Dec 2020 21:03:22 -0800 Subject: [PATCH 0975/1837] test --- .../browser/diff/backLayerWebview2.ts | 105 +++++++----------- .../contrib/notebook/browser/diff/common.ts | 7 +- .../notebook/browser/diff/diffComponents.ts | 28 ++--- .../browser/diff/diffElementOutputs.ts | 6 +- .../browser/diff/diffElementViewModel.ts | 14 +-- .../browser/diff/diffNestedCellViewModel.ts | 64 +++++++++++ .../browser/diff/notebookDiffActions.ts | 6 +- .../browser/diff/notebookTextDiffEditor.ts | 30 ++--- .../browser/view/renderers/webviewPreloads.ts | 1 + 9 files changed, 154 insertions(+), 107 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 0af765801a5..0168d38a14a 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -11,23 +11,20 @@ import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; -import { dirname, joinPath } from 'vs/base/common/resources'; +import { dirname } from 'vs/base/common/resources'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IFileService } from 'vs/platform/files/common/files'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; +import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -200,7 +197,8 @@ export type AnyMessage = FromWebviewMessage | ToWebviewMessage; interface ICachedInset { outputId: string; - cell: CodeCellViewModel; + diffElement: DiffElementViewModelBase; + cell: DiffNestedCellViewModel; renderer?: INotebookRendererInfo; cachedCreation: ICreationRequestMessage; } @@ -244,8 +242,6 @@ export class BackLayerWebView extends Disposable { @INotebookService private readonly notebookService: INotebookService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IFileDialogService private readonly fileDialogService: IFileDialogService, - @IFileService private readonly fileService: IFileService, ) { super(); @@ -338,27 +334,27 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cell: CodeCellViewModel, output: IDisplayOutputViewModel } | undefined { + private resolveOutputId(id: string): { cell: DiffNestedCellViewModel, diffElement: DiffElementViewModelBase, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; } - const cell = this.insetMapping.get(output)!.cell; + const info = this.insetMapping.get(output)!; // const currCell = this.notebookEditor.viewModel?.viewCells.find(vc => vc.handle === cell.handle); // if (currCell !== cell && currCell !== undefined) { // this.insetMapping.get(output)!.cell = currCell as CodeCellViewModel; // } - return { cell: this.insetMapping.get(output)!.cell, output }; + return { cell: info.cell, diffElement: info.diffElement, output }; } async createWebview(): Promise { let coreDependencies = ''; let resolveFunc: () => void; - this._initalized = new Promise((resolve, reject) => { + this._initalized = new Promise((resolve) => { resolveFunc = resolve; }); @@ -455,18 +451,25 @@ var requirejs = (function() { return; } - // if (data.__vscode_notebook_message) { - // if (data.type === 'dimension') { - // const height = data.data.height; - // const outputHeight = height; + if (data.__vscode_notebook_message) { + if (data.type === 'dimension') { + const height = data.data.height; + const outputHeight = height; - // const info = this.resolveOutputId(data.id); - // if (info) { - // const { cell, output } = info; - // const outputIndex = cell.outputsViewModels.indexOf(output); - // cell.updateOutputHeight(outputIndex, outputHeight); - // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); - // } + const info = this.resolveOutputId(data.id); + if (info) { + const { diffElement, cell, output } = info; + const outputIndex = cell.outputsViewModels.indexOf(output); + + if (diffElement instanceof SideBySideDiffElementViewModel) { + diffElement.updateOutputHeight(false, outputIndex, outputHeight); + } else { + (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); + } + // cell.updateOutputHeight(outputIndex, outputHeight); + // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); + } + } // } else if (data.type === 'mouseenter') { // const info = this.resolveOutputId(data.id); // if (info) { @@ -514,46 +517,12 @@ var requirejs = (function() { // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); // } // return; - // } + } this._onMessage.fire({ message: data }); })); } - private async _onDidClickDataLink(event: IClickedDataUrlMessage): Promise { - const [splitStart, splitData] = event.data.split(';base64,'); - if (!splitData || !splitStart) { - return; - } - - const defaultDir = dirname(this.documentUri); - let defaultName: string; - if (event.downloadName) { - defaultName = event.downloadName; - } else { - const mimeType = splitStart.replace(/^data:/, ''); - const candidateExtension = mimeType && getExtensionForMimeType(mimeType); - defaultName = candidateExtension ? `download${candidateExtension}` : 'download'; - } - - const defaultUri = joinPath(defaultDir, defaultName); - const newFileUri = await this.fileDialogService.showSaveDialog({ - defaultUri - }); - if (!newFileUri) { - return; - } - - const decoded = atob(splitData); - const typedArray = new Uint8Array(decoded.length); - for (let i = 0; i < decoded.length; i++) { - typedArray[i] = decoded.charCodeAt(i); - } - - const buff = VSBuffer.wrap(typedArray); - await this.fileService.writeFile(newFileUri, buff); - await this.openerService.open(newFileUri); - } private _createInset(webviewService: IWebviewService, content: string) { const rootPath = isWeb ? FileAccess.asBrowserUri('', require) : FileAccess.asFileUri('', require); @@ -572,7 +541,7 @@ var requirejs = (function() { }, undefined); let resolveFunc: () => void; - this._loaded = new Promise((resolve, reject) => { + this._loaded = new Promise((resolve) => { resolveFunc = resolve; }); @@ -611,7 +580,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: { diffElement: DiffElementViewModelBase, cell: DiffNestedCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { if (this._disposed) { return; } @@ -620,8 +589,14 @@ var requirejs = (function() { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; const outputIndex = item.cell.outputsViewModels.indexOf(item.output); + let outputOffset = 0; + if (item.diffElement instanceof SideBySideDiffElementViewModel) { + outputOffset = item.diffElement.getOutputOffsetInCell(false, outputIndex); + } else { + outputOffset = (item.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } - const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); + // const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); outputCache.cachedCreation.top = outputOffset; this.hiddenInsetMapping.delete(item.output); @@ -641,7 +616,7 @@ var requirejs = (function() { }); } - async createInset(cell: NotebookCellTextModel, content: IInsetRenderOutput, cellTop: number, offset: number) { + async createInset(cellDiffViewModel: DiffElementViewModelBase, cell: DiffNestedCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) { if (this._disposed) { return; } @@ -703,7 +678,7 @@ var requirejs = (function() { } this._sendMessageToWebview(message); - this.insetMapping.set(content.source, { outputId: message.outputId, cell, renderer, cachedCreation: message }); + this.insetMapping.set(content.source, { outputId: message.outputId, diffElement: cellDiffViewModel, cell, renderer, cachedCreation: message }); this.hiddenInsetMapping.delete(content.source); this.reversedInsetMapping.set(message.outputId, content.source); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 46abd5d8d2f..521e0b053bf 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -13,7 +13,6 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; -import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -22,7 +21,11 @@ export interface INotebookTextDiffEditor { getLayoutInfo(): NotebookLayoutInfo; layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; - createInset(cellDiffViewModel: DiffElementViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; +} + +export interface IDiffNestedCellViewModel { + } export interface CellDiffSingleSideRenderTemplate { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 2bf42f22011..45357266a99 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -371,7 +371,7 @@ abstract class AbstractElementRenderer extends Disposable { } if (newLangauge !== undefined && newLangauge !== this.cell.modified!.language) { - const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!); + const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!.textModel); this.notebookEditor.textModel!.applyEdits( this.notebookEditor.textModel!.versionId, [{ editType: CellEditType.CellLanguage, index, language: newLangauge }], @@ -382,7 +382,7 @@ abstract class AbstractElementRenderer extends Disposable { ); } - const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!); + const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!.textModel); if (index < 0) { return; @@ -444,7 +444,7 @@ abstract class AbstractElementRenderer extends Disposable { respondingToContentChange = false; })); - this._register(this.cell.modified!.onDidChangeMetadata(() => { + this._register(this.cell.modified!.textModel.onDidChangeMetadata(() => { if (respondingToContentChange) { return; } @@ -538,7 +538,7 @@ abstract class AbstractElementRenderer extends Disposable { } })); - this._register(this.cell.modified!.onDidChangeOutputs(() => { + this._register(this.cell.modified!.textModel.onDidChangeOutputs(() => { const modifiedOutputsSource = this._getFormatedOutputJSON(this.cell.modified?.outputs || []); modifiedModel.setValue(modifiedOutputsSource); this._outputHeader.refresh(); @@ -742,7 +742,7 @@ export class DeletedElement extends SingleSideDiffElement { updateSourceEditor(): void { const originalCell = this.cell.original!; - const lineCount = originalCell.textBuffer.getLineCount(); + const lineCount = originalCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; @@ -760,7 +760,7 @@ export class DeletedElement extends SingleSideDiffElement { } })); - originalCell.resolveTextModelRef().then(ref => { + originalCell.textModel.resolveTextModelRef().then(ref => { if (this._isDisposed) { return; } @@ -831,7 +831,7 @@ export class InsertElement extends SingleSideDiffElement { updateSourceEditor(): void { const modifiedCell = this.cell.modified!; - const lineCount = modifiedCell.textBuffer.getLineCount(); + const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; @@ -851,7 +851,7 @@ export class InsertElement extends SingleSideDiffElement { } })); - modifiedCell.resolveTextModelRef().then(ref => { + modifiedCell.textModel.resolveTextModelRef().then(ref => { if (this._isDisposed) { return; } @@ -1036,7 +1036,7 @@ export class ModifiedElement extends AbstractElementRenderer { updateSourceEditor(): void { const modifiedCell = this.cell.modified!; - const lineCount = modifiedCell.textBuffer.getLineCount(); + const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; this._editorContainer = this.templateData.editorContainer; @@ -1072,14 +1072,14 @@ export class ModifiedElement extends AbstractElementRenderer { createAndFillInActionBarActions(this._menu, { shouldForwardArgs: true }, actions); this._toolbar.setActions(actions); - if (this.cell.modified!.getValue() !== this.cell.original!.getValue()) { + if (this.cell.modified!.textModel.getValue() !== this.cell.original!.textModel.getValue()) { this._inputToolbarContainer.style.display = 'block'; } else { this._inputToolbarContainer.style.display = 'none'; } - this._register(this.cell.modified!.onDidChangeContent(() => { - if (this.cell.modified!.getValue() !== this.cell.original!.getValue()) { + this._register(this.cell.modified!.textModel.onDidChangeContent(() => { + if (this.cell.modified!.textModel.getValue() !== this.cell.original!.textModel.getValue()) { this._inputToolbarContainer.style.display = 'block'; } else { this._inputToolbarContainer.style.display = 'none'; @@ -1091,8 +1091,8 @@ export class ModifiedElement extends AbstractElementRenderer { const originalCell = this.cell.original!; const modifiedCell = this.cell.modified!; - const originalRef = await originalCell.resolveTextModelRef(); - const modifiedRef = await modifiedCell.resolveTextModelRef(); + const originalRef = await originalCell.textModel.resolveTextModelRef(); + const modifiedRef = await modifiedCell.textModel.resolveTextModelRef(); if (this._isDisposed) { return; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 7a90e32bdae..91cfe7de933 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -11,11 +11,11 @@ import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/d import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; -import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { BUILTIN_RENDERER_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; export class OutputElement extends Disposable { readonly resizeListener = new DisposableStore(); @@ -29,7 +29,7 @@ export class OutputElement extends Disposable { private cellViewModel: DiffElementViewModelBase, private modified: boolean, - private cell: NotebookCellTextModel, + private cell: DiffNestedCellViewModel, private outputContainer: HTMLElement, readonly output: ICellOutputViewModel ) { @@ -176,7 +176,7 @@ export class OutputContainer extends Disposable { private _editor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, private cellViewModel: DiffElementViewModelBase, - private cell: NotebookCellTextModel, + private cell: DiffNestedCellViewModel, private modified: boolean, private outputContainer: HTMLElement, @INotebookService private notebookService: INotebookService, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index ed66e8523ae..33442495fb1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookDiffEditorEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -16,6 +15,7 @@ import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; +import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; export enum PropertyFoldingState { Expanded, @@ -100,8 +100,8 @@ export abstract class DiffElementViewModelBase extends Disposable { constructor( readonly documentTextModel: NotebookTextModel, - readonly original: NotebookCellTextModel | undefined, - readonly modified: NotebookCellTextModel | undefined, + readonly original: DiffNestedCellViewModel | undefined, + readonly modified: DiffNestedCellViewModel | undefined, readonly type: 'unchanged' | 'insert' | 'delete' | 'modified', readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { @@ -151,8 +151,8 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { constructor( readonly documentTextModel: NotebookTextModel, - readonly original: NotebookCellTextModel, - readonly modified: NotebookCellTextModel, + readonly original: DiffNestedCellViewModel, + readonly modified: DiffNestedCellViewModel, readonly type: 'unchanged' | 'modified', readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { @@ -306,8 +306,8 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { constructor( readonly documentTextModel: NotebookTextModel, - readonly original: NotebookCellTextModel | undefined, - readonly modified: NotebookCellTextModel | undefined, + readonly original: DiffNestedCellViewModel | undefined, + readonly modified: DiffNestedCellViewModel | undefined, readonly type: 'insert' | 'delete', readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts new file mode 100644 index 00000000000..ed4e2c14c63 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts @@ -0,0 +1,64 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { generateUuid } from 'vs/base/common/uuid'; +import { IDiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; + +export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCellViewModel { + private _id: string; + get id() { + return this._id; + } + + get outputs() { + return this.textModel.outputs; + } + + get language() { + return this.textModel.language; + } + + get metadata() { + return this.textModel.metadata; + } + + get uri() { + return this.textModel.uri; + } + + get handle() { + return this.textModel.handle; + } + + private _outputViewModels: ICellOutputViewModel[]; + + get outputsViewModels() { + return this._outputViewModels; + } + + constructor( + readonly textModel: NotebookCellTextModel, + @INotebookService private _notebookService: INotebookService + ) { + super(); + this._id = generateUuid(); + + this._outputViewModels = this.textModel.outputs.map(output => new CellOutputViewModel(output, this._notebookService)); + // this._register(this.textModel.onDidChangeOutputs((splices) => { + // splices.reverse().forEach(splice => { + // this._outputCollection.splice(splice[0], splice[1], ...splice[2].map(() => 0)); + // this._outputViewModels.splice(splice[0], splice[1], ...splice[2].map(output => new CellOutputViewModel(output, this._notebookService))); + // }); + + // this._outputsTop = null; + // this._onDidChangeOutputs.fire(splices); + // })); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index 1f2dcffe0e3..b88069d4fc4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -77,7 +77,7 @@ registerAction2(class extends Action2 { return; } - modified.metadata = original.metadata; + modified.textModel.metadata = original.metadata; } }); @@ -107,7 +107,7 @@ registerAction2(class extends Action2 { return; } - modified.spliceNotebookCellOutputs([[0, modified.outputs.length, original.outputs]]); + modified.textModel.spliceNotebookCellOutputs([[0, modified.outputs.length, original.outputs]]); } }); @@ -139,7 +139,7 @@ registerAction2(class extends Action2 { const bulkEditService = accessor.get(IBulkEditService); return bulkEditService.apply([ - new ResourceTextEdit(modified.uri, { range: modified.getFullModelRange(), text: original.getValue() }), + new ResourceTextEdit(modified.uri, { range: modified.textModel.getFullModelRange(), text: original.textModel.getValue() }), ], { quotableLabel: 'Split Notebook Cell' }); } }); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 07861ff1596..74d56b87b92 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -37,11 +37,11 @@ import { Schemas } from 'vs/base/common/network'; import { IDiffChange } from 'vs/base/common/diff/diff'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; -import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { SequencerByKey } from 'vs/base/common/async'; import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/backLayerWebview2'; import { generateUuid } from 'vs/base/common/uuid'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; const $ = DOM.$; @@ -282,8 +282,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD if (originalCell.getHashValue() === modifiedCell.getHashValue()) { diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, - originalCell, - modifiedCell, + this.instantiationService.createInstance(DiffNestedCellViewModel, originalCell), + this.instantiationService.createInstance(DiffNestedCellViewModel, modifiedCell), 'unchanged', this._eventDispatcher! )); @@ -294,8 +294,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, - originalCell, - modifiedCell, + this.instantiationService.createInstance(DiffNestedCellViewModel, originalCell), + this.instantiationService.createInstance(DiffNestedCellViewModel, modifiedCell), 'modified', this._eventDispatcher! )); @@ -315,8 +315,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let i = originalCellIndex; i < originalModel.cells.length; i++) { diffElementViewModels.push(new SideBySideDiffElementViewModel( this._model.modified.notebook, - originalModel.cells[i], - modifiedModel.cells[i - originalCellIndex + modifiedCellIndex], + this.instantiationService.createInstance(DiffNestedCellViewModel, originalModel.cells[i]), + this.instantiationService.createInstance(DiffNestedCellViewModel, modifiedModel.cells[i - originalCellIndex + modifiedCellIndex]), 'unchanged', this._eventDispatcher! )); @@ -339,8 +339,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD for (let j = 0; j < modifiedLen; j++) { result.push(new SideBySideDiffElementViewModel( modifiedModel, - originalModel.cells[change.originalStart + j], - modifiedModel.cells[change.modifiedStart + j], + this.instantiationService.createInstance(DiffNestedCellViewModel, originalModel.cells[change.originalStart + j]), + this.instantiationService.createInstance(DiffNestedCellViewModel, modifiedModel.cells[change.modifiedStart + j]), 'modified', this._eventDispatcher! )); @@ -350,7 +350,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // deletion result.push(new SingleSideDiffElementViewModel( originalModel, - originalModel.cells[change.originalStart + j], + this.instantiationService.createInstance(DiffNestedCellViewModel, originalModel.cells[change.originalStart + j]), undefined, 'delete', this._eventDispatcher! @@ -362,7 +362,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD result.push(new SingleSideDiffElementViewModel( modifiedModel, undefined, - modifiedModel.cells[change.modifiedStart + j], + this.instantiationService.createInstance(DiffNestedCellViewModel, modifiedModel.cells[change.modifiedStart + j]), 'insert', this._eventDispatcher! )); @@ -402,13 +402,17 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } - createInset(cellDiffViewModel: DiffElementViewModelBase, cellTextModel: NotebookCellTextModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { if (rightEditor) { if (!this._modifiedWebview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._modifiedWebview?.createInset(cellTextModel, output, cellTop, offset); + await this._modifiedWebview?.createInset(cellDiffViewModel, cellViewModel, output, cellTop, offset); + } else { + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + const scrollTop = this._list.scrollTop; + this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ diffElement: cellDiffViewModel, cell: cellViewModel, output: output.source, cellTop }]); } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 4ef35e2bdad..6a8de1fac10 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -397,6 +397,7 @@ function webviewPreloads() { window.addEventListener('message', rawEvent => { const event = rawEvent as ({ data: ToWebviewMessage; }); + console.log(event); switch (event.data.type) { case 'html': From f9bb8e62001b45233684ff7ca93a59d4ea6f8c82 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 08:12:49 +0100 Subject: [PATCH 0976/1837] fix #112467 --- .../codeEditor/browser/quickaccess/gotoLineQuickAccess.ts | 2 +- .../codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts | 2 +- src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts | 2 +- src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index eb4566740d8..e9de8b4f01f 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -44,7 +44,7 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use - if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) { + if ((options.keyMods.ctrlCmd || (this.configuration.openEditorPinned && options.keyMods.alt) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor this.editorService.openEditor(this.editorService.activeEditor, { diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index bb7642fe74a..e4939db8548 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -67,7 +67,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use - if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) { + if ((options.keyMods.ctrlCmd || (this.configuration.openEditorPinned && options.keyMods.alt) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor this.editorService.openEditor(this.editorService.activeEditor, { diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 4ada8402619..5baf3285897 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -936,7 +936,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider Date: Tue, 15 Dec 2020 08:16:28 +0100 Subject: [PATCH 0977/1837] quick pick - configure openEditorPinned properly --- .../codeEditor/browser/quickaccess/gotoLineQuickAccess.ts | 2 +- .../codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts | 2 +- src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts | 2 +- src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index e9de8b4f01f..045c9157583 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -33,7 +33,7 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv const editorConfig = this.configurationService.getValue().workbench.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, + openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview }; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index e4939db8548..c6dbcdb1e58 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -55,7 +55,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess const editorConfig = this.configurationService.getValue().workbench.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, + openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, openSideBySideDirection: editorConfig.openSideBySideDirection }; } diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 5baf3285897..7949e85a1e1 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -189,7 +189,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider().workbench.quickOpen; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, + openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, openSideBySideDirection: editorConfig.openSideBySideDirection, includeSymbols: searchConfig.quickOpen.includeSymbols, includeHistory: searchConfig.quickOpen.includeHistory, diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index 79805505bef..fc42cb555e7 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -78,7 +78,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider().workbench.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, + openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, openSideBySideDirection: editorConfig.openSideBySideDirection }; } From 6b950b3d68556f35e6e9b19f0af3d3bf5a7f39c8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 08:17:57 +0100 Subject: [PATCH 0978/1837] :lipstick: --- .../electron-main/windowsMainService.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index e1bcd6c2063..65820a3f817 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -745,18 +745,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic detail = localize('uriInvalidDetail', "The URI '{0}' is not valid and can not be opened.", uri.toString()); } - const options: MessageBoxOptions = { - title: product.nameLong, - type: 'info', - buttons: [localize('ok', "OK")], - message, - detail, - noLink: true - }; + const options: MessageBoxOptions = { title: product.nameLong, type: 'info', buttons: [localize('ok', "OK")], message, detail, noLink: true }; this.dialogMainService.showMessageBox(options, withNullAsUndefined(BrowserWindow.getFocusedWindow())); } } + return pathsToOpen; } @@ -892,6 +886,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const uri = URI.parse(arg); if (!uri.scheme) { this.logService.error(`Invalid URI input string, scheme missing: ${arg}`); + return undefined; } @@ -1357,9 +1352,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } getFocusedWindow(): ICodeWindow | undefined { - const win = BrowserWindow.getFocusedWindow(); - if (win) { - return this.getWindowById(win.id); + const window = BrowserWindow.getFocusedWindow(); + if (window) { + return this.getWindowById(window.id); } return undefined; @@ -1406,9 +1401,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } getWindowById(windowId: number): ICodeWindow | undefined { - const res = this.getWindows().filter(window => window.id === windowId); + const windows = this.getWindows().filter(window => window.id === windowId); - return firstOrDefault(res); + return firstOrDefault(windows); } getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined { From 29e3f670384d1576a853a9388a8a52da95cec23c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 08:30:34 +0100 Subject: [PATCH 0979/1837] config - careful with undefined/null config props --- .../workbench/browser/parts/editor/editorStatus.ts | 2 +- src/vs/workbench/common/editor.ts | 6 +++--- .../browser/quickaccess/gotoLineQuickAccess.ts | 4 ++-- .../browser/quickaccess/gotoSymbolQuickAccess.ts | 6 +++--- .../contrib/files/browser/explorerViewlet.ts | 2 +- .../contrib/search/browser/anythingQuickAccess.ts | 12 ++++++------ .../contrib/search/browser/symbolsQuickAccess.ts | 6 +++--- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 1d85f0ad554..fa1b2a87b74 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -766,7 +766,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { if (editorWidget) { const screenReaderDetected = this.accessibilityService.isScreenReaderOptimized(); if (screenReaderDetected) { - const screenReaderConfiguration = this.configurationService.getValue('editor').accessibilitySupport; + const screenReaderConfiguration = this.configurationService.getValue('editor')?.accessibilitySupport; if (screenReaderConfiguration === 'auto') { if (!this.promptedScreenReader) { this.promptedScreenReader = true; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index f104149d8d5..7eaad2dd6c1 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1257,9 +1257,9 @@ export interface IEditorCloseEvent extends IEditorIdentifier { export type GroupIdentifier = number; export interface IWorkbenchEditorConfiguration { - workbench: { - editor: IEditorPartConfiguration, - iconTheme: string; + workbench?: { + editor?: IEditorPartConfiguration, + iconTheme?: string; }; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index 045c9157583..67115614768 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -30,10 +30,10 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv } private get configuration() { - const editorConfig = this.configurationService.getValue().workbench.editor; + const editorConfig = this.configurationService.getValue().workbench?.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview + openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview }; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index c6dbcdb1e58..6a3c2d9b1f0 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -52,11 +52,11 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess } private get configuration() { - const editorConfig = this.configurationService.getValue().workbench.editor; + const editorConfig = this.configurationService.getValue().workbench?.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, - openSideBySideDirection: editorConfig.openSideBySideDirection + openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview, + openSideBySideDirection: editorConfig?.openSideBySideDirection }; } diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 3b0e5404104..82b38b5c71b 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -208,7 +208,7 @@ export class ExplorerViewPaneContainer extends ViewPaneContainer { let delay = 0; const config = this.configurationService.getValue(); - const delayEditorOpeningInOpenedEditors = !!config.workbench.editor.enablePreview; // No need to delay if preview is disabled + const delayEditorOpeningInOpenedEditors = !!config.workbench?.editor?.enablePreview; // No need to delay if preview is disabled const activeGroup = this.editorGroupService.activeGroup; if (delayEditorOpeningInOpenedEditors && group === activeGroup && !activeGroup.previewEditor) { diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 7949e85a1e1..28ac3519150 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -184,16 +184,16 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider().workbench.editor; + const editorConfig = this.configurationService.getValue().workbench?.editor; const searchConfig = this.configurationService.getValue().search; const quickAccessConfig = this.configurationService.getValue().workbench.quickOpen; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, - openSideBySideDirection: editorConfig.openSideBySideDirection, - includeSymbols: searchConfig.quickOpen.includeSymbols, - includeHistory: searchConfig.quickOpen.includeHistory, - historyFilterSortOrder: searchConfig.quickOpen.history.filterSortOrder, + openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview, + openSideBySideDirection: editorConfig?.openSideBySideDirection, + includeSymbols: searchConfig?.quickOpen.includeSymbols, + includeHistory: searchConfig?.quickOpen.includeHistory, + historyFilterSortOrder: searchConfig?.quickOpen.history.filterSortOrder, shortAutoSaveDelay: this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY, preserveInput: quickAccessConfig.preserveInput }; diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index fc42cb555e7..3038dd70630 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -75,11 +75,11 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider().workbench.editor; + const editorConfig = this.configurationService.getValue().workbench?.editor; return { - openEditorPinned: !editorConfig.enablePreviewFromQuickOpen || !editorConfig.enablePreview, - openSideBySideDirection: editorConfig.openSideBySideDirection + openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview, + openSideBySideDirection: editorConfig?.openSideBySideDirection }; } From f3e95ede9e4b9818c29a5bca3564d6fd162fb210 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 14 Dec 2020 23:31:40 -0800 Subject: [PATCH 0980/1837] Remove unused import --- .../contrib/welcome/gettingStarted/browser/gettingStarted.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index ef84c8a3b0d..c03606751b5 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -14,7 +14,7 @@ import { IEditorInputFactory } from 'vs/workbench/common/editor'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { assertIsDefined } from 'vs/base/common/types'; -import { $, addDisposableListener, Dimension } from 'vs/base/browser/dom'; +import { $, addDisposableListener } from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IProductService } from 'vs/platform/product/common/productService'; import { IGettingStartedCategoryWithProgress, IGettingStartedService } from 'vs/workbench/services/gettingStarted/common/gettingStartedService'; From a1f815a4c9aeb245442f68438abe683a413e9a9c Mon Sep 17 00:00:00 2001 From: Leonard Goldstein <43523968+goldst@users.noreply.github.com> Date: Tue, 15 Dec 2020 08:40:44 +0100 Subject: [PATCH 0981/1837] add option for preview navigation behavior (#112389) * add option for preview navigation behavior #112348 * fix test to comply with changes for #112348 * fix test to comply with changes for #112348 * get pinPreview using IWorkbenchEditorConfiguration * adjust for changes Co-authored-by: Benjamin Pasero --- src/vs/workbench/browser/workbench.contribution.ts | 5 +++++ src/vs/workbench/common/editor.ts | 1 + .../services/editor/browser/codeEditorService.ts | 8 ++++++-- src/vs/workbench/test/browser/workbenchTestServices.ts | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index fdc99470bb5..1aab4bb97a2 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -133,6 +133,11 @@ import { isStandalone } from 'vs/base/browser/browser'; 'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing)."), 'default': false }, + 'workbench.editor.enablePreviewFromCodeNavigation': { + 'type': 'boolean', + 'description': nls.localize('enablePreviewFromCodeNavigation', "Controls whether editors remain in preview when a code navigation is started from them. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing)."), + 'default': false + }, 'workbench.editor.closeOnFileDelete': { 'type': 'boolean', 'description': nls.localize('closeOnFileDelete', "Controls whether editors showing a file that was opened during the session should close automatically when getting deleted or renamed by some other process. Disabling this will keep the editor open on such an event. Note that deleting from within the application will always close the editor and that dirty files will never close to preserve your data."), diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 7eaad2dd6c1..a613f75e58a 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1275,6 +1275,7 @@ interface IEditorPartConfiguration { showIcons?: boolean; enablePreview?: boolean; enablePreviewFromQuickOpen?: boolean; + enablePreviewFromCodeNavigation?: boolean; closeOnFileDelete?: boolean; openPositioning?: 'left' | 'right' | 'first' | 'last'; openSideBySideDirection?: 'right' | 'down'; diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index 89e4328177c..770b1b34bf3 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -8,17 +8,19 @@ import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServ import { ScrollType } from 'vs/editor/common/editorCommon'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { TextEditorOptions } from 'vs/workbench/common/editor'; +import { IWorkbenchEditorConfiguration, TextEditorOptions } from 'vs/workbench/common/editor'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { isEqual } from 'vs/base/common/resources'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class CodeEditorService extends CodeEditorServiceImpl { constructor( @IEditorService private readonly editorService: IEditorService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @IConfigurationService private readonly configurationService: IConfigurationService, ) { super(themeService); } @@ -75,7 +77,9 @@ export class CodeEditorService extends CodeEditorServiceImpl { // should be pinned or not. This ensures that the source of a navigation // is not being replaced by the target. An example is "Goto definition" // that otherwise would replace the editor everytime the user navigates. + const enablePreviewFromCodeNavigation = this.configurationService.getValue().workbench?.editor?.enablePreviewFromCodeNavigation; if ( + !enablePreviewFromCodeNavigation && // we only need to do this if the configuration requires it source && // we need to know the origin of the navigation !input.options?.pinned && // we only need to look at preview editors that open !sideBySide && // we only need to care if editor opens in same group diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index d3b078b1f08..3b19e52026f 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -180,7 +180,7 @@ export function workbenchInstantiationService(overrides?: { instantiationService.stub(ILabelService, instantiationService.createInstance(LabelService)); const editorService = overrides?.editorService ? overrides.editorService(instantiationService) : new TestEditorService(editorGroupService); instantiationService.stub(IEditorService, editorService); - instantiationService.stub(ICodeEditorService, new CodeEditorService(editorService, themeService)); + instantiationService.stub(ICodeEditorService, new CodeEditorService(editorService, themeService, configService)); instantiationService.stub(IViewletService, new TestViewletService()); instantiationService.stub(IListService, new TestListService()); instantiationService.stub(IQuickInputService, new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, accessibilityService, layoutService)); From c42e44e756b70b7dbf67c005234f7677c2c8e4fe Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 08:55:43 +0100 Subject: [PATCH 0982/1837] :lipstick: settings descriptions referencing other settings --- src/vs/workbench/browser/workbench.contribution.ts | 14 +++++++------- .../contrib/files/browser/files.contribution.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index 1aab4bb97a2..21b0d2d0596 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -35,12 +35,12 @@ import { isStandalone } from 'vs/base/browser/browser'; }, 'workbench.editor.scrollToSwitchTabs': { 'type': 'boolean', - 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls whether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration. This value is ignored when `#workbench.editor.showTabs#` is `false`."), + 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls whether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration. This value is ignored when `#workbench.editor.showTabs#` is disabled."), 'default': false }, 'workbench.editor.highlightModifiedTabs': { 'type': 'boolean', - 'markdownDescription': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not. This value is ignored when `#workbench.editor.showTabs#` is `false`."), + 'markdownDescription': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not. This value is ignored when `#workbench.editor.showTabs#` is disabled."), 'default': false }, 'workbench.editor.labelFormat': { @@ -75,7 +75,7 @@ import { isStandalone } from 'vs/base/browser/browser'; 'type': 'string', 'enum': ['left', 'right', 'off'], 'default': 'right', - 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'. This value is ignored when `#workbench.editor.showTabs#` is `false`.") + 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'. This value is ignored when `#workbench.editor.showTabs#` is disabled.") }, 'workbench.editor.tabSizing': { 'type': 'string', @@ -85,7 +85,7 @@ import { isStandalone } from 'vs/base/browser/browser'; nls.localize('workbench.editor.tabSizing.fit', "Always keep tabs large enough to show the full editor label."), nls.localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once.") ], - 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. This value is ignored when `#workbench.editor.showTabs#` is `false`.") + 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. This value is ignored when `#workbench.editor.showTabs#` is disabled.") }, 'workbench.editor.pinnedTabSizing': { 'type': 'string', @@ -96,7 +96,7 @@ import { isStandalone } from 'vs/base/browser/browser'; nls.localize('workbench.editor.pinnedTabSizing.compact', "A pinned tab will show in a compact form with only icon or first letter of the editor name."), nls.localize('workbench.editor.pinnedTabSizing.shrink', "A pinned tab shrinks to a compact fixed size showing parts of the editor name.") ], - 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the sizing of pinned editor tabs. Pinned tabs are sorted to the beginning of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is `false`.") + 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the sizing of pinned editor tabs. Pinned tabs are sorted to the beginning of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is disabled.") }, 'workbench.editor.splitSizing': { 'type': 'string', @@ -130,12 +130,12 @@ import { isStandalone } from 'vs/base/browser/browser'; }, 'workbench.editor.enablePreviewFromQuickOpen': { 'type': 'boolean', - 'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing)."), + 'markdownDescription': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing). This value is ignored when `#workbench.editor.enablePreview#` is disabled."), 'default': false }, 'workbench.editor.enablePreviewFromCodeNavigation': { 'type': 'boolean', - 'description': nls.localize('enablePreviewFromCodeNavigation', "Controls whether editors remain in preview when a code navigation is started from them. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing)."), + 'markdownDescription': nls.localize('enablePreviewFromCodeNavigation', "Controls whether editors remain in preview when a code navigation is started from them. Preview editors do not keep open and are reused until explicitly set to be kept open (e.g. via double click or editing). This value is ignored when `#workbench.editor.enablePreview#` is disabled."), 'default': false }, 'workbench.editor.closeOnFileDelete': { diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 7ea77d336c6..dfac8e99d7e 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -386,7 +386,7 @@ configurationRegistry.registerConfiguration({ nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), ], - 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is `true`."), + 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, }, } From afbd2e826c79002ba416a58bc3cd81a77b19ea3d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 09:00:09 +0100 Subject: [PATCH 0983/1837] Remove Build jobs for now --- .github/workflows/ci.yml | 688 +++++++++++++++++++-------------------- 1 file changed, 344 insertions(+), 344 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 217911223bf..d6552532c48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,408 +54,408 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check - build-compile-core: - name: "Build: Compile Core" - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-compile-core: + # name: "Build: Compile Core" + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- - - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - 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: Cache node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # 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: Cache compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Cache compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Compile Core - if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} - run: yarn gulp compile-build + # - name: Compile Core + # if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} + # run: yarn gulp compile-build - - name: Minify VS Code - if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} - run: yarn gulp minify-vscode + # - name: Minify VS Code + # if: ${{ steps.cacheCompiledCoreCode.outputs.cache-hit != 'true' }} + # run: yarn gulp minify-vscode - build-compile-extensions: - name: "Build: Compile Extensions" - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-compile-extensions: + # name: "Build: Compile Extensions" + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- - - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - 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: Cache node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # 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: Cache compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Cache compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Compile Extensions - if: ${{ steps.cacheCompiledExtensionsCode.outputs.cache-hit != 'true' }} - run: yarn gulp compile-extensions-build + # - name: Compile Extensions + # if: ${{ steps.cacheCompiledExtensionsCode.outputs.cache-hit != 'true' }} + # run: yarn gulp compile-extensions-build - build-linux-unit-tests: - name: "Build: Linux Unit Tests" - needs: [build-compile-core, build-compile-extensions] - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-linux-unit-tests: + # name: "Build: Linux Unit Tests" + # needs: [build-compile-core, build-compile-extensions] + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start + # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + # - name: Setup Build Environment + # run: | + # sudo apt-get update + # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + # sudo chmod +x /etc/init.d/xvfb + # sudo update-rc.d xvfb defaults + # sudo service xvfb start - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- - - name: Restore compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Restore compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Restore compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Restore compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Build VS Code - run: yarn gulp vscode-linux-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-linux-x64-min-ci - - name: Download Electron - run: yarn electron x64 + # - name: Download Electron + # run: yarn electron x64 - - name: Run Unit Tests (Electron) - run: DISPLAY=:10 ./scripts/test.sh --build + # - name: Run Unit Tests (Electron) + # run: DISPLAY=:10 ./scripts/test.sh --build - - name: Download Playwright - run: node ./node_modules/playwright/install.js + # - name: Download Playwright + # run: node ./node_modules/playwright/install.js - - name: Run Unit Tests (Browser) - run: DISPLAY=:10 yarn test-browser --build --browser chromium + # - name: Run Unit Tests (Browser) + # run: DISPLAY=:10 yarn test-browser --build --browser chromium - build-linux-integration-tests: - name: "Build: Linux Integration Tests" - needs: [build-compile-core, build-compile-extensions] - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-linux-integration-tests: + # name: "Build: Linux Integration Tests" + # needs: [build-compile-core, build-compile-extensions] + # runs-on: ubuntu-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start + # # TODO: rename azure-pipelines/linux/xvfb.init to github-actions + # - name: Setup Build Environment + # run: | + # sudo apt-get update + # sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + # sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + # sudo chmod +x /etc/init.d/xvfb + # sudo update-rc.d xvfb defaults + # sudo service xvfb start - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- - - name: Restore compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Restore compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Restore compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Restore compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Build VS Code - run: yarn gulp vscode-linux-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-linux-x64-min-ci - - name: Download Electron - run: yarn electron x64 + # - name: Download Electron + # run: yarn electron x64 - - name: Run Integration Tests (Electron) - run: DISPLAY=:10 ./scripts/test-integration.sh --build + # - name: Run Integration Tests (Electron) + # run: DISPLAY=:10 ./scripts/test-integration.sh --build - build-darwin-node-modules: - name: "Build: macOS Node Modules" - runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-darwin-node-modules: + # name: "Build: macOS Node Modules" + # runs-on: macos-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- - - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - 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: Cache node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - 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-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # 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 - build-darwin-unit-tests: - name: "Build: macOS Unit Tests" - needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] - runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-darwin-unit-tests: + # name: "Build: macOS Unit Tests" + # needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] + # runs-on: macos-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- - - name: Restore compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Restore compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Restore compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Restore compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Build VS Code - run: yarn gulp vscode-darwin-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-darwin-x64-min-ci - - name: Download Electron - run: yarn electron x64 + # - name: Download Electron + # run: yarn electron x64 - - name: Run Unit Tests (Electron) - run: ./scripts/test.sh --build + # - name: Run Unit Tests (Electron) + # run: ./scripts/test.sh --build - - name: Download Playwright - run: node ./node_modules/playwright/install.js + # - name: Download Playwright + # run: node ./node_modules/playwright/install.js - - name: Run Unit Tests (Browser) - run: yarn test-browser --build --browser chromium --browser webkit --browser firefox + # - name: Run Unit Tests (Browser) + # run: yarn test-browser --build --browser chromium --browser webkit --browser firefox - build-darwin-integration-tests: - name: "Build: macOS Integration Tests" - needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] - runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-darwin-integration-tests: + # name: "Build: macOS Integration Tests" + # needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] + # runs-on: macos-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- - - name: Restore compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Restore compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Restore compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Restore compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Build VS Code - run: yarn gulp vscode-darwin-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-darwin-x64-min-ci - - name: Download Electron - run: yarn electron x64 + # - name: Download Electron + # run: yarn electron x64 - - name: Run Integration Tests (Electron) - run: ./scripts/test-integration.sh --build + # - name: Run Integration Tests (Electron) + # run: ./scripts/test-integration.sh --build - build-darwin-smoke-tests: - name: "Build: macOS Smoke Tests" - needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] - runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v2 + # build-darwin-smoke-tests: + # name: "Build: macOS Smoke Tests" + # needs: [build-compile-core, build-compile-extensions, build-darwin-node-modules] + # runs-on: macos-latest + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # steps: + # - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: 12 + # - uses: actions/setup-node@v2-beta + # with: + # node-version: 12 - - name: Restore cached node modules - id: cacheNodeModules - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + # - name: Restore cached node modules + # id: cacheNodeModules + # uses: actions/cache@v2 + # with: + # path: '**/node_modules' + # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules3- - - name: Restore compiled core code - id: cacheCompiledCoreCode - uses: actions/cache@v2 - with: - path: | - out-build - out-vscode-min - key: cacheCompiledCoreCode-${{ github.sha }} + # - name: Restore compiled core code + # id: cacheCompiledCoreCode + # uses: actions/cache@v2 + # with: + # path: | + # out-build + # out-vscode-min + # key: cacheCompiledCoreCode-${{ github.sha }} - - name: Restore compiled extensions code - id: cacheCompiledExtensionsCode - uses: actions/cache@v2 - with: - path: .build - key: cacheCompiledExtensionsCode-${{ github.sha }} + # - name: Restore compiled extensions code + # id: cacheCompiledExtensionsCode + # uses: actions/cache@v2 + # with: + # path: .build + # key: cacheCompiledExtensionsCode-${{ github.sha }} - - name: Build VS Code - run: yarn gulp vscode-darwin-x64-min-ci + # - name: Build VS Code + # run: yarn gulp vscode-darwin-x64-min-ci - - name: Run Smoke Tests (Electron) - continue-on-error: true - run: | - set -e - APP_ROOT=$(GITHUB_WORKSPACE)/VSCode-darwin-x64 - APP_NAME="`ls $APP_ROOT | head -n 1`" - yarn smoketest --build "$APP_ROOT/$APP_NAME" + # - name: Run Smoke Tests (Electron) + # continue-on-error: true + # run: | + # set -e + # APP_ROOT=$(GITHUB_WORKSPACE)/VSCode-darwin-x64 + # APP_NAME="`ls $APP_ROOT | head -n 1`" + # yarn smoketest --build "$APP_ROOT/$APP_NAME" linux: name: Linux From 1537b5bcc2513d6256678732909d00a75305c2f5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 10:07:53 +0100 Subject: [PATCH 0984/1837] windows - cleanup hack for empty windows when restoring --- .../electron-main/windowsMainService.ts | 106 +++++++++--------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 65820a3f817..470654e2d89 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -17,7 +17,7 @@ import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; -import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows'; import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder'; import { Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; @@ -319,7 +319,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const isDiff = filesToOpen && filesToOpen.filesToDiff.length > 0; if (!usedWindows.some(window => window.isExtensionDevelopmentHost) && !isDiff && !openConfig.noRecentEntry) { const recents: IRecent[] = []; - for (let pathToOpen of pathsToOpen) { + for (const pathToOpen of pathsToOpen) { if (pathToOpen.workspace) { recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace }); } else if (pathToOpen.folderUri) { @@ -601,16 +601,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic window.focus(); // make sure window has focus - const params: { filesToOpenOrCreate?: IPath[], filesToDiff?: IPath[], filesToWait?: IPathsToWaitFor, termProgram?: string } = {}; - if (filesToOpen) { - params.filesToOpenOrCreate = filesToOpen.filesToOpenOrCreate; - params.filesToDiff = filesToOpen.filesToDiff; - params.filesToWait = filesToOpen.filesToWait; - } - - if (configuration.userEnv) { - params.termProgram = configuration.userEnv['TERM_PROGRAM']; - } + const params: INativeOpenFileRequest = { + filesToOpenOrCreate: filesToOpen?.filesToOpenOrCreate, + filesToDiff: filesToOpen?.filesToDiff, + filesToWait: filesToOpen?.filesToWait, + termProgram: configuration?.userEnv?.['TERM_PROGRAM'] + }; window.sendWhenReady('vscode:openFiles', CancellationToken.None, params); @@ -618,9 +614,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } private doAddFoldersToExistingWindow(window: ICodeWindow, foldersToAdd: URI[]): ICodeWindow { + this.logService.trace('windowsManager#doAddFoldersToExistingWindow'); + window.focus(); // make sure window has focus const request: IAddFoldersRequest = { foldersToAdd }; + window.sendWhenReady('vscode:addFolders', CancellationToken.None, request); return window; @@ -649,15 +648,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } return this.openInBrowserWindow({ + workspace: folderOrWorkspace.workspace, + folderUri: folderOrWorkspace.folderUri, userEnv: openConfig.userEnv, cli: openConfig.cli, initialStartup: openConfig.initialStartup, - workspace: folderOrWorkspace.workspace, - folderUri: folderOrWorkspace.folderUri, - filesToOpen, remoteAuthority: folderOrWorkspace.remoteAuthority, forceNewWindow, forceNewTabbedWindow: openConfig.forceNewTabbedWindow, + filesToOpen, windowToUse }); } @@ -681,12 +680,18 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Extract paths: from CLI else if (openConfig.cli._.length || openConfig.cli['folder-uri'] || openConfig.cli['file-uri']) { windowsToOpen = this.doExtractPathsFromCLI(openConfig.cli); + if (windowsToOpen.length === 0) { + windowsToOpen.push(Object.create(null)); // add an empty window if we did not have windows to open from command line + } isCommandLineOrAPICall = true; } // Extract windows: from previous session else { windowsToOpen = this.doGetWindowsFromLastSession(); + if (windowsToOpen.length === 0) { + windowsToOpen.push(Object.create(null)); // add an empty window if we did not have windows to restore + } restoredWindows = true; } @@ -761,8 +766,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // folder uris const folderUris = cli['folder-uri']; if (folderUris) { - for (let f of folderUris) { - const folderUri = this.argToUri(f); + for (const rawFolderUri of folderUris) { + const folderUri = this.argToUri(rawFolderUri); if (folderUri) { const path = this.parseUri({ folderUri }, parseOptions); if (path) { @@ -775,10 +780,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // file uris const fileUris = cli['file-uri']; if (fileUris) { - for (let f of fileUris) { - const fileUri = this.argToUri(f); + for (const rawFileUri of fileUris) { + const fileUri = this.argToUri(rawFileUri); if (fileUri) { - const path = this.parseUri(hasWorkspaceFileExtension(f) ? { workspaceUri: fileUri } : { fileUri }, parseOptions); + const path = this.parseUri(hasWorkspaceFileExtension(rawFileUri) ? { workspaceUri: fileUri } : { fileUri }, parseOptions); if (path) { pathsToOpen.push(path); } @@ -787,9 +792,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } // folder or file paths - const cliArgs = cli._; - for (let cliArg of cliArgs) { - const path = this.parsePath(cliArg, parseOptions); + const cliPaths = cli._; + for (const cliPath of cliPaths) { + const path = this.parsePath(cliPath, parseOptions); if (path) { pathsToOpen.push(path); } @@ -799,8 +804,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return pathsToOpen; } - // No path provided, return empty to open empty - return [Object.create(null)]; + // No path provided + return []; } private doGetWindowsFromLastSession(): IPathToOpen[] { @@ -808,9 +813,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic switch (restoreWindowsSetting) { - // none: we always open an empty window + // none: no window to restore case 'none': - return [Object.create(null)]; + return []; // one: restore last opened workspace/folder or empty window // all: restore all windows @@ -854,15 +859,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } } - if (windowsToOpen.length > 0) { - return windowsToOpen; - } - - break; + return windowsToOpen; } - - // Always fallback to empty window - return [Object.create(null)]; } private getRestoreWindowsSetting(): RestoreWindowsSetting { @@ -962,8 +960,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return openable.fileUri; } - private parsePath(anyPath: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined { - if (!anyPath) { + private parsePath(path: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined { + if (!path) { return undefined; } @@ -971,36 +969,36 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic let columnNumber: number | undefined; if (options.gotoLineMode) { - const parsedPath = parseLineAndColumnAware(anyPath); + const parsedPath = parseLineAndColumnAware(path); lineNumber = parsedPath.line; columnNumber = parsedPath.column; - anyPath = parsedPath.path; + path = parsedPath.path; } // open remote if either specified in the cli even if it is a local file. const remoteAuthority = options.remoteAuthority; if (remoteAuthority) { - const first = anyPath.charCodeAt(0); + const first = path.charCodeAt(0); // make absolute if (first !== CharCode.Slash) { - if (isWindowsDriveLetter(first) && anyPath.charCodeAt(anyPath.charCodeAt(1)) === CharCode.Colon) { - anyPath = toSlashes(anyPath); + if (isWindowsDriveLetter(first) && path.charCodeAt(path.charCodeAt(1)) === CharCode.Colon) { + path = toSlashes(path); } - anyPath = `/${anyPath}`; + path = `/${path}`; } - const uri = URI.from({ scheme: Schemas.vscodeRemote, authority: remoteAuthority, path: anyPath }); + const uri = URI.from({ scheme: Schemas.vscodeRemote, authority: remoteAuthority, path: path }); // guess the file type: If it ends with a slash it's a folder. If it has a file extension, it's a file or a workspace. By defaults it's a folder. - if (anyPath.charCodeAt(anyPath.length - 1) !== CharCode.Slash) { - if (hasWorkspaceFileExtension(anyPath)) { + if (path.charCodeAt(path.length - 1) !== CharCode.Slash) { + if (hasWorkspaceFileExtension(path)) { if (forceOpenWorkspaceAsFile) { return { fileUri: uri, remoteAuthority }; } - } else if (posix.basename(anyPath).indexOf('.') !== -1) { // file name starts with a dot or has an file extension + } else if (posix.basename(path).indexOf('.') !== -1) { // file name starts with a dot or has an file extension return { fileUri: uri, remoteAuthority }; } } @@ -1008,7 +1006,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return { folderUri: uri, remoteAuthority }; } - let candidate = normalize(anyPath); + let candidate = normalize(path); try { const candidateStat = statSync(candidate); @@ -1105,12 +1103,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return { openFolderInNewWindow: !!openFolderInNewWindow, openFilesInNewWindow }; } - openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[] { + openExtensionDevelopmentHostWindow(extensionDevelopmentPaths: string[], openConfig: IOpenConfiguration): ICodeWindow[] { // Reload an existing extension development host window on the same path // We currently do not allow more than one extension development window // on the same extension path. - const existingWindow = findWindowOnExtensionDevelopmentPath(this.getWindows(), extensionDevelopmentPath); + const existingWindow = findWindowOnExtensionDevelopmentPath(this.getWindows(), extensionDevelopmentPaths); if (existingWindow) { this.lifecycleMainService.reload(existingWindow, openConfig.cli); existingWindow.focus(); // make sure it gets focus and is restored @@ -1144,9 +1142,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } let authority = ''; - for (let p of extensionDevelopmentPath) { - if (p.match(/^[a-zA-Z][a-zA-Z0-9\+\-\.]+:/)) { - const url = URI.parse(p); + for (const extensionDevelopmentPath of extensionDevelopmentPaths) { + if (extensionDevelopmentPath.match(/^[a-zA-Z][a-zA-Z0-9\+\-\.]+:/)) { + const url = URI.parse(extensionDevelopmentPath); if (url.scheme === Schemas.vscodeRemote) { if (authority) { if (url.authority !== authority) { @@ -1216,7 +1214,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow { - // Build INativeWindowConfiguration from config and options + // Build `INativeWindowConfiguration` from config and options const configuration = { ...options.cli } as INativeWindowConfiguration; configuration.appRoot = this.environmentService.appRoot; configuration.machineId = this.machineId; From 460b6e720efe02c8ece4e60ef7ca25c268054c91 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 10:25:02 +0100 Subject: [PATCH 0985/1837] in browsers perf util is just a wrapper around native performance --- src/vs/base/common/performance.js | 63 ++++++++++++------- .../services/timer/browser/timerService.ts | 25 +------- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 46c834352b9..5a03e119067 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -9,31 +9,50 @@ function _factory(sharedObj) { - sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || []; - - const _dataLen = 2; - const _nativeMark = typeof performance === 'object' && typeof performance.mark === 'function' ? performance.mark.bind(performance) : () => { }; - - function getMarks() { - const result = []; - const entries = sharedObj.MonacoPerformanceMarks; - for (let i = 0; i < entries.length; i += _dataLen) { - result.push({ - name: entries[i], - startTime: entries[i + 1], + if (typeof performance === 'object' && typeof performance.mark === 'function') { + // in a browser context, reuse performance-util + function mark(name) { + performance.mark(name); + } + function getMarks() { + let timeOrigin = performance.timeOrigin; + if (!timeOrigin) { + // polyfill for Safari + const entry = performance.timing; + timeOrigin = entry.navigationStart || entry.redirectStart || entry.fetchStart; + } + return performance.getEntriesByType('mark').map(entry => { + return { + name: entry.name, + startTime: Math.round(timeOrigin + entry.startTime) + }; }); } - return result; + + return { mark, getMarks }; + + } else { + // node.js context, use mock and a shared obj that's share between module systems + sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || []; + + function mark(name) { + sharedObj.MonacoPerformanceMarks.push(name, Date.now()); + } + + function getMarks() { + const result = []; + const entries = sharedObj.MonacoPerformanceMarks; + for (let i = 0; i < entries.length; i += 2) { + result.push({ + name: entries[i], + startTime: entries[i + 1], + }); + } + return result; + } + + return { mark, getMarks }; } - - function mark(name) { - sharedObj.MonacoPerformanceMarks.push(name, Date.now()); - _nativeMark(name); - } - - const exports = { mark, getMarks }; - - return exports; } // This module can be loaded in an amd and commonjs-context. diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 31dd63a4d6d..93d042637f1 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -399,13 +399,8 @@ export abstract class AbstractTimerService implements ITimerService { _lifecycleService.when(LifecyclePhase.Restored) ]).then(() => { - // import native-browser marks - this._submitNativeMarks(); - - // because "our" perf.mark-util also adds native performance marks - // no extra import of "our" marks is needed, they are already imported - // by importing native perf marks (see above) - // this.submitPerformanceMarks(perf.getMarks()); + // set perf mark from renderer + this.setPerformanceMarks('renderer', perf.getMarks()); return this._computeStartupMetrics(); }).then(metrics => { @@ -414,22 +409,6 @@ export abstract class AbstractTimerService implements ITimerService { }); } - private _submitNativeMarks(): void { - let timeOrigin = performance.timeOrigin; - if (!timeOrigin) { - // polyfill for Safari - const entry = performance.timing; - timeOrigin = entry.navigationStart || entry.redirectStart || entry.fetchStart; - } - const marks: perf.PerformanceMark[] = performance.getEntriesByType('mark').map(entry => { - return { - name: entry.name, - startTime: Math.round(timeOrigin + entry.startTime) - }; - }); - this.setPerformanceMarks('renderer', marks); - } - setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { this._marks.setMarks(source, marks); } From 9cc0fb57434065940859d3232569589eb210f596 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 10:37:11 +0100 Subject: [PATCH 0986/1837] windows - add helper method to know used window --- .../electron-main/windowsMainService.ts | 96 +++++-------------- 1 file changed, 26 insertions(+), 70 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 470654e2d89..a29c310bcfa 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -246,9 +246,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic filesToOpen.filesToWait = { paths: [...filesToOpen.filesToDiff, ...filesToOpen.filesToOpenOrCreate], waitMarkerFileUri: openConfig.waitMarkerFileURI }; } - // // These are windows to restore because of hot-exit or from previous session (only performed once on startup!) - // if (openConfig.initialStartup) { // Untitled workspaces are always restored @@ -362,8 +360,19 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic filesToOpen: IFilesToOpen | undefined, foldersToAdd: IFolderPathToOpen[] ): { windows: ICodeWindow[], filesOpenedInWindow: ICodeWindow | undefined } { + + // Keep track of used windows and remember + // if files have been opened in one of them const usedWindows: ICodeWindow[] = []; let filesOpenedInWindow: ICodeWindow | undefined = undefined; + function addUsedWindow(window: ICodeWindow, openedFiles?: boolean): void { + usedWindows.push(window); + + if (openedFiles) { + filesOpenedInWindow = window; + filesToOpen = undefined; // reset `filesToOpen` since files have been opened + } + } // Settings can decide if files/folders open in new window or not let { openFolderInNewWindow, openFilesInNewWindow } = this.shouldOpenNewWindow(openConfig); @@ -373,13 +382,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const authority = foldersToAdd[0].remoteAuthority; const lastActiveWindow = this.getLastActiveWindowForAuthority(authority); if (lastActiveWindow) { - usedWindows.push(this.doAddFoldersToExistingWindow(lastActiveWindow, foldersToAdd.map(f => f.folderUri))); + addUsedWindow(this.doAddFoldersToExistingWindow(lastActiveWindow, foldersToAdd.map(folderToAdd => folderToAdd.folderUri))); } } - // Handle files to open/diff or to create when we dont open a folder and we do not restore any folder/untitled from hot-exit - const potentialWindowsCount = foldersToOpen.length + workspacesToOpen.length + emptyToRestore.length; - if (potentialWindowsCount === 0 && filesToOpen) { + // Handle files to open/diff or to create when we dont open a folder and we do not restore any + // folder/untitled from hot-exit by trying to open them in the window that fits best + const potentialNewWindowsCount = foldersToOpen.length + workspacesToOpen.length + emptyToRestore.length; + if (filesToOpen && potentialNewWindowsCount === 0) { // Find suitable window or folder path to open files in const fileToCheck = filesToOpen.filesToOpenOrCreate[0] || filesToOpen.filesToDiff[0]; @@ -418,20 +428,13 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Window is empty else { - - // Do open files - const window = this.doOpenFilesInExistingWindow(openConfig, windowToUseForFiles, filesToOpen); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - filesToOpen = undefined; - filesOpenedInWindow = window; + addUsedWindow(this.doOpenFilesInExistingWindow(openConfig, windowToUseForFiles, filesToOpen), true); } } // Finally, if no window or folder is found, just open the files in an empty window else { - const window = this.openInBrowserWindow({ + addUsedWindow(this.openInBrowserWindow({ userEnv: openConfig.userEnv, cli: openConfig.cli, initialStartup: openConfig.initialStartup, @@ -439,12 +442,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic forceNewWindow: true, remoteAuthority: filesToOpen.remoteAuthority, forceNewTabbedWindow: openConfig.forceNewTabbedWindow - }); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - filesToOpen = undefined; - filesOpenedInWindow = window; + }), true); } } @@ -459,14 +457,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const filesToOpenInWindow = (filesToOpen?.remoteAuthority === windowOnWorkspace.remoteAuthority) ? filesToOpen : undefined; // Do open files - const window = this.doOpenFilesInExistingWindow(openConfig, windowOnWorkspace, filesToOpenInWindow); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpenInWindow) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + addUsedWindow(this.doOpenFilesInExistingWindow(openConfig, windowOnWorkspace, filesToOpenInWindow), !!filesToOpenInWindow); openFolderInNewWindow = true; // any other folders to open must open in new window then } @@ -481,14 +472,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const filesToOpenInWindow = (filesToOpen?.remoteAuthority === remoteAuthority) ? filesToOpen : undefined; // Do open folder - const window = this.doOpenFolderOrWorkspace(openConfig, workspaceToOpen, openFolderInNewWindow, filesToOpenInWindow); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpenInWindow) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + addUsedWindow(this.doOpenFolderOrWorkspace(openConfig, workspaceToOpen, openFolderInNewWindow, filesToOpenInWindow), !!filesToOpenInWindow); openFolderInNewWindow = true; // any other folders to open must open in new window then }); @@ -505,14 +489,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const filesToOpenInWindow = filesToOpen?.remoteAuthority === windowOnFolderPath.remoteAuthority ? filesToOpen : undefined; // Do open files - const window = this.doOpenFilesInExistingWindow(openConfig, windowOnFolderPath, filesToOpenInWindow); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpenInWindow) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + addUsedWindow(this.doOpenFilesInExistingWindow(openConfig, windowOnFolderPath, filesToOpenInWindow), !!filesToOpenInWindow); openFolderInNewWindow = true; // any other folders to open must open in new window then } @@ -528,14 +505,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const filesToOpenInWindow = (filesToOpen?.remoteAuthority === remoteAuthority) ? filesToOpen : undefined; // Do open folder - const window = this.doOpenFolderOrWorkspace(openConfig, folderToOpen, openFolderInNewWindow, filesToOpenInWindow); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpenInWindow) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + addUsedWindow(this.doOpenFolderOrWorkspace(openConfig, folderToOpen, openFolderInNewWindow, filesToOpenInWindow), !!filesToOpenInWindow); openFolderInNewWindow = true; // any other folders to open must open in new window then }); @@ -548,7 +518,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const remoteAuthority = emptyWindowBackupInfo.remoteAuthority; const filesToOpenInWindow = (filesToOpen?.remoteAuthority === remoteAuthority) ? filesToOpen : undefined; - const window = this.openInBrowserWindow({ + addUsedWindow(this.openInBrowserWindow({ userEnv: openConfig.userEnv, cli: openConfig.cli, initialStartup: openConfig.initialStartup, @@ -557,14 +527,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic forceNewWindow: true, forceNewTabbedWindow: openConfig.forceNewTabbedWindow, emptyWindowBackupInfo - }); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpenInWindow) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + }), !!filesToOpenInWindow); openFolderInNewWindow = true; // any other folders to open must open in new window then }); @@ -579,14 +542,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const remoteAuthority = filesToOpen ? filesToOpen.remoteAuthority : (openConfig.cli && openConfig.cli.remote || undefined); for (let i = 0; i < emptyToOpen; i++) { - const window = this.doOpenEmpty(openConfig, openFolderInNewWindow, remoteAuthority, filesToOpen); - usedWindows.push(window); - - // Reset `filesToOpen` because we handled them and also remember window we used - if (filesToOpen) { - filesToOpen = undefined; - filesOpenedInWindow = window; - } + addUsedWindow(this.doOpenEmpty(openConfig, openFolderInNewWindow, remoteAuthority, filesToOpen), !!filesToOpen); // any other window to open must open in new window then openFolderInNewWindow = true; From 27cefc2a818e5dd0ada8178b55c34d39c25fd7e9 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 11:07:12 +0100 Subject: [PATCH 0987/1837] Rename `Protocol.onClose` to `Protocol.onDidDispose` --- src/vs/base/parts/ipc/common/ipc.net.ts | 16 ++++++++-------- .../extensions/common/remoteExtensionHost.ts | 2 +- .../extensions/node/extensionHostProcessSetup.ts | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts index b27c8734f75..3f986e86486 100644 --- a/src/vs/base/parts/ipc/common/ipc.net.ts +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -365,8 +365,8 @@ export class Protocol extends Disposable implements IMessagePassingProtocol { private readonly _onMessage = new Emitter(); readonly onMessage: Event = this._onMessage.event; - private readonly _onClose = new Emitter(); - readonly onClose: Event = this._onClose.event; + private readonly _onDidDispose = new Emitter(); + readonly onDidDispose: Event = this._onDidDispose.event; constructor(socket: ISocket) { super(); @@ -380,7 +380,7 @@ export class Protocol extends Disposable implements IMessagePassingProtocol { } })); - this._register(this._socket.onClose(() => this._onClose.fire())); + this._register(this._socket.onClose(() => this._onDidDispose.fire())); } drain(): Promise { @@ -406,7 +406,7 @@ export class Client extends IPCClient { return new Client(new Protocol(socket), id); } - get onClose(): Event { return this.protocol.onClose; } + get onDidDispose(): Event { return this.protocol.onDidDispose; } constructor(private protocol: Protocol | PersistentProtocol, id: TContext, ipcLogger: IIPCLogger | null = null) { super(protocol, id, ipcLogger); @@ -621,8 +621,8 @@ export class PersistentProtocol implements IMessagePassingProtocol { private readonly _onMessage = new BufferedEmitter(); readonly onMessage: Event = this._onMessage.event; - private readonly _onClose = new BufferedEmitter(); - readonly onClose: Event = this._onClose.event; + private readonly _onDidDispose = new BufferedEmitter(); + readonly onDidDispose: Event = this._onDidDispose.event; private readonly _onSocketClose = new BufferedEmitter(); readonly onSocketClose: Event = this._onSocketClose.event; @@ -783,7 +783,7 @@ export class PersistentProtocol implements IMessagePassingProtocol { } public acceptDisconnect(): void { - this._onClose.fire(); + this._onDidDispose.fire(); } private _receiveMessage(msg: ProtocolMessage): void { @@ -820,7 +820,7 @@ export class PersistentProtocol implements IMessagePassingProtocol { } else if (msg.type === ProtocolMessageType.Control) { this._onControlMessage.fire(msg.data); } else if (msg.type === ProtocolMessageType.Disconnect) { - this._onClose.fire(); + this._onDidDispose.fire(); } else if (msg.type === ProtocolMessageType.ReplayRequest) { // Send again all unacknowledged messages const toSend = this._outgoingUnackMsg.toArray(); diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts index eddbd5f010d..40967da4cad 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts @@ -130,7 +130,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, debugPort, this._initDataProvider.remoteAuthority); } - protocol.onClose(() => { + protocol.onDidDispose(() => { this._onExtHostConnectionLost(); }); diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index e39d131fe7b..88076f1364c 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -130,7 +130,7 @@ function _createExtHostProtocol(): Promise { } else { clearTimeout(timer); protocol = new PersistentProtocol(socket, initialDataChunk); - protocol.onClose(() => onTerminate()); + protocol.onDidDispose(() => onTerminate()); resolve(protocol); // Wait for rich client to reconnect From 05b94398d5a42fe7eb824ec022d8dcfdafd3f06a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 11:12:12 +0100 Subject: [PATCH 0988/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 66ee8a569bc..9be22084329 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "e856403a200fb74359bbc46af1b5a2a59f36d2ef", + "distro": "47d34c9d35c811ed6a3832be96c8f71e5c1701da", "author": { "name": "Microsoft Corporation" }, From aa587fe40a3a31bcc90e0041ddba18e2ead01972 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 15 Dec 2020 11:47:28 +0100 Subject: [PATCH 0989/1837] Catch bad progress location in extension trees Fixes #112211 --- src/vs/workbench/browser/parts/views/treeView.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index c6febce166d..4464bf5e47a 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -776,10 +776,17 @@ class TreeDataSource implements IAsyncDataSource { } async getChildren(element: ITreeItem): Promise { + let result: ITreeItem[] = []; if (this.treeView.dataProvider) { - return this.withProgress(this.treeView.dataProvider.getChildren(element)); + try { + result = await this.withProgress(this.treeView.dataProvider.getChildren(element)); + } catch (e) { + if (!(e.message).startsWith('Bad progress location:')) { + throw e; + } + } } - return []; + return result; } } From bee1e6489794de81e5b0f881beb9277b38f07fa8 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 15 Dec 2020 12:02:06 +0100 Subject: [PATCH 0990/1837] Fix Configure Task for workspace w/ 0 folders Fixes #111815 --- src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 64f74982d46..436edea336c 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -2866,7 +2866,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } if (this.isTaskEntry(selection)) { this.configureTask(selection.task); - } else if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { + } else if (selection.folder && (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY)) { this.openTaskFile(selection.folder.toResource('.vscode/tasks.json'), TaskSourceKind.Workspace); } else { const resource = this.getResourceForKind(TaskSourceKind.User); From 690e9f1e02f98ad22fe5e127838bd96ccbb201ae Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 12:06:02 +0100 Subject: [PATCH 0991/1837] add ITimerService#whenReady --- .../performance/browser/perfviewEditor.ts | 16 ++++--- .../electron-browser/startupTimings.ts | 6 +-- .../services/timer/browser/timerService.ts | 47 +++++++++++++++---- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index 3f84050a818..fe06a15dfe7 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -12,7 +12,7 @@ import { ILifecycleService, LifecyclePhase, StartupKindToString } from 'vs/workb import { IModeService } from 'vs/editor/common/services/modeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { ITimerService, IStartupMetrics } from 'vs/workbench/services/timer/browser/timerService'; +import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; @@ -116,17 +116,17 @@ class PerfModelContentProvider implements ITextModelContentProvider { private _updateModel(): void { Promise.all([ - this._timerService.startupMetrics, + this._timerService.whenReady(), this._lifecycleService.when(LifecyclePhase.Eventually), this._extensionService.whenInstalledExtensionsRegistered() - ]).then(([metrics]) => { + ]).then(() => { if (this._model && !this._model.isDisposed()) { let stats = LoaderStats.get(); let md = new MarkdownBuilder(); - this._addSummary(md, metrics); + this._addSummary(md); md.blank(); - this._addSummaryTable(md, metrics, stats); + this._addSummaryTable(md, stats); md.blank(); this._addExtensionsTable(md); md.blank(); @@ -142,7 +142,8 @@ class PerfModelContentProvider implements ITextModelContentProvider { } - private _addSummary(md: MarkdownBuilder, metrics: IStartupMetrics): void { + private _addSummary(md: MarkdownBuilder): void { + const metrics = this._timerService.startupMetrics; md.heading(2, 'System Info'); md.li(`${this._productService.nameShort}: ${this._productService.version} (${this._productService.commit || '0000000'})`); md.li(`OS: ${metrics.platform}(${metrics.release})`); @@ -162,8 +163,9 @@ class PerfModelContentProvider implements ITextModelContentProvider { md.li(`Empty Workspace: ${metrics.emptyWorkbench}`); } - private _addSummaryTable(md: MarkdownBuilder, metrics: IStartupMetrics, stats?: LoaderStats): void { + private _addSummaryTable(md: MarkdownBuilder, stats?: LoaderStats): void { + const metrics = this._timerService.startupMetrics; const table: Array> = []; table.push(['start => app.isReady', metrics.timers.ellapsedAppReady, '[main]', `initial startup: ${metrics.initialStartup}`]); table.push(['nls:start => nls:end', metrics.timers.ellapsedNlsGeneration, '[main]', `initial startup: ${metrics.initialStartup}`]); diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts index 52f82c64dab..47c85ed5304 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts @@ -55,10 +55,10 @@ export class StartupTimings implements IWorkbenchContribution { const { sessionId } = await this._telemetryService.getTelemetryInfo(); Promise.all([ - this._timerService.startupMetrics, + this._timerService.whenReady(), timeout(15000), // wait: cached data creation, telemetry sending - ]).then(([startupMetrics]) => { - return promisify(appendFile)(appendTo, `${startupMetrics.ellapsed}\t${this._productService.nameShort}\t${(this._productService.commit || '').slice(0, 10) || '0000000000'}\t${sessionId}\t${standardStartupError === undefined ? 'standard_start' : 'NO_standard_start : ' + standardStartupError}\n`); + ]).then(() => { + return promisify(appendFile)(appendTo, `${this._timerService.startupMetrics.ellapsed}\t${this._productService.nameShort}\t${(this._productService.commit || '').slice(0, 10) || '0000000000'}\t${sessionId}\t${standardStartupError === undefined ? 'standard_start' : 'NO_standard_start : ' + standardStartupError}\n`); }).then(() => { this._nativeHostService.quit(); }).catch(err => { diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 93d042637f1..4096f477c71 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -14,6 +14,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { Barrier } from 'vs/base/common/async'; /* __GDPR__FRAGMENT__ "IMemoryInfo" : { @@ -326,10 +327,29 @@ export interface IStartupMetrics { export interface ITimerService { readonly _serviceBrand: undefined; - readonly startupMetrics: Promise; + /** + * A promise that resolved when startup timings and perf marks + * are available. This depends on lifecycle phases and extension + * hosts being started. + */ + whenReady(): Promise; + + /** + * Startup metrics. Can ONLY be accessed after `whenReady` has resolved. + */ + readonly startupMetrics: IStartupMetrics; + + /** + * Deliver performance marks from a source, like the main process or extension hosts. + * The source argument acts as an identifier and therefore it must be unique. + */ setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void; + /** + * Get all currently known performance marks by source. There is no sorting of the + * returned tuples but the marks of a tuple are guaranteed to be sorted by start times. + */ getPerformanceMarks(): [source: string, marks: readonly perf.PerformanceMark[]][]; } @@ -380,8 +400,9 @@ export abstract class AbstractTimerService implements ITimerService { declare readonly _serviceBrand: undefined; - private readonly _startupMetrics: Promise; + private readonly _barrier = new Barrier(); private readonly _marks = new PerfMarks(); + private _startupMetrics?: IStartupMetrics; constructor( @ILifecycleService private readonly _lifecycleService: ILifecycleService, @@ -394,21 +415,31 @@ export abstract class AbstractTimerService implements ITimerService { @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @ITelemetryService private readonly _telemetryService: ITelemetryService, ) { - this._startupMetrics = Promise.all([ + Promise.all([ this._extensionService.whenInstalledExtensionsRegistered(), _lifecycleService.when(LifecyclePhase.Restored) ]).then(() => { - // set perf mark from renderer this.setPerformanceMarks('renderer', perf.getMarks()); - return this._computeStartupMetrics(); }).then(metrics => { + this._startupMetrics = metrics; this._reportStartupTimes(metrics); - return metrics; + this._barrier.open(); }); } + whenReady(): Promise { + return this._barrier.wait(); + } + + get startupMetrics(): IStartupMetrics { + if (!this._startupMetrics) { + throw new Error('illegal state, MUST NOT access startupMetrics before whenReady has resolved'); + } + return this._startupMetrics; + } + setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { this._marks.setMarks(source, marks); } @@ -417,10 +448,6 @@ export abstract class AbstractTimerService implements ITimerService { return this._marks.getEntries(); } - get startupMetrics(): Promise { - return this._startupMetrics; - } - private _reportStartupTimes(metrics: IStartupMetrics): void { // report IStartupMetrics as telemetry /* __GDPR__ From 092b1365c76a06d0ed6d1429adef41b473cdd9fb Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 11:30:15 +0100 Subject: [PATCH 0992/1837] variables view: use registerAction2 #92038 --- .../contrib/debug/browser/variablesView.ts | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index 57fc19ff931..a7ba7e4dda1 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as dom from 'vs/base/browser/dom'; -import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IDebugService, IExpression, IScope, CONTEXT_VARIABLES_FOCUSED, IStackFrame, CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT, IDataBreakpointInfoResponse, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, IExpression, IScope, CONTEXT_VARIABLES_FOCUSED, IStackFrame, CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT, IDataBreakpointInfoResponse, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, VARIABLES_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; import { Variable, Scope, ErrorScope, StackFrame } from 'vs/workbench/contrib/debug/common/debugModel'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -16,7 +14,7 @@ import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRe import { IAction } from 'vs/base/common/actions'; import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; +import { ViewPane, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { ITreeRenderer, ITreeNode, ITreeMouseEvent, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; @@ -26,17 +24,18 @@ import { IAsyncDataTreeViewState } from 'vs/base/browser/ui/tree/asyncDataTree'; import { FuzzyScore, createMatches } from 'vs/base/common/filters'; import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { dispose } from 'vs/base/common/lifecycle'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { withUndefinedAsNull } from 'vs/base/common/types'; -import { IMenuService, IMenu, MenuId } from 'vs/platform/actions/common/actions'; +import { IMenuService, IMenu, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { debugCollapseAll } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { localize } from 'vs/nls'; +import { Codicon } from 'vs/base/common/codicons'; const $ = dom.$; let forgetScopes = true; @@ -179,10 +178,6 @@ export class VariablesView extends ViewPane { })); } - getActions(): IAction[] { - return [new CollapseAction(() => this.tree, true, 'explorer-action ' + ThemeIcon.asClassName(debugCollapseAll))]; - } - layoutBody(width: number, height: number): void { super.layoutBody(height, width); this.tree.layout(width, height); @@ -192,6 +187,10 @@ export class VariablesView extends ViewPane { this.tree.domFocus(); } + collapseAll(): void { + this.tree.collapseAll(); + } + private onMouseDblClick(e: ITreeMouseEvent): void { const session = this.debugService.getViewModel().focusedSession; if (session && e.element instanceof Variable && session.capabilities.supportsSetVariable) { @@ -345,7 +344,7 @@ export class VariablesRenderer extends AbstractExpressionsRenderer { const variable = expression; return { initialValue: expression.value, - ariaLabel: nls.localize('variableValueAriaLabel', "Type new variable value"), + ariaLabel: localize('variableValueAriaLabel', "Type new variable value"), validationOptions: { validation: () => variable.errorMessage ? ({ content: variable.errorMessage }) : null }, @@ -368,15 +367,15 @@ export class VariablesRenderer extends AbstractExpressionsRenderer { class VariablesAccessibilityProvider implements IListAccessibilityProvider { getWidgetAriaLabel(): string { - return nls.localize('variablesAriaTreeLabel', "Debug Variables"); + return localize('variablesAriaTreeLabel', "Debug Variables"); } getAriaLabel(element: IExpression | IScope): string | null { if (element instanceof Scope) { - return nls.localize('variableScopeAriaLabel', "Scope {0}", element.name); + return localize('variableScopeAriaLabel', "Scope {0}", element.name); } if (element instanceof Variable) { - return nls.localize({ key: 'variableAriaLabel', comment: ['Placeholders are variable name and variable value respectivly. They should not be translated.'] }, "{0}, value {1}", element.name, element.value); + return localize({ key: 'variableAriaLabel', comment: ['Placeholders are variable name and variable value respectivly. They should not be translated.'] }, "{0}, value {1}", element.name, element.value); } return null; @@ -433,3 +432,24 @@ CommandsRegistry.registerCommand({ } }); +registerAction2(class Collapse extends ViewAction { + constructor() { + super({ + id: 'variables.collapse', + viewId: VARIABLES_VIEW_ID, + title: localize('collapse', "Collapse All"), + f1: false, + icon: Codicon.collapseAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', VARIABLES_VIEW_ID) + } + }); + } + + runInView(_accessor: ServicesAccessor, view: VariablesView) { + view.collapseAll(); + } +}); + From 6eb9b8938fc4c04822f4be3a3e212e86091a084e Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 12:34:46 +0100 Subject: [PATCH 0993/1837] debug watch: use registerAction2 #92038 --- .../contrib/debug/browser/debugActions.ts | 38 ------ .../debug/browser/watchExpressionsView.ts | 120 ++++++++++++++---- .../workbench/contrib/debug/common/debug.ts | 1 + 3 files changed, 95 insertions(+), 64 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 3c94721040d..1fa14a14b21 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -327,44 +327,6 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { } } -export class AddWatchExpressionAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.addWatchExpression'; - static readonly LABEL = nls.localize('addWatchExpression', "Add Expression"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsAdd), debugService, keybindingService); - this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); - this._register(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement())); - } - - async run(): Promise { - this.debugService.addWatchExpression(); - } - - protected isEnabled(_: State): boolean { - const focusedExpression = this.debugService.getViewModel().getSelectedExpression(); - return this.debugService.getModel().getWatchExpressions().every(we => !!we.name && we !== focusedExpression); - } -} - -export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions'; - static readonly LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsRemoveAll), debugService, keybindingService); - this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); - } - - async run(): Promise { - this.debugService.removeWatchExpressions(); - } - - protected isEnabled(_: State): boolean { - return this.debugService.getModel().getWatchExpressions().length > 0; - } -} - export class FocusSessionAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.focusProcess'; static readonly LABEL = nls.localize('focusSession', "Focus Session"); diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index 3d7452aa018..4dcdd228f8d 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -3,20 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IDebugService, IExpression, CONTEXT_WATCH_EXPRESSIONS_FOCUSED } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, IExpression, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, WATCH_VIEW_ID, CONTEXT_WATCH_EXPRESSIONS_EXIST } from 'vs/workbench/contrib/debug/common/debug'; import { Expression, Variable } from 'vs/workbench/contrib/debug/common/debugModel'; -import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IAction, Action, Separator } from 'vs/base/common/actions'; import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; +import { ViewPane, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; @@ -26,13 +24,16 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { FuzzyScore } from 'vs/base/common/filters'; import { IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { VariablesRenderer } from 'vs/workbench/contrib/debug/browser/variablesView'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, ContextKeyEqualsExpr, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { dispose } from 'vs/base/common/lifecycle'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { debugCollapseAll } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { watchExpressionsAdd, watchExpressionsRemoveAll } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { registerAction2, MenuId, Action2, MenuItemAction } from 'vs/platform/actions/common/actions'; +import { localize } from 'vs/nls'; +import { Codicon } from 'vs/base/common/codicons'; const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024; let ignoreViewUpdates = false; @@ -43,6 +44,7 @@ export class WatchExpressionsView extends ViewPane { private watchExpressionsUpdatedScheduler: RunOnceScheduler; private needsRefresh = false; private tree!: WorkbenchAsyncDataTree; + private watchExpressionsExist: IContextKey; constructor( options: IViewletViewOptions, @@ -63,6 +65,8 @@ export class WatchExpressionsView extends ViewPane { this.needsRefresh = false; this.tree.updateChildren(); }, 50); + this.watchExpressionsExist = CONTEXT_WATCH_EXPRESSIONS_EXIST.bindTo(contextKeyService); + this.watchExpressionsExist.set(this.debugService.getModel().getWatchExpressions().length > 0); } renderBody(container: HTMLElement): void { @@ -98,6 +102,7 @@ export class WatchExpressionsView extends ViewPane { this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); this._register(this.tree.onMouseDblClick(e => this.onMouseDblClick(e))); this._register(this.debugService.getModel().onDidChangeWatchExpressions(async we => { + this.watchExpressionsExist.set(this.debugService.getModel().getWatchExpressions().length > 0); if (!this.isBodyVisible()) { this.needsRefresh = true; } else { @@ -158,12 +163,8 @@ export class WatchExpressionsView extends ViewPane { this.tree.domFocus(); } - getActions(): IAction[] { - return [ - new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService), - new CollapseAction(() => this.tree, true, 'explorer-action ' + ThemeIcon.asClassName(debugCollapseAll)), - new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService) - ]; + collapseAll(): void { + this.tree.collapseAll(); } private onMouseDblClick(e: ITreeMouseEvent): void { @@ -192,27 +193,27 @@ export class WatchExpressionsView extends ViewPane { if (element instanceof Expression) { const expression = element; - actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService)); - actions.push(new Action('debug.editWatchExpression', nls.localize('editWatchExpression', "Edit Expression"), undefined, true, () => { + actions.push(this.instantiationService.createInstance(MenuItemAction, addWatchExpressionCommand, undefined, {})); + actions.push(new Action('debug.editWatchExpression', localize('editWatchExpression', "Edit Expression"), undefined, true, () => { this.debugService.getViewModel().setSelectedExpression(expression); return Promise.resolve(); })); actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, expression, 'watch')); actions.push(new Separator()); - actions.push(new Action('debug.removeWatchExpression', nls.localize('removeWatchExpression', "Remove Expression"), undefined, true, () => { + actions.push(new Action('debug.removeWatchExpression', localize('removeWatchExpression', "Remove Expression"), undefined, true, () => { this.debugService.removeWatchExpressions(expression.getId()); return Promise.resolve(); })); - actions.push(new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService)); + actions.push(this.instantiationService.createInstance(MenuItemAction, removeAllWatchExpressionsCommand, undefined, {})); } else { - actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService)); + actions.push(this.instantiationService.createInstance(MenuItemAction, addWatchExpressionCommand, undefined, {})); if (element instanceof Variable) { const variable = element as Variable; actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, variable, 'watch')); actions.push(new Separator()); } - actions.push(new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService)); + actions.push(this.instantiationService.createInstance(MenuItemAction, removeAllWatchExpressionsCommand, undefined, {})); } this.contextMenuService.showContextMenu({ @@ -287,8 +288,8 @@ export class WatchExpressionsRenderer extends AbstractExpressionsRenderer { protected getInputBoxOptions(expression: IExpression): IInputBoxOptions { return { initialValue: expression.name ? expression.name : '', - ariaLabel: nls.localize('watchExpressionInputAriaLabel', "Type watch expression"), - placeholder: nls.localize('watchExpressionPlaceholder', "Expression to watch"), + ariaLabel: localize('watchExpressionInputAriaLabel', "Type watch expression"), + placeholder: localize('watchExpressionPlaceholder', "Expression to watch"), onFinish: (value: string, success: boolean) => { if (success && value) { this.debugService.renameWatchExpression(expression.getId(), value); @@ -306,16 +307,16 @@ export class WatchExpressionsRenderer extends AbstractExpressionsRenderer { class WatchExpressionsAccessibilityProvider implements IListAccessibilityProvider { getWidgetAriaLabel(): string { - return nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel' }, "Debug Watch Expressions"); + return localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel' }, "Debug Watch Expressions"); } getAriaLabel(element: IExpression): string { if (element instanceof Expression) { - return nls.localize('watchExpressionAriaLabel', "{0}, value {1}", (element).name, (element).value); + return localize('watchExpressionAriaLabel', "{0}, value {1}", (element).name, (element).value); } // Variable - return nls.localize('watchVariableAriaLabel', "{0}, value {1}", (element).name, (element).value); + return localize('watchVariableAriaLabel', "{0}, value {1}", (element).name, (element).value); } } @@ -359,3 +360,70 @@ class WatchExpressionsDragAndDrop implements ITreeDragAndDrop { this.debugService.moveWatchExpression(draggedElement.getId(), position); } } + +registerAction2(class Collapse extends ViewAction { + constructor() { + super({ + id: 'watch.collapse', + viewId: WATCH_VIEW_ID, + title: localize('collapse', "Collapse All"), + f1: false, + icon: Codicon.collapseAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', WATCH_VIEW_ID) + } + }); + } + + runInView(_accessor: ServicesAccessor, view: WatchExpressionsView) { + view.collapseAll(); + } +}); + + +const addWatchExpressionCommand = { + id: 'workbench.debug.viewlet.action.addWatchExpression', // Use old and long id for backwards compatibility + title: localize('addWatchExpression', "Add Expression"), + f1: false, + icon: watchExpressionsAdd, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', WATCH_VIEW_ID) + } +}; +registerAction2(class AddWatchExpressionAction extends Action2 { + constructor() { + super(addWatchExpressionCommand); + } + + run(accessor: ServicesAccessor): void { + const debugService = accessor.get(IDebugService); + debugService.addWatchExpression(); + } +}); + +const removeAllWatchExpressionsCommand = { + id: 'workbench.debug.viewlet.action.removeAllWatchExpressions', // Use old and long id for backwards compatibility + title: localize('removeAllWatchExpressions', "Remove All Expressions"), + f1: false, + icon: watchExpressionsRemoveAll, + precondition: CONTEXT_WATCH_EXPRESSIONS_EXIST, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', WATCH_VIEW_ID) + } +}; +registerAction2(class RemoveAllWatchExpressionsAction extends Action2 { + constructor() { + super(removeAllWatchExpressionsCommand); + } + + run(accessor: ServicesAccessor): void { + const debugService = accessor.get(IDebugService); + debugService.removeWatchExpressions(); + } +}); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 253547f14a5..49b70cd0aed 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -47,6 +47,7 @@ export const CONTEXT_BREAKPOINT_WIDGET_VISIBLE = new RawContextKey('bre export const CONTEXT_IN_BREAKPOINT_WIDGET = new RawContextKey('inBreakpointWidget', false); export const CONTEXT_BREAKPOINTS_FOCUSED = new RawContextKey('breakpointsFocused', true); export const CONTEXT_WATCH_EXPRESSIONS_FOCUSED = new RawContextKey('watchExpressionsFocused', true); +export const CONTEXT_WATCH_EXPRESSIONS_EXIST = new RawContextKey('watchExpressionsExist', true); export const CONTEXT_VARIABLES_FOCUSED = new RawContextKey('variablesFocused', true); export const CONTEXT_EXPRESSION_SELECTED = new RawContextKey('expressionSelected', false); export const CONTEXT_BREAKPOINT_SELECTED = new RawContextKey('breakpointSelected', false); From 0f56b9b68682aaf6d2d7ff226f0a995464c3f85f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 13:03:24 +0100 Subject: [PATCH 0994/1837] add embedder API to retrieve (startup) performance marks --- src/vs/workbench/browser/web.main.ts | 8 ++++++++ src/vs/workbench/workbench.web.api.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 4a234587574..0241ac71a71 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -62,6 +62,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; import { BrowserWindow } from 'vs/workbench/browser/window'; +import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; class BrowserMain extends Disposable { @@ -114,11 +115,18 @@ class BrowserMain extends Disposable { return instantiationService.invokeFunction(accessor => { const commandService = accessor.get(ICommandService); const lifecycleService = accessor.get(ILifecycleService); + const timerService = accessor.get(ITimerService); return { commands: { executeCommand: (command, ...args) => commandService.executeCommand(command, ...args) }, + env: { + async retrievePerformanceMarks() { + await timerService.whenReady(); + return timerService.getPerformanceMarks(); + } + }, shutdown: () => lifecycleService.shutdown() }; }); diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index e4409b3bc16..f17c4c61b2e 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -442,10 +442,36 @@ interface IWorkbenchConstructionOptions { //#endregion } +interface IPerformanceMark { + /** + * The name of a performace marker. + */ + readonly name: string; + + /** + * The UNIX timestamp at which the marker has been set. + */ + readonly startTime: number; +} + interface IWorkbench { commands: { executeCommand(command: string, ...args: any[]): Promise; }, + env: { + /** + * Retrieve performance marks that have been collected during startup. This function + * returns tuples of source and marks. A source is a dedicated context, like + * the renderer or an extension host. + * + * *Note* that marks can be collected on different machines and in different processes + * and that therefore "different clocks" are used. So, comparing `startTime`-properties + * across contexts should be taken with a grain of salt. + * + * @returns A promise that resolves to tuples of source and marks. + */ + retrievePerformanceMarks(): Promise<[string, readonly IPerformanceMark[]][]>; + } shutdown: () => void; } From 607a0b8f133464c9bbc438a95413b5112b12060f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 14:41:21 +0100 Subject: [PATCH 0995/1837] in addition to file watching, use text file service onDidSave, fixes https://github.com/microsoft/vscode/issues/112477 --- .../workbench/contrib/snippets/browser/snippetsService.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts index a1bace7ed6a..4fd656c8b1c 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts @@ -29,6 +29,7 @@ import { ResourceMap } from 'vs/base/common/map'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { isStringArray } from 'vs/base/common/types'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; namespace snippetExt { @@ -180,6 +181,7 @@ class SnippetsService implements ISnippetsService { @IModeService private readonly _modeService: IModeService, @ILogService private readonly _logService: ILogService, @IFileService private readonly _fileService: IFileService, + @ITextFileService private readonly _textfileService: ITextFileService, @IExtensionResourceLoaderService private readonly _extensionResourceLoaderService: IExtensionResourceLoaderService, @ILifecycleService lifecycleService: ILifecycleService, @IInstantiationService instantiationService: IInstantiationService, @@ -371,6 +373,11 @@ class SnippetsService implements ISnippetsService { } }; + bucket.add(this._textfileService.files.onDidSave(e => { + if (resources.isEqualOrParent(e.model.resource, folder)) { + addFolderSnippets(); + } + })); bucket.add(watch(this._fileService, folder, addFolderSnippets)); bucket.add(disposables); return addFolderSnippets(); From 6c5916cafe13f1a258f458e8d4ed7ac014e4a7e4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 14:50:53 +0100 Subject: [PATCH 0996/1837] web api - document some methods I forgot --- src/vs/workbench/workbench.web.api.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index f17c4c61b2e..8a7d6bb4c09 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -456,8 +456,13 @@ interface IPerformanceMark { interface IWorkbench { commands: { + + /** + * Allows to execute a command, either built-in or from extensions. + */ executeCommand(command: string, ...args: any[]): Promise; }, + env: { /** * Retrieve performance marks that have been collected during startup. This function @@ -472,6 +477,15 @@ interface IWorkbench { */ retrievePerformanceMarks(): Promise<[string, readonly IPerformanceMark[]][]>; } + + /** + * Triggers shutdown of the workbench programmatically. After this method is + * called, the workbench is not usable anymore and the page needs to reload + * or closed. + * + * This will also remove any `beforeUnload` handlers that would bring up a + * confirmation dialog. + */ shutdown: () => void; } @@ -626,7 +640,10 @@ export { IDefaultEditor, IDefaultLayout, IDefaultPanelLayout, - IDefaultSideBarLayout + IDefaultSideBarLayout, + + // Env + IPerformanceMark }; //#endregion From d444826441aed51d7190a58349e5b7f4049baa68 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 15:18:59 +0100 Subject: [PATCH 0997/1837] Revert "debug: stop supporting enableBreakpointsFor" This reverts commit 9f2ce5386713184ef65d1917e84eb6da8b480395. --- .../workbench/contrib/debug/browser/debugAdapterManager.ts | 5 +++++ src/vs/workbench/contrib/debug/common/debug.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts index bf1fc62feef..7c5a4122ed5 100644 --- a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts @@ -54,6 +54,11 @@ export class AdapterManager implements IAdapterManager { if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { added.collector.error(nls.localize('debugNoType', "Debugger 'type' can not be omitted and must be of type 'string'.")); } + if (rawAdapter.enableBreakpointsFor) { // Support deprecated field since the php-debug extension depends on it + rawAdapter.enableBreakpointsFor.languageIds.forEach(modeId => { + this.breakpointModeIdsSet.add(modeId); + }); + } if (rawAdapter.type !== '*') { const existing = this.getDebugger(rawAdapter.type); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 49b70cd0aed..b2dabf752df 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -630,6 +630,7 @@ export interface IDebuggerContribution extends IPlatformSpecificAdapterContribut // supported languages languages?: string[]; + enableBreakpointsFor?: { languageIds: string[] }; // debug configuration support configurationAttributes?: any; From 7743d971b1082924342c50f4cd2ae05564643c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 14:47:25 +0100 Subject: [PATCH 0998/1837] concurrently -> run-run-all --- package.json | 4 +- test/automation/package.json | 9 +- test/automation/yarn.lock | 321 +++++++++++++++++++++++++++-------- test/smoke/package.json | 8 +- test/smoke/yarn.lock | 256 ++++++++++++++++++++-------- yarn.lock | 216 ++++++++++++++++++----- 6 files changed, 624 insertions(+), 190 deletions(-) diff --git a/package.json b/package.json index 9be22084329..12e2fdd39ce 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "preinstall": "node build/npm/preinstall.js", "postinstall": "node build/npm/postinstall.js", "compile": "gulp compile --max_old_space_size=4095", - "watch": "concurrently \"npm:watch-client\" \"npm:watch-extensions\"", + "watch": "npm-run-all -lp watch-client watch-extensions", "watchd": "deemon yarn watch", "watch-webd": "deemon yarn watch-web", "kill-watchd": "deemon --kill yarn watch", @@ -106,7 +106,6 @@ "ansi-colors": "^3.2.3", "asar": "^3.0.3", "chromium-pickle-js": "^0.2.0", - "concurrently": "^5.2.0", "copy-webpack-plugin": "^4.5.2", "cson-parser": "^1.3.3", "css-loader": "^3.2.0", @@ -157,6 +156,7 @@ "mkdirp": "^0.5.0", "mocha": "^2.2.5", "mocha-junit-reporter": "^1.17.0", + "npm-run-all": "^4.1.5", "opn": "^6.0.0", "optimist": "0.3.5", "p-all": "^1.0.0", diff --git a/test/automation/package.json b/test/automation/package.json index 8fced3ba824..1ec921e5bef 100644 --- a/test/automation/package.json +++ b/test/automation/package.json @@ -11,7 +11,8 @@ "scripts": { "prepare": "npm run compile", "compile": "npm run copy-driver && npm run copy-driver-definition && tsc", - "watch": "concurrently \"npm run watch-driver\" \"npm run watch-driver-definition\" \"tsc --watch\"", + "watch": "npm-run-all -lp watch-driver watch-driver-definition watch-tsc", + "watch-tsc": "tsc --watch --preserveWatchOutput", "copy-driver": "cpx src/driver.js out/", "watch-driver": "cpx src/driver.js out/ -w", "copy-driver-definition": "node tools/copy-driver-definition.js", @@ -25,11 +26,11 @@ "@types/ncp": "2.0.1", "@types/node": "^12.11.7", "@types/tmp": "0.1.0", - "concurrently": "^3.5.1", "cpx": "^1.5.0", + "npm-run-all": "^4.1.5", + "tree-kill": "1.2.2", "typescript": "3.7.5", - "watch": "^1.0.2", - "tree-kill": "1.2.2" + "watch": "^1.0.2" }, "dependencies": { "mkdirp": "^0.5.1", diff --git a/test/automation/yarn.lock b/test/automation/yarn.lock index 11785373d40..cf8184cc4c5 100644 --- a/test/automation/yarn.lock +++ b/test/automation/yarn.lock @@ -205,6 +205,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -270,11 +278,6 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -commander@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" - integrity sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0= - component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -285,21 +288,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concurrently@^3.5.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.6.1.tgz#2f95baec5c4051294dfbb55b57a3b98a3e2b45ec" - integrity sha512-/+ugz+gwFSEfTGUxn0KHkY+19XPRTXR8+7oUK/HxgiN1n7FjeJmkrbSiXAJfyQ0zORgJYPaenmymwon51YXH9Q== - dependencies: - chalk "^2.4.1" - commander "2.6.0" - date-fns "^1.23.0" - lodash "^4.5.1" - read-pkg "^3.0.0" - rx "2.3.24" - spawn-command "^0.0.2-1" - supports-color "^3.2.3" - tree-kill "^1.1.0" - console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -337,10 +325,16 @@ cpx@^1.5.0: shell-quote "^1.6.1" subarg "^1.0.0" -date-fns@^1.23.0: - version "1.30.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" - integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" debug@^2.2.0, debug@^2.3.3: version "2.6.9" @@ -366,6 +360,13 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -410,6 +411,33 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -555,6 +583,11 @@ fsevents@^1.0.0: nan "^2.12.1" node-pre-gyp "^0.12.0" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -569,6 +602,15 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -608,21 +650,26 @@ glob@^7.0.5, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= +graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -659,10 +706,17 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hosted-git-info@^2.1.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" - integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== iconv-lite@^0.4.4: version "0.4.24" @@ -727,6 +781,18 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -741,6 +807,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -807,6 +878,11 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-negative-zero@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -843,6 +919,20 @@ is-primitive@^2.0.0: resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -853,6 +943,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -904,11 +999,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -lodash@^4.5.1: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -926,6 +1016,11 @@ math-random@^1.0.1: resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + merge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" @@ -1062,6 +1157,11 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + node-pre-gyp@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" @@ -1116,6 +1216,21 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -1145,6 +1260,16 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.8.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -1152,6 +1277,16 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1220,6 +1355,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -1232,6 +1372,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +pidtree@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" + integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== + pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -1342,13 +1487,21 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.7, resolve@^1.10.0: +resolve@^1.1.7: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== dependencies: path-parse "^1.0.6" +resolve@^1.10.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -1361,11 +1514,6 @@ rimraf@^2.6.1, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rx@2.3.24: - version "2.3.24" - resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" - integrity sha1-FPlQpCF9fjXapxu8vljv9o6ksrc= - safe-buffer@^5.0.1, safe-buffer@^5.1.2: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -1393,7 +1541,7 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -"semver@2 || 3 || 4 || 5", semver@^5.3.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -1413,6 +1561,18 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + shell-quote@^1.6.1: version "1.7.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.1.tgz#3161d969886fb14f9140c65245a5dd19b6f0b06b" @@ -1474,36 +1634,31 @@ source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -spawn-command@^0.0.2-1: - version "0.0.2-1" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= - spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.7" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -1537,6 +1692,31 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string.prototype.padend@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz#824c84265dbac46cade2b957b38b6a5d8d1683c5" + integrity sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + +string.prototype.trimend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1575,13 +1755,6 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1639,11 +1812,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== -tree-kill@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" - integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== - typescript@3.7.5: version "3.7.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" @@ -1703,6 +1871,13 @@ watch@^1.0.2: exec-sh "^0.2.0" minimist "^1.2.0" +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" diff --git a/test/smoke/package.json b/test/smoke/package.json index 28acde77a9f..0080562312b 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -5,7 +5,9 @@ "scripts": { "postinstall": "npm run compile", "compile": "yarn --cwd ../automation compile && tsc", - "watch": "concurrently \"yarn --cwd ../automation watch --preserveWatchOutput\" \"tsc --watch --preserveWatchOutput\"", + "watch-automation": "yarn --cwd ../automation watch", + "watch-smoke": "tsc --watch --preserveWatchOutput", + "watch": "npm-run-all -lp watch-automation watch-smoke", "mocha": "mocha" }, "devDependencies": { @@ -15,7 +17,6 @@ "@types/ncp": "2.0.1", "@types/node": "^12.11.7", "@types/rimraf": "2.0.2", - "concurrently": "^3.5.1", "cpx": "^1.5.0", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", @@ -29,5 +30,8 @@ "tmp": "0.0.33", "typescript": "3.7.5", "watch": "^1.0.2" + }, + "dependencies": { + "npm-run-all": "^4.1.5" } } diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 9ce4feaa1e8..9da8729e642 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -243,6 +243,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + camelcase@^5.0.0: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -317,11 +325,6 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -commander@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" - integrity sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0= - commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -337,21 +340,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concurrently@^3.5.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.6.1.tgz#2f95baec5c4051294dfbb55b57a3b98a3e2b45ec" - integrity sha512-/+ugz+gwFSEfTGUxn0KHkY+19XPRTXR8+7oUK/HxgiN1n7FjeJmkrbSiXAJfyQ0zORgJYPaenmymwon51YXH9Q== - dependencies: - chalk "^2.4.1" - commander "2.6.0" - date-fns "^1.23.0" - lodash "^4.5.1" - read-pkg "^3.0.0" - rx "2.3.24" - spawn-command "^0.0.2-1" - supports-color "^3.2.3" - tree-kill "^1.1.0" - copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" @@ -384,16 +372,22 @@ cpx@^1.5.0: shell-quote "^1.6.1" subarg "^1.0.0" +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -date-fns@^1.23.0: - version "1.30.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" - integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== - debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -529,6 +523,24 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -710,6 +722,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -761,21 +782,21 @@ glob@^7.0.5, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -900,6 +921,18 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -978,6 +1011,11 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-negative-zero@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -1021,6 +1059,13 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -1110,7 +1155,7 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.16.4, lodash@^4.17.15, lodash@^4.5.1: +lodash@^4.16.4, lodash@^4.17.15: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== @@ -1148,6 +1193,11 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + merge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" @@ -1308,6 +1358,11 @@ ncp@^2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + node-environment-flags@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" @@ -1333,6 +1388,21 @@ normalize-path@^2.0.0, normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -1347,6 +1417,11 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== +object-inspect@^1.8.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -1369,6 +1444,16 @@ object.assign@4.1.0, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.getownpropertydescriptors@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" @@ -1456,6 +1541,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -1468,6 +1558,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +pidtree@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" + integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== + pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -1596,13 +1691,21 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.7, resolve@^1.10.0: +resolve@^1.1.7: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" +resolve@^1.10.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -1615,11 +1718,6 @@ rimraf@^2.6.1: dependencies: glob "^7.1.3" -rx@2.3.24: - version "2.3.24" - resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" - integrity sha1-FPlQpCF9fjXapxu8vljv9o6ksrc= - safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -1637,7 +1735,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"semver@2 || 3 || 4 || 5", semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -1657,6 +1755,18 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + shell-quote@^1.6.1: version "1.7.2" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" @@ -1713,36 +1823,31 @@ source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -spawn-command@^0.0.2-1: - version "0.0.2-1" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= - spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.7" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -1781,6 +1886,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string.prototype.padend@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz#824c84265dbac46cade2b957b38b6a5d8d1683c5" + integrity sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string.prototype.trimend@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz#ee497fd29768646d84be2c9b819e292439614373" @@ -1789,6 +1903,14 @@ string.prototype.trimend@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string.prototype.trimleft@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" @@ -1815,6 +1937,14 @@ string.prototype.trimstart@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimstart@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -1867,13 +1997,6 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1913,11 +2036,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tree-kill@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - typescript@3.7.5: version "3.7.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" @@ -1977,7 +2095,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1: +which@1.3.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== diff --git a/yarn.lock b/yarn.lock index 7a328eec3e6..652ee9b7e06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1567,6 +1567,14 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + callsites@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" @@ -1622,7 +1630,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2139,21 +2147,6 @@ concat-with-sourcemaps@^1.0.0: dependencies: source-map "^0.5.1" -concurrently@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-5.2.0.tgz#ead55121d08a0fc817085584c123cedec2e08975" - integrity sha512-XxcDbQ4/43d6CxR7+iV8IZXhur4KbmEJk1CetVMUqCy34z9l0DkszbY+/9wvmSnToTej0SYomc2WSRH+L0zVJw== - dependencies: - chalk "^2.4.2" - date-fns "^2.0.1" - lodash "^4.17.15" - read-pkg "^4.0.1" - rxjs "^6.5.2" - spawn-command "^0.0.2-1" - supports-color "^6.1.0" - tree-kill "^1.2.2" - yargs "^13.3.0" - config-chain@^1.1.11, config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -2462,11 +2455,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@^2.0.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.14.0.tgz#359a87a265bb34ef2e38f93ecf63ac453f9bc7ba" - integrity sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw== - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -2983,6 +2971,33 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: version "0.10.35" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.35.tgz#18ee858ce6a3c45c7d79e91c15fcca9ec568494f" @@ -3939,6 +3954,15 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4574,6 +4598,11 @@ has-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -5015,6 +5044,11 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + is-ci@^1.0.9: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" @@ -5036,6 +5070,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -5143,6 +5182,11 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= +is-negative-zero@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-number@^2.0.2, is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -5213,6 +5257,13 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-relative@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" @@ -5239,6 +5290,13 @@ is-svg@^2.0.0: dependencies: html-comment-regex "^1.1.0" +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5711,6 +5769,16 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -6019,6 +6087,11 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + merge-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" @@ -6636,6 +6709,21 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6699,11 +6787,21 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.8.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + object-keys@^1.0.11, object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" @@ -6726,6 +6824,16 @@ object.assign@^4.0.4: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" @@ -7229,6 +7337,11 @@ picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +pidtree@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" + integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -7931,14 +8044,14 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" - integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= dependencies: + load-json-file "^4.0.0" normalize-package-data "^2.3.2" - parse-json "^4.0.0" - pify "^3.0.0" + path-type "^3.0.0" read@^1.0.7: version "1.0.7" @@ -8438,13 +8551,6 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" -rxjs@^6.5.2: - version "6.6.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84" - integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg== - dependencies: - tslib "^1.9.0" - rxjs@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" @@ -8646,6 +8752,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shell-quote@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + shimmer@^1.1.0, shimmer@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" @@ -8815,11 +8926,6 @@ sparkles@^1.0.0: resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= -spawn-command@^0.0.2-1: - version "0.0.2-1" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= - spdlog@^0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/spdlog/-/spdlog-0.11.1.tgz#29721b31018a5fe6a3ce2531f9d8d43e0bd6b825" @@ -9046,6 +9152,31 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string.prototype.padend@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz#824c84265dbac46cade2b957b38b6a5d8d1683c5" + integrity sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + +string.prototype.trimend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -9127,6 +9258,11 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -10554,7 +10690,7 @@ yargs@^13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" -yargs@^13.3.0, yargs@^13.3.2: +yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== From 175c1298b84d587516aaf82efba5443c9fdf25e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 15:27:23 +0100 Subject: [PATCH 0999/1837] remove all usage of concurrently --- .github/workflows/ci.yml | 18 +++++++++--------- package.json | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6552532c48..fd519deb7d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: id: cacheNodeModules uses: actions/cache@v2 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path @@ -483,7 +483,7 @@ jobs: id: cacheNodeModules uses: actions/cache@v2 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path @@ -505,7 +505,7 @@ jobs: run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download - run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + run: yarn npm-run-all --max_old_space_size=4095 -lp compile "electron x64" playwright-install download-builtin-extensions - name: Run Unit Tests (Electron) id: electron-unit-tests @@ -534,13 +534,13 @@ jobs: - uses: actions/setup-python@v2 with: - python-version: '2.x' + python-version: "2.x" - name: Cache node modules id: cacheNodeModules uses: actions/cache@v2 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path @@ -562,7 +562,7 @@ jobs: run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download - run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + run: yarn npm-run-all --max_old_space_size=4095 -lp compile "electron x64" playwright-install download-builtin-extensions - name: Run Unit Tests (Electron) run: .\scripts\test.bat @@ -589,7 +589,7 @@ jobs: id: cacheNodeModules uses: actions/cache@v2 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Get yarn cache directory path @@ -611,7 +611,7 @@ jobs: run: yarn --frozen-lockfile --network-timeout 180000 - name: Compile and Download - run: yarn concurrently --max_old_space_size=4095 --names "compile,electron,playwright,builtin-extensions" "yarn compile" "yarn electron x64" "node ./node_modules/playwright/install.js" "yarn download-builtin-extensions" + run: yarn npm-run-all --max_old_space_size=4095 -lp compile "electron x64" playwright-install download-builtin-extensions - name: Run Unit Tests (Electron) run: DISPLAY=:10 ./scripts/test.sh @@ -638,7 +638,7 @@ jobs: id: cacheNodeModules uses: actions/cache@v2 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} restore-keys: ${{ runner.os }}-cacheNodeModules3- - name: Execute yarn diff --git a/package.json b/package.json index 12e2fdd39ce..fc90cca75a9 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "compile-web": "gulp compile-web --max_old_space_size=4095", "watch-web": "gulp watch-web --max_old_space_size=4095", "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", - "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.5" + "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.5", + "playwright-install": "node node_modules/playwright/install.js" }, "dependencies": { "applicationinsights": "1.0.8", From 181d5dafba6f0456af10fa779d8b2cae6a5cee57 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 15:37:28 +0100 Subject: [PATCH 1000/1837] editors - show progress when waiting for auto save to complete to take long (fix #112278) --- .../backup/electron-sandbox/backupTracker.ts | 22 +++++++++++++++---- .../electron-browser/backupTracker.test.ts | 6 +++-- .../browser/browserTextFileService.ts | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts index d2c4f92fbd5..60a54808e43 100644 --- a/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts @@ -20,7 +20,9 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { SaveReason } from 'vs/workbench/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CancellationToken } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; +import { raceCancellation } from 'vs/base/common/async'; export class NativeBackupTracker extends BackupTracker implements IWorkbenchContribution { @@ -47,7 +49,8 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont @INativeHostService private readonly nativeHostService: INativeHostService, @ILogService logService: ILogService, @IEditorService private readonly editorService: IEditorService, - @IEnvironmentService private readonly environmentService: IEnvironmentService + @IEnvironmentService private readonly environmentService: IEnvironmentService, + @IProgressService private readonly progressService: IProgressService ) { super(backupFileService, workingCopyService, logService, lifecycleService); } @@ -87,8 +90,19 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont // and then check again for dirty copies if (this.filesConfigurationService.getAutoSaveMode() !== AutoSaveMode.OFF) { - // Save all files - await this.doSaveAllBeforeShutdown(false /* not untitled */, SaveReason.AUTO); + // Save all files but show progress and allow to cancel + // (https://github.com/microsoft/vscode/issues/112278) + const cts = new CancellationTokenSource(); + await this.progressService.withProgress({ + location: ProgressLocation.Notification, + cancellable: true, + delay: 800, // delay notification so that it only appears when saving takes a long time + title: localize('saveBeforeShutdown', "Waiting for dirty editors to save...") + }, () => { + const autoSavePromise = this.doSaveAllBeforeShutdown(false /* not untitled */, SaveReason.AUTO); + + return raceCancellation(autoSavePromise, cts.token); + }, () => cts.dispose(true)); // If we still have dirty working copies, we either have untitled ones or working copies that cannot be saved const remainingDirtyWorkingCopies = this.workingCopyService.dirtyWorkingCopies; diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts index f5943dc4866..0be5a78b4ad 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts @@ -49,6 +49,7 @@ import { TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices' import { CancellationToken } from 'vs/base/common/cancellation'; import { timeout } from 'vs/base/common/async'; import { Workspace } from 'vs/platform/workspace/test/common/testWorkspace'; +import { IProgressService } from 'vs/platform/progress/common/progress'; const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backuprestorer'); const backupHome = path.join(userdataDir, 'Backups'); @@ -70,9 +71,10 @@ class TestBackupTracker extends NativeBackupTracker { @INativeHostService nativeHostService: INativeHostService, @ILogService logService: ILogService, @IEditorService editorService: IEditorService, - @IEnvironmentService environmentService: IEnvironmentService + @IEnvironmentService environmentService: IEnvironmentService, + @IProgressService progressService: IProgressService ) { - super(backupFileService, filesConfigurationService, workingCopyService, lifecycleService, fileDialogService, dialogService, contextService, nativeHostService, logService, editorService, environmentService); + super(backupFileService, filesConfigurationService, workingCopyService, lifecycleService, fileDialogService, dialogService, contextService, nativeHostService, logService, editorService, environmentService, progressService); } protected getBackupScheduleDelay(): number { diff --git a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts index 941b946dcb2..47cc41a2739 100644 --- a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts +++ b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts @@ -17,7 +17,7 @@ export class BrowserTextFileService extends AbstractTextFileService { this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason), 'veto.textFiles')); } - protected onBeforeShutdown(reason: ShutdownReason): boolean { + private onBeforeShutdown(reason: ShutdownReason): boolean { if (this.files.models.some(model => model.hasState(TextFileEditorModelState.PENDING_SAVE))) { return true; // files are pending to be saved: veto } From 3a8b161dcc803e9f1e50100f4edbea81acd560cb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 15 Dec 2020 15:40:05 +0100 Subject: [PATCH 1001/1837] #103869 remove user value if set to default and target is not passed --- .../browser/configurationService.ts | 30 +++++++++++-------- .../configurationService.test.ts | 12 ++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 66576ad7646..9a2fd8e3049 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -288,13 +288,22 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat updateValue(key: string, value: any, target: ConfigurationTarget): Promise; updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): Promise; updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError: boolean): Promise; - updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): Promise { - return this.cyclicDependency.then(() => { - const overrides = isConfigurationOverrides(arg3) ? arg3 : undefined; - const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); - return target ? this.writeConfigurationValue(key, value, target, overrides, donotNotifyError) - : Promise.resolve(); - }); + async updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): Promise { + await this.cyclicDependency; + const overrides = isConfigurationOverrides(arg3) ? arg3 : undefined; + let target: ConfigurationTarget | undefined = overrides ? arg4 : arg3; + + if (!target) { + const inspect = this.inspect(key, overrides); + target = this.deriveConfigurationTarget(key, value, inspect); + if (target === ConfigurationTarget.USER && equals(value, inspect.defaultValue)) { + value = undefined; + } + } + + if (target) { + await this.writeConfigurationValue(key, value, target, overrides, donotNotifyError); + } } async reloadConfiguration(target?: ConfigurationTarget | IWorkspaceFolder): Promise { @@ -748,17 +757,12 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat }); } - private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides | undefined, target: ConfigurationTarget): ConfigurationTarget | undefined { - if (target) { - return target; - } - + private deriveConfigurationTarget(key: string, value: any, inspect: IConfigurationValue): ConfigurationTarget | undefined { if (value === undefined) { // Ignore. But expected is to remove the value from all targets return undefined; } - const inspect = this.inspect(key, overrides); if (equals(value, inspect.value)) { // No change. So ignore. return undefined; diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index a7f455cd539..d6443a0c833 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -1174,6 +1174,18 @@ suite('WorkspaceConfigurationService - Folder', () => { .then(() => assert.ok(target.called)); }); + test('update user configuration to default value when target is not passed', async () => { + await testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER); + await testObject.updateValue('configurationService.folder.testSetting', 'isSet'); + assert.equal(testObject.inspect('configurationService.folder.testSetting').userValue, undefined); + }); + + test('update user configuration to default value when target is passed', async () => { + await testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER); + await testObject.updateValue('configurationService.folder.testSetting', 'isSet', ConfigurationTarget.USER); + assert.equal(testObject.inspect('configurationService.folder.testSetting').userValue, 'isSet'); + }); + test('update task configuration should trigger change event before promise is resolve', () => { const target = sinon.spy(); testObject.onDidChangeConfiguration(target); From 02bf5807169da8013b3dbb1acb9caa590729d0bf Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 15 Dec 2020 15:41:56 +0100 Subject: [PATCH 1002/1837] remove migrating sync settings --- .../browser/userDataSync.contribution.ts | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts index 51517c3e562..595b2875da1 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts @@ -12,7 +12,6 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/ import { Disposable } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { isWeb } from 'vs/base/common/platform'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { UserDataSyncTrigger } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger'; class UserDataSyncReportIssueContribution extends Disposable implements IWorkbenchContribution { @@ -40,34 +39,8 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben } } -export class UserDataSyncSettingsMigrationContribution implements IWorkbenchContribution { - - constructor( - @IConfigurationService private readonly configurationService: IConfigurationService - ) { - this.migrateSettings(); - } - - private async migrateSettings(): Promise { - await this.migrateSetting('sync.keybindingsPerPlatform', 'settingsSync.keybindingsPerPlatform'); - await this.migrateSetting('sync.ignoredExtensions', 'settingsSync.ignoredExtensions'); - await this.migrateSetting('sync.ignoredSettings', 'settingsSync.ignoredSettings'); - } - - private async migrateSetting(oldSetting: string, newSetting: string): Promise { - const userValue = this.configurationService.inspect(oldSetting).userValue; - if (userValue !== undefined) { - // remove the old setting - await this.configurationService.updateValue(oldSetting, undefined, ConfigurationTarget.USER); - // add the new setting - await this.configurationService.updateValue(newSetting, userValue, ConfigurationTarget.USER); - } - } -} - const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(UserDataSyncWorkbenchContribution, LifecyclePhase.Ready); -workbenchRegistry.registerWorkbenchContribution(UserDataSyncSettingsMigrationContribution, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(UserDataSyncTrigger, LifecyclePhase.Eventually); if (isWeb) { From 43c613c7009fd7fdb47cc193c40e72cb20a73fde Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 15:42:38 +0100 Subject: [PATCH 1003/1837] timer mark event should also include unix timestamp --- src/vs/workbench/services/timer/browser/timerService.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 4096f477c71..52e7a9bf8a1 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -464,13 +464,18 @@ export abstract class AbstractTimerService implements ITimerService { // event and it is "normalized" to a relative timestamp where the first mark // defines the start for (const [source, marks] of this.getPerformanceMarks()) { - type Mark = { source: string; name: string; relativeStartTime: number; }; + type Mark = { source: string; name: string; relativeStartTime: number; startTime: number }; type MarkClassification = { [K in keyof Mark]: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; let lastMark: perf.PerformanceMark = marks[0]; for (const mark of marks) { let delta = mark.startTime - lastMark.startTime; - this._telemetryService.publicLog2('startup.timer.mark', { source, name: mark.name, relativeStartTime: delta }); + this._telemetryService.publicLog2('startup.timer.mark', { + source, + name: mark.name, + relativeStartTime: delta, + startTime: mark.startTime + }); lastMark = mark; } } From 6aa034b1ca498411044937641f7ab573a9c4c857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 15:48:34 +0100 Subject: [PATCH 1004/1837] fix build --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fc90cca75a9..01eb9cc87d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "47d34c9d35c811ed6a3832be96c8f71e5c1701da", + "distro": "6147f7fceb6892b8d7c9f04684fd70ca90973982", "author": { "name": "Microsoft Corporation" }, @@ -198,4 +198,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file From d782f11c7b295c507a1fcc4ddab35d2fb0a64127 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 15 Dec 2020 15:52:50 +0100 Subject: [PATCH 1005/1837] do not restore theme if setting has changed --- .../themes/browser/workbenchThemeService.ts | 10 +++++++--- .../services/themes/common/colorThemeData.ts | 14 ++++---------- .../services/themes/common/themeConfiguration.ts | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 1a74be71986..2af2fef727a 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -139,7 +139,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // In order to avoid paint flashing for tokens, because // themes are loaded asynchronously, we need to initialize // a color theme document with good defaults until the theme is loaded - let themeData: ColorThemeData | undefined = ColorThemeData.fromStorageData(this.storageService, isWeb); + let themeData: ColorThemeData | undefined = ColorThemeData.fromStorageData(this.storageService); + if (themeData && this.settings.colorTheme !== themeData.settingsId && this.settings.isDefaultColorTheme()) { + // the web has different defaults than the desktop, therefore do not restore when the setting is the default theme and the storage doesn't match that. + themeData = undefined; + } // the preferred color scheme (high contrast, light, dark) has changed since the last start const preferredColorScheme = this.getPreferredColorScheme(); @@ -495,8 +499,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.onColorThemeChange.fire(this.currentColorTheme); // remember theme data for a quick restore - if (newTheme.isLoaded) { - newTheme.toStorage(this.storageService, this.settings.isDefaultColorTheme(newTheme)); + if (newTheme.isLoaded && settingsTarget) { + newTheme.toStorage(this.storageService); } return this.settings.setColorTheme(this.currentColorTheme, settingsTarget); diff --git a/src/vs/workbench/services/themes/common/colorThemeData.ts b/src/vs/workbench/services/themes/common/colorThemeData.ts index a6fb53721dc..cb4dc5694b4 100644 --- a/src/vs/workbench/services/themes/common/colorThemeData.ts +++ b/src/vs/workbench/services/themes/common/colorThemeData.ts @@ -505,7 +505,7 @@ export class ColorThemeData implements IWorkbenchColorTheme { this.customTokenScopeMatchers = undefined; } - toStorage(storageService: IStorageService, isDefaultTheme: boolean) { + toStorage(storageService: IStorageService) { let colorMapData: { [key: string]: string } = {}; for (let key in this.colorMap) { colorMapData[key] = Color.Format.CSS.formatHexA(this.colorMap[key], true); @@ -520,8 +520,7 @@ export class ColorThemeData implements IWorkbenchColorTheme { extensionData: ExtensionData.toJSONObject(this.extensionData), themeSemanticHighlighting: this.themeSemanticHighlighting, colorMap: colorMapData, - watch: this.watch, - isDefaultTheme + watch: this.watch }); // roam persisted color theme colors. Don't enable for icons as they contain references to fonts and images. @@ -571,14 +570,12 @@ export class ColorThemeData implements IWorkbenchColorTheme { return themeData; } - static fromStorageData(storageService: IStorageService, doNotRestoreDefaultTheme: boolean): ColorThemeData | undefined { + static fromStorageData(storageService: IStorageService): ColorThemeData | undefined { const input = storageService.get(ColorThemeData.STORAGE_KEY, StorageScope.GLOBAL); if (!input) { return undefined; } try { - let isDefaultTheme = false; - let data = JSON.parse(input); let theme = new ColorThemeData('', '', ''); for (let key in data) { @@ -610,12 +607,9 @@ export class ColorThemeData implements IWorkbenchColorTheme { case 'extensionData': theme.extensionData = ExtensionData.fromJSONObject(data.extensionData); break; - case 'isDefaultTheme': - isDefaultTheme = data.isDefaultTheme; - break; } } - if (!theme.id || !theme.settingsId || doNotRestoreDefaultTheme && isDefaultTheme) { + if (!theme.id || !theme.settingsId) { return undefined; } return theme; diff --git a/src/vs/workbench/services/themes/common/themeConfiguration.ts b/src/vs/workbench/services/themes/common/themeConfiguration.ts index 090ec9ac24c..33314367b0a 100644 --- a/src/vs/workbench/services/themes/common/themeConfiguration.ts +++ b/src/vs/workbench/services/themes/common/themeConfiguration.ts @@ -308,9 +308,9 @@ export class ThemeConfiguration { return theme; } - public isDefaultColorTheme(theme: IWorkbenchColorTheme): boolean { + public isDefaultColorTheme(): boolean { let settings = this.configurationService.inspect(ThemeSettings.COLOR_THEME); - return settings && settings.default?.value === theme.settingsId; + return settings && settings.default?.value === settings.value; } public findAutoConfigurationTarget(key: string) { From e135eee1f1d07739304aacf18cea0592b85f9ae1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 15:56:54 +0100 Subject: [PATCH 1006/1837] add perf mark when file systems are registered, fyi @bpasero --- src/vs/platform/files/common/fileService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index 81ee5fe2580..adb0bb16f00 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -20,6 +20,7 @@ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cance import { Schemas } from 'vs/base/common/network'; import { readFileIntoStream } from 'vs/platform/files/common/io'; import { Iterable } from 'vs/base/common/iterator'; +import * as perf from 'vs/base/common/performance'; export class FileService extends Disposable implements IFileService { @@ -49,6 +50,8 @@ export class FileService extends Disposable implements IFileService { throw new Error(`A filesystem provider for the scheme '${scheme}' is already registered.`); } + perf.mark(`code/registerFilesystem/${scheme}`); + // Add provider with event this.provider.set(scheme, provider); this._onDidChangeFileSystemProviderRegistrations.fire({ added: true, scheme, provider }); From 5ae66f37a8920fda725a0d39bbbce63f44192778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 15:58:47 +0100 Subject: [PATCH 1007/1837] build: use ELECTRON_SKIP_BINARY_DOWNLOAD --- build/azure-pipelines/darwin/product-build-darwin.yml | 2 ++ build/azure-pipelines/linux/product-build-alpine.yml | 2 ++ build/azure-pipelines/linux/product-build-linux.yml | 2 ++ build/azure-pipelines/product-compile.yml | 2 ++ build/azure-pipelines/product-hygiene.yml | 2 ++ build/azure-pipelines/web/product-build-web.yml | 2 ++ build/azure-pipelines/win32/product-build-win32.yml | 2 ++ 7 files changed, 14 insertions(+) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index d76daf8788d..3965a6c22b0 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -97,6 +97,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 9998b482d59..d01617825c3 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -90,6 +90,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 797d4db8884..a630a128511 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -93,6 +93,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 8dc27649502..4faab0e49e1 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -86,6 +86,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 1c971c7404c..e7764beddd6 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -58,6 +58,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 1beae9506eb..fc04ed4e6bd 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -80,6 +80,8 @@ steps: fi echo "Yarn failed $i, trying again..." done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index ed7c526cf3f..9f05af646b4 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -79,6 +79,8 @@ steps: $env:npm_config_arch="$(VSCODE_ARCH)" $env:CHILD_CONCURRENCY="1" retry { exec { yarn --frozen-lockfile } } + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) From c97d5e1033770e0c343d4121394bee38c9a3d932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:07:52 +0100 Subject: [PATCH 1008/1837] build: use PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD --- build/azure-pipelines/darwin/product-build-darwin.yml | 5 +++-- build/azure-pipelines/linux/product-build-alpine.yml | 1 + build/azure-pipelines/linux/product-build-linux.yml | 7 +++++++ build/azure-pipelines/product-compile.yml | 1 + build/azure-pipelines/product-hygiene.yml | 1 + build/azure-pipelines/web/product-build-web.yml | 1 + build/azure-pipelines/win32/product-build-win32.yml | 8 ++++++++ 7 files changed, 22 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 3965a6c22b0..9322286df0b 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -99,6 +99,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) @@ -154,8 +155,8 @@ steps: - script: | set -e - yarn electron $(VSCODE_ARCH) - displayName: Download Electron + yarn npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install" + displayName: Download Electron and Playwright condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index d01617825c3..712c4c1b0f1 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -92,6 +92,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index a630a128511..a5062ecaaa2 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -95,6 +95,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) @@ -140,6 +141,12 @@ steps: yarn gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci displayName: Build Server + - script: | + set -e + yarn npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install" + displayName: Download Electron and Playwright + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | set -e DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 4faab0e49e1..dcc890f8db3 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -88,6 +88,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index e7764beddd6..47f8baf725f 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -60,6 +60,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index fc04ed4e6bd..f0807d00483 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -82,6 +82,7 @@ steps: done env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 9f05af646b4..0bfbeec5e96 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -81,6 +81,7 @@ steps: retry { exec { yarn --frozen-lockfile } } env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) @@ -131,6 +132,13 @@ steps: displayName: Build Server condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install" } + displayName: Download Electron and Playwright + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) + - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" From be2d9834342325a60ac43da0a805eb063ddff892 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 16:13:43 +0100 Subject: [PATCH 1009/1837] debug console: use registerAction2 #92038 --- .../debug/browser/debug.contribution.ts | 3 +- .../workbench/contrib/debug/browser/repl.ts | 161 ++++++++++-------- .../workbench/contrib/debug/common/debug.ts | 1 + 3 files changed, 91 insertions(+), 74 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 9438ac11cad..232ffafb9bf 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -35,7 +35,7 @@ import { LoadedScriptsView } from 'vs/workbench/contrib/debug/browser/loadedScri import { ADD_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID, RunToCursorAction, registerEditorActions } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; import { WatchExpressionsView } from 'vs/workbench/contrib/debug/browser/watchExpressionsView'; import { VariablesView, SET_VARIABLE_ID, COPY_VALUE_ID, BREAK_WHEN_VALUE_CHANGES_ID, COPY_EVALUATE_PATH_ID, ADD_TO_WATCH_ID } from 'vs/workbench/contrib/debug/browser/variablesView'; -import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl'; +import { Repl } from 'vs/workbench/contrib/debug/browser/repl'; import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -109,7 +109,6 @@ function registerCommandsAndActions(): void { registry.registerWorkbenchAction(SyncActionDescriptor.from(EnableAllBreakpointsAction), 'Debug: Enable All Breakpoints', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); registry.registerWorkbenchAction(SyncActionDescriptor.from(DisableAllBreakpointsAction), 'Debug: Disable All Breakpoints', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); registry.registerWorkbenchAction(SyncActionDescriptor.from(SelectAndStartAction), 'Debug: Select and Start Debugging', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); - registry.registerWorkbenchAction(SyncActionDescriptor.from(ClearReplAction), 'Debug: Clear Console', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); const registerDebugCommandPaletteItem = (id: string, title: string, when?: ContextKeyExpression, precondition?: ContextKeyExpression) => { MenuRegistry.appendMenuItem(MenuId.CommandPalette, { diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index f4a61cdcaa0..c32f5fbf47c 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -14,11 +14,11 @@ import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { ITextModel } from 'vs/editor/common/model'; import { Range } from 'vs/editor/common/core/range'; import { Position } from 'vs/editor/common/core/position'; -import { registerEditorAction, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; +import { registerEditorAction, EditorAction } from 'vs/editor/browser/editorExtensions'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IContextKeyService, IContextKey, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -26,7 +26,7 @@ import { memoize } from 'vs/base/common/decorators'; import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { IDebugService, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL, IDebugSession, State, IReplElement, IDebugConfiguration, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL, IDebugSession, State, IReplElement, IDebugConfiguration, REPL_VIEW_ID, CONTEXT_MULTI_SESSION_REPL } from 'vs/workbench/contrib/debug/common/debug'; import { HistoryNavigator } from 'vs/base/common/history'; import { IHistoryNavigationWidget } from 'vs/base/browser/history'; import { createAndBindHistoryNavigationWidgetScopedContextKeyService } from 'vs/platform/browser/contextScopedHistoryWidget'; @@ -50,7 +50,7 @@ import { FuzzyScore } from 'vs/base/common/filters'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ReplDelegate, ReplVariablesRenderer, ReplSimpleElementsRenderer, ReplEvaluationInputsRenderer, ReplEvaluationResultsRenderer, ReplRawObjectsRenderer, ReplDataSource, ReplAccessibilityProvider, ReplGroupRenderer } from 'vs/workbench/contrib/debug/browser/replViewer'; import { localize } from 'vs/nls'; -import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; +import { ViewPane, IViewPaneOptions, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; @@ -60,6 +60,7 @@ import { EDITOR_FONT_DEFAULTS, EditorOption } from 'vs/editor/common/config/edit import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor'; import { ReplFilter, ReplFilterState, ReplFilterActionViewItem } from 'vs/workbench/contrib/debug/browser/replFilter'; import { debugConsoleClearAll, debugConsoleEvaluationPrompt } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { registerAction2, MenuId, MenuItemAction, Action2 } from 'vs/platform/actions/common/actions'; const $ = dom.$; @@ -98,6 +99,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { private filter: ReplFilter; private filterState: ReplFilterState; private filterActionViewItem: ReplFilterActionViewItem | undefined; + private multiSessionRepl: IContextKey; constructor( options: IViewPaneOptions, @@ -123,6 +125,8 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { this.history = new HistoryNavigator(JSON.parse(this.storageService.get(HISTORY_STORAGE_KEY, StorageScope.WORKSPACE, '[]')), 50); this.filter = new ReplFilter(); this.filterState = new ReplFilterState(this); + this.multiSessionRepl = CONTEXT_MULTI_SESSION_REPL.bindTo(contextKeyService); + this.multiSessionRepl.set(this.isMultiSessionView); codeEditorService.registerDecorationType(DECORATION_KEY, {}); this.registerListeners(); @@ -207,7 +211,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { if (!input || input.state === State.Inactive) { await this.selectSession(newSession); } - this.updateActions(); + this.multiSessionRepl.set(this.isMultiSessionView); })); this._register(this.themeService.onDidColorThemeChange(() => { this.refreshReplElements(false); @@ -397,7 +401,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { // Ignore inactive sessions which got cleared - so they are not shown any more sessionsToIgnore.add(session); await this.selectSession(); - this.updateActions(); + this.multiSessionRepl.set(this.isMultiSessionView); } } this.replInput.focus(); @@ -460,9 +464,9 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { } getActionViewItem(action: IAction): IActionViewItem | undefined { - if (action.id === SelectReplAction.ID) { + if (action.id === selectReplCommandId) { const session = (this.tree ? this.tree.getInput() : undefined) ?? this.debugService.getViewModel().focusedSession; - return this.instantiationService.createInstance(SelectReplActionViewItem, this.selectReplAction, session); + return this.instantiationService.createInstance(SelectReplActionViewItem, action, session); } else if (action.id === FILTER_ACTION_ID) { const filterHistory = JSON.parse(this.storageService.get(FILTER_HISTORY_STORAGE_KEY, StorageScope.WORKSPACE, '[]')) as string[]; this.filterActionViewItem = this.instantiationService.createInstance(ReplFilterActionViewItem, action, @@ -473,29 +477,11 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { return super.getActionViewItem(action); } - getActions(): IAction[] { - const result: IAction[] = []; - result.push(new Action(FILTER_ACTION_ID)); - if (this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s)).length > 1) { - result.push(this.selectReplAction); - } - result.push(this.clearReplAction); - - result.forEach(a => this._register(a)); - - return result; + private get isMultiSessionView(): boolean { + return this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s)).length > 1; } // --- Cached locals - @memoize - private get selectReplAction(): SelectReplAction { - return this.instantiationService.createInstance(SelectReplAction, SelectReplAction.ID, SelectReplAction.LABEL); - } - - @memoize - private get clearReplAction(): ClearReplAction { - return this.instantiationService.createInstance(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL); - } @memoize private get refreshScheduler(): RunOnceScheduler { @@ -660,7 +646,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { return Promise.resolve(); })); actions.push(new Separator()); - actions.push(this.clearReplAction); + actions.push(this.instantiationService.createInstance(MenuItemAction, clearReplCommand, undefined, {})); this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, @@ -825,48 +811,79 @@ class SelectReplActionViewItem extends FocusSessionActionViewItem { } } -class SelectReplAction extends Action { - - static readonly ID = 'workbench.action.debug.selectRepl'; - static readonly LABEL = localize('selectRepl', "Select Debug Console"); - - constructor(id: string, label: string, - @IDebugService private readonly debugService: IDebugService, - @IViewsService private readonly viewsService: IViewsService - ) { - super(id, label); - } - - async run(session: IDebugSession): Promise { - // If session is already the focused session we need to manualy update the tree since view model will not send a focused change event - if (session && session.state !== State.Inactive && session !== this.debugService.getViewModel().focusedSession) { - await this.debugService.focusStackFrame(undefined, undefined, session, true); - } else { - const repl = getReplView(this.viewsService); - if (repl) { - await repl.selectSession(session); - } - } - } -} - -export class ClearReplAction extends Action { - static readonly ID = 'workbench.debug.panel.action.clearReplAction'; - static readonly LABEL = localize('clearRepl', "Clear Console"); - - constructor(id: string, label: string, - @IViewsService private readonly viewsService: IViewsService - ) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(debugConsoleClearAll)); - } - - async run(): Promise { - const view = await this.viewsService.openView(REPL_VIEW_ID) as Repl; - await view.clearRepl(); - aria.status(localize('debugConsoleCleared', "Debug console was cleared")); - } -} - function getReplView(viewsService: IViewsService): Repl | undefined { return viewsService.getActiveViewWithId(REPL_VIEW_ID) as Repl ?? undefined; } + +registerAction2(class FilterAction extends Action2 { + constructor() { + super({ + id: FILTER_ACTION_ID, + title: localize('filter', "Filter"), + f1: true, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', REPL_VIEW_ID), + order: 10 + } + }); + } + + run(_accessor: ServicesAccessor) { + // noop this action is just a placeholder for the filter action view item + } +}); + +const selectReplCommandId = 'workbench.action.debug.selectRepl'; +registerAction2(class SelectRepl extends ViewAction { + constructor() { + super({ + id: selectReplCommandId, + viewId: REPL_VIEW_ID, + title: localize('selectRepl', "Select Debug Console"), + f1: true, + icon: debugConsoleClearAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', REPL_VIEW_ID), CONTEXT_MULTI_SESSION_REPL), + order: 20 + } + }); + } + + async runInView(accessor: ServicesAccessor, view: Repl, session: IDebugSession | undefined) { + const debugService = accessor.get(IDebugService); + // If session is already the focused session we need to manualy update the tree since view model will not send a focused change event + if (session && session.state !== State.Inactive && session !== debugService.getViewModel().focusedSession) { + await debugService.focusStackFrame(undefined, undefined, session, true); + } else { + await view.selectSession(session); + } + } +}); + +const clearReplCommand = { + id: 'workbench.debug.panel.action.clearReplAction', + viewId: REPL_VIEW_ID, + title: localize('clearRepl', "Clear Console"), + f1: true, + icon: debugConsoleClearAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', REPL_VIEW_ID), + order: 30 + } +}; +registerAction2(class ClearRepl extends ViewAction { + constructor() { + super(clearReplCommand); + } + + runInView(_accessor: ServicesAccessor, view: Repl) { + view.clearRepl(); + aria.status(localize('debugConsoleCleared', "Debug console was cleared")); + } +}); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index b2dabf752df..9fa240acae0 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -66,6 +66,7 @@ export const CONTEXT_SET_VARIABLE_SUPPORTED = new RawContextKey('debugS export const CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED = new RawContextKey('breakWhenValueChangesSupported', false); export const CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT = new RawContextKey('variableEvaluateNamePresent', false); export const CONTEXT_EXCEPTION_WIDGET_VISIBLE = new RawContextKey('exceptionWidgetVisible', false); +export const CONTEXT_MULTI_SESSION_REPL = new RawContextKey('multiSessionRepl', false); export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug'; export const BREAKPOINT_EDITOR_CONTRIBUTION_ID = 'editor.contrib.breakpoint'; From 9293efd7e7dcc7dc4f84bb0c320d417feddf23b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:16:45 +0100 Subject: [PATCH 1010/1837] build: remove postinstall script invocation --- build/azure-pipelines/darwin/product-build-darwin.yml | 10 ---------- build/azure-pipelines/linux/product-build-alpine.yml | 6 ------ build/azure-pipelines/linux/product-build-linux.yml | 6 ------ build/azure-pipelines/product-compile.yml | 6 ------ build/azure-pipelines/product-hygiene.yml | 6 ------ build/azure-pipelines/web/product-build-web.yml | 6 ------ build/azure-pipelines/win32/product-build-win32.yml | 7 ------- 7 files changed, 47 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 9322286df0b..8d778087cdb 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -110,16 +110,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - export npm_config_arch=$(VSCODE_ARCH) - export npm_config_node_gyp=$(which node-gyp) - export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - ls /Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - script: | set -e export npm_config_arch=$(VSCODE_ARCH) diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 712c4c1b0f1..7f204da84f0 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -103,12 +103,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - script: | set -e node build/azure-pipelines/mixin diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index a5062ecaaa2..ca269dc460f 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -106,12 +106,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - script: | set -e export CC=$(which gcc-4.8) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index dcc890f8db3..80f2b019a3c 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -99,12 +99,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) - # Mixin must run before optimize, because the CSS loader will inline small SVGs - script: | set -e diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 47f8baf725f..697144cc3de 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -64,12 +64,6 @@ steps: displayName: Install dependencies condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - # Mixin must run before optimize, because the CSS loader will inline small SVGs - script: | set -e diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index f0807d00483..ba82abecda1 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -93,12 +93,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - script: | - set -e - yarn postinstall - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - script: | set -e node build/azure-pipelines/mixin diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 0bfbeec5e96..b52165a07a3 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -92,13 +92,6 @@ steps: vstsFeed: "npm-vscode" condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - - powershell: | - . build/azure-pipelines/win32/exec.ps1 - $ErrorActionPreference = "Stop" - exec { yarn postinstall } - displayName: Run postinstall scripts - condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" From b7d648a873945e4c31fe372a212aec0dd79c8bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:34:21 +0100 Subject: [PATCH 1011/1837] remove CHILD_CONCURRENCY=1 for all except windows --- build/azure-pipelines/darwin/product-build-darwin.yml | 1 - build/azure-pipelines/linux/product-build-alpine.yml | 3 +-- build/azure-pipelines/linux/product-build-linux.yml | 1 - build/azure-pipelines/product-compile.yml | 1 - build/azure-pipelines/product-hygiene.yml | 1 - build/azure-pipelines/web/product-build-web.yml | 1 - 6 files changed, 1 insertion(+), 7 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 9322286df0b..a79484631cd 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -87,7 +87,6 @@ steps: export npm_config_arch=$(VSCODE_ARCH) export npm_config_node_gyp=$(which node-gyp) export SDKROOT=/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 712c4c1b0f1..181199f25be 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -81,7 +81,6 @@ steps: - script: | set -e - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break if [ $i -eq 3 ]; then @@ -116,7 +115,7 @@ steps: - script: | set -e - docker run -e VSCODE_QUALITY -e CHILD_CONCURRENCY=1 -v $(pwd):/root/vscode -v ~/.netrc:/root/.netrc vscodehub.azurecr.io/vscode-linux-build-agent:alpine /root/vscode/build/azure-pipelines/linux/alpine/install-dependencies.sh + docker run -e VSCODE_QUALITY -v $(pwd):/root/vscode -v ~/.netrc:/root/.netrc vscodehub.azurecr.io/vscode-linux-build-agent:alpine /root/vscode/build/azure-pipelines/linux/alpine/install-dependencies.sh displayName: Prebuild - script: | diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index a5062ecaaa2..fe14fa2c912 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -84,7 +84,6 @@ steps: export CXX=$(which g++-5) fi export npm_config_arch=$(NPM_ARCH) - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break if [ $i -eq 3 ]; then diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index dcc890f8db3..04d8571f263 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -77,7 +77,6 @@ steps: export CC=$(which gcc-5) export CXX=$(which g++-5) fi - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break if [ $i -eq 3 ]; then diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 47f8baf725f..bf6d16b3f80 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -49,7 +49,6 @@ steps: - script: | set -e - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break if [ $i -eq 3 ]; then diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index f0807d00483..a3bf30c6b8f 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -71,7 +71,6 @@ steps: - script: | set -e - export CHILD_CONCURRENCY="1" for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break if [ $i -eq 3 ]; then From 834b2b1570f6faa08324b8d30d055e075df11972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:34:50 +0100 Subject: [PATCH 1012/1837] bump cache salt --- build/.cachesalt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/.cachesalt b/build/.cachesalt index 909042d161e..2d4b0cf2154 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2020-12-15T04:06:58.201Z +2020-12-15T15:34:44.634Z From 208380cf7663846650621be1802582db57a14890 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 16:34:00 +0100 Subject: [PATCH 1013/1837] Dispose a permanent failed connection and fail any further requests through a disposed `ChannelClient` (#112278 , #112568) --- src/vs/base/parts/ipc/common/ipc.ts | 8 ++++++++ .../services/remote/common/abstractRemoteAgentService.ts | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index a45ee66bb9a..b459b90de71 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -505,6 +505,7 @@ export interface IIPCLogger { export class ChannelClient implements IChannelClient, IDisposable { + private isDisposed: boolean = false; private state: State = State.Uninitialized; private activeRequests = new Set(); private handlers = new Map(); @@ -525,9 +526,15 @@ export class ChannelClient implements IChannelClient, IDisposable { return { call(command: string, arg?: any, cancellationToken?: CancellationToken) { + if (that.isDisposed) { + return Promise.resolve(errors.canceled()); + } return that.requestPromise(channelName, command, arg, cancellationToken); }, listen(event: string, arg: any) { + if (that.isDisposed) { + return Promise.resolve(errors.canceled()); + } return that.requestEvent(channelName, event, arg); } } as T; @@ -725,6 +732,7 @@ export class ChannelClient implements IChannelClient, IDisposable { } dispose(): void { + this.isDisposed = true; if (this.protocolListener) { this.protocolListener.dispose(); this.protocolListener = null; diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index 1feea3dd9d3..5fbc58f2a05 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -198,6 +198,9 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon ipcLogger: false ? new IPCLogger(`Local \u2192 Remote`, `Remote \u2192 Local`) : null }; const connection = this._register(await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`)); + connection.protocol.onDidDispose(() => { + connection.dispose(); + }); this._register(connection.onDidStateChange(e => this._onDidStateChange.fire(e))); return connection.client; } From d79f4e7b887c25dce8527498d7e9fad3d03c6ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:40:43 +0100 Subject: [PATCH 1014/1837] add test timeouts --- build/azure-pipelines/darwin/product-build-darwin.yml | 7 +++++++ build/azure-pipelines/linux/product-build-linux.yml | 5 +++++ build/azure-pipelines/win32/product-build-win32.yml | 7 ++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 9322286df0b..d6bb2c321b9 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -175,12 +175,14 @@ steps: set -e ./scripts/test.sh --build --tfs "Unit Tests" displayName: Run unit tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e yarn test-browser --build --browser chromium --browser webkit --browser firefox --tfs "Browser Unit Tests" displayName: Run unit tests (Browser) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -194,6 +196,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ ./scripts/test-integration.sh --build --tfs "Integration Tests" displayName: Run integration tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -201,6 +204,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ ./resources/server/test/test-web-integration.sh --browser webkit displayName: Run integration tests (Browser) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -211,6 +215,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ ./resources/server/test/test-remote-integration.sh displayName: Run remote integration tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -219,6 +224,7 @@ steps: APP_NAME="`ls $APP_ROOT | head -n 1`" yarn smoketest --build "$APP_ROOT/$APP_NAME" continueOnError: true + timeoutInMinutes: 5 displayName: Run smoke tests (Electron) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) @@ -227,6 +233,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \ yarn smoketest --web --headless continueOnError: true + timeoutInMinutes: 5 displayName: Run smoke tests (Browser) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index a5062ecaaa2..733ee37aa22 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -151,12 +151,14 @@ steps: set -e DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" displayName: Run unit tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e DISPLAY=:10 yarn test-browser --build --browser chromium --tfs "Browser Unit Tests" displayName: Run unit tests (Browser) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -171,6 +173,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" displayName: Run integration tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -178,6 +181,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \ DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium displayName: Run integration tests (Browser) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | @@ -189,6 +193,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \ DISPLAY=:10 ./resources/server/test/test-remote-integration.sh displayName: Run remote integration tests (Electron) + timeoutInMinutes: 5 condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - task: PublishPipelineArtifact@0 diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 0bfbeec5e96..36cf9f90916 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -59,7 +59,7 @@ steps: - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages - timeoutInMinutes: 5 + timeoutInMinutes: 7 condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) - powershell: | @@ -145,6 +145,7 @@ steps: exec { yarn electron $(VSCODE_ARCH) } exec { .\scripts\test.bat --build --tfs "Unit Tests" } displayName: Run unit tests (Electron) + timeoutInMinutes: 7 condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | @@ -152,6 +153,7 @@ steps: $ErrorActionPreference = "Stop" exec { yarn test-browser --build --browser chromium --browser firefox --tfs "Browser Unit Tests" } displayName: Run unit tests (Browser) + timeoutInMinutes: 7 condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | @@ -165,6 +167,7 @@ steps: $AppNameShort = $AppProductJson.nameShort exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\scripts\test-integration.bat --build --tfs "Integration Tests" } displayName: Run integration tests (Electron) + timeoutInMinutes: 10 condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | @@ -172,6 +175,7 @@ steps: $ErrorActionPreference = "Stop" exec { $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-web-integration.bat --browser firefox } displayName: Run integration tests (Browser) + timeoutInMinutes: 7 condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | @@ -182,6 +186,7 @@ steps: $AppNameShort = $AppProductJson.nameShort exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"; .\resources\server\test\test-remote-integration.bat } displayName: Run remote integration tests (Electron) + timeoutInMinutes: 7 condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - task: PublishPipelineArtifact@0 From e2f6cc5a9658e651189bed2dfa1be81ce5f57d26 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 16:40:50 +0100 Subject: [PATCH 1015/1837] breakpoints: use registerAction2 #92038 --- .../contrib/debug/browser/breakpointsView.ts | 136 +++++++++++++----- .../debug/browser/debug.contribution.ts | 10 +- .../contrib/debug/browser/debugActions.ts | 62 -------- .../workbench/contrib/debug/browser/repl.ts | 6 +- .../contrib/debug/browser/variablesView.ts | 2 +- 5 files changed, 108 insertions(+), 108 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index cc8b4a9ef12..e941ae8fd55 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -3,13 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import * as resources from 'vs/base/common/resources'; import * as dom from 'vs/base/browser/dom'; import { IAction, Action, Separator } from 'vs/base/common/actions'; -import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, IDebugModel, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, IDebugModel, IDataBreakpoint, BREAKPOINTS_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel'; -import { AddFunctionBreakpointAction, ToggleBreakpointsActivatedAction, RemoveAllBreakpointsAction, RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -29,7 +28,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { Gesture } from 'vs/base/browser/touch'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; @@ -38,6 +37,9 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { registerAction2, Action2, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; +import { localize } from 'vs/nls'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; const $ = dom.$; @@ -190,15 +192,15 @@ export class BreakpointsView extends ViewPane { if (element instanceof ExceptionBreakpoint) { if (element.supportsCondition) { - actions.push(new Action('workbench.action.debug.editExceptionBreakpointCondition', nls.localize('editCondition', "Edit Condition"), '', true, async () => { + actions.push(new Action('workbench.action.debug.editExceptionBreakpointCondition', localize('editCondition', "Edit Condition"), '', true, async () => { this.debugService.getViewModel().setSelectedBreakpoint(element); this.onBreakpointsChange(); })); } } else { - const breakpointType = element instanceof Breakpoint && element.logMessage ? nls.localize('Logpoint', "Logpoint") : nls.localize('Breakpoint', "Breakpoint"); + const breakpointType = element instanceof Breakpoint && element.logMessage ? localize('Logpoint', "Logpoint") : localize('Breakpoint', "Breakpoint"); if (element instanceof Breakpoint || element instanceof FunctionBreakpoint) { - actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', nls.localize('editBreakpoint', "Edit {0}...", breakpointType), '', true, async () => { + actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', localize('editBreakpoint', "Edit {0}...", breakpointType), '', true, async () => { if (element instanceof Breakpoint) { const editor = await openBreakpointSource(element, false, false, true, this.debugService, this.editorService); if (editor) { @@ -216,10 +218,10 @@ export class BreakpointsView extends ViewPane { } - actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService)); + actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService)); if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length >= 1) { - actions.push(new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService)); + actions.push(this.instantiationService.createInstance(MenuItemAction, removeAllBreakpointsCommand, undefined, {})); actions.push(new Separator()); actions.push(new EnableAllBreakpointsAction(EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL, this.debugService, this.keybindingService)); @@ -238,14 +240,6 @@ export class BreakpointsView extends ViewPane { }); } - public getActions(): IAction[] { - return [ - new AddFunctionBreakpointAction(AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL, this.debugService, this.keybindingService), - new ToggleBreakpointsActivatedAction(ToggleBreakpointsActivatedAction.ID, ToggleBreakpointsActivatedAction.ACTIVATE_LABEL, this.debugService, this.keybindingService), - new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService) - ]; - } - private updateSize(): void { const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!; @@ -459,7 +453,7 @@ class ExceptionBreakpointsRenderer implements IListRenderer this.updateEnablement())); - } - - run(): Promise { - return Promise.all([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints(), this.debugService.removeDataBreakpoints()]); - } - - protected isEnabled(_: State): boolean { - const model = this.debugService.getModel(); - return (model.getBreakpoints().length > 0 || model.getFunctionBreakpoints().length > 0 || model.getDataBreakpoints().length > 0); - } -} - export class EnableAllBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.enableAllBreakpoints'; static readonly LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints"); @@ -264,30 +245,6 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction { } } -export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction'; - static readonly ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints"); - static readonly DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.breakpointsActivate), debugService, keybindingService); - this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); - - this._register(this.debugService.getModel().onDidChangeBreakpoints(() => { - this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); - this.updateEnablement(); - })); - } - - run(): Promise { - return this.debugService.setBreakpointsActivated(!this.debugService.getModel().areBreakpointsActivated()); - } - - protected isEnabled(_: State): boolean { - return !!(this.debugService.getModel().getFunctionBreakpoints().length || this.debugService.getModel().getBreakpoints().length || this.debugService.getModel().getDataBreakpoints().length); - } -} - export class ReapplyBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction'; static readonly LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints"); @@ -308,25 +265,6 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction { } } -export class AddFunctionBreakpointAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; - static readonly LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.watchExpressionsAddFuncBreakpoint), debugService, keybindingService); - this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); - } - - async run(): Promise { - this.debugService.addFunctionBreakpoint(); - } - - protected isEnabled(_: State): boolean { - return !this.debugService.getViewModel().getSelectedBreakpoint() - && this.debugService.getModel().getFunctionBreakpoints().every(fbp => !!fbp.name); - } -} - export class FocusSessionAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.focusProcess'; static readonly LABEL = nls.localize('focusSession', "Focus Session"); diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index c32f5fbf47c..a6335cde82d 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -815,7 +815,7 @@ function getReplView(viewsService: IViewsService): Repl | undefined { return viewsService.getActiveViewWithId(REPL_VIEW_ID) as Repl ?? undefined; } -registerAction2(class FilterAction extends Action2 { +registerAction2(class extends Action2 { constructor() { super({ id: FILTER_ACTION_ID, @@ -836,7 +836,7 @@ registerAction2(class FilterAction extends Action2 { }); const selectReplCommandId = 'workbench.action.debug.selectRepl'; -registerAction2(class SelectRepl extends ViewAction { +registerAction2(class extends ViewAction { constructor() { super({ id: selectReplCommandId, @@ -877,7 +877,7 @@ const clearReplCommand = { order: 30 } }; -registerAction2(class ClearRepl extends ViewAction { +registerAction2(class extends ViewAction { constructor() { super(clearReplCommand); } diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index a7ba7e4dda1..7c756f47c76 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -432,7 +432,7 @@ CommandsRegistry.registerCommand({ } }); -registerAction2(class Collapse extends ViewAction { +registerAction2(class extends ViewAction { constructor() { super({ id: 'variables.collapse', From dfeaeb5740a84161ad12fc8eb1c23f23a0c902fa Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 16:42:05 +0100 Subject: [PATCH 1016/1837] debug: check if languageIds is there --- src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts | 2 +- src/vs/workbench/contrib/debug/common/debug.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts index 7c5a4122ed5..ea61d8877bd 100644 --- a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts @@ -54,7 +54,7 @@ export class AdapterManager implements IAdapterManager { if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { added.collector.error(nls.localize('debugNoType', "Debugger 'type' can not be omitted and must be of type 'string'.")); } - if (rawAdapter.enableBreakpointsFor) { // Support deprecated field since the php-debug extension depends on it + if (rawAdapter.enableBreakpointsFor && rawAdapter.enableBreakpointsFor.languageIds) { // Support deprecated field since the php-debug extension depends on it rawAdapter.enableBreakpointsFor.languageIds.forEach(modeId => { this.breakpointModeIdsSet.add(modeId); }); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 9fa240acae0..8912ce6c0bf 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -631,7 +631,7 @@ export interface IDebuggerContribution extends IPlatformSpecificAdapterContribut // supported languages languages?: string[]; - enableBreakpointsFor?: { languageIds: string[] }; + enableBreakpointsFor?: { languageIds?: string[] }; // debug configuration support configurationAttributes?: any; From 41628e3326709db817e3ab488dd4db38cbd78188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 15 Dec 2020 16:45:16 +0100 Subject: [PATCH 1017/1837] merge distro in a single command --- build/azure-pipelines/darwin/product-build-darwin.yml | 4 +--- build/azure-pipelines/linux/product-build-alpine.yml | 4 +--- build/azure-pipelines/linux/product-build-linux.yml | 4 +--- build/azure-pipelines/product-compile.yml | 4 +--- build/azure-pipelines/product-hygiene.yml | 4 +--- build/azure-pipelines/web/product-build-web.yml | 4 +--- build/azure-pipelines/win32/product-build-win32.yml | 4 +--- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index d6bb2c321b9..f87c4833a61 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -55,9 +55,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - script: | diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index 712c4c1b0f1..9b332dbd962 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -58,9 +58,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - script: | diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 733ee37aa22..296a058ff5f 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -48,9 +48,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - script: | diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index dcc890f8db3..d867d909a8b 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -47,9 +47,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 47f8baf725f..ebde7f23ad7 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -32,9 +32,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - script: | diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index f0807d00483..1a6df4de572 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -48,9 +48,7 @@ steps: - script: | set -e - git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" - git fetch distro - git merge $(node -p "require('./package.json').distro") + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - script: | diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 36cf9f90916..e2060a24555 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -51,9 +51,7 @@ steps: - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" - exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } - exec { git fetch distro } - exec { git merge $(node -p "require('./package.json').distro") } + exec { git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") } displayName: Merge distro - script: | From 2daa49098b1546257652529cd1d69bf92cb5124c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 15 Dec 2020 17:03:50 +0100 Subject: [PATCH 1018/1837] Catch all localhost duplicates when forwarding a port Part of #112571 --- .../workbench/services/remote/common/remoteExplorerService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index fbf76ceda2e..ceddc7e961e 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -97,7 +97,7 @@ export function mapHasAddressLocalhostOrAllInterfaces(map: Map, ho if (originalAddress) { return originalAddress; } - const otherHost = isAllInterfaces(host) ? 'localhost' : (host === 'localhost' ? '0.0.0.0' : undefined); + const otherHost = isAllInterfaces(host) ? 'localhost' : (isLocalhost(host) ? '0.0.0.0' : undefined); if (otherHost) { return mapHasAddress(map, otherHost, port); } From 5b33fdd6507d8bb4ff732218cb3f11a426ba63bd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 17:18:59 +0100 Subject: [PATCH 1019/1837] API: finalize status bar backgroundColor (#110214) --- src/vs/vscode.d.ts | 12 ++++++++++ src/vs/vscode.proposed.d.ts | 23 ------------------- .../workbench/api/common/extHost.api.impl.ts | 2 +- .../workbench/api/common/extHostStatusBar.ts | 18 +++------------ 4 files changed, 16 insertions(+), 39 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 81b27da542b..0def9b1af79 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5419,6 +5419,18 @@ declare module 'vscode' { */ color: string | ThemeColor | undefined; + /** + * The background color for this entry. + * + * *Note*: only `new ThemeColor('statusBarItem.errorBackground')` is + * supported for now. More background colors may be supported in the + * future. + * + * *Note*: when a background color is set, the statusbar may override + * the `color` choice to ensure the entry is readable in all themes. + */ + backgroundColor: ThemeColor | undefined; + /** * [`Command`](#Command) or identifier of a command to run on click. * diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 50649100004..2a960c7821b 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2297,27 +2297,4 @@ declare module 'vscode' { location?: Location; } //#endregion - - //#region Statusbar Item Background Color (https://github.com/microsoft/vscode/issues/110214) - - /** - * A status bar item is a status bar contribution that can - * show text and icons and run a command on click. - */ - export interface StatusBarItem { - - /** - * The background color for this entry. - * - * Note: only `new ThemeColor('statusBarItem.errorBackground')` is - * supported for now. More background colors may be supported in the - * future. - * - * Note: when a background color is set, the statusbar may override - * the `color` choice to ensure the entry is readable in all themes. - */ - backgroundColor: ThemeColor | undefined; - } - - //#endregion } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index fa880fcfc8f..b7ec8703834 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -591,7 +591,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I priority = priority; } - return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation, extension); + return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation); }, setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): vscode.Disposable { return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable); diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index a89e9fe3081..877d56e7972 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -10,8 +10,6 @@ import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto } from import { localize } from 'vs/nls'; import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private static ID_GEN = 0; @@ -48,9 +46,8 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private _proxy: MainThreadStatusBarShape; private _commands: CommandsConverter; private _accessibilityInformation?: vscode.AccessibilityInformation; - private _extension?: IExtensionDescription; - constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation, extension?: IExtensionDescription) { + constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation) { this._id = ExtHostStatusBarEntry.ID_GEN++; this._proxy = proxy; this._commands = commands; @@ -59,7 +56,6 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { this._alignment = alignment; this._priority = priority; this._accessibilityInformation = accessibilityInformation; - this._extension = extension; } public get id(): number { @@ -87,10 +83,6 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { } public get backgroundColor(): ThemeColor | undefined { - if (this._extension) { - checkProposedApiEnabled(this._extension); - } - return this._backgroundColor; } @@ -118,10 +110,6 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { } public set backgroundColor(color: ThemeColor | undefined) { - if (this._extension) { - checkProposedApiEnabled(this._extension); - } - if (color && !ExtHostStatusBarEntry.ALLOWED_BACKGROUND_COLORS.has(color.id)) { color = undefined; } @@ -248,8 +236,8 @@ export class ExtHostStatusBar { this._statusMessage = new StatusBarMessage(this); } - createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation, extension?: IExtensionDescription): vscode.StatusBarItem { - return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation, extension); + createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation): vscode.StatusBarItem { + return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation); } setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): Disposable { From 66bf5744fa5da1d533bf6d361da24f756ce485c3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 15 Dec 2020 17:21:10 +0100 Subject: [PATCH 1020/1837] :up: distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 01eb9cc87d1..2cfa4597017 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "6147f7fceb6892b8d7c9f04684fd70ca90973982", + "distro": "76f83677fb51b70361bf5d0e77f18a09ed4be467", "author": { "name": "Microsoft Corporation" }, @@ -198,4 +198,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From 063ecfe0768226bb1198d7d45f18a276cebf43c6 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 17:29:20 +0100 Subject: [PATCH 1021/1837] explorer: adopt registerAction2 #92038 --- .../files/browser/fileActions.contribution.ts | 4 +- .../contrib/files/browser/fileActions.ts | 77 ------------ .../files/browser/views/explorerView.ts | 119 +++++++++++++++--- 3 files changed, 100 insertions(+), 100 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 80deb82690e..46bc3a043e1 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ToggleAutoSaveAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions'; +import { ToggleAutoSaveAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions'; import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; @@ -40,8 +40,6 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(SaveAllAction, { prim registry.registerWorkbenchAction(SyncActionDescriptor.from(GlobalCompareResourcesAction), 'File: Compare Active File With...', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusFilesExplorer), 'File: Focus on Files Explorer', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowActiveFileInExplorer), 'File: Reveal Active File in Side Bar', category.value); -registry.registerWorkbenchAction(SyncActionDescriptor.from(CollapseExplorerView), 'File: Collapse Folders in Explorer', category.value); -registry.registerWorkbenchAction(SyncActionDescriptor.from(RefreshExplorerView), 'File: Refresh Explorer', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(CompareWithClipboardAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_C) }), 'File: Compare Active File with Clipboard', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAutoSaveAction), 'File: Toggle Auto Save', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowOpenedFileInNewWindow, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_O) }), 'File: Open Active File in New Window', category.value, EmptyWorkspaceSupportContext); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 8e3c6d86c76..8f2c1735c38 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -15,7 +15,6 @@ import { DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/com import { VIEWLET_ID, IFilesConfiguration, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; import { ByteSize, IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; -import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { IQuickInputService, ItemActivation } from 'vs/platform/quickinput/common/quickInput'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -83,40 +82,6 @@ async function refreshIfSeparator(value: string, explorerService: IExplorerServi } } -/* New File */ -export class NewFileAction extends Action { - static readonly ID = 'workbench.files.action.createFileFromExplorer'; - static readonly LABEL = nls.localize('createNewFile', "New File"); - - constructor( - @ICommandService private commandService: ICommandService - ) { - super('explorer.newFile', NEW_FILE_LABEL); - this.class = 'explorer-action ' + Codicon.newFile.classNames; - } - - run(): Promise { - return this.commandService.executeCommand(NEW_FILE_COMMAND_ID); - } -} - -/* New Folder */ -export class NewFolderAction extends Action { - static readonly ID = 'workbench.files.action.createFolderFromExplorer'; - static readonly LABEL = nls.localize('createNewFolder', "New Folder"); - - constructor( - @ICommandService private commandService: ICommandService - ) { - super('explorer.newFolder', NEW_FOLDER_LABEL); - this.class = 'explorer-action ' + Codicon.newFolder.classNames; - } - - run(): Promise { - return this.commandService.executeCommand(NEW_FOLDER_COMMAND_ID); - } -} - async function deleteFiles(explorerService: IExplorerService, workingCopyFileService: IWorkingCopyFileService, dialogService: IDialogService, configurationService: IConfigurationService, elements: ExplorerItem[], useTrash: boolean, skipConfirm = false): Promise { let primaryButton: string; if (useTrash) { @@ -648,48 +613,6 @@ export class ShowActiveFileInExplorer extends Action { } } -export class CollapseExplorerView extends Action { - - static readonly ID = 'workbench.files.action.collapseExplorerFolders'; - static readonly LABEL = nls.localize('collapseExplorerFolders', "Collapse Folders in Explorer"); - - constructor(id: string, - label: string, - @IViewletService private readonly viewletService: IViewletService, - @IExplorerService readonly explorerService: IExplorerService - ) { - super(id, label, 'explorer-action ' + Codicon.collapseAll.classNames); - } - - async run(): Promise { - const explorerViewlet = (await this.viewletService.openViewlet(VIEWLET_ID))?.getViewPaneContainer() as ExplorerViewPaneContainer; - const explorerView = explorerViewlet.getExplorerView(); - if (explorerView) { - explorerView.collapseAll(); - } - } -} - -export class RefreshExplorerView extends Action { - - static readonly ID = 'workbench.files.action.refreshFilesExplorer'; - static readonly LABEL = nls.localize('refreshExplorer', "Refresh Explorer"); - - - constructor( - id: string, label: string, - @IViewletService private readonly viewletService: IViewletService, - @IExplorerService private readonly explorerService: IExplorerService - ) { - super(id, label, 'explorer-action ' + Codicon.refresh.classNames); - } - - async run(): Promise { - await this.viewletService.openViewlet(VIEWLET_ID); - await this.explorerService.refresh(); - } -} - export class ShowOpenedFileInNewWindow extends Action { static readonly ID = 'workbench.action.files.showOpenedFileInNewWindow'; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 33761289571..508bdacc13b 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -8,30 +8,30 @@ import { URI } from 'vs/base/common/uri'; import * as perf from 'vs/base/common/performance'; import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { memoize } from 'vs/base/common/decorators'; -import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, ExplorerRootContext, ExplorerResourceReadonlyContext, ExplorerResourceCut, ExplorerResourceMoveableToTrash, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, ExplorerResourceAvailableEditorIdsContext } from 'vs/workbench/contrib/files/common/files'; -import { NewFolderAction, NewFileAction, FileCopiedContext, RefreshExplorerView, CollapseExplorerView } from 'vs/workbench/contrib/files/browser/fileActions'; +import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, ExplorerRootContext, ExplorerResourceReadonlyContext, ExplorerResourceCut, ExplorerResourceMoveableToTrash, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, ExplorerResourceAvailableEditorIdsContext, VIEW_ID, VIEWLET_ID } from 'vs/workbench/contrib/files/common/files'; +import { FileCopiedContext, NEW_FILE_COMMAND_ID, NEW_FOLDER_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileActions'; import * as DOM from 'vs/base/browser/dom'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ExplorerDecorationsProvider } from 'vs/workbench/contrib/files/browser/views/explorerDecorationsProvider'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; import { WorkbenchCompressibleAsyncDataTree } from 'vs/platform/list/browser/listService'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; +import { IViewPaneOptions, ViewPane, ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { ILabelService } from 'vs/platform/label/common/label'; import { ExplorerDelegate, ExplorerDataSource, FilesRenderer, ICompressedNavigationController, FilesFilter, FileSorter, FileDragAndDrop, ExplorerCompressionDelegate, isCompressedFolderName } from 'vs/workbench/contrib/files/browser/views/explorerViewer'; import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { ITreeContextMenuEvent, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; -import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; +import { IMenuService, MenuId, IMenu, Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ExplorerItem, NewExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; @@ -52,6 +52,9 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { Codicon } from 'vs/base/common/codicons'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; interface IExplorerViewColors extends IColorMapping { listDropBackground?: ColorValue | undefined; @@ -146,7 +149,6 @@ export class ExplorerView extends ViewPane { private shouldRefresh = true; private dragHandler!: DelayedDragHandler; private autoReveal: boolean | 'focusNoScroll' = false; - private actions: IAction[] | undefined; private decorationsProvider: ExplorerDecorationsProvider | undefined; constructor( @@ -284,19 +286,6 @@ export class ExplorerView extends ViewPane { })); } - getActions(): IAction[] { - if (!this.actions) { - this.actions = [ - this.instantiationService.createInstance(NewFileAction), - this.instantiationService.createInstance(NewFolderAction), - this.instantiationService.createInstance(RefreshExplorerView, RefreshExplorerView.ID, RefreshExplorerView.LABEL), - this.instantiationService.createInstance(CollapseExplorerView, CollapseExplorerView.ID, CollapseExplorerView.LABEL) - ]; - this.actions.forEach(a => this._register(a)); - } - return this.actions; - } - focus(): void { this.tree.domFocus(); @@ -856,3 +845,93 @@ function createFileIconThemableTreeContainerScope(container: HTMLElement, themeS onDidChangeFileIconTheme(themeService.getFileIconTheme()); return themeService.onDidFileIconThemeChange(onDidChangeFileIconTheme); } + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.files.action.createFileFromExplorer', + title: nls.localize('createNewFile', "New File"), + f1: false, + icon: Codicon.newFile, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', VIEW_ID), + order: 10 + } + }); + } + + run(accessor: ServicesAccessor): void { + const commandService = accessor.get(ICommandService); + commandService.executeCommand(NEW_FILE_COMMAND_ID); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.files.action.createFolderFromExplorer', + title: nls.localize('createNewFolder', "New Folder"), + f1: false, + icon: Codicon.newFolder, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', VIEW_ID), + order: 20 + } + }); + } + + run(accessor: ServicesAccessor): void { + const commandService = accessor.get(ICommandService); + commandService.executeCommand(NEW_FOLDER_COMMAND_ID); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.files.action.refreshFilesExplorer', + title: nls.localize('refreshExplorer', "Refresh Explorer"), + f1: true, + icon: Codicon.refresh, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', VIEW_ID), + order: 30 + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const viewletService = accessor.get(IViewletService); + const explorerService = accessor.get(IExplorerService); + await viewletService.openViewlet(VIEWLET_ID); + await explorerService.refresh(); + } +}); + +registerAction2(class extends ViewAction { + constructor() { + super({ + id: 'workbench.files.action.collapseExplorerFolders', + title: nls.localize('collapseExplorerFolders', "Collapse Folders in Explorer"), + viewId: VIEW_ID, + f1: true, + icon: Codicon.collapseAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', VIEW_ID), + order: 40 + } + }); + } + + runInView(_accessor: ServicesAccessor, view: ExplorerView): void { + view.collapseAll(); + } +}); From f158da4d7c4710b1f8e0715cafc7d1b20782344d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 15 Dec 2020 17:33:31 +0100 Subject: [PATCH 1022/1837] Fix microsoft/vscode-remote-release/issues/1801 --- .../browser/configurationService.ts | 20 +++++++++---- .../configurationService.test.ts | 29 ++++++++++++++++++- .../test/browser/workbenchTestServices.ts | 4 ++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 9a2fd8e3049..3218d90d3ab 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -16,7 +16,7 @@ import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides import { Configuration } from 'vs/workbench/services/configuration/common/configurationModels'; import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId, IConfigurationCache, machineSettingsSchemaId, LOCAL_MACHINE_SCOPES, IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings, machineOverridableSettings } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings, machineOverridableSettings, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ConfigurationEditingService, EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditingService'; @@ -70,6 +70,8 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat protected readonly _onDidChangeWorkbenchState: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event; + private readonly configurationRegistry: IConfigurationRegistry; + // TODO@sandeep debt with cyclic dependencies private configurationEditingService!: ConfigurationEditingService; private jsonEditingService!: JSONEditingService; @@ -86,11 +88,11 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat ) { super(); - const configurationRegistry = Registry.as(Extensions.Configuration); + this.configurationRegistry = Registry.as(Extensions.Configuration); // register defaults before creating default configuration model // so that the model is not required to be updated after registering if (environmentService.options?.configurationDefaults) { - configurationRegistry.registerDefaultConfigurations([environmentService.options.configurationDefaults]); + this.configurationRegistry.registerDefaultConfigurations([environmentService.options.configurationDefaults]); } this.initRemoteUserConfigurationBarrier = new Barrier(); @@ -123,7 +125,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat }); })); - this._register(configurationRegistry.onDidUpdateConfiguration(configurationProperties => this.onDefaultConfigurationChanged(configurationProperties))); + this._register(this.configurationRegistry.onDidUpdateConfiguration(configurationProperties => this.onDefaultConfigurationChanged(configurationProperties))); this.workspaceEditingQueue = new Queue(); } @@ -802,8 +804,14 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat private toEditableConfigurationTarget(target: ConfigurationTarget, key: string): EditableConfigurationTarget | null { if (target === ConfigurationTarget.USER) { - if (this.inspect(key).userRemoteValue !== undefined) { - return EditableConfigurationTarget.USER_REMOTE; + if (this.remoteUserConfiguration) { + const scope = this.configurationRegistry.getConfigurationProperties()[key]?.scope; + if (scope === ConfigurationScope.MACHINE || scope === ConfigurationScope.MACHINE_OVERRIDABLE) { + return EditableConfigurationTarget.USER_REMOTE; + } + if (this.inspect(key).userRemoteValue !== undefined) { + return EditableConfigurationTarget.USER_REMOTE; + } } return EditableConfigurationTarget.USER_LOCAL; } diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index d6443a0c833..27c9d2abe5a 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -2029,6 +2029,33 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { assert.equal(testObject.getValue('configurationService.remote.machineOverridableSetting'), 'isSet'); }); + test('non machine setting is written in local settings', async () => { + registerRemoteFileSystemProvider(); + resolveRemoteEnvironment(); + await initialize(); + await testObject.updateValue('configurationService.remote.applicationSetting', 'applicationValue'); + await testObject.reloadConfiguration(); + assert.equal(testObject.inspect('configurationService.remote.applicationSetting').userLocalValue, 'applicationValue'); + }); + + test('machine setting is written in remote settings', async () => { + registerRemoteFileSystemProvider(); + resolveRemoteEnvironment(); + await initialize(); + await testObject.updateValue('configurationService.remote.machineSetting', 'machineValue'); + await testObject.reloadConfiguration(); + assert.equal(testObject.inspect('configurationService.remote.machineSetting').userRemoteValue, 'machineValue'); + }); + + test('machine overridable setting is written in remote settings', async () => { + registerRemoteFileSystemProvider(); + resolveRemoteEnvironment(); + await initialize(); + await testObject.updateValue('configurationService.remote.machineOverridableSetting', 'machineValue'); + await testObject.reloadConfiguration(); + assert.equal(testObject.inspect('configurationService.remote.machineOverridableSetting').userRemoteValue, 'machineValue'); + }); + test('machine settings in local user settings does not override defaults after defalts are registered ', async () => { fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.newMachineSetting": "userValue" }'); registerRemoteFileSystemProvider(); @@ -2048,7 +2075,7 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { assert.equal(testObject.getValue('configurationService.remote.newMachineSetting'), 'isSet'); }); - test('machine overridable settings in local user settings does not override defaults after defalts are registered ', async () => { + test('machine overridable settings in local user settings does not override defaults after defaults are registered ', async () => { fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.newMachineOverridableSetting": "userValue" }'); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 3b19e52026f..f7aefffa1d6 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -23,7 +23,7 @@ import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbe import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ILifecycleService, BeforeShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase, WillShutdownEvent } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { FileOperationEvent, IFileService, IFileStat, IResolveFileResult, FileChangesEvent, IResolveFileOptions, ICreateFileOptions, IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, IFileStatWithMetadata, IResolveMetadataFileOptions, IWriteFileOptions, IReadFileOptions, IFileContent, IFileStreamContent, FileOperationError, IFileSystemProviderWithFileReadStreamCapability } from 'vs/platform/files/common/files'; +import { FileOperationEvent, IFileService, IFileStat, IResolveFileResult, FileChangesEvent, IResolveFileOptions, ICreateFileOptions, IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, IFileStatWithMetadata, IResolveMetadataFileOptions, IWriteFileOptions, IReadFileOptions, IFileContent, IFileStreamContent, FileOperationError, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; @@ -993,6 +993,8 @@ export class RemoteFileSystemProvider implements IFileSystemProvider { read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise { return this.diskFileSystemProvider.read!(fd, pos, data, offset, length); } write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise { return this.diskFileSystemProvider.write!(fd, pos, data, offset, length); } + readFileStream(resource: URI, opts: FileReadStreamOptions, token: CancellationToken): ReadableStreamEvents { return this.diskFileSystemProvider.readFileStream!(this.toFileResource(resource), opts, token); } + private toFileResource(resource: URI): URI { return resource.with({ scheme: Schemas.file, authority: '' }); } } From 3080c3e88c4dd7e703daf04dbd64e87dfda94fa2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 09:24:49 -0800 Subject: [PATCH 1023/1837] webview output first load --- .../browser/diff/backLayerWebview2.ts | 10 ++--- .../contrib/notebook/browser/diff/common.ts | 3 +- .../notebook/browser/diff/diffComponents.ts | 45 +++++++++++++++++-- .../browser/diff/diffElementOutputs.ts | 28 +++++++----- .../notebook/browser/diff/notebookDiff.css | 3 +- .../browser/diff/notebookTextDiffEditor.ts | 10 ++++- .../browser/view/renderers/webviewPreloads.ts | 9 +++- 7 files changed, 84 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 0168d38a14a..79cdd189693 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -13,7 +13,7 @@ import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener' import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellOutputKind, IDisplayOutput, INotebookRendererInfo, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; @@ -588,15 +588,15 @@ var requirejs = (function() { const widgets: IContentWidgetTopRequest[] = items.map(item => { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; - const outputIndex = item.cell.outputsViewModels.indexOf(item.output); + // why? does it mean, we create new output view model every time? + const outputIndex = item.cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (item.output.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; if (item.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = item.diffElement.getOutputOffsetInCell(false, outputIndex); + outputOffset = item.cellTop + item.diffElement.getOutputOffsetInCell(false, outputIndex); } else { - outputOffset = (item.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + outputOffset = item.cellTop + (item.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } - // const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); outputCache.cachedCreation.top = outputOffset; this.hiddenInsetMapping.delete(item.output); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 521e0b053bf..0365d2ae16f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputViewModel, IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; @@ -22,6 +22,7 @@ export interface INotebookTextDiffEditor { layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; + hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IDisplayOutputViewModel): void; } export interface IDiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 45357266a99..6b6b4cf83ed 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -292,7 +292,9 @@ abstract class AbstractElementRenderer extends Disposable { this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); this._buildOutputContainer(); } else { - this.cell.layoutChange(); + // todo, show insets + this._showOutputs(); + // this.cell.layoutChange(); } } else { this._outputInfoContainer.style.display = 'block'; @@ -306,13 +308,20 @@ abstract class AbstractElementRenderer extends Disposable { } } } else { - this._outputInfoContainer.style.display = 'none'; - this._outputEditorDisposeStore.clear(); - this.cell.layoutChange(); + if (RENDER_RICH_OUTPUT) { + this._hideOutputs(); + this.cell.layoutChange(); + } else { + this._outputInfoContainer.style.display = 'none'; + this._outputEditorDisposeStore.clear(); + this.cell.layoutChange(); + } } } abstract _buildOutputContainer(): void; + abstract _hideOutputs(): void; + abstract _showOutputs(): void; private _applySanitizedMetadataChanges(currentMetadata: NotebookCellMetadata, newMetadata: any) { let result: { [key: string]: any } = {}; @@ -805,6 +814,14 @@ export class DeletedElement extends SingleSideDiffElement { // this._outputView.render(); // this.layout({ outputView: true }); } + + _showOutputs() { + + } + + _hideOutputs() { + + } } export class InsertElement extends SingleSideDiffElement { @@ -870,6 +887,15 @@ export class InsertElement extends SingleSideDiffElement { this.cell.layoutChange(); } + _showOutputs() { + this._outputLeftView?.render(); + this.cell.layoutChange(); + } + + _hideOutputs() { + this._outputLeftView?.hideOutputs(); + } + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { @@ -1033,6 +1059,15 @@ export class ModifiedElement extends AbstractElementRenderer { this.cell.layoutChange(); } + _showOutputs() { + this._outputLeftView?.render(); + this._outputRightView?.render(); + this.cell.layoutChange(); + } + + _hideOutputs() { + + } updateSourceEditor(): void { const modifiedCell = this.cell.modified!; @@ -1128,6 +1163,8 @@ export class ModifiedElement extends AbstractElementRenderer { this.cell.editorHeight = contentHeight; } + + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 91cfe7de933..425be86467d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -85,7 +85,7 @@ export class OutputElement extends Disposable { this.cellViewModel, this.cell, result, - this.getOutputOffsetInContainer(index), + this.getOutputOffsetInCell(index), this.cellViewModel instanceof SideBySideDiffElementViewModel ? this.modified : this.cellViewModel.type === 'insert' @@ -175,8 +175,8 @@ export class OutputContainer extends Disposable { constructor( private _editor: INotebookTextDiffEditor, private notebookTextModel: NotebookTextModel, - private cellViewModel: DiffElementViewModelBase, - private cell: DiffNestedCellViewModel, + private diffElementViewModel: DiffElementViewModelBase, + private cellViewModel: DiffNestedCellViewModel, private modified: boolean, private outputContainer: HTMLElement, @INotebookService private notebookService: INotebookService, @@ -186,22 +186,22 @@ export class OutputContainer extends Disposable { ) { super(); - this._outputViewModels = cell.outputs.map(output => new CellOutputViewModel(output, notebookService)); + this._outputViewModels = cellViewModel.outputs.map(output => new CellOutputViewModel(output, notebookService)); // TODO, onDidChangeOutputs // viewCell.onDidChangeLayout // say the height of the cell editor changes - this._register(this.cellViewModel.onDidLayoutChange(() => { + this._register(this.diffElementViewModel.onDidLayoutChange(() => { this.outputEntries.forEach((value, key) => { - const index = cell.outputs.indexOf(key.model); + const index = cellViewModel.outputs.indexOf(key.model); if (index >= 0) { - if (this.cellViewModel instanceof SideBySideDiffElementViewModel) { - const top = this.cellViewModel.getOutputOffsetInContainer(!this.modified, index); + if (this.diffElementViewModel instanceof SideBySideDiffElementViewModel) { + const top = this.diffElementViewModel.getOutputOffsetInContainer(!this.modified, index); value.domNode.style.top = `${top}px`; } else { - const top = (this.cellViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); + const top = (this.diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); value.domNode.style.top = `${top}px`; } } @@ -219,9 +219,17 @@ export class OutputContainer extends Disposable { } } + hideOutputs() { + this.outputEntries.forEach((outputElement, cellOutputViewModel) => { + if (cellOutputViewModel.isDisplayOutput()) { + this._editor.hideInset(this.diffElementViewModel, this.cellViewModel, cellOutputViewModel); + } + }); + } + private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this.outputEntries.has(currOutput)) { - this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.cellViewModel, this.modified, this.cell, this.outputContainer, currOutput)); + this.outputEntries.set(currOutput, new OutputElement(this._editor, this.notebookTextModel, this.notebookService, this.diffElementViewModel, this.modified, this.cellViewModel, this.outputContainer, currOutput)); } const renderElement = this.outputEntries.get(currOutput)!; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index 22266135923..e1cb48d1588 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -115,6 +115,7 @@ .monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover, .monaco-workbench .notebook-text-diff-editor > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused { outline: none !important; + background-color: transparent !important; } .notebook-text-diff-editor .cell-diff-editor-container .editor-input-toolbar-container { @@ -137,7 +138,7 @@ .monaco-workbench .notebook-text-diff-editor .cell-body.left .output-view-container .output-inner-container, .monaco-workbench .notebook-text-diff-editor .cell-body.right .output-view-container .output-inner-container { width: 100%; - padding: 4px 8px; + padding: 0px 8px; box-sizing: border-box; } .monaco-workbench .notebook-text-diff-editor .cell-body.full .output-view-container .output-inner-container { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 74d56b87b92..d9e0fece457 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; -import { IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -418,6 +418,14 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD }); } + removeInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput) { + + } + + hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IDisplayOutputViewModel) { + this._modifiedWebview?.hideInset(output); + } + // private async _resolveWebview(rightEditor: boolean): Promise { // if (rightEditor) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 6a8de1fac10..6565898f513 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -20,6 +20,12 @@ declare module globalThis { }); } +declare var acquireVsCodeApi: () => ({ + getState(): { [key: string]: unknown; }; + setState(data: { [key: string]: unknown; }): void; + postMessage: (msg: unknown) => void; +}); + declare class ResizeObserver { constructor(onChange: (entries: { target: HTMLElement, contentRect?: ClientRect; }[]) => void); observe(element: Element): void; @@ -36,7 +42,7 @@ interface EmitterLike { } function webviewPreloads() { - const acquireVsCodeApi = globalThis.acquireVsCodeApi; + // const acquireVsCodeApi = acquireVsCodeApi; const vscode = acquireVsCodeApi(); delete (globalThis as any).acquireVsCodeApi; @@ -397,7 +403,6 @@ function webviewPreloads() { window.addEventListener('message', rawEvent => { const event = rawEvent as ({ data: ToWebviewMessage; }); - console.log(event); switch (event.data.type) { case 'html': From caa595fc06613b7f05e72665cc435e3c21388424 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 10:22:38 -0800 Subject: [PATCH 1024/1837] absolute position of mixed static and dynamic webview --- .../browser/diff/backLayerWebview2.ts | 93 +++++++++---------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 79cdd189693..2d53fc60926 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -459,8 +459,7 @@ var requirejs = (function() { const info = this.resolveOutputId(data.id); if (info) { const { diffElement, cell, output } = info; - const outputIndex = cell.outputsViewModels.indexOf(output); - + const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.model as ITransformedDisplayOutputDto).outputId); if (diffElement instanceof SideBySideDiffElementViewModel) { diffElement.updateOutputHeight(false, outputIndex, outputHeight); } else { @@ -470,53 +469,53 @@ var requirejs = (function() { // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); } } - // } else if (data.type === 'mouseenter') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // const { cell } = info; - // cell.outputIsHovered = true; - // } - // } else if (data.type === 'mouseleave') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // const { cell } = info; - // cell.outputIsHovered = false; - // } - // } else if (data.type === '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()); - // } else if (data.type === 'did-scroll-wheel') { - // this.notebookEditor.triggerScroll({ - // ...data.payload, - // preventDefault: () => { }, - // stopPropagation: () => { } - // }); - // } else if (data.type === 'focus-editor') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // if (data.focusNext) { - // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); - // if (typeof idx !== 'number') { - // return; - // } + // } else if (data.type === 'mouseenter') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // const { cell } = info; + // cell.outputIsHovered = true; + // } + // } else if (data.type === 'mouseleave') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // const { cell } = info; + // cell.outputIsHovered = false; + // } + // } else if (data.type === '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()); + // } else if (data.type === 'did-scroll-wheel') { + // this.notebookEditor.triggerScroll({ + // ...data.payload, + // preventDefault: () => { }, + // stopPropagation: () => { } + // }); + // } else if (data.type === 'focus-editor') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // if (data.focusNext) { + // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); + // if (typeof idx !== 'number') { + // return; + // } - // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; - // if (!newCell) { - // return; - // } + // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; + // if (!newCell) { + // return; + // } - // this.notebookEditor.focusNotebookCell(newCell, 'editor'); - // } else { - // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); - // } - // } - // } else if (data.type === 'clicked-data-url') { - // this._onDidClickDataLink(data); - // } else if (data.type === 'customRendererMessage') { - // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); - // } - // return; + // this.notebookEditor.focusNotebookCell(newCell, 'editor'); + // } else { + // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); + // } + // } + // } else if (data.type === 'clicked-data-url') { + // this._onDidClickDataLink(data); + // } else if (data.type === 'customRendererMessage') { + // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); + // } + // return; } this._onMessage.fire({ message: data }); From bbb797d3e4d1f897120401c03fd9bc6119ee583a Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 10:23:38 -0800 Subject: [PATCH 1025/1837] clear static outputs when collapse outputs panel --- .../workbench/contrib/notebook/browser/diff/diffComponents.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 6b6b4cf83ed..2771f8b135b 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -310,6 +310,8 @@ abstract class AbstractElementRenderer extends Disposable { } else { if (RENDER_RICH_OUTPUT) { this._hideOutputs(); + this._outputInfoContainer.style.display = 'none'; + this._outputEditorDisposeStore.clear(); this.cell.layoutChange(); } else { this._outputInfoContainer.style.display = 'none'; From 35be51e43d90b37e72fb4a565a822f4124ab5bba Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 15 Dec 2020 19:35:37 +0100 Subject: [PATCH 1026/1837] open editors: adopt registerAction2 #92038 --- .../browser/actions/layoutActions.ts | 51 --------- .../files/browser/fileActions.contribution.ts | 7 +- .../contrib/files/browser/fileActions.ts | 16 +-- .../contrib/files/browser/fileCommands.ts | 7 +- .../files/browser/views/openEditorsView.ts | 108 +++++++++++++++--- 5 files changed, 103 insertions(+), 86 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 784dc905a15..41eb6d4362c 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -10,10 +10,8 @@ import { SyncActionDescriptor, MenuId, MenuRegistry, registerAction2, Action2 } import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions, CATEGORIES } from 'vs/workbench/common/actions'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; -import { IEditorGroupsService, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; -import { DisposableStore } from 'vs/base/common/lifecycle'; import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { isWindows, isLinux, isWeb } from 'vs/base/common/platform'; import { IsMacNativeContext } from 'vs/platform/contextkey/common/contextkeys'; @@ -26,7 +24,6 @@ import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/plat import { INotificationService } from 'vs/platform/notification/common/notification'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { Codicon } from 'vs/base/common/codicons'; const registry = Registry.as(WorkbenchExtensions.WorkbenchActions); @@ -125,54 +122,6 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { order: 3 }); -// --- Toggle Editor Layout - -export class ToggleEditorLayoutAction extends Action { - - static readonly ID = 'workbench.action.toggleEditorGroupLayout'; - static readonly LABEL = nls.localize('flipLayout', "Toggle Vertical/Horizontal Editor Layout"); - - private readonly toDispose = this._register(new DisposableStore()); - - constructor( - id: string, - label: string, - @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService - ) { - super(id, label); - - this.class = Codicon.editorLayout.classNames; - this.updateEnablement(); - - this.registerListeners(); - } - - private registerListeners(): void { - this.toDispose.add(this.editorGroupService.onDidAddGroup(() => this.updateEnablement())); - this.toDispose.add(this.editorGroupService.onDidRemoveGroup(() => this.updateEnablement())); - } - - private updateEnablement(): void { - this.enabled = this.editorGroupService.count > 1; - } - - async run(): Promise { - const newOrientation = (this.editorGroupService.orientation === GroupOrientation.VERTICAL) ? GroupOrientation.HORIZONTAL : GroupOrientation.VERTICAL; - this.editorGroupService.setGroupOrientation(newOrientation); - } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleEditorLayoutAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_0 } }), 'View: Toggle Vertical/Horizontal Editor Layout', CATEGORIES.View.value); - -MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, { - group: 'z_flip', - command: { - id: ToggleEditorLayoutAction.ID, - title: nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Flip &&Layout") - }, - order: 1 -}); - // --- Toggle Sidebar Position export class ToggleSidebarPositionAction extends Action { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 46bc3a043e1..c9b2dcd2a7f 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -5,12 +5,12 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ToggleAutoSaveAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions'; +import { ToggleAutoSaveAction, FocusFilesExplorer, GlobalCompareResourcesAction, ShowActiveFileInExplorer, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions'; import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; -import { openWindowCommand, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, OpenEditorsDirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL, newWindowCommand, OpenEditorsReadonlyEditorContext, OPEN_WITH_EXPLORER_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { openWindowCommand, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, OpenEditorsDirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL, newWindowCommand, OpenEditorsReadonlyEditorContext, OPEN_WITH_EXPLORER_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, SAVE_ALL_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -36,7 +36,6 @@ import { Codicon } from 'vs/base/common/codicons'; const category = { value: nls.localize('filesCategory', "File"), original: 'File' }; const registry = Registry.as(ActionExtensions.WorkbenchActions); -registry.registerWorkbenchAction(SyncActionDescriptor.from(SaveAllAction, { primary: undefined, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_S }, win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_S) } }), 'File: Save All', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(GlobalCompareResourcesAction), 'File: Compare Active File With...', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusFilesExplorer), 'File: Focus on Files Explorer', category.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowActiveFileInExplorer), 'File: Reveal Active File in Side Bar', category.value); @@ -610,7 +609,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { group: '4_save', command: { - id: SaveAllAction.ID, + id: SAVE_ALL_COMMAND_ID, title: nls.localize({ key: 'miSaveAll', comment: ['&& denotes a mnemonic'] }, "Save A&&ll"), precondition: DirtyWorkingCopiesContext }, diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 8f2c1735c38..c51159ec4e7 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -20,7 +20,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ITextModel } from 'vs/editor/common/model'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { REVEAL_IN_EXPLORER_COMMAND_ID, SAVE_ALL_COMMAND_ID, SAVE_ALL_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { REVEAL_IN_EXPLORER_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -528,20 +528,6 @@ export abstract class BaseSaveAllAction extends Action { } } -export class SaveAllAction extends BaseSaveAllAction { - - static readonly ID = 'workbench.action.files.saveAll'; - static readonly LABEL = SAVE_ALL_LABEL; - - get class(): string { - return 'explorer-action ' + Codicon.saveAll.classNames; - } - - protected doRun(): Promise { - return this.commandService.executeCommand(SAVE_ALL_COMMAND_ID); - } -} - export class SaveAllInGroupAction extends BaseSaveAllAction { static readonly ID = 'workbench.files.action.saveAllInGroup'; diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 8e1badc5fe5..96479b1229c 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -482,7 +482,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -CommandsRegistry.registerCommand({ +KeybindingsRegistry.registerCommandAndKeybindingRule({ + when: undefined, + weight: KeybindingWeight.WorkbenchContrib, + primary: undefined, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_S }, + win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_S) }, id: SAVE_ALL_COMMAND_ID, handler: (accessor) => { return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index c925f2ad8ad..d123cd99535 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -9,16 +9,15 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { IAction, ActionRunner, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import * as dom from 'vs/base/browser/dom'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IEditorInput, Verbosity, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; -import { SaveAllAction, SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions'; +import { SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions'; import { OpenEditorsFocusedContext, ExplorerFocusedContext, IFilesConfiguration, OpenEditor } from 'vs/workbench/contrib/files/common/files'; import { CloseAllEditorsAction, CloseEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; -import { ToggleEditorLayoutAction } from 'vs/workbench/browser/actions/layoutActions'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { badgeBackground, badgeForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -30,8 +29,8 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; -import { OpenEditorsDirtyEditorContext, OpenEditorsGroupContext, OpenEditorsReadonlyEditorContext } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { IMenuService, MenuId, IMenu, Action2, registerAction2, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { OpenEditorsDirtyEditorContext, OpenEditorsGroupContext, OpenEditorsReadonlyEditorContext, SAVE_ALL_LABEL, SAVE_ALL_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ResourcesDropHandler, fillResourceDataTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; @@ -49,6 +48,10 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { compareFileNamesDefault } from 'vs/base/common/comparers'; +import { Codicon } from 'vs/base/common/codicons'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { ICommandService } from 'vs/platform/commands/common/commands'; const $ = dom.$; @@ -294,14 +297,6 @@ export class OpenEditorsView extends ViewPane { })); } - getActions(): IAction[] { - return [ - this.instantiationService.createInstance(ToggleEditorLayoutAction, ToggleEditorLayoutAction.ID, ToggleEditorLayoutAction.LABEL), - this.instantiationService.createInstance(SaveAllAction, SaveAllAction.ID, SaveAllAction.LABEL), - this.instantiationService.createInstance(CloseAllEditorsAction, CloseAllEditorsAction.ID, CloseAllEditorsAction.LABEL) - ]; - } - focus(): void { super.focus(); this.list.domFocus(); @@ -705,3 +700,86 @@ class OpenEditorsAccessibilityProvider implements IListAccessibilityProvider { + const editorGroupService = accessor.get(IEditorGroupsService); + const newOrientation = (editorGroupService.orientation === GroupOrientation.VERTICAL) ? GroupOrientation.HORIZONTAL : GroupOrientation.VERTICAL; + editorGroupService.setGroupOrientation(newOrientation); + } +}); + +MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, { + group: 'z_flip', + command: { + id: toggleEditorGroupLayoutId, + title: nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Flip &&Layout") + }, + order: 1 +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.files.saveAll', + title: SAVE_ALL_LABEL, + f1: true, + icon: Codicon.saveAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', OpenEditorsView.ID), + order: 20 + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const commandService = accessor.get(ICommandService); + await commandService.executeCommand(SAVE_ALL_COMMAND_ID); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'openEditors.closeAll', + title: CloseAllEditorsAction.LABEL, + f1: false, + icon: Codicon.closeAll, + menu: { + id: MenuId.ViewTitle, + group: 'navigation', + when: ContextKeyEqualsExpr.create('view', OpenEditorsView.ID), + order: 30 + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const instantiationService = accessor.get(IInstantiationService); + const closeAll = instantiationService.createInstance(CloseAllEditorsAction, CloseAllEditorsAction.ID, CloseAllEditorsAction.LABEL); + await closeAll.run(); + } +}); From 284ace0bb6f566239a7d4760d8ea4674c05a92ed Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 15 Dec 2020 10:36:19 -0800 Subject: [PATCH 1027/1837] Cleqn up codicons --- .../welcome/gettingStarted/browser/gettingStarted.ts | 10 +++++----- .../browser/vs_code_editor_getting_started.ts | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index c03606751b5..817d7d4fdef 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -94,12 +94,12 @@ export class GettingStartedPage extends Disposable { if (category.id === this.currentCategory?.id) { const badgeelement = assertIsDefined(document.getElementById('done-task-' + task.id)); if (task.done) { - badgeelement.classList.remove('codicon-star-empty'); - badgeelement.classList.add('codicon-star-full'); + badgeelement.classList.remove('codicon-circle-large-outline'); + badgeelement.classList.add('codicon-pass-filled'); } else { - badgeelement.classList.add('codicon-star-empty'); - badgeelement.classList.remove('codicon-star-full'); + badgeelement.classList.add('codicon-circle-large-outline'); + badgeelement.classList.remove('codicon-pass-filled'); } } this.updateCategoryProgress(); @@ -303,7 +303,7 @@ export class GettingStartedPage extends Disposable { const categoryElements = category.content.items.map( (task, i, arr) => $('button.getting-started-task', { 'x-dispatch': 'selectTask:' + task.id, id: 'getting-started-task-' + task.id }, - $('.codicon' + (task.done ? '.complete.codicon-pass-filled' : '.codicon-circle-large-outline'), { id: 'done-task-' + task.id }), + $('.codicon' + (task.done ? '.codicon-pass-filled' : '.codicon-circle-large-outline'), { id: 'done-task-' + task.id }), $('.task-description-container', {}, $('h3.task-title', {}, task.title), $('.task-description.description', {}, task.description), diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index 6bb3e6fd883..92221ba66c4 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -17,10 +17,9 @@ export default () => `
- Back + Back
-
+
From 179adc5f7fd6fe7f1398b333a176ec511d51e684 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 15 Dec 2020 20:00:31 +0100 Subject: [PATCH 1028/1837] support removing a setting from all targets --- .../browser/configurationService.ts | 44 +++++++++++-------- .../configurationService.test.ts | 30 +++++++++++++ 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 3218d90d3ab..d858cfd0b1a 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -293,19 +293,20 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat async updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): Promise { await this.cyclicDependency; const overrides = isConfigurationOverrides(arg3) ? arg3 : undefined; - let target: ConfigurationTarget | undefined = overrides ? arg4 : arg3; + const target: ConfigurationTarget | undefined = overrides ? arg4 : arg3; + const targets: ConfigurationTarget[] = target ? [target] : []; - if (!target) { + if (!targets.length) { const inspect = this.inspect(key, overrides); - target = this.deriveConfigurationTarget(key, value, inspect); - if (target === ConfigurationTarget.USER && equals(value, inspect.defaultValue)) { + targets.push(...this.deriveConfigurationTargets(key, value, inspect)); + + // Remove the setting, if the value is same as default value and is updated only in user target + if (equals(value, inspect.defaultValue) && targets.length === 1 && (targets[0] === ConfigurationTarget.USER || targets[0] === ConfigurationTarget.USER_LOCAL)) { value = undefined; } } - if (target) { - await this.writeConfigurationValue(key, value, target, overrides, donotNotifyError); - } + await Promise.all(targets.map(target => this.writeConfigurationValue(key, value, target, overrides, donotNotifyError))); } async reloadConfiguration(target?: ConfigurationTarget | IWorkspaceFolder): Promise { @@ -759,26 +760,31 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat }); } - private deriveConfigurationTarget(key: string, value: any, inspect: IConfigurationValue): ConfigurationTarget | undefined { - if (value === undefined) { - // Ignore. But expected is to remove the value from all targets - return undefined; - } - + private deriveConfigurationTargets(key: string, value: any, inspect: IConfigurationValue): ConfigurationTarget[] { if (equals(value, inspect.value)) { - // No change. So ignore. - return undefined; + return []; } + const definedTargets: ConfigurationTarget[] = []; if (inspect.workspaceFolderValue !== undefined) { - return ConfigurationTarget.WORKSPACE_FOLDER; + definedTargets.push(ConfigurationTarget.WORKSPACE_FOLDER); } - if (inspect.workspaceValue !== undefined) { - return ConfigurationTarget.WORKSPACE; + definedTargets.push(ConfigurationTarget.WORKSPACE); + } + if (inspect.userRemoteValue !== undefined) { + definedTargets.push(ConfigurationTarget.USER_REMOTE); + } + if (inspect.userLocalValue !== undefined) { + definedTargets.push(ConfigurationTarget.USER_LOCAL); } - return ConfigurationTarget.USER; + if (value === undefined) { + // Remove the setting in all defined targets + return definedTargets; + } + + return [definedTargets[0] || ConfigurationTarget.USER]; } private triggerConfigurationChange(change: IConfigurationChange, previous: { data: IConfigurationData, workspace?: Workspace } | undefined, target: ConfigurationTarget): void { diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 27c9d2abe5a..7629a329976 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -1174,6 +1174,20 @@ suite('WorkspaceConfigurationService - Folder', () => { .then(() => assert.ok(target.called)); }); + test('remove setting from all targets', async () => { + const key = 'configurationService.folder.testSetting'; + await testObject.updateValue(key, 'workspaceValue', ConfigurationTarget.WORKSPACE); + await testObject.updateValue(key, 'userValue', ConfigurationTarget.USER); + + await testObject.updateValue(key, undefined); + await testObject.reloadConfiguration(); + + const actual = testObject.inspect(key, { resource: workspaceService.getWorkspace().folders[0].uri }); + assert.equal(actual.userValue, undefined); + assert.equal(actual.workspaceValue, undefined); + assert.equal(actual.workspaceFolderValue, undefined); + }); + test('update user configuration to default value when target is not passed', async () => { await testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER); await testObject.updateValue('configurationService.folder.testSetting', 'isSet'); @@ -1805,6 +1819,22 @@ suite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.ok(target.called)); }); + test('remove setting from all targets', async () => { + const workspace = workspaceContextService.getWorkspace(); + const key = 'configurationService.workspace.testResourceSetting'; + await testObject.updateValue(key, 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); + await testObject.updateValue(key, 'workspaceValue', ConfigurationTarget.WORKSPACE); + await testObject.updateValue(key, 'userValue', ConfigurationTarget.USER); + + await testObject.updateValue(key, undefined, { resource: workspace.folders[0].uri }); + await testObject.reloadConfiguration(); + + const actual = testObject.inspect(key, { resource: workspace.folders[0].uri }); + assert.equal(actual.userValue, undefined); + assert.equal(actual.workspaceValue, undefined); + assert.equal(actual.workspaceFolderValue, undefined); + }); + test('update tasks configuration in a folder', () => { const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) From ff02224c1bcb4d2998133d74de99093b38919e65 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 11:03:12 -0800 Subject: [PATCH 1029/1837] move output layout info into genericCellViewModel shared by notebook and diff. --- .../browser/diff/backLayerWebview2.ts | 10 +- .../browser/diff/diffElementOutputs.ts | 2 +- .../browser/diff/diffElementViewModel.ts | 132 +++--------------- .../browser/diff/diffNestedCellViewModel.ts | 67 +++++++-- .../contrib/notebook/browser/genericTypes.ts | 18 +++ 5 files changed, 102 insertions(+), 127 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/genericTypes.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 2d53fc60926..c3c95e2355e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -12,7 +12,6 @@ import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; @@ -25,6 +24,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; +import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -198,7 +198,7 @@ export type AnyMessage = FromWebviewMessage | ToWebviewMessage; interface ICachedInset { outputId: string; diffElement: DiffElementViewModelBase; - cell: DiffNestedCellViewModel; + cell: IGenericCellViewModel; renderer?: INotebookRendererInfo; cachedCreation: ICreationRequestMessage; } @@ -334,7 +334,7 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cell: DiffNestedCellViewModel, diffElement: DiffElementViewModelBase, output: IDisplayOutputViewModel } | undefined { + private resolveOutputId(id: string): { cell: IGenericCellViewModel, diffElement: DiffElementViewModelBase, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; @@ -555,7 +555,7 @@ var requirejs = (function() { return webview; } - shouldUpdateInset(cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { + shouldUpdateInset(cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { if (this._disposed) { return; } @@ -615,7 +615,7 @@ var requirejs = (function() { }); } - async createInset(cellDiffViewModel: DiffElementViewModelBase, cell: DiffNestedCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) { + async createInset(cellDiffViewModel: DiffElementViewModelBase, cell: IGenericCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) { if (this._disposed) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 425be86467d..0361db6bed1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -140,7 +140,7 @@ export class OutputElement extends Disposable { return this.cellViewModel.original.outputs.indexOf(this.output.model); } } else { - return (this.cellViewModel as SingleSideDiffElementViewModel).cellTextModel!.outputs.indexOf(this.output.model); + return (this.cellViewModel as SingleSideDiffElementViewModel).cellViewModel!.outputs.indexOf(this.output.model); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 33442495fb1..181d4557e2b 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -131,7 +131,6 @@ export abstract class DiffElementViewModelBase extends Disposable { abstract checkIfOutputsModified(): boolean; abstract checkMetadataIfModified(): boolean; - abstract ensureOutputsTop(): void; abstract layoutChange(): void; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { @@ -144,11 +143,6 @@ export abstract class DiffElementViewModelBase extends Disposable { } export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { - protected _originalOutputCollection: number[] = []; - protected _originalOutputsTop: PrefixSumComputer | null = null; - protected _modifiedOutputCollection: number[] = []; - protected _modifiedOutputsTop: PrefixSumComputer | null = null; - constructor( readonly documentTextModel: NotebookTextModel, readonly original: DiffNestedCellViewModel, @@ -174,13 +168,16 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { this.outputFoldingState = PropertyFoldingState.Expanded; } - this._originalOutputCollection = new Array(this.original.outputs.length); - this._modifiedOutputCollection = new Array(this.modified.outputs.length); + this._register(this.original.onDidChangeOutputLayout(() => { + this.layoutChange(); + })); + + this._register(this.modified.onDidChangeOutputLayout(() => { + this.layoutChange(); + })); } layoutChange() { - this.ensureOutputsTop(); - let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); this._layoutInfo = { width: this._layoutInfo.width, @@ -206,69 +203,17 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { updateOutputHeight(original: boolean, index: number, height: number) { if (original) { - if (index >= this._originalOutputCollection.length) { - throw new Error('Output index out of range!'); - } - - this.ensureOriginalOutputsTop(); - this.ensureModifiedOutputsTop(); - this._originalOutputCollection[index] = height; - - if (this._originalOutputsTop!.changeValue(index, height)) { - this.layoutChange(); - } + this.original.updateOutputHeight(index, height); } else { - if (index >= this._modifiedOutputCollection.length) { - throw new Error('Output index out of range!'); - } - - this.ensureOriginalOutputsTop(); - this.ensureModifiedOutputsTop(); - this._modifiedOutputCollection[index] = height; - - if (this._modifiedOutputsTop!.changeValue(index, height)) { - this.layoutChange(); - } - } - } - - ensureOriginalOutputsTop() { - if (!this._originalOutputsTop) { - const values = new Uint32Array(this._originalOutputCollection.length); - for (let i = 0; i < this._originalOutputCollection.length; i++) { - values[i] = this._originalOutputCollection[i]; - } - - this._originalOutputsTop = new PrefixSumComputer(values); - } - } - - ensureModifiedOutputsTop() { - if (!this._modifiedOutputsTop) { - const values = new Uint32Array(this._modifiedOutputCollection.length); - for (let i = 0; i < this._modifiedOutputCollection.length; i++) { - values[i] = this._modifiedOutputCollection[i]; - } - - this._modifiedOutputsTop = new PrefixSumComputer(values); + this.modified.updateOutputHeight(index, height); } } getOutputOffsetInContainer(original: boolean, index: number) { - this.ensureOutputsTop(); - if (original) { - if (index >= this._originalOutputCollection.length) { - throw new Error('Output index out of range!'); - } - - return this._originalOutputsTop!.getAccumulatedValue(index - 1); + return this.original.getOutputOffset(index); } else { - if (index >= this._modifiedOutputCollection.length) { - throw new Error('Output index out of range!'); - } - - return this._modifiedOutputsTop!.getAccumulatedValue(index - 1); + return this.modified.getOutputOffset(index); } } @@ -285,22 +230,12 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { } getOutputTotalHeight() { - this.ensureOutputsTop(); - - return Math.max(this._originalOutputsTop?.getTotalValue() ?? 0, this._modifiedOutputsTop?.getTotalValue() ?? 0); - } - - ensureOutputsTop() { - this.ensureOriginalOutputsTop(); - this.ensureModifiedOutputsTop(); + return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); } } export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { - protected _outputCollection: number[] = []; - protected _outputsTop: PrefixSumComputer | null = null; - - get cellTextModel() { + get cellViewModel() { return this.type === 'insert' ? this.modified : this.original; } @@ -312,12 +247,12 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { readonly editorEventDispatcher: NotebookDiffEditorEventDispatcher ) { super(documentTextModel, original, modified, type, editorEventDispatcher); - this._outputCollection = new Array(this.original ? this.original.outputs.length : this.modified!.outputs.length); + this._register(this.cellViewModel!.onDidChangeOutputLayout(() => { + this.layoutChange(); + })); } layoutChange() { - this.ensureOutputsTop(); - let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); this._layoutInfo = { width: this._layoutInfo.width, @@ -343,40 +278,15 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { } updateOutputHeight(index: number, height: number) { - if (index >= this._outputCollection.length) { - throw new Error('Output index out of range!'); - } - - this.ensureOutputsTop(); - this._outputCollection[index] = height; - if (this._outputsTop!.changeValue(index, height)) { - this.layoutChange(); - } - } - - ensureOutputsTop() { - if (!this._outputsTop) { - const values = new Uint32Array(this._outputCollection.length); - for (let i = 0; i < this._outputCollection.length; i++) { - values[i] = this._outputCollection[i]; - } - - this._outputsTop = new PrefixSumComputer(values); - } + this.cellViewModel?.updateOutputHeight(index, height); } getOutputOffsetInContainer(index: number) { - this.ensureOutputsTop(); - - if (index >= this._outputCollection.length) { - throw new Error('Output index out of range!'); - } - - return this._outputsTop!.getAccumulatedValue(index - 1); + return this.cellViewModel!.getOutputOffset(index); } getOutputOffsetInCell(index: number) { - const offsetInOutputsContainer = this.getOutputOffsetInContainer(index); + const offsetInOutputsContainer = this.cellViewModel!.getOutputOffset(index); return this._layoutInfo.editorHeight + this._layoutInfo.editorMargin @@ -388,9 +298,7 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { } getOutputTotalHeight() { - this.ensureOutputsTop(); - - return this._outputsTop?.getTotalValue() ?? 0; + return this.cellViewModel?.getOutputTotalHeight() ?? 0; } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts index ed4e2c14c63..e0817b93cbc 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts @@ -3,15 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { generateUuid } from 'vs/base/common/uuid'; +import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IDiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; import { ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; -export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCellViewModel { +export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCellViewModel, IGenericCellViewModel { private _id: string; get id() { return this._id; @@ -43,6 +46,12 @@ export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCe return this._outputViewModels; } + protected _outputCollection: number[] = []; + protected _outputsTop: PrefixSumComputer | null = null; + protected readonly _onDidChangeOutputLayout = new Emitter(); + readonly onDidChangeOutputLayout = this._onDidChangeOutputLayout.event; + + constructor( readonly textModel: NotebookCellTextModel, @INotebookService private _notebookService: INotebookService @@ -51,14 +60,54 @@ export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCe this._id = generateUuid(); this._outputViewModels = this.textModel.outputs.map(output => new CellOutputViewModel(output, this._notebookService)); - // this._register(this.textModel.onDidChangeOutputs((splices) => { - // splices.reverse().forEach(splice => { - // this._outputCollection.splice(splice[0], splice[1], ...splice[2].map(() => 0)); - // this._outputViewModels.splice(splice[0], splice[1], ...splice[2].map(output => new CellOutputViewModel(output, this._notebookService))); - // }); + this._register(this.textModel.onDidChangeOutputs((splices) => { + splices.reverse().forEach(splice => { + this._outputCollection.splice(splice[0], splice[1], ...splice[2].map(() => 0)); + this._outputViewModels.splice(splice[0], splice[1], ...splice[2].map(output => new CellOutputViewModel(output, this._notebookService))); + }); - // this._outputsTop = null; - // this._onDidChangeOutputs.fire(splices); - // })); + this._outputsTop = null; + this._onDidChangeOutputLayout.fire(); + })); + this._outputCollection = new Array(this.textModel.outputs.length); + } + + private _ensureOutputsTop() { + if (!this._outputsTop) { + const values = new Uint32Array(this._outputCollection.length); + for (let i = 0; i < this._outputCollection.length; i++) { + values[i] = this._outputCollection[i]; + } + + this._outputsTop = new PrefixSumComputer(values); + } + } + + getOutputOffset(index: number): number { + this._ensureOutputsTop(); + + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + return this._outputsTop!.getAccumulatedValue(index - 1); + } + + updateOutputHeight(index: number, height: number): void { + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + this._ensureOutputsTop(); + this._outputCollection[index] = height; + if (this._outputsTop!.changeValue(index, height)) { + this._onDidChangeOutputLayout.fire(); + } + } + + getOutputTotalHeight() { + this._ensureOutputsTop(); + + return this._outputsTop?.getTotalValue() ?? 0; } } diff --git a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts new file mode 100644 index 00000000000..dc531714626 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { URI } from 'vs/base/common/uri'; +import { ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; + +export interface IGenericCellViewModel { + id: string; + handle: number; + uri: URI; + metadata: NotebookCellMetadata; + outputsViewModels: ICellOutputViewModel[]; + getOutputOffset(index: number): number; + updateOutputHeight(index: number, height: number): void; +} From bd67f0d0cabb9d1c11e2b50bbf0ee1851033de11 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 11:03:34 -0800 Subject: [PATCH 1030/1837] :lipstick: --- .../contrib/notebook/browser/diff/diffElementViewModel.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 181d4557e2b..e5a1415708f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -14,7 +14,6 @@ import { hash } from 'vs/base/common/hash'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; export enum PropertyFoldingState { From 7284389d4bcb93c0d3b8e15efe1400809739ca78 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 15 Dec 2020 11:11:26 -0800 Subject: [PATCH 1031/1837] Update Codicons: Make circle-large-outline 1px outline (fixes #112310) https://github.com/microsoft/vscode-codicons/commit/7a530b493aadaaadee5ae62e33a90235795dfc09 --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 62836 -> 62840 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 7fdf6ed7b9db8580b4a762998936d06b55c37b51..9b7584b919420e01753ca74665c531bef7cde2fd 100644 GIT binary patch delta 897 zcmezJiuuPY<_QiWX6Nq+Gcd@`VPH7ol98I2BF(u=YGQ~EOIF0Zq=_xcf)5xNn79h^ zi%ZH^y^LmHc>HGK4g;CJ?VY;u{5D@1xS3xt0Kx5lyH>*J%`A+*QuR7qQCv&7mAE6g zH*tUB;o&Lbxxs6~8^znldyJ2bPmeEwFOTmJe-{540V9Ddfe8Yu1ojA=6SyPrMUX{M zOK_9m86hX32%%*{_k?~3>j`@Z=Lk0l9}s>eA|?_ck|)X{Y9*Q`dPMY@n1Gm>Sc+Ji z*c!1X;u7Kx;sxRh#Lr3C)k~a^WRjGVOp!bxB_`D-^-Nktx=#9sjEBq|nJ2OVvSqTX zWY5S&$<@g%k~<?n-5I)f^w{+3OY|n_ZO~89 zuhCzkf5*VX;Fn>TVUOV}BQYZzqco#g#(c&a#x2HMjDMLpm^7K}G5KVwVj5+-$n=t# zkl6yWALf57Y%D4)URX+5wphNfa=W##IB+<4I21TsaQNiN;CQ9pDZr`1nZY^4`J9W5%QTlyu4=AHuE*RA+-A64a{J>h z=N{+2#{HTHpNEgfHjiJP4xX31oV*Tr^LS74zTzY1)8uo`*Uz`ecZ%OKzbF0-{yP4B z{+s+?1Q-Rp2owqo37ivnB=AR&LQq_=N^nx}jNm6B%R(-NCWS5tlL&JOYYO*g3wH_c z3%?Q}6Ok7&BjQD*K%`S-T;zc$g{W)M646@GHqn033DKuwgkrK{=EZ!8t%*Gs#}ele zw<7LKyjy%u{Dk-m2`mY12`dsC60amFZJr|=BFtoMIr)=;bG@1pKO-AE8@nMNqlmbe zxEzy_nYp2vxtTqqnTbB5n!2GHgj5Hr;$u|OW3gj2H#4_mG!mC%6c-a=V+uD&Gho!$ z3N@0H;+1w&3Q0(h2XS~9d3hOmBqfy?l{B^V8O5xV4GYQ&k^-#c8RcZHlZ*<=EDILP z3pmI##{m`cN*IM|$EWKjxG5P)Ndq}REe7fOKyx*L21rWs{N0sgEh{f?6_8X=o^O~8 SWDCeIF0iP`-~7R_WQ?HbdB^k88?|(GLK~aWJ_dM z$exmmkgJhfAa_V!LOw{oLxD+QgCdKfpW-d0B4s({Bo!%@Evi*&JZeE|X=>Zl8Pqk@ z^VDx>NNM+&Ier+-D$eF^jP%ji}d>R*6GLT zSLrX(zh&TN@WU{~u*>j;k%*C%QHs$FV;*BQ<0j)x#y?E#Od3pfnS3x+GL0}@V0yt! zz-*q`H}hW>Ru*Lz&nzV@n=GGM*;(ze7P79g?z28(!)N1XlVvl@W}mH-ZJV8xU7Otp z`#Aea4r~r?4tWme96mVwbG%gV%!&CFTNQgIjw#M9 zZdu%?c$fIB_`dja2}}ts3Cj}e5-%kwY@Q<nYo#{shNqoshYZ>nm!|lRA*#k=VMgTV=)0q+A$i5%Q1?JiLf!bGirpYGpZ}Q zYl(`9Yg)Sbhxr59BHTPYT%sbfj55l~Kw0Z#!-BGcqyQ^ Date: Tue, 15 Dec 2020 11:13:58 -0800 Subject: [PATCH 1032/1837] Update codicons: use new loading icon and animation (fixes #112593) https://github.com/microsoft/vscode-codicons/commit/ca2658d7973430426109b97f9f57c9f50b4f1717 --- .../ui/codicons/codicon/codicon-modifiers.css | 7 +++++++ .../browser/ui/codicons/codicon/codicon.ttf | Bin 62840 -> 62556 bytes 2 files changed, 7 insertions(+) diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css b/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css index 6007a997eac..cb82d3a6570 100644 --- a/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css +++ b/src/vs/base/browser/ui/codicons/codicon/codicon-modifiers.css @@ -21,3 +21,10 @@ .codicon-modifier-disabled { opacity: 0.4; } + +/* custom speed & easing for loading icon */ +.codicon-loading, +.codicon-tree-item-loading::before { + animation-duration: 1s !important; + animation-timing-function: cubic-bezier(0.53, 0.21, 0.29, 0.67) !important; +} diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 9b7584b919420e01753ca74665c531bef7cde2fd..acbaeafa87d4f4669c0b6aa5678254cf961e85ad 100644 GIT binary patch delta 498 zcmezIiuuk9<_QiWt2-+vFfho@VPH6{k&&91BF(w$!Nd?97Q410rim>|LJy8GFfefy zSEerCS;ano@c(!{FOzNMUTZd z%P7lDRt8pWR`0BttSzjYtPfe=v*EKbve{2a@AJ^`$nn_Z z>EgM?%gC$Fo5kDByTkj7kAu$vpC`U-eiD9Reno!s{2BaJ{Gt5myj!=LZMxu+d{vDRfKH|X9#x-?+bqr!4(k|Vc!(7CE`M) zQRJj3kEpJwIZ^AP4n$pwwux?uz7r!5lNR$X)*-emc2}HKTw2_YxO?$T@lNq&@jnuz z5Ffefy zFPo^rSQKpMbFPRCMEin6G{>Q?`qQc^ZrIclh ztdH3U*aX<**vzpxVC!PrVJBnPVfV>C!G4MZhl7Vhfx`udPmTwq_p_ayHtK4LyiKIeS>e2aXi_$~8$;?Ll(&9Ie|w4 ze*`H6#RaPbCk4+4eiE`QN!AR%G}Moi$RD%iNT1$iNTv8gdvuph=GC8NL)-@OoWd~NnK4{ z&BTt0Rn5%YOk9ppT#S!VU5|;~NQ_;KosFGMNsq}~%}m$?Br67#XXj%CYG5@I6Jb+Q z1B#lML72iY5oU_ zg}F4OR2dmrxg@xy#09w+8C3&?_{BuI*m>C5Ikhx6Ss5Kfq@^{arN40PKwMl=T!PU8WRa8*qXWqD0n7p-m_9OhGYB#$GH5ZF14CDjQJax(b6?%LQUG-0((V8N From c782b708b18dca14bb195c92b1366a090d4072e7 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 11:22:24 -0800 Subject: [PATCH 1033/1837] cell body height to 0 so I can click into the webview --- .../workbench/contrib/notebook/browser/diff/notebookDiff.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index e1cb48d1588..ba600aa00c7 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -125,6 +125,9 @@ margin: 4px 2px; } +.monaco-workbench .notebook-text-diff-editor .cell-body { + height: 0; +} .monaco-workbench .notebook-text-diff-editor .cell-body .output-view-container { user-select: text; From 0ff71d3213829113ce3a7dbc549c774614fc14d4 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 11:49:51 -0800 Subject: [PATCH 1034/1837] update output in webview position when list view layout change. --- .../browser/diff/backLayerWebview2.ts | 2 +- .../browser/diff/notebookTextDiffEditor.ts | 51 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index c3c95e2355e..b41c94fde88 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -579,7 +579,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { diffElement: DiffElementViewModelBase, cell: DiffNestedCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: { diffElement: DiffElementViewModelBase, cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { if (this._disposed) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index d9e0fece457..96affc78bc6 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -29,7 +29,7 @@ import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { NotebookDiffEditorEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { INotebookDiffEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookDiffEditorModel, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; @@ -42,6 +42,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; +import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -178,6 +179,54 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._webviewTransparentCover.style.display = 'none'; } })); + + this._register(this._list.onDidChangeContentHeight(() => { + DOM.scheduleAtNextAnimationFrame(() => { + const scrollTop = this._list.scrollTop; + const scrollHeight = this._list.scrollHeight; + + if (!this._modifiedWebview) { + return; + } + + this._modifiedWebview!.element.style.height = `${scrollHeight}px`; + + if (this._modifiedWebview?.insetMapping) { + const updateItems: { diffElement: DiffElementViewModelBase, cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[] = []; + const removedItems: IDisplayOutputViewModel[] = []; + this._modifiedWebview?.insetMapping.forEach((value, key) => { + const cell = value.cell; + const viewIndex = this._list.indexOf(value.diffElement); + + if (viewIndex === undefined) { + return; + } + + if (cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId) < 0) { + // output is already gone + removedItems.push(key); + } + + const cellTop = this._list.getAbsoluteTopOfElement(value.diffElement); + if (this._modifiedWebview!.shouldUpdateInset(cell, key, cellTop)) { + updateItems.push({ + diffElement: value.diffElement, + cell: cell, + output: key, + cellTop: cellTop + }); + } + }); + + removedItems.forEach(output => this._modifiedWebview?.removeInset(output)); + + if (updateItems.length) { + this._modifiedWebview?.updateViewScrollTop(-scrollTop, false, updateItems); + } + } + + }); + })); } async setInput(input: NotebookDiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { From 976b9b5cda29fbe46bbe90f5558605c75a039a77 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 11:58:54 -0800 Subject: [PATCH 1035/1837] :lipstick: --- .../workbench/contrib/notebook/browser/diff/backLayerWebview2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index b41c94fde88..8b74d9ef9bd 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -22,7 +22,6 @@ import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/re import { FileAccess, Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; From 691a2ce4ecdf01e693f86f63e05f0ea0343211f5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 15 Dec 2020 21:11:29 +0100 Subject: [PATCH 1036/1837] add timeOrigin as implict mark whenever possible --- src/vs/base/common/performance.js | 112 ++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 5a03e119067..ceb864ebf24 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -7,54 +7,89 @@ //@ts-check -function _factory(sharedObj) { +/** + * @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}} + */ +function _definePolyfillMarks(timeOrigin) { + + const _data = []; + if (typeof timeOrigin === 'number') { + _data.push('code/timeOrigin', timeOrigin); + } + + function mark(name) { + _data.push(name, Date.now()); + } + function getMarks() { + const result = []; + for (let i = 0; i < _data.length; i += 2) { + result.push({ + name: _data[i], + startTime: _data[i + 1], + }); + } + return result; + } + return { mark, getMarks }; +} + +/** + * @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}} + */ +function _define() { if (typeof performance === 'object' && typeof performance.mark === 'function') { // in a browser context, reuse performance-util - function mark(name) { - performance.mark(name); - } - function getMarks() { - let timeOrigin = performance.timeOrigin; - if (!timeOrigin) { - // polyfill for Safari - const entry = performance.timing; - timeOrigin = entry.navigationStart || entry.redirectStart || entry.fetchStart; - } - return performance.getEntriesByType('mark').map(entry => { - return { - name: entry.name, - startTime: Math.round(timeOrigin + entry.startTime) - }; - }); + + if (typeof performance.timeOrigin !== 'number' && !performance.timing) { + // safari & webworker: because there is no timeOrigin and no workaround + // we use the `Date.now`-based polyfill. + return _definePolyfillMarks(); + + } else { + // use "native" performance for mark and getMarks + return { + mark(name) { + performance.mark(name); + }, + getMarks() { + let timeOrigin = performance.timeOrigin; + if (typeof timeOrigin !== 'number') { + // safari: there is no timerOrigin but in renderers there is the timing-property + timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart; + } + const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; + for (const entry of performance.getEntriesByType('mark')) { + result.push({ + name: entry.name, + startTime: Math.round(timeOrigin + entry.startTime) + }); + } + return result; + } + }; } - return { mark, getMarks }; + } else if (typeof process === 'object') { + // node.js: use the normal polyfill but add the timeOrigin + // from the node perf_hooks API as very first mark + const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin); + return _definePolyfillMarks(timeOrigin); } else { - // node.js context, use mock and a shared obj that's share between module systems - sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || []; - - function mark(name) { - sharedObj.MonacoPerformanceMarks.push(name, Date.now()); - } - - function getMarks() { - const result = []; - const entries = sharedObj.MonacoPerformanceMarks; - for (let i = 0; i < entries.length; i += 2) { - result.push({ - name: entries[i], - startTime: entries[i + 1], - }); - } - return result; - } - - return { mark, getMarks }; + // unknown environment + console.trace('perf-util loaded in UNKNOWN environment'); + return _definePolyfillMarks(); } } +function _factory(sharedObj) { + if (!sharedObj.MonacoPerformanceMarks) { + sharedObj.MonacoPerformanceMarks = _define(); + } + return sharedObj.MonacoPerformanceMarks; +} + // This module can be loaded in an amd and commonjs-context. // Because we want both instances to use the same perf-data // we store them globally @@ -78,5 +113,6 @@ if (typeof define === 'function') { // commonjs module.exports = _factory(sharedObj); } else { + console.trace('perf-util defined in UNKNOWN context (neither requirejs or commonjs)'); sharedObj.perf = _factory(sharedObj); } From fbe4aa28ff4e074380a74615d8aff0653dada26c Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 21:47:59 +0100 Subject: [PATCH 1037/1837] Collect and deliver perf marks from extension hosts (#112552) --- src/bootstrap-amd.js | 2 ++ src/bootstrap-fork.js | 3 ++ .../api/browser/mainThreadExtensionService.ts | 36 ++++++++++--------- .../workbench/api/common/extHost.protocol.ts | 7 ++-- .../api/common/extHostExtensionService.ts | 27 ++++++++++++-- .../api/common/extHostRequireInterceptor.ts | 3 ++ .../api/node/extHostExtensionService.ts | 13 +++++-- .../api/worker/extHostExtensionService.ts | 18 ++++++++-- .../extensions/common/extensionHostMain.ts | 2 ++ .../extensions/common/extensionHostManager.ts | 1 + .../node/extensionHostProcessSetup.ts | 5 ++- .../extensions/worker/extensionHostWorker.ts | 5 +-- .../browser/api/mainThreadDiagnostics.test.ts | 2 ++ .../browser/api/mainThreadTreeViews.test.ts | 2 ++ .../test/browser/api/testRPCProtocol.ts | 5 ++- 15 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/bootstrap-amd.js b/src/bootstrap-amd.js index 58355aebdba..d9ca4f690cd 100644 --- a/src/bootstrap-amd.js +++ b/src/bootstrap-amd.js @@ -8,6 +8,7 @@ const loader = require('./vs/loader'); const bootstrap = require('./bootstrap'); +const performance = require('./vs/base/common/performance'); // Bootstrap: NLS const nlsConfig = bootstrap.setupNLS(); @@ -55,5 +56,6 @@ exports.load = function (entrypoint, onLoad, onError) { onLoad = onLoad || function () { }; onError = onError || function (err) { console.error(err); }; + performance.mark(`fork/willLoadCode`); loader([entrypoint], onLoad, onError); }; diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index 2787af39e18..f32627f531f 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -6,6 +6,9 @@ //@ts-check 'use strict'; +const performance = require('./vs/base/common/performance'); +performance.mark('fork/start'); + const bootstrap = require('./bootstrap'); const bootstrapNode = require('./bootstrap-node'); diff --git a/src/vs/workbench/api/browser/mainThreadExtensionService.ts b/src/vs/workbench/api/browser/mainThreadExtensionService.ts index 5d0132e2989..11cfcc3db8f 100644 --- a/src/vs/workbench/api/browser/mainThreadExtensionService.ts +++ b/src/vs/workbench/api/browser/mainThreadExtensionService.ts @@ -7,7 +7,7 @@ import { SerializedError } from 'vs/base/common/errors'; import Severity from 'vs/base/common/severity'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { IExtHostContext, MainContext, MainThreadExtensionServiceShape } from 'vs/workbench/api/common/extHost.protocol'; -import { IExtensionService, ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, ExtensionActivationError, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { localize } from 'vs/nls'; @@ -19,29 +19,23 @@ import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/com import { CancellationToken } from 'vs/base/common/cancellation'; import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; +import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; @extHostNamedCustomer(MainContext.MainThreadExtensionService) export class MainThreadExtensionService implements MainThreadExtensionServiceShape { - private readonly _extensionService: IExtensionService; - private readonly _notificationService: INotificationService; - private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService; - private readonly _hostService: IHostService; - private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService; + private readonly _extensionHostKind: ExtensionHostKind; constructor( extHostContext: IExtHostContext, - @IExtensionService extensionService: IExtensionService, - @INotificationService notificationService: INotificationService, - @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService, - @IHostService hostService: IHostService, - @IWorkbenchExtensionEnablementService extensionEnablementService: IWorkbenchExtensionEnablementService + @IExtensionService private readonly _extensionService: IExtensionService, + @INotificationService private readonly _notificationService: INotificationService, + @IExtensionsWorkbenchService private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService, + @IHostService private readonly _hostService: IHostService, + @IWorkbenchExtensionEnablementService private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, + @ITimerService private readonly _timerService: ITimerService, ) { - this._extensionService = extensionService; - this._notificationService = notificationService; - this._extensionsWorkbenchService = extensionsWorkbenchService; - this._hostService = hostService; - this._extensionEnablementService = extensionEnablementService; + this._extensionHostKind = extHostContext.extensionHostKind; } public dispose(): void { @@ -131,4 +125,14 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha async $onExtensionHostExit(code: number): Promise { this._extensionService._onExtensionHostExit(code); } + + async $setPerformanceMarks(marks: PerformanceMark[]): Promise { + if (this._extensionHostKind === ExtensionHostKind.LocalProcess) { + this._timerService.setPerformanceMarks('localExtHost', marks); + } else if (this._extensionHostKind === ExtensionHostKind.LocalWebWorker) { + this._timerService.setPerformanceMarks('workerExtHost', marks); + } else { + this._timerService.setPerformanceMarks('remoteExtHost', marks); + } + } } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index a2ff7b55eed..733bd6f3971 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as performance from 'vs/base/common/performance'; import { VSBuffer } from 'vs/base/common/buffer'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IRemoteConsoleLog } from 'vs/base/common/console'; @@ -41,7 +42,7 @@ import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views'; import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug'; import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder'; import { ITerminalDimensions, IShellLaunchConfig, ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal'; -import { ActivationKind, ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions'; +import { ActivationKind, ExtensionActivationError, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import * as search from 'vs/workbench/services/search/common/search'; import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor'; @@ -108,7 +109,8 @@ export interface IConfigurationInitData extends IConfigurationData { } export interface IExtHostContext extends IRPCProtocol { - remoteAuthority: string | null; + readonly remoteAuthority: string | null; + readonly extensionHostKind: ExtensionHostKind; } export interface IMainContext extends IRPCProtocol { @@ -853,6 +855,7 @@ export interface MainThreadExtensionServiceShape extends IDisposable { $onExtensionActivationError(extensionId: ExtensionIdentifier, error: ExtensionActivationError): Promise; $onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void; $onExtensionHostExit(code: number): Promise; + $setPerformanceMarks(marks: performance.PerformanceMark[]): Promise; } export interface SCMProviderFeatures { diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 328b9327207..63f33e8ce8d 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -5,6 +5,7 @@ import * as nls from 'vs/nls'; import * as path from 'vs/base/common/path'; +import * as performance from 'vs/base/common/performance'; import { originalFSPath, joinPath } from 'vs/base/common/resources'; import { Barrier, timeout } from 'vs/base/common/async'; import { dispose, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; @@ -184,6 +185,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme this._almostReadyToRunExtensions.open(); await this._extHostWorkspace.waitForInitializeCall(); + performance.mark('extHost/ready'); this._readyToStartExtensionHost.open(); if (this._initData.autoStart) { @@ -362,10 +364,14 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup); return Promise.all([ - this._loadCommonJSModule(joinPath(extensionDescription.extensionLocation, entryPoint), activationTimesBuilder), + this._loadCommonJSModule(extensionDescription.identifier, joinPath(extensionDescription.extensionLocation, entryPoint), activationTimesBuilder), this._loadExtensionContext(extensionDescription) ]).then(values => { + performance.mark(`extHost/willActivateExtension/${extensionDescription.identifier.value}`); return AbstractExtHostExtensionService._callActivate(this._logService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder); + }).then((activatedExtension) => { + performance.mark(`extHost/didActivateExtension/${extensionDescription.identifier.value}`); + return activatedExtension; }); } @@ -456,6 +462,18 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } private _activateAllStartupFinished(): void { + // startup is considered finished + const marks = performance.getMarks().map((entry) => { + if (entry.name.startsWith('fork/')) { + return { + name: `extHost/` + entry.name.substr('fork/'.length), + startTime: entry.startTime + }; + } + return entry; + }); + this._mainThreadExtensionsProxy.$setPerformanceMarks(marks); + for (const desc of this._registry.getAllExtensionDescriptions()) { if (desc.activationEvents) { for (const activationEvent of desc.activationEvents) { @@ -541,7 +559,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme let testRunner: ITestRunner | INewTestRunner | undefined; let requireError: Error | undefined; try { - testRunner = await this._loadCommonJSModule(URI.file(extensionTestsPath), new ExtensionActivationTimesBuilder(false)); + testRunner = await this._loadCommonJSModule(null, URI.file(extensionTestsPath), new ExtensionActivationTimesBuilder(false)); } catch (error) { requireError = error; } @@ -644,7 +662,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } try { + performance.mark(`extHost/willResolveAuthority/${authorityPrefix}`); const result = await resolver.resolve(remoteAuthority, { resolveAttempt }); + performance.mark(`extHost/didResolveAuthorityOK/${authorityPrefix}`); this._disposables.add(await this._extHostTunnelService.setTunnelExtensionFunctions(resolver)); // Split merged API result into separate authority/options @@ -667,6 +687,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } }; } catch (err) { + performance.mark(`extHost/didResolveAuthorityError/${authorityPrefix}`); if (err instanceof RemoteAuthorityResolverError) { return { type: 'error', @@ -754,7 +775,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme protected abstract _beforeAlmostReadyToRunExtensions(): Promise; protected abstract _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined; - protected abstract _loadCommonJSModule(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise; + protected abstract _loadCommonJSModule(extensionId: ExtensionIdentifier | null, module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise; public abstract $setRemoteEnvironment(env: { [key: string]: string | null }): Promise; } diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index fd9ae5f2d97..2446cf89b36 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as performance from 'vs/base/common/performance'; import { TernarySearchTree } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; import { MainThreadTelemetryShape, MainContext } from 'vs/workbench/api/common/extHost.protocol'; @@ -52,7 +53,9 @@ export abstract class RequireInterceptor { this._installInterceptor(); + performance.mark('extHost/willWaitForConfig'); const configProvider = await this._extHostConfiguration.getConfigProvider(); + performance.mark('extHost/didWaitForConfig'); const extensionPaths = await this._extHostExtensionService.getExtensionPathIndex(); this.register(new VSCodeNodeModuleFactory(this._apiFactory, extensionPaths, this._extensionRegistry, configProvider, this._logService)); diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 3d92a699151..85a05c33032 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as performance from 'vs/base/common/performance'; import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; import { MainContext } from 'vs/workbench/api/common/extHost.protocol'; @@ -13,7 +14,7 @@ import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadSer import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; class NodeModuleRequireInterceptor extends RequireInterceptor { @@ -62,10 +63,12 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { // Module loading tricks const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, this._registry); await interceptor.install(); + performance.mark('extHost/didInitAPI'); // Do this when extension service exists, but extensions are not being activated yet. const configProvider = await this._extHostConfiguration.getConfigProvider(); await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._logService, this._mainThreadTelemetryProxy, this._initData); + performance.mark('extHost/didInitProxyResolver'); // Use IPC messages to forward console-calls, note that the console is // already patched to use`process.send()` @@ -84,7 +87,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { return extensionDescription.main; } - protected _loadCommonJSModule(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { + protected _loadCommonJSModule(extensionId: ExtensionIdentifier | null, module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { if (module.scheme !== Schemas.file) { throw new Error(`Cannot load URI: '${module}', must be of file-scheme`); } @@ -93,10 +96,16 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { this._logService.info(`ExtensionService#loadCommonJSModule ${module.toString(true)}`); this._logService.flush(); try { + if (extensionId) { + performance.mark(`extHost/willLoadExtensionCode/${extensionId.value}`); + } r = require.__$__nodeRequire(module.fsPath); } catch (e) { return Promise.reject(e); } finally { + if (extensionId) { + performance.mark(`extHost/didLoadExtensionCode/${extensionId.value}`); + } activationTimesBuilder.codeLoadingStop(); } return Promise.resolve(r); diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index 021af6e0f89..e69e48b0b8d 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -8,7 +8,7 @@ import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHost import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; import { URI } from 'vs/base/common/uri'; import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; import { timeout } from 'vs/base/common/async'; @@ -42,6 +42,8 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, this._registry); await this._fakeModules.install(); + performance.mark('extHost/didInitAPI'); + await this._waitForDebuggerAttachment(); } @@ -49,10 +51,16 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { return extensionDescription.browser; } - protected async _loadCommonJSModule(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { + protected async _loadCommonJSModule(extensionId: ExtensionIdentifier | null, module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { module = module.with({ path: ensureSuffix(module.path, '.js') }); + if (extensionId) { + performance.mark(`extHost/willFetchExtensionCode/${extensionId.value}`); + } const response = await fetch(module.toString(true)); + if (extensionId) { + performance.mark(`extHost/didFetchExtensionCode/${extensionId.value}`); + } if (response.status !== 200) { throw new Error(response.statusText); @@ -78,9 +86,15 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { try { activationTimesBuilder.codeLoadingStart(); + if (extensionId) { + performance.mark(`extHost/willLoadExtensionCode/${extensionId.value}`); + } initFn(_module, _exports, _require); return (_module.exports !== _exports ? _module.exports : _exports); } finally { + if (extensionId) { + performance.mark(`extHost/didLoadExtensionCode/${extensionId.value}`); + } activationTimesBuilder.codeLoadingStop(); } } diff --git a/src/vs/workbench/services/extensions/common/extensionHostMain.ts b/src/vs/workbench/services/extensions/common/extensionHostMain.ts index b91ba18adbe..3590d05969f 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostMain.ts @@ -5,6 +5,7 @@ import { timeout } from 'vs/base/common/async'; import * as errors from 'vs/base/common/errors'; +import * as performance from 'vs/base/common/performance'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IURITransformer } from 'vs/base/common/uriIpc'; @@ -67,6 +68,7 @@ export class ExtensionHostMain { const logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); this._disposables.add(logService); + performance.mark(`extHost/didCreateServices`); logService.info('extension host started'); logService.trace('initData', initData); diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index b25ff919d24..46b7a59b691 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -182,6 +182,7 @@ export class ExtensionHostManager extends Disposable { this._register(this._rpcProtocol.onDidChangeResponsiveState((responsiveState: ResponsiveState) => this._onDidChangeResponsiveState.fire(responsiveState))); const extHostContext: IExtHostContext = { remoteAuthority: this._extensionHost.remoteAuthority, + extensionHostKind: this.kind, getProxy: (identifier: ProxyIdentifier): T => this._rpcProtocol!.getProxy(identifier), set: (identifier: ProxyIdentifier, instance: R): R => this._rpcProtocol!.set(identifier, instance), assertRegistered: (identifiers: ProxyIdentifier[]): void => this._rpcProtocol!.assertRegistered(identifiers), diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index 88076f1364c..0e5e8e3d23f 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -6,6 +6,7 @@ import * as nativeWatchdog from 'native-watchdog'; import * as net from 'net'; import * as minimist from 'minimist'; +import * as performance from 'vs/base/common/performance'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; @@ -295,9 +296,11 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise { - + performance.mark(`extHost/willConnectToRenderer`); const protocol = await createExtHostProtocol(); + performance.mark(`extHost/didConnectToRenderer`); const renderer = await connectToRenderer(protocol); + performance.mark(`extHost/didWaitForInitData`); const { initData } = renderer; // setup things patchProcess(!!initData.environment.extensionTestsLocationURI); // to support other test frameworks like Jasmin that use process.exit (https://github.com/microsoft/vscode/issues/37708) diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 488e8060718..72607f084db 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -12,6 +12,7 @@ import { ExtensionHostMain } from 'vs/workbench/services/extensions/common/exten import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; import { NestedWorker } from 'vs/workbench/services/extensions/worker/polyfillNestedWorker'; import * as path from 'vs/base/common/path'; +import * as performance from 'vs/base/common/performance'; import 'vs/workbench/api/common/extHost.common.services'; import 'vs/workbench/api/worker/extHost.worker.services'; @@ -150,9 +151,9 @@ let onTerminate = nativeClose; (function create(): void { const res = new ExtensionWorker(); - + performance.mark(`extHost/willConnectToRenderer`); connectToRenderer(res.protocol).then(data => { - + performance.mark(`extHost/didWaitForInitData`); const extHostMain = new ExtensionHostMain( data.protocol, data.initData, diff --git a/src/vs/workbench/test/browser/api/mainThreadDiagnostics.test.ts b/src/vs/workbench/test/browser/api/mainThreadDiagnostics.test.ts index 3f10f0cffd6..958e2a2f7ca 100644 --- a/src/vs/workbench/test/browser/api/mainThreadDiagnostics.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadDiagnostics.test.ts @@ -10,6 +10,7 @@ import { URI } from 'vs/base/common/uri'; import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; import { mock } from 'vs/workbench/test/common/workbenchTestServices'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; suite('MainThreadDiagnostics', function () { @@ -25,6 +26,7 @@ suite('MainThreadDiagnostics', function () { let diag = new MainThreadDiagnostics( new class implements IExtHostContext { remoteAuthority = ''; + extensionHostKind = ExtensionHostKind.LocalProcess; assertRegistered() { } set(v: any): any { return null; } getProxy(): any { diff --git a/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts b/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts index 4d93df2209e..2888c4e22b1 100644 --- a/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts @@ -17,6 +17,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ViewDescriptorService } from 'vs/workbench/services/views/browser/viewDescriptorService'; import { CustomTreeView } from 'vs/workbench/browser/parts/views/treeView'; +import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; suite('MainThreadHostTreeView', function () { const testTreeViewId = 'testTreeView'; @@ -61,6 +62,7 @@ suite('MainThreadHostTreeView', function () { mainThreadTreeViews = new MainThreadTreeViews( new class implements IExtHostContext { remoteAuthority = ''; + extensionHostKind = ExtensionHostKind.LocalProcess; assertRegistered() { } set(v: any): any { return null; } getProxy(): any { diff --git a/src/vs/workbench/test/browser/api/testRPCProtocol.ts b/src/vs/workbench/test/browser/api/testRPCProtocol.ts index d2d2b1c504f..196bff1c56d 100644 --- a/src/vs/workbench/test/browser/api/testRPCProtocol.ts +++ b/src/vs/workbench/test/browser/api/testRPCProtocol.ts @@ -8,6 +8,7 @@ import { CharCode } from 'vs/base/common/charCode'; import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; import { isThenable } from 'vs/base/common/async'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; export function SingleProxyRPCProtocol(thing: any): IExtHostContext & IExtHostRpcService { return { @@ -20,7 +21,8 @@ export function SingleProxyRPCProtocol(thing: any): IExtHostContext & IExtHostRp return value; }, assertRegistered: undefined!, - drain: undefined! + drain: undefined!, + extensionHostKind: ExtensionHostKind.LocalProcess }; } @@ -28,6 +30,7 @@ export class TestRPCProtocol implements IExtHostContext, IExtHostRpcService { public _serviceBrand: undefined; public remoteAuthority = null!; + public extensionHostKind = ExtensionHostKind.LocalProcess; private _callCountValue: number = 0; private _idle?: Promise; From 15ba91d098cc413ad70c35ae616135662c66c581 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 22:07:01 +0100 Subject: [PATCH 1038/1837] Massage mark name to align --- src/vs/workbench/api/common/extHostExtensionService.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 63f33e8ce8d..812a850c7e5 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -470,6 +470,12 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme startTime: entry.startTime }; } + if (entry.name.startsWith('code/')) { + return { + name: `extHost/` + entry.name.substr('code/'.length), + startTime: entry.startTime + }; + } return entry; }); this._mainThreadExtensionsProxy.$setPerformanceMarks(marks); From 65bc4153aed1e42427367cd5ca782cbd1bb3bcc4 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 13:11:27 -0800 Subject: [PATCH 1039/1837] support scroll position syncing. --- .../browser/diff/backLayerWebview2.ts | 95 +++++++++---------- .../contrib/notebook/browser/diff/common.ts | 5 + .../browser/diff/diffNestedCellViewModel.ts | 13 ++- .../browser/diff/notebookTextDiffEditor.ts | 5 +- .../browser/diff/notebookTextDiffList.ts | 5 + .../contrib/notebook/browser/genericTypes.ts | 1 + 6 files changed, 74 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 8b74d9ef9bd..79767a5f7ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -464,57 +464,56 @@ var requirejs = (function() { } else { (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); } - // cell.updateOutputHeight(outputIndex, outputHeight); // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); } + } else if (data.type === 'mouseenter') { + const info = this.resolveOutputId(data.id); + if (info) { + const { cell } = info; + cell.outputIsHovered = true; + } + } else if (data.type === 'mouseleave') { + const info = this.resolveOutputId(data.id); + if (info) { + const { cell } = info; + cell.outputIsHovered = false; + } + // } else if (data.type === '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()); + } else if (data.type === 'did-scroll-wheel') { + this.notebookEditor.triggerScroll({ + ...data.payload, + preventDefault: () => { }, + stopPropagation: () => { } + }); + // } else if (data.type === 'focus-editor') { + // const info = this.resolveOutputId(data.id); + // if (info) { + // if (data.focusNext) { + // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); + // if (typeof idx !== 'number') { + // return; + // } + + // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; + // if (!newCell) { + // return; + // } + + // this.notebookEditor.focusNotebookCell(newCell, 'editor'); + // } else { + // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); + // } + // } + // } else if (data.type === 'clicked-data-url') { + // this._onDidClickDataLink(data); + // } else if (data.type === 'customRendererMessage') { + // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); + // } + // return; } - // } else if (data.type === 'mouseenter') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // const { cell } = info; - // cell.outputIsHovered = true; - // } - // } else if (data.type === 'mouseleave') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // const { cell } = info; - // cell.outputIsHovered = false; - // } - // } else if (data.type === '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()); - // } else if (data.type === 'did-scroll-wheel') { - // this.notebookEditor.triggerScroll({ - // ...data.payload, - // preventDefault: () => { }, - // stopPropagation: () => { } - // }); - // } else if (data.type === 'focus-editor') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // if (data.focusNext) { - // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); - // if (typeof idx !== 'number') { - // return; - // } - - // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; - // if (!newCell) { - // return; - // } - - // this.notebookEditor.focusNotebookCell(newCell, 'editor'); - // } else { - // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); - // } - // } - // } else if (data.type === 'clicked-data-url') { - // this._onDidClickDataLink(data); - // } else if (data.type === 'customRendererMessage') { - // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); - // } - // return; } this._onMessage.fire({ message: data }); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 0365d2ae16f..80b30b9c832 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -13,6 +13,7 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -23,6 +24,10 @@ export interface INotebookTextDiffEditor { getOutputRenderer(): OutputRenderer; createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IDisplayOutputViewModel): void; + /** + * Trigger the editor to scroll from scroll event programmatically + */ + triggerScroll(event: IMouseWheelEvent): void; } export interface IDiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts index e0817b93cbc..050b6feb951 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts @@ -9,7 +9,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IDiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; -import { ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellViewModelStateChangeEvent, ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -40,6 +40,17 @@ export class DiffNestedCellViewModel extends Disposable implements IDiffNestedCe return this.textModel.handle; } + protected readonly _onDidChangeState: Emitter = this._register(new Emitter()); + + private _hoveringOutput: boolean = false; + public get outputIsHovered(): boolean { + return this._hoveringOutput; + } + + public set outputIsHovered(v: boolean) { + this._hoveringOutput = v; + this._onDidChangeState.fire({ outputIsHoveredChanged: true }); + } private _outputViewModels: ICellOutputViewModel[]; get outputsViewModels() { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 96affc78bc6..fed830b7a9a 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -40,7 +40,7 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu import { SequencerByKey } from 'vs/base/common/async'; import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/backLayerWebview2'; import { generateUuid } from 'vs/base/common/uuid'; -import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; @@ -450,6 +450,9 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return new Promise(resolve => { r = resolve; }); } + triggerScroll(event: IMouseWheelEvent) { + this._list.triggerScrollFromMouseWheelEvent(event); + } createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index 2c3c565a7d4..a879142635a 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -34,6 +34,7 @@ import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEdito import { TabCompletionController } from 'vs/workbench/contrib/snippets/browser/tabCompletion'; import { AccessibilityHelpController } from 'vs/workbench/contrib/codeEditor/browser/accessibility/accessibility'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; const fixedEditorOptions: IEditorOptions = { padding: { @@ -341,6 +342,10 @@ export class NotebookTextDiffList extends WorkbenchList Date: Tue, 15 Dec 2020 13:20:35 -0800 Subject: [PATCH 1040/1837] link clicking in the output webview --- .../browser/diff/backLayerWebview2.ts | 62 +++++++++++++++---- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 79767a5f7ae..4c722f9a270 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -16,7 +16,7 @@ import { CellOutputKind, IDisplayOutput, INotebookRendererInfo, ITransformedDisp import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; -import { dirname } from 'vs/base/common/resources'; +import { dirname, joinPath } from 'vs/base/common/resources'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { FileAccess, Schemas } from 'vs/base/common/network'; @@ -24,6 +24,10 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { getExtensionForMimeType } from 'vs/base/common/mime'; +import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { IFileService } from 'vs/platform/files/common/files'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -241,6 +245,8 @@ export class BackLayerWebView extends Disposable { @INotebookService private readonly notebookService: INotebookService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, + @IFileDialogService private readonly fileDialogService: IFileDialogService, + @IFileService private readonly fileService: IFileService, ) { super(); @@ -478,10 +484,10 @@ var requirejs = (function() { const { cell } = info; cell.outputIsHovered = false; } - // } else if (data.type === '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()); + } else if (data.type === '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()); } else if (data.type === 'did-scroll-wheel') { this.notebookEditor.triggerScroll({ ...data.payload, @@ -507,19 +513,53 @@ var requirejs = (function() { // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); // } // } - // } else if (data.type === 'clicked-data-url') { - // this._onDidClickDataLink(data); - // } else if (data.type === 'customRendererMessage') { - // this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); - // } - // return; + } else if (data.type === 'clicked-data-url') { + this._onDidClickDataLink(data); + } else if (data.type === 'customRendererMessage') { + this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); } + return; } + this._onMessage.fire({ message: data }); })); } + private async _onDidClickDataLink(event: IClickedDataUrlMessage): Promise { + const [splitStart, splitData] = event.data.split(';base64,'); + if (!splitData || !splitStart) { + return; + } + + const defaultDir = dirname(this.documentUri); + let defaultName: string; + if (event.downloadName) { + defaultName = event.downloadName; + } else { + const mimeType = splitStart.replace(/^data:/, ''); + const candidateExtension = mimeType && getExtensionForMimeType(mimeType); + defaultName = candidateExtension ? `download${candidateExtension}` : 'download'; + } + + const defaultUri = joinPath(defaultDir, defaultName); + const newFileUri = await this.fileDialogService.showSaveDialog({ + defaultUri + }); + if (!newFileUri) { + return; + } + + const decoded = atob(splitData); + const typedArray = new Uint8Array(decoded.length); + for (let i = 0; i < decoded.length; i++) { + typedArray[i] = decoded.charCodeAt(i); + } + + const buff = VSBuffer.wrap(typedArray); + await this.fileService.writeFile(newFileUri, buff); + await this.openerService.open(newFileUri); + } private _createInset(webviewService: IWebviewService, content: string) { const rootPath = isWeb ? FileAccess.asBrowserUri('', require) : FileAccess.asFileUri('', require); From a7cac8062304fb08b1b37c933460f7ffba031049 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 13:37:29 -0800 Subject: [PATCH 1041/1837] no need to pass in cell for updateViewScrollTop. it only talks about output and offsets. --- .../browser/diff/backLayerWebview2.ts | 11 ++------ .../browser/diff/notebookTextDiffEditor.ts | 25 ++++++++++++++++--- .../notebook/browser/notebookEditorWidget.ts | 14 ++++++++--- .../view/renderers/backLayerWebView.ts | 6 ++--- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 4c722f9a270..fb9472a3d5c 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -617,7 +617,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { diffElement: DiffElementViewModelBase, cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[]) { if (this._disposed) { return; } @@ -625,14 +625,7 @@ var requirejs = (function() { const widgets: IContentWidgetTopRequest[] = items.map(item => { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; - // why? does it mean, we create new output view model every time? - const outputIndex = item.cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (item.output.model as ITransformedDisplayOutputDto).outputId); - let outputOffset = 0; - if (item.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = item.cellTop + item.diffElement.getOutputOffsetInCell(false, outputIndex); - } else { - outputOffset = item.cellTop + (item.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); - } + const outputOffset = item.outputOffset; outputCache.cachedCreation.top = outputOffset; this.hiddenInsetMapping.delete(item.output); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index fed830b7a9a..6cc6767d7c3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -192,7 +192,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._modifiedWebview!.element.style.height = `${scrollHeight}px`; if (this._modifiedWebview?.insetMapping) { - const updateItems: { diffElement: DiffElementViewModelBase, cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[] = []; + const updateItems: { cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._modifiedWebview?.insetMapping.forEach((value, key) => { const cell = value.cell; @@ -209,11 +209,21 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const cellTop = this._list.getAbsoluteTopOfElement(value.diffElement); if (this._modifiedWebview!.shouldUpdateInset(cell, key, cellTop)) { + // TODO: why? does it mean, we create new output view model every time? + const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); + let outputOffset = 0; + if (value.diffElement instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + value.diffElement.getOutputOffsetInCell(false, outputIndex); + } else { + outputOffset = cellTop + (value.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } + + updateItems.push({ - diffElement: value.diffElement, cell: cell, output: key, - cellTop: cellTop + cellTop: cellTop, + outputOffset: outputOffset }); } }); @@ -463,8 +473,15 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } else { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; + const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); + let outputOffset = 0; + if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(false, outputIndex); + } else { + outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } - this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ diffElement: cellDiffViewModel, cell: cellViewModel, output: output.source, cellTop }]); + this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ cell: cellViewModel, output: output.source, cellTop, outputOffset }]); } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index d7a80939d4c..dcfba890ac8 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1016,7 +1016,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview!.element.style.height = `${scrollHeight}px`; if (this._webview?.insetMapping) { - const updateItems: { cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[] = []; + const updateItems: { output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._webview?.insetMapping.forEach((value, key) => { const cell = value.cell; @@ -1033,10 +1033,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cellTop = this._list.getAbsoluteTopOfElement(cell); if (this._webview!.shouldUpdateInset(cell, key, cellTop)) { + const outputIndex = cell.outputsViewModels.indexOf(key); + + const outputOffset = cellTop + cell.getOutputOffset(outputIndex); + updateItems.push({ - cell: cell, output: key, - cellTop: cellTop + cellTop: cellTop, + outputOffset }); } }); @@ -1860,8 +1864,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } else { const cellTop = this._list.getAbsoluteTopOfElement(cell); const scrollTop = this._list.scrollTop; + const outputIndex = cell.outputsViewModels.indexOf(output.source); + const outputOffset = cellTop + cell.getOutputOffset(outputIndex); - this._webview!.updateViewScrollTop(-scrollTop, true, [{ cell, output: output.source, cellTop }]); + this._webview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } }); } 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 7f81379160c..bed48e33859 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -609,7 +609,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: { output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[]) { if (this._disposed) { return; } @@ -617,9 +617,7 @@ var requirejs = (function() { const widgets: IContentWidgetTopRequest[] = items.map(item => { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; - const outputIndex = item.cell.outputsViewModels.indexOf(item.output); - - const outputOffset = item.cellTop + item.cell.getOutputOffset(outputIndex); + const outputOffset = item.outputOffset; outputCache.cachedCreation.top = outputOffset; this.hiddenInsetMapping.delete(item.output); From 9c70421d47666acfce36212e0335d3b139b25002 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 13:40:00 -0800 Subject: [PATCH 1042/1837] IDisplayOutputLayoutUpdateRequest. --- .../contrib/notebook/browser/diff/backLayerWebview2.ts | 4 ++-- .../notebook/browser/diff/notebookTextDiffEditor.ts | 8 +++----- src/vs/workbench/contrib/notebook/browser/genericTypes.ts | 8 +++++++- .../contrib/notebook/browser/notebookEditorWidget.ts | 3 ++- .../notebook/browser/view/renderers/backLayerWebView.ts | 3 ++- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index fb9472a3d5c..548bd9f3385 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -23,7 +23,7 @@ import { FileAccess, Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; -import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { VSBuffer } from 'vs/base/common/buffer'; @@ -617,7 +617,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: IDisplayOutputLayoutUpdateRequest[]) { if (this._disposed) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 6cc6767d7c3..03b60f4b9ba 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -42,7 +42,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -192,7 +192,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._modifiedWebview!.element.style.height = `${scrollHeight}px`; if (this._modifiedWebview?.insetMapping) { - const updateItems: { cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[] = []; + const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._modifiedWebview?.insetMapping.forEach((value, key) => { const cell = value.cell; @@ -218,9 +218,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD outputOffset = cellTop + (value.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } - updateItems.push({ - cell: cell, output: key, cellTop: cellTop, outputOffset: outputOffset @@ -481,7 +479,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } - this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ cell: cellViewModel, output: output.source, cellTop, outputOffset }]); + this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts index 2a011a6697e..dc80abef4fa 100644 --- a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts +++ b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICellOutputViewModel, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export interface IGenericCellViewModel { @@ -17,3 +17,9 @@ export interface IGenericCellViewModel { getOutputOffset(index: number): number; updateOutputHeight(index: number, height: number): void; } + +export interface IDisplayOutputLayoutUpdateRequest { + output: IDisplayOutputViewModel; + cellTop: number; + outputOffset: number; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index dcfba890ac8..0a968822785 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -62,6 +62,7 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -1016,7 +1017,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webview!.element.style.height = `${scrollHeight}px`; if (this._webview?.insetMapping) { - const updateItems: { output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[] = []; + const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._webview?.insetMapping.forEach((value, key) => { const cell = value.cell; 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 bed48e33859..99ec3784c74 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -26,6 +26,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -609,7 +610,7 @@ var requirejs = (function() { return true; } - updateViewScrollTop(top: number, forceDisplay: boolean, items: { output: IDisplayOutputViewModel, cellTop: number, outputOffset: number }[]) { + updateViewScrollTop(top: number, forceDisplay: boolean, items: IDisplayOutputLayoutUpdateRequest[]) { if (this._disposed) { return; } From e2458c2d70552806aa834c87019cb2a70735a183 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 15 Dec 2020 22:40:44 +0100 Subject: [PATCH 1043/1837] Fixes #112483: Use `JSON.parse` and fall back to the tolerant parser only to extract better errors --- .../services/extensions/node/extensionPoints.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/node/extensionPoints.ts b/src/vs/workbench/services/extensions/node/extensionPoints.ts index 94f0a9deaae..40e8dbe6fc9 100644 --- a/src/vs/workbench/services/extensions/node/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/node/extensionPoints.ts @@ -47,10 +47,19 @@ abstract class ExtensionManifestHandler { class ExtensionManifestParser extends ExtensionManifestHandler { + private static _fastParseJSON(text: string, errors: json.ParseError[]): any { + try { + return JSON.parse(text); + } catch (err) { + // invalid JSON, let's get good errors + return json.parse(text, errors); + } + } + public parse(): Promise { return pfs.readFile(this._absoluteManifestPath).then((manifestContents) => { const errors: json.ParseError[] = []; - const manifest = json.parse(manifestContents.toString(), errors); + const manifest = ExtensionManifestParser._fastParseJSON(manifestContents.toString(), errors); if (json.getNodeType(manifest) !== 'object') { this._log.error(this._absoluteFolderPath, nls.localize('jsonParseInvalidType', "Invalid manifest file {0}: Not an JSON object.", this._absoluteManifestPath)); } else if (errors.length === 0) { From 9694d9f5c964620e6e07dd9315b1bc6996ae59d1 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 14:58:09 -0800 Subject: [PATCH 1044/1837] move output layout update logic out of back layer webview. --- .../browser/diff/backLayerWebview2.ts | 55 ++++++-------- .../contrib/notebook/browser/diff/common.ts | 7 ++ .../browser/diff/diffElementViewModel.ts | 15 ++++ .../browser/diff/notebookTextDiffEditor.ts | 45 ++++++++--- .../contrib/notebook/browser/genericTypes.ts | 6 ++ .../notebook/browser/notebookBrowser.ts | 5 ++ .../notebook/browser/notebookEditorWidget.ts | 31 ++++++-- .../view/renderers/backLayerWebView.ts | 75 ++++++++++--------- .../viewModel/markdownCellViewModel.ts | 9 +++ 9 files changed, 163 insertions(+), 85 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 548bd9f3385..dfda7200276 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -23,7 +23,7 @@ import { FileAccess, Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; -import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { VSBuffer } from 'vs/base/common/buffer'; @@ -198,10 +198,9 @@ export type ToWebviewMessage = export type AnyMessage = FromWebviewMessage | ToWebviewMessage; -interface ICachedInset { +interface ICachedInset { outputId: string; - diffElement: DiffElementViewModelBase; - cell: IGenericCellViewModel; + cellInfo: K; renderer?: INotebookRendererInfo; cachedCreation: ICreationRequestMessage; } @@ -220,10 +219,10 @@ export interface INotebookWebviewMessage { } let version = 0; -export class BackLayerWebView extends Disposable { +export class BackLayerWebView extends Disposable { element: HTMLElement; webview: WebviewElement | undefined = undefined; - insetMapping: Map = new Map(); + insetMapping: Map> = new Map(); hiddenInsetMapping: Set = new Set(); reversedInsetMapping: Map = new Map(); localResourceRootsCache: URI[] | undefined = undefined; @@ -339,7 +338,7 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cell: IGenericCellViewModel, diffElement: DiffElementViewModelBase, output: IDisplayOutputViewModel } | undefined { + private resolveOutputId(id: string): { cachedInset: ICachedInset, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; @@ -352,7 +351,7 @@ export class BackLayerWebView extends Disposable { // this.insetMapping.get(output)!.cell = currCell as CodeCellViewModel; // } - return { cell: info.cell, diffElement: info.diffElement, output }; + return { cachedInset: info, output }; } async createWebview(): Promise { @@ -461,27 +460,21 @@ var requirejs = (function() { const height = data.data.height; const outputHeight = height; - const info = this.resolveOutputId(data.id); - if (info) { - const { diffElement, cell, output } = info; - const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.model as ITransformedDisplayOutputDto).outputId); - if (diffElement instanceof SideBySideDiffElementViewModel) { - diffElement.updateOutputHeight(false, outputIndex, outputHeight); - } else { - (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); - } - // this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const { cachedInset, output } = resolvedResult; + this.notebookEditor.updateOutputHeight(cachedInset.cellInfo, output, outputHeight); } } else if (data.type === 'mouseenter') { - const info = this.resolveOutputId(data.id); - if (info) { - const { cell } = info; + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const cell = this.notebookEditor.getCellByInfo(resolvedResult.cachedInset.cellInfo); cell.outputIsHovered = true; } } else if (data.type === 'mouseleave') { - const info = this.resolveOutputId(data.id); - if (info) { - const { cell } = info; + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const cell = this.notebookEditor.getCellByInfo(resolvedResult.cachedInset.cellInfo); cell.outputIsHovered = false; } } else if (data.type === 'scroll-ack') { @@ -646,7 +639,7 @@ var requirejs = (function() { }); } - async createInset(cellDiffViewModel: DiffElementViewModelBase, cell: IGenericCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) { + async createInset(cellInfo: T, content: IInsetRenderOutput, cellTop: number, offset: number) { if (this._disposed) { return; } @@ -660,7 +653,7 @@ var requirejs = (function() { this.hiddenInsetMapping.delete(content.source); this._sendMessageToWebview({ type: 'showOutput', - cellId: outputCache.cell.id, + cellId: outputCache.cellInfo.cellId, outputId: outputCache.outputId, top: initialTop }); @@ -670,7 +663,7 @@ var requirejs = (function() { const messageBase = { type: 'html', - cellId: cell.id, + cellId: cellInfo.cellId, top: initialTop, left: 0, requiredPreloads: [], @@ -708,7 +701,7 @@ var requirejs = (function() { } this._sendMessageToWebview(message); - this.insetMapping.set(content.source, { outputId: message.outputId, diffElement: cellDiffViewModel, cell, renderer, cachedCreation: message }); + this.insetMapping.set(content.source, { outputId: message.outputId, cellInfo: cellInfo, renderer, cachedCreation: message }); this.hiddenInsetMapping.delete(content.source); this.reversedInsetMapping.set(message.outputId, content.source); } @@ -728,9 +721,9 @@ var requirejs = (function() { this._sendMessageToWebview({ type: 'clearOutput', apiNamespace: outputCache.cachedCreation.apiNamespace, - cellUri: outputCache.cell.uri.toString(), + cellUri: outputCache.cellInfo.cellUri.toString(), outputId: id, - cellId: outputCache.cell.id + cellId: outputCache.cellInfo.cellId }); this.insetMapping.delete(output); this.reversedInsetMapping.delete(id); @@ -751,7 +744,7 @@ var requirejs = (function() { this._sendMessageToWebview({ type: 'hideOutput', outputId: outputCache.outputId, - cellId: outputCache.cell.id, + cellId: outputCache.cellInfo.cellId, }); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 80b30b9c832..94e15720410 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -14,6 +14,11 @@ import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; +import { ICommonCellInfo, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; + +export interface IDiffCellInfo extends ICommonCellInfo { + diffElement: DiffElementViewModelBase; +} export interface INotebookTextDiffEditor { readonly textModel?: NotebookTextModel; @@ -28,6 +33,8 @@ export interface INotebookTextDiffEditor { * Trigger the editor to scroll from scroll event programmatically */ triggerScroll(event: IMouseWheelEvent): void; + getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; } export interface IDiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index e5a1415708f..464e55126eb 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -15,6 +15,8 @@ import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; +import { URI } from 'vs/base/common/uri'; +import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export enum PropertyFoldingState { Expanded, @@ -131,6 +133,7 @@ export abstract class DiffElementViewModelBase extends Disposable { abstract checkIfOutputsModified(): boolean; abstract checkMetadataIfModified(): boolean; abstract layoutChange(): void; + abstract getCellByUri(cellUri: URI): IGenericCellViewModel; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -231,6 +234,14 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { getOutputTotalHeight() { return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); } + + getCellByUri(cellUri: URI): IGenericCellViewModel { + if (cellUri.toString() === this.original.uri.toString()) { + return this.original; + } else { + return this.modified; + } + } } export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { @@ -299,6 +310,10 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { getOutputTotalHeight() { return this.cellViewModel?.getOutputTotalHeight() ?? 0; } + + getCellByUri(cellUri: URI): IGenericCellViewModel { + return this.cellViewModel!; + } } export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, metadata: NotebookCellMetadata, language?: string) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 03b60f4b9ba..28befc58c99 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -24,7 +24,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; +import { DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { NotebookDiffEditorEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; @@ -42,20 +42,22 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; export const IN_NOTEBOOK_TEXT_DIFF_EDITOR = new RawContextKey('isInNotebookTextDiffEditor', false); + export class NotebookTextDiffEditor extends EditorPane implements INotebookTextDiffEditor { static readonly ID: string = 'workbench.editor.notebookTextDiffEditor'; private _rootElement!: HTMLElement; private _overflowContainer!: HTMLElement; private _dimension: DOM.Dimension | null = null; + private _diffElementViewModels: DiffElementViewModelBase[] = []; private _list!: NotebookTextDiffList; - private _modifiedWebview: BackLayerWebView | null = null; + private _modifiedWebview: BackLayerWebView | null = null; private _webviewTransparentCover: HTMLElement | null = null; private _fontInfo: BareFontInfo | undefined; @@ -95,6 +97,18 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._outputRenderer = new OutputRenderer(this as unknown as INotebookEditor, this.instantiationService); } + updateOutputHeight(cellInfo: IDiffCellInfo, output: IDisplayOutputViewModel, outputHeight: number): void { + const diffElement = cellInfo.diffElement; + const cell = this.getCellByInfo(cellInfo); + const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.model as ITransformedDisplayOutputDto).outputId); + + if (diffElement instanceof SideBySideDiffElementViewModel) { + diffElement.updateOutputHeight(false, outputIndex, outputHeight); + } else { + (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); + } + } + protected createEditor(parent: HTMLElement): void { this._rootElement = DOM.append(parent, DOM.$('.notebook-text-diff-editor')); this._overflowContainer = document.createElement('div'); @@ -195,8 +209,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._modifiedWebview?.insetMapping.forEach((value, key) => { - const cell = value.cell; - const viewIndex = this._list.indexOf(value.diffElement); + const cell = value.cellInfo.diffElement.modified; + if (!cell) { + return; + } + + const viewIndex = this._list.indexOf(value.cellInfo.diffElement); if (viewIndex === undefined) { return; @@ -207,15 +225,15 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD removedItems.push(key); } - const cellTop = this._list.getAbsoluteTopOfElement(value.diffElement); + const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); if (this._modifiedWebview!.shouldUpdateInset(cell, key, cellTop)) { // TODO: why? does it mean, we create new output view model every time? const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; - if (value.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + value.diffElement.getOutputOffsetInCell(false, outputIndex); + if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(false, outputIndex); } else { - outputOffset = cellTop + (value.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } updateItems.push({ @@ -293,7 +311,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } private async _createModifiedWebview(id: string, resource: URI): Promise { - this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource); + this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource) as BackLayerWebView; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); await this._modifiedWebview.createWebview(); @@ -379,6 +397,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD )); } + this._diffElementViewModels = diffElementViewModels; this._list.splice(0, this._list.length, diffElementViewModels); if (this._revealFirst && firstChangeIndex !== -1) { @@ -467,7 +486,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD if (rightEditor) { if (!this._modifiedWebview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._modifiedWebview?.createInset(cellDiffViewModel, cellViewModel, output, cellTop, offset); + await this._modifiedWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, offset); } else { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; @@ -485,6 +504,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD }); } + getCellByInfo(cellInfo: IDiffCellInfo): IGenericCellViewModel { + return cellInfo.diffElement.getCellByUri(cellInfo.cellUri); + } + removeInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput) { } diff --git a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts index dc80abef4fa..0ca27ab86c6 100644 --- a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts +++ b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts @@ -23,3 +23,9 @@ export interface IDisplayOutputLayoutUpdateRequest { cellTop: number; outputOffset: number; } + +export interface ICommonCellInfo { + cellId: string; + cellHandle: number; + cellUri: URI; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 5c8a46f1063..ea6da79cd8e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -31,6 +31,7 @@ import { EditorOptions } from 'vs/workbench/common/editor'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +import { ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); @@ -185,6 +186,7 @@ export interface ICellViewModel { cellKind: CellKind; editState: CellEditState; focusMode: CellFocusMode; + outputIsHovered: boolean; getText(): string; getTextLength(): number; metadata: NotebookCellMetadata | undefined; @@ -528,6 +530,9 @@ export interface INotebookEditor extends IEditor { * @return The contribution or null if contribution not found. */ getContribution(id: string): T; + + getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; } export interface INotebookCellList { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 0a968822785..706350f2caf 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -62,7 +62,7 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -74,9 +74,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _overlayContainer!: HTMLElement; private _body!: HTMLElement; private _overflowContainer!: HTMLElement; - private _webview: BackLayerWebView | null = null; + private _webview: BackLayerWebView | null = null; private _webviewResolved: boolean = false; - private _webviewResolvePromise: Promise | null = null; + private _webviewResolvePromise: Promise | null> | null = null; private _webviewTransparentCover: HTMLElement | null = null; private _list!: INotebookCellList; private _dndController: CellDragAndDropController | null = null; @@ -893,7 +893,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._notebookExecuting?.set(notebookMetadata.runState === NotebookRunState.Running); } - private async _resolveWebview(): Promise { + private async _resolveWebview(): Promise | null> { if (!this.textModel) { return null; } @@ -1020,7 +1020,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._webview?.insetMapping.forEach((value, key) => { - const cell = value.cell; + const cell = this.viewModel?.getCellByHandle(value.cellInfo.cellHandle); + if (!cell || !(cell instanceof CodeCellViewModel)) { + return; + } + + this.viewModel?.viewCells.find(cell => cell.handle === value.cellInfo.cellHandle); const viewIndex = this._list.getViewIndex(cell); if (viewIndex === undefined) { @@ -1861,7 +1866,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (!this._webview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cell); - await this._webview!.createInset(cell, output, cellTop, offset); + await this._webview!.createInset({ cellId: cell.id, cellHandle: cell.handle, cellUri: cell.uri }, output, cellTop, offset); } else { const cellTop = this._list.getAbsoluteTopOfElement(cell); const scrollTop = this._list.scrollTop; @@ -1928,6 +1933,20 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._overlayContainer.classList.remove(className); } + getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel { + const { cellHandle } = cellInfo; + return this.viewModel?.viewCells.find(vc => vc.handle === cellHandle) as CodeCellViewModel; + } + + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, outputHeight: number): void { + const cell = this.viewModel?.viewCells.find(vc => vc.handle === cellInfo.cellHandle); + if (cell && cell instanceof CodeCellViewModel) { + const outputIndex = cell.outputsViewModels.indexOf(output); + cell.updateOutputHeight(outputIndex, outputHeight); + this.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); + } + } + //#endregion 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 99ec3784c74..528342eced6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -26,7 +26,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -197,9 +197,9 @@ export type ToWebviewMessage = export type AnyMessage = FromWebviewMessage | ToWebviewMessage; -interface ICachedInset { +interface ICachedInset { outputId: string; - cell: CodeCellViewModel; + cellInfo: K; renderer?: INotebookRendererInfo; cachedCreation: ICreationRequestMessage; } @@ -218,10 +218,10 @@ export interface INotebookWebviewMessage { } let version = 0; -export class BackLayerWebView extends Disposable { +export class BackLayerWebView extends Disposable { element: HTMLElement; webview: WebviewElement | undefined = undefined; - insetMapping: Map = new Map(); + insetMapping: Map> = new Map(); hiddenInsetMapping: Set = new Set(); reversedInsetMapping: Map = new Map(); localResourceRootsCache: URI[] | undefined = undefined; @@ -337,20 +337,14 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cell: CodeCellViewModel, output: IDisplayOutputViewModel } | undefined { + private resolveOutputId(id: string): { cellInfo: T, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; } - const cell = this.insetMapping.get(output)!.cell; - - const currCell = this.notebookEditor.viewModel?.viewCells.find(vc => vc.handle === cell.handle); - if (currCell !== cell && currCell !== undefined) { - this.insetMapping.get(output)!.cell = currCell as CodeCellViewModel; - } - - return { cell: this.insetMapping.get(output)!.cell, output }; + const cellInfo = this.insetMapping.get(output)!.cellInfo; + return { cellInfo, output }; } async createWebview(): Promise { @@ -461,22 +455,24 @@ var requirejs = (function() { const info = this.resolveOutputId(data.id); if (info) { - const { cell, output } = info; - const outputIndex = cell.outputsViewModels.indexOf(output); - cell.updateOutputHeight(outputIndex, outputHeight); - this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); + const { cellInfo, output } = info; + this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight); } } else if (data.type === 'mouseenter') { - const info = this.resolveOutputId(data.id); - if (info) { - const { cell } = info; - cell.outputIsHovered = true; + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = true; + } } } else if (data.type === 'mouseleave') { - const info = this.resolveOutputId(data.id); - if (info) { - const { cell } = info; - cell.outputIsHovered = false; + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = false; + } } } else if (data.type === 'scroll-ack') { // const date = new Date(); @@ -489,10 +485,15 @@ var requirejs = (function() { stopPropagation: () => { } }); } else if (data.type === 'focus-editor') { - const info = this.resolveOutputId(data.id); - if (info) { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (!latestCell) { + return; + } + if (data.focusNext) { - const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); + const idx = this.notebookEditor.viewModel?.getCellIndex(latestCell); if (typeof idx !== 'number') { return; } @@ -504,7 +505,7 @@ var requirejs = (function() { this.notebookEditor.focusNotebookCell(newCell, 'editor'); } else { - this.notebookEditor.focusNotebookCell(info.cell, 'editor'); + this.notebookEditor.focusNotebookCell(latestCell, 'editor'); } } } else if (data.type === 'clicked-data-url') { @@ -638,7 +639,7 @@ var requirejs = (function() { }); } - async createInset(cell: CodeCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) { + async createInset(cellInfo: T, content: IInsetRenderOutput, cellTop: number, offset: number) { if (this._disposed) { return; } @@ -652,7 +653,7 @@ var requirejs = (function() { this.hiddenInsetMapping.delete(content.source); this._sendMessageToWebview({ type: 'showOutput', - cellId: outputCache.cell.id, + cellId: outputCache.cellInfo.cellId, outputId: outputCache.outputId, top: initialTop }); @@ -662,7 +663,7 @@ var requirejs = (function() { const messageBase = { type: 'html', - cellId: cell.id, + cellId: cellInfo.cellId, top: initialTop, left: 0, requiredPreloads: [], @@ -700,7 +701,7 @@ var requirejs = (function() { } this._sendMessageToWebview(message); - this.insetMapping.set(content.source, { outputId: message.outputId, cell, renderer, cachedCreation: message }); + this.insetMapping.set(content.source, { outputId: message.outputId, cellInfo: cellInfo, renderer, cachedCreation: message }); this.hiddenInsetMapping.delete(content.source); this.reversedInsetMapping.set(message.outputId, content.source); } @@ -720,9 +721,9 @@ var requirejs = (function() { this._sendMessageToWebview({ type: 'clearOutput', apiNamespace: outputCache.cachedCreation.apiNamespace, - cellUri: outputCache.cell.uri.toString(), + cellUri: outputCache.cellInfo.cellUri.toString(), outputId: id, - cellId: outputCache.cell.id + cellId: outputCache.cellInfo.cellId }); this.insetMapping.delete(output); this.reversedInsetMapping.delete(id); @@ -743,7 +744,7 @@ var requirejs = (function() { this._sendMessageToWebview({ type: 'hideOutput', outputId: outputCache.outputId, - cellId: outputCache.cell.id, + cellId: outputCache.cellInfo.cellId, }); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 75e027a9e1c..cb88e6fe00c 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -60,6 +60,15 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie return this.foldingDelegate.getFoldingState(this.foldingDelegate.getCellIndex(this)); } + private _hoveringOutput: boolean = false; + public get outputIsHovered(): boolean { + return this._hoveringOutput; + } + + public set outputIsHovered(v: boolean) { + this._hoveringOutput = v; + } + constructor( readonly viewType: string, readonly model: NotebookCellTextModel, From fa464a731cce285741d0267f4277d36bb7907e4e Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 14:59:42 -0800 Subject: [PATCH 1045/1837] :guard: --- .../contrib/notebook/browser/diff/backLayerWebview2.ts | 3 +-- .../contrib/notebook/browser/diff/notebookTextDiffEditor.ts | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index dfda7200276..630aa43d37c 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -12,7 +12,7 @@ import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CellOutputKind, IDisplayOutput, INotebookRendererInfo, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; @@ -22,7 +22,6 @@ import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/re import { FileAccess, Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 28befc58c99..6677d7712ae 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -42,7 +42,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -55,7 +55,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _rootElement!: HTMLElement; private _overflowContainer!: HTMLElement; private _dimension: DOM.Dimension | null = null; - private _diffElementViewModels: DiffElementViewModelBase[] = []; + // private _diffElementViewModels: DiffElementViewModelBase[] = []; private _list!: NotebookTextDiffList; private _modifiedWebview: BackLayerWebView | null = null; private _webviewTransparentCover: HTMLElement | null = null; @@ -397,7 +397,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD )); } - this._diffElementViewModels = diffElementViewModels; + // this._diffElementViewModels = diffElementViewModels; this._list.splice(0, this._list.length, diffElementViewModels); if (this._revealFirst && firstChangeIndex !== -1) { From c761670411560b4ed61525fa8b68c38cdfc70a69 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 15:10:00 -0800 Subject: [PATCH 1046/1837] fix build errors --- .../browser/diff/backLayerWebview2.ts | 42 +++++++++---------- .../view/renderers/backLayerWebView.ts | 11 +++-- .../browser/view/renderers/cellContextKeys.ts | 5 +-- .../notebook/test/testNotebookEditor.ts | 9 +++- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index 630aa43d37c..edbba675077 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -20,13 +20,13 @@ import { dirname, joinPath } from 'vs/base/common/resources'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; -import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { VSBuffer } from 'vs/base/common/buffer'; import { IFileService } from 'vs/platform/files/common/files'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { getExtensionForMimeType } from 'vs/base/common/mime'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -337,27 +337,21 @@ export class BackLayerWebView extends Disposable { }); } - private resolveOutputId(id: string): { cachedInset: ICachedInset, output: IDisplayOutputViewModel } | undefined { + private resolveOutputId(id: string): { cellInfo: T, output: IDisplayOutputViewModel } | undefined { const output = this.reversedInsetMapping.get(id); if (!output) { return; } - const info = this.insetMapping.get(output)!; - - // const currCell = this.notebookEditor.viewModel?.viewCells.find(vc => vc.handle === cell.handle); - // if (currCell !== cell && currCell !== undefined) { - // this.insetMapping.get(output)!.cell = currCell as CodeCellViewModel; - // } - - return { cachedInset: info, output }; + const cellInfo = this.insetMapping.get(output)!.cellInfo; + return { cellInfo, output }; } async createWebview(): Promise { let coreDependencies = ''; let resolveFunc: () => void; - this._initalized = new Promise((resolve) => { + this._initalized = new Promise((resolve, reject) => { resolveFunc = resolve; }); @@ -461,20 +455,24 @@ var requirejs = (function() { const resolvedResult = this.resolveOutputId(data.id); if (resolvedResult) { - const { cachedInset, output } = resolvedResult; - this.notebookEditor.updateOutputHeight(cachedInset.cellInfo, output, outputHeight); + const { cellInfo, output } = resolvedResult; + this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight); } } else if (data.type === 'mouseenter') { const resolvedResult = this.resolveOutputId(data.id); if (resolvedResult) { - const cell = this.notebookEditor.getCellByInfo(resolvedResult.cachedInset.cellInfo); - cell.outputIsHovered = true; + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = true; + } } } else if (data.type === 'mouseleave') { const resolvedResult = this.resolveOutputId(data.id); if (resolvedResult) { - const cell = this.notebookEditor.getCellByInfo(resolvedResult.cachedInset.cellInfo); - cell.outputIsHovered = false; + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = false; + } } } else if (data.type === 'scroll-ack') { // const date = new Date(); @@ -513,7 +511,6 @@ var requirejs = (function() { return; } - this._onMessage.fire({ message: data }); })); } @@ -570,7 +567,7 @@ var requirejs = (function() { }, undefined); let resolveFunc: () => void; - this._loaded = new Promise((resolve) => { + this._loaded = new Promise((resolve, reject) => { resolveFunc = resolve; }); @@ -618,7 +615,6 @@ var requirejs = (function() { const outputCache = this.insetMapping.get(item.output)!; const id = outputCache.outputId; const outputOffset = item.outputOffset; - outputCache.cachedCreation.top = outputOffset; this.hiddenInsetMapping.delete(item.output); 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 528342eced6..a61496083ac 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -12,7 +12,6 @@ import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; @@ -26,7 +25,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -453,9 +452,9 @@ var requirejs = (function() { const height = data.data.height; const outputHeight = height; - const info = this.resolveOutputId(data.id); - if (info) { - const { cellInfo, output } = info; + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const { cellInfo, output } = resolvedResult; this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight); } } else if (data.type === 'mouseenter') { @@ -587,7 +586,7 @@ var requirejs = (function() { return webview; } - shouldUpdateInset(cell: CodeCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { + shouldUpdateInset(cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { if (this._disposed) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys.ts index 3d138d8840a..bd6cacbaead 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys.ts @@ -5,7 +5,6 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { INotebookTextModel, NotebookCellRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; import { NOTEBOOK_CELL_TYPE, NOTEBOOK_VIEW_TYPE, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUN_STATE, NOTEBOOK_CELL_HAS_OUTPUTS, CellViewModelStateChangeEvent, CellEditState, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_FOCUSED, INotebookEditor, NOTEBOOK_CELL_EDITOR_FOCUSED, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; @@ -32,7 +31,7 @@ export class CellContextKeyManager extends Disposable { private readonly contextKeyService: IContextKeyService, private readonly notebookEditor: INotebookEditor, private readonly notebookTextModel: INotebookTextModel, - private element: BaseCellViewModel + private element: CodeCellViewModel | MarkdownCellViewModel ) { super(); @@ -53,7 +52,7 @@ export class CellContextKeyManager extends Disposable { }); } - public updateForElement(element: BaseCellViewModel) { + public updateForElement(element: MarkdownCellViewModel | CodeCellViewModel) { this.elementDisposables.clear(); this.elementDisposables.add(element.onDidChangeState(e => this.onDidChangeState(e))); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index ea7c4180a81..cf5fe7a1636 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -12,7 +12,7 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { Range } from 'vs/editor/common/core/range'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { EditorModel } from 'vs/workbench/common/editor'; -import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; @@ -36,6 +36,7 @@ import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService import { ScrollEvent } from 'vs/base/common/scrollable'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; +import { ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export class TestCell extends NotebookCellTextModel { constructor( @@ -66,6 +67,12 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel { + throw new Error('Method not implemented.'); + } + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void { + throw new Error('Method not implemented.'); + } async beginComputeContributedKernels(): Promise { return []; } From b56da5e92aa7ba18e9f42b4d4cf7ed06772ab65a Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 15:56:25 -0800 Subject: [PATCH 1047/1837] align backlayer 1 and 2 --- .../browser/diff/backLayerWebview2.ts | 31 ++++++++----------- .../contrib/notebook/browser/diff/common.ts | 2 ++ .../browser/diff/notebookTextDiffEditor.ts | 10 +++++- .../notebook/browser/notebookBrowser.ts | 2 ++ .../notebook/browser/notebookEditorWidget.ts | 14 +++++++++ .../view/renderers/backLayerWebView.ts | 12 +------ 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index edbba675077..f77d7828d47 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -484,25 +484,20 @@ var requirejs = (function() { preventDefault: () => { }, stopPropagation: () => { } }); - // } else if (data.type === 'focus-editor') { - // const info = this.resolveOutputId(data.id); - // if (info) { - // if (data.focusNext) { - // const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell); - // if (typeof idx !== 'number') { - // return; - // } + } else if (data.type === 'focus-editor') { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (!latestCell) { + return; + } - // const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; - // if (!newCell) { - // return; - // } - - // this.notebookEditor.focusNotebookCell(newCell, 'editor'); - // } else { - // this.notebookEditor.focusNotebookCell(info.cell, 'editor'); - // } - // } + if (data.focusNext) { + this.notebookEditor.focusNextNotebookCell(latestCell, 'editor'); + } else { + this.notebookEditor.focusNotebookCell(latestCell, 'editor'); + } + } } else if (data.type === 'clicked-data-url') { this._onDidClickDataLink(data); } else if (data.type === 'customRendererMessage') { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 94e15720410..fb6733298ed 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -34,6 +34,8 @@ export interface INotebookTextDiffEditor { */ triggerScroll(event: IMouseWheelEvent): void; getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; + focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; + focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 6677d7712ae..16f78c288a0 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -42,7 +42,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; @@ -97,6 +97,14 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._outputRenderer = new OutputRenderer(this as unknown as INotebookEditor, this.instantiationService); } + focusNotebookCell(cell: IGenericCellViewModel, focus: 'output' | 'editor' | 'container'): void { + // throw new Error('Method not implemented.'); + } + + focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'output' | 'editor' | 'container'): void { + // throw new Error('Method not implemented.'); + } + updateOutputHeight(cellInfo: IDiffCellInfo, output: IDisplayOutputViewModel, outputHeight: number): void { const diffElement = cellInfo.diffElement; const cell = this.getCellByInfo(cellInfo); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index ea6da79cd8e..ffb0ef98fa4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -377,6 +377,8 @@ export interface INotebookEditor extends IEditor { */ focusNotebookCell(cell: ICellViewModel, focus: 'editor' | 'container' | 'output'): void; + focusNextNotebookCell(cell: ICellViewModel, focus: 'editor' | 'container' | 'output'): void; + /** * Execute the given notebook cell */ diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 706350f2caf..6e7d34aa768 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1828,6 +1828,20 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } + focusNextNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output') { + const idx = this.viewModel?.getCellIndex(cell); + if (typeof idx !== 'number') { + return; + } + + const newCell = this.viewModel?.viewCells[idx + 1]; + if (!newCell) { + return; + } + + this.focusNotebookCell(newCell, focusItem); + } + //#endregion //#region MISC 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 a61496083ac..df8a4479b00 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -492,17 +492,7 @@ var requirejs = (function() { } if (data.focusNext) { - const idx = this.notebookEditor.viewModel?.getCellIndex(latestCell); - if (typeof idx !== 'number') { - return; - } - - const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1]; - if (!newCell) { - return; - } - - this.notebookEditor.focusNotebookCell(newCell, 'editor'); + this.notebookEditor.focusNextNotebookCell(latestCell, 'editor'); } else { this.notebookEditor.focusNotebookCell(latestCell, 'editor'); } From 64f7c1b0444d41a2c8b9a9bd40638bd3b4deb039 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 15:57:04 -0800 Subject: [PATCH 1048/1837] :lipstick: --- .../contrib/notebook/browser/diff/notebookTextDiffEditor.ts | 2 +- src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 16f78c288a0..98f32e0af59 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -42,7 +42,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/bac import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index cf5fe7a1636..dacce8299ae 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -67,6 +67,9 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + focusNextNotebookCell(cell: ICellViewModel, focus: 'editor' | 'container' | 'output'): void { + throw new Error('Method not implemented.'); + } getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel { throw new Error('Method not implemented.'); } From 05f69f7bbd3c090a103e3c07e1b8b73973bb60a9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 16:08:12 -0800 Subject: [PATCH 1049/1837] share the logic for renderers in webview --- .../notebook/browser/diff/backLayerWebview2.ts | 6 ++---- .../contrib/notebook/browser/diff/common.ts | 4 ++-- .../contrib/notebook/browser/genericTypes.ts | 11 ++++++++++- .../contrib/notebook/browser/notebookBrowser.ts | 6 +++--- .../notebook/browser/notebookEditorWidget.ts | 3 +++ .../browser/view/renderers/backLayerWebView.ts | 7 +++---- .../browser/viewModel/markdownCellViewModel.ts | 14 +++++++++++++- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts index f77d7828d47..4dab3eba4d3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts @@ -20,13 +20,12 @@ import { dirname, joinPath } from 'vs/base/common/resources'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -235,7 +234,7 @@ export class BackLayerWebView extends Disposable { private _disposed = false; constructor( - public notebookEditor: INotebookTextDiffEditor, + public notebookEditor: ICommonNotebookEditor, public id: string, public documentUri: URI, @IWebviewService readonly webviewService: IWebviewService, @@ -253,7 +252,6 @@ export class BackLayerWebView extends Disposable { this.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; this.element.style.height = '1400px'; this.element.style.position = 'absolute'; - // this.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; } generateContent(outputNodePadding: number, coreDependencies: string, baseUrl: string) { return html` diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index fb6733298ed..9d7b73aeb6c 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -14,13 +14,13 @@ import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; -import { ICommonCellInfo, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, ICommonNotebookEditor, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface IDiffCellInfo extends ICommonCellInfo { diffElement: DiffElementViewModelBase; } -export interface INotebookTextDiffEditor { +export interface INotebookTextDiffEditor extends ICommonNotebookEditor { readonly textModel?: NotebookTextModel; onMouseUp: Event<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>; getOverflowContainerDomNode(): HTMLElement; diff --git a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts index 0ca27ab86c6..80261d31163 100644 --- a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts +++ b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { URI } from 'vs/base/common/uri'; import { ICellOutputViewModel, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -11,7 +12,7 @@ export interface IGenericCellViewModel { id: string; handle: number; uri: URI; - metadata: NotebookCellMetadata; + metadata: NotebookCellMetadata | undefined; outputIsHovered: boolean; outputsViewModels: ICellOutputViewModel[]; getOutputOffset(index: number): number; @@ -29,3 +30,11 @@ export interface ICommonCellInfo { cellHandle: number; cellUri: URI; } + +export interface ICommonNotebookEditor { + triggerScroll(event: IMouseWheelEvent): void; + getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; + focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; + focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index ffb0ef98fa4..744c663361f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -31,7 +31,7 @@ import { EditorOptions } from 'vs/workbench/common/editor'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; -import { ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, ICommonNotebookEditor, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); @@ -175,7 +175,7 @@ export interface IStreamOutputViewModel extends ICellOutputViewModel { model: IStreamOutput; } -export interface ICellViewModel { +export interface ICellViewModel extends IGenericCellViewModel { readonly model: NotebookCellTextModel; readonly id: string; readonly textBuffer: IReadonlyTextBuffer; @@ -266,7 +266,7 @@ export interface IActiveNotebookEditor extends INotebookEditor { uri: URI; } -export interface INotebookEditor extends IEditor { +export interface INotebookEditor extends IEditor, ICommonNotebookEditor { isEmbedded: boolean; cursorNavigationMode: boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 6e7d34aa768..880ba066d17 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -904,6 +904,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (!this._webview) { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, this.getId(), this.textModel!.uri); + this._webview.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; + // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); } @@ -952,6 +954,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private async _createWebview(id: string, resource: URI): Promise { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource); + this._webview.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); } 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 df8a4479b00..4dab3eba4d3 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; @@ -25,7 +25,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; @@ -234,7 +234,7 @@ export class BackLayerWebView extends Disposable { private _disposed = false; constructor( - public notebookEditor: INotebookEditor, + public notebookEditor: ICommonNotebookEditor, public id: string, public documentUri: URI, @IWebviewService readonly webviewService: IWebviewService, @@ -252,7 +252,6 @@ export class BackLayerWebView extends Disposable { this.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; this.element.style.height = '1400px'; this.element.style.position = 'absolute'; - this.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; } generateContent(outputNodePadding: number, coreDependencies: string, baseUrl: string) { return html` diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index cb88e6fe00c..eae9ae0070c 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -11,7 +11,7 @@ import * as nls from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; -import { CellFindMatch, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFindMatch, ICellOutputViewModel, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer'; import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; import { NotebookCellStateChangedEvent, NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; @@ -93,6 +93,18 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie })); } + /** + * we put outputs stuff here to make compiler happy + */ + outputsViewModels: ICellOutputViewModel[] = []; + getOutputOffset(index: number): number { + // throw new Error('Method not implemented.'); + return -1; + } + updateOutputHeight(index: number, height: number): void { + // throw new Error('Method not implemented.'); + } + triggerfoldingStateChange() { this._onDidChangeState.fire({ foldingStateChanged: true }); } From 706b8ddf9834fb61b141e89d193a94ae0da2c33e Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 16:10:29 -0800 Subject: [PATCH 1050/1837] single backlayerwebview! --- .../browser/diff/backLayerWebview2.ts | 876 ------------------ .../browser/diff/notebookTextDiffEditor.ts | 2 +- 2 files changed, 1 insertion(+), 877 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts b/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts deleted file mode 100644 index 4dab3eba4d3..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/diff/backLayerWebview2.ts +++ /dev/null @@ -1,876 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as DOM from 'vs/base/browser/dom'; -import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { isWeb } from 'vs/base/common/platform'; -import { URI } from 'vs/base/common/uri'; -import * as UUID from 'vs/base/common/uuid'; -import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; -import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; -import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; -import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri'; -import { dirname, joinPath } from 'vs/base/common/resources'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { preloadsScriptStr } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; -import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IFileService } from 'vs/platform/files/common/files'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { getExtensionForMimeType } from 'vs/base/common/mime'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; - -export interface WebviewIntialized { - __vscode_notebook_message: boolean; - type: 'initialized' -} - -export interface IDimensionMessage { - __vscode_notebook_message: boolean; - type: 'dimension'; - id: string; - data: DOM.Dimension; -} - -export interface IMouseEnterMessage { - __vscode_notebook_message: boolean; - type: 'mouseenter'; - id: string; -} - -export interface IMouseLeaveMessage { - __vscode_notebook_message: boolean; - type: 'mouseleave'; - id: string; -} - -export interface IWheelMessage { - __vscode_notebook_message: boolean; - type: 'did-scroll-wheel'; - payload: any; -} - - -export interface IScrollAckMessage { - __vscode_notebook_message: boolean; - type: 'scroll-ack'; - data: { top: number }; - version: number; -} - -export interface IBlurOutputMessage { - __vscode_notebook_message: boolean; - type: 'focus-editor'; - id: string; - focusNext?: boolean; -} - -export interface IClickedDataUrlMessage { - __vscode_notebook_message: boolean; - type: 'clicked-data-url'; - data: string; - downloadName?: string; -} - -export interface IClearMessage { - type: 'clear'; -} - -export interface ICreationRequestMessage { - type: 'html'; - content: - | { type: RenderOutputType.Html; htmlContent: string } - | { type: RenderOutputType.Extension; output: IDisplayOutput; mimeType: string }; - cellId: string; - outputId: string; - top: number; - left: number; - requiredPreloads: ReadonlyArray; - initiallyHidden?: boolean; - apiNamespace?: string | undefined; -} - -export interface IContentWidgetTopRequest { - id: string; - top: number; - left: number; -} - -export interface IViewScrollTopRequestMessage { - type: 'view-scroll'; - top?: number; - forceDisplay: boolean; - widgets: IContentWidgetTopRequest[]; - version: number; -} - -export interface IScrollRequestMessage { - type: 'scroll'; - id: string; - top: number; - widgetTop?: number; - version: number; -} - -export interface IClearOutputRequestMessage { - type: 'clearOutput'; - cellId: string; - outputId: string; - cellUri: string; - apiNamespace: string | undefined; -} - -export interface IHideOutputMessage { - type: 'hideOutput'; - outputId: string; - cellId: string; -} - -export interface IShowOutputMessage { - type: 'showOutput'; - cellId: string; - outputId: string; - top: number; -} - -export interface IFocusOutputMessage { - type: 'focus-output'; - cellId: string; -} - -export interface IPreloadResource { - originalUri: string; - uri: string; -} - -export interface IUpdatePreloadResourceMessage { - type: 'preload'; - resources: IPreloadResource[]; - source: 'renderer' | 'kernel'; -} - -export interface IUpdateDecorationsMessage { - type: 'decorations'; - cellId: string; - addedClassNames: string[]; - removedClassNames: string[]; -} - -export interface ICustomRendererMessage { - __vscode_notebook_message: boolean; - type: 'customRendererMessage'; - rendererId: string; - message: unknown; -} - -export type FromWebviewMessage = - | WebviewIntialized - | IDimensionMessage - | IMouseEnterMessage - | IMouseLeaveMessage - | IWheelMessage - | IScrollAckMessage - | IBlurOutputMessage - | ICustomRendererMessage - | IClickedDataUrlMessage; - -export type ToWebviewMessage = - | IClearMessage - | IFocusOutputMessage - | ICreationRequestMessage - | IViewScrollTopRequestMessage - | IScrollRequestMessage - | IClearOutputRequestMessage - | IHideOutputMessage - | IShowOutputMessage - | IUpdatePreloadResourceMessage - | IUpdateDecorationsMessage - | ICustomRendererMessage; - -export type AnyMessage = FromWebviewMessage | ToWebviewMessage; - -interface ICachedInset { - outputId: string; - cellInfo: K; - renderer?: INotebookRendererInfo; - cachedCreation: ICreationRequestMessage; -} - -function html(strings: TemplateStringsArray, ...values: any[]): string { - let str = ''; - strings.forEach((string, i) => { - str += string + (values[i] || ''); - }); - return str; -} - -export interface INotebookWebviewMessage { - message: unknown; - forRenderer?: string; -} - -let version = 0; -export class BackLayerWebView extends Disposable { - element: HTMLElement; - webview: WebviewElement | undefined = undefined; - insetMapping: Map> = new Map(); - hiddenInsetMapping: Set = new Set(); - reversedInsetMapping: Map = new Map(); - localResourceRootsCache: URI[] | undefined = undefined; - rendererRootsCache: URI[] = []; - kernelRootsCache: URI[] = []; - private readonly _onMessage = this._register(new Emitter()); - private readonly _preloadsCache = new Set(); - public readonly onMessage: Event = this._onMessage.event; - private _loaded!: Promise; - private _initalized?: Promise; - private _disposed = false; - - constructor( - public notebookEditor: ICommonNotebookEditor, - public id: string, - public documentUri: URI, - @IWebviewService readonly webviewService: IWebviewService, - @IOpenerService readonly openerService: IOpenerService, - @INotebookService private readonly notebookService: INotebookService, - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IFileDialogService private readonly fileDialogService: IFileDialogService, - @IFileService private readonly fileService: IFileService, - ) { - super(); - - this.element = document.createElement('div'); - - this.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; - this.element.style.height = '1400px'; - this.element.style.position = 'absolute'; - } - generateContent(outputNodePadding: number, coreDependencies: string, baseUrl: string) { - return html` - - - - - - - - - ${coreDependencies} -
- - - `; - } - - postRendererMessage(rendererId: string, message: any) { - this._sendMessageToWebview({ - __vscode_notebook_message: true, - type: 'customRendererMessage', - message, - rendererId - }); - } - - private resolveOutputId(id: string): { cellInfo: T, output: IDisplayOutputViewModel } | undefined { - const output = this.reversedInsetMapping.get(id); - if (!output) { - return; - } - - const cellInfo = this.insetMapping.get(output)!.cellInfo; - return { cellInfo, output }; - } - - async createWebview(): Promise { - let coreDependencies = ''; - let resolveFunc: () => void; - - this._initalized = new Promise((resolve, reject) => { - resolveFunc = resolve; - }); - - const baseUrl = asWebviewUri(this.environmentService, this.id, dirname(this.documentUri)); - - if (!isWeb) { - const loaderUri = FileAccess.asFileUri('vs/loader.js', require); - const loader = asWebviewUri(this.environmentService, this.id, loaderUri); - - coreDependencies = ``; - const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); - this._initialize(htmlContent); - resolveFunc!(); - } else { - const loaderUri = FileAccess.asBrowserUri('vs/loader.js', require); - - fetch(loaderUri.toString(true)).then(async response => { - if (response.status !== 200) { - throw new Error(response.statusText); - } - - const loaderJs = await response.text(); - - coreDependencies = ` - - -`; - - const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); - this._initialize(htmlContent); - resolveFunc!(); - }); - } - - await this._initalized; - } - - private async _initialize(content: string) { - if (!document.body.contains(this.element)) { - throw new Error('Element is already detached from the DOM tree'); - } - - this.webview = this._createInset(this.webviewService, content); - this.webview.mountTo(this.element); - this._register(this.webview); - - this._register(this.webview.onDidClickLink(link => { - if (this._disposed) { - return; - } - - if (!link) { - return; - } - - if (matchesScheme(link, Schemas.http) || matchesScheme(link, Schemas.https) || matchesScheme(link, Schemas.mailto) - || matchesScheme(link, Schemas.command)) { - this.openerService.open(link, { fromUserGesture: true }); - } - })); - - this._register(this.webview.onDidReload(() => { - if (this._disposed) { - return; - } - - let renderers = new Set(); - for (const inset of this.insetMapping.values()) { - if (inset.renderer) { - renderers.add(inset.renderer); - } - } - - this._preloadsCache.clear(); - this.updateRendererPreloads(renderers); - - for (const [output, inset] of this.insetMapping.entries()) { - this._sendMessageToWebview({ ...inset.cachedCreation, initiallyHidden: this.hiddenInsetMapping.has(output) }); - } - })); - - this._register(this.webview.onMessage((data: FromWebviewMessage) => { - if (this._disposed) { - return; - } - - if (data.__vscode_notebook_message) { - if (data.type === 'dimension') { - const height = data.data.height; - const outputHeight = height; - - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const { cellInfo, output } = resolvedResult; - this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight); - } - } else if (data.type === 'mouseenter') { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsHovered = true; - } - } - } else if (data.type === 'mouseleave') { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsHovered = false; - } - } - } else if (data.type === '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()); - } else if (data.type === 'did-scroll-wheel') { - this.notebookEditor.triggerScroll({ - ...data.payload, - preventDefault: () => { }, - stopPropagation: () => { } - }); - } else if (data.type === 'focus-editor') { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (!latestCell) { - return; - } - - if (data.focusNext) { - this.notebookEditor.focusNextNotebookCell(latestCell, 'editor'); - } else { - this.notebookEditor.focusNotebookCell(latestCell, 'editor'); - } - } - } else if (data.type === 'clicked-data-url') { - this._onDidClickDataLink(data); - } else if (data.type === 'customRendererMessage') { - this._onMessage.fire({ message: data.message, forRenderer: data.rendererId }); - } - return; - } - - this._onMessage.fire({ message: data }); - })); - } - - private async _onDidClickDataLink(event: IClickedDataUrlMessage): Promise { - const [splitStart, splitData] = event.data.split(';base64,'); - if (!splitData || !splitStart) { - return; - } - - const defaultDir = dirname(this.documentUri); - let defaultName: string; - if (event.downloadName) { - defaultName = event.downloadName; - } else { - const mimeType = splitStart.replace(/^data:/, ''); - const candidateExtension = mimeType && getExtensionForMimeType(mimeType); - defaultName = candidateExtension ? `download${candidateExtension}` : 'download'; - } - - const defaultUri = joinPath(defaultDir, defaultName); - const newFileUri = await this.fileDialogService.showSaveDialog({ - defaultUri - }); - if (!newFileUri) { - return; - } - - const decoded = atob(splitData); - const typedArray = new Uint8Array(decoded.length); - for (let i = 0; i < decoded.length; i++) { - typedArray[i] = decoded.charCodeAt(i); - } - - const buff = VSBuffer.wrap(typedArray); - await this.fileService.writeFile(newFileUri, buff); - await this.openerService.open(newFileUri); - } - - private _createInset(webviewService: IWebviewService, content: string) { - const rootPath = isWeb ? FileAccess.asBrowserUri('', require) : FileAccess.asFileUri('', require); - - const workspaceFolders = this.contextService.getWorkspace().folders.map(x => x.uri); - - this.localResourceRootsCache = [...this.notebookService.getNotebookProviderResourceRoots(), ...workspaceFolders, rootPath]; - - const webview = webviewService.createWebviewElement(this.id, { - purpose: WebviewContentPurpose.NotebookRenderer, - enableFindWidget: false, - }, { - allowMultipleAPIAcquire: true, - allowScripts: true, - localResourceRoots: this.localResourceRootsCache - }, undefined); - - let resolveFunc: () => void; - this._loaded = new Promise((resolve, reject) => { - resolveFunc = resolve; - }); - - const dispose = webview.onMessage((data: FromWebviewMessage) => { - if (data.__vscode_notebook_message && data.type === 'initialized') { - resolveFunc(); - dispose.dispose(); - } - }); - - webview.html = content; - return webview; - } - - shouldUpdateInset(cell: IGenericCellViewModel, output: IDisplayOutputViewModel, cellTop: number) { - if (this._disposed) { - return; - } - - if (cell.metadata?.outputCollapsed) { - return false; - } - - const outputCache = this.insetMapping.get(output)!; - const outputIndex = cell.outputsViewModels.indexOf(output); - const outputOffset = cellTop + cell.getOutputOffset(outputIndex); - - if (this.hiddenInsetMapping.has(output)) { - return true; - } - - if (outputOffset === outputCache.cachedCreation.top) { - return false; - } - - return true; - } - - updateViewScrollTop(top: number, forceDisplay: boolean, items: IDisplayOutputLayoutUpdateRequest[]) { - if (this._disposed) { - return; - } - - const widgets: IContentWidgetTopRequest[] = items.map(item => { - const outputCache = this.insetMapping.get(item.output)!; - const id = outputCache.outputId; - const outputOffset = item.outputOffset; - outputCache.cachedCreation.top = outputOffset; - this.hiddenInsetMapping.delete(item.output); - - return { - id: id, - top: outputOffset, - left: 0 - }; - }); - - this._sendMessageToWebview({ - top, - type: 'view-scroll', - version: version++, - forceDisplay, - widgets: widgets - }); - } - - async createInset(cellInfo: T, content: IInsetRenderOutput, cellTop: number, offset: number) { - if (this._disposed) { - return; - } - - const initialTop = cellTop + offset; - - if (this.insetMapping.has(content.source)) { - const outputCache = this.insetMapping.get(content.source); - - if (outputCache) { - this.hiddenInsetMapping.delete(content.source); - this._sendMessageToWebview({ - type: 'showOutput', - cellId: outputCache.cellInfo.cellId, - outputId: outputCache.outputId, - top: initialTop - }); - return; - } - } - - const messageBase = { - type: 'html', - cellId: cellInfo.cellId, - top: initialTop, - left: 0, - requiredPreloads: [], - } as const; - - let message: ICreationRequestMessage; - let renderer: INotebookRendererInfo | undefined; - if (content.type === RenderOutputType.Extension) { - const output = content.source.model; - renderer = content.renderer; - message = { - ...messageBase, - outputId: output.outputId, - apiNamespace: content.renderer.id, - requiredPreloads: await this.updateRendererPreloads([content.renderer]), - content: { - type: RenderOutputType.Extension, - mimeType: content.mimeType, - output: { - outputKind: CellOutputKind.Rich, - metadata: output.metadata, - data: output.data, - }, - }, - }; - } else { - message = { - ...messageBase, - outputId: UUID.generateUuid(), - content: { - type: content.type, - htmlContent: content.htmlContent, - } - }; - } - - this._sendMessageToWebview(message); - this.insetMapping.set(content.source, { outputId: message.outputId, cellInfo: cellInfo, renderer, cachedCreation: message }); - this.hiddenInsetMapping.delete(content.source); - this.reversedInsetMapping.set(message.outputId, content.source); - } - - removeInset(output: IDisplayOutputViewModel) { - if (this._disposed) { - return; - } - - const outputCache = this.insetMapping.get(output); - if (!outputCache) { - return; - } - - const id = outputCache.outputId; - - this._sendMessageToWebview({ - type: 'clearOutput', - apiNamespace: outputCache.cachedCreation.apiNamespace, - cellUri: outputCache.cellInfo.cellUri.toString(), - outputId: id, - cellId: outputCache.cellInfo.cellId - }); - this.insetMapping.delete(output); - this.reversedInsetMapping.delete(id); - } - - hideInset(output: IDisplayOutputViewModel) { - if (this._disposed) { - return; - } - - const outputCache = this.insetMapping.get(output); - if (!outputCache) { - return; - } - - this.hiddenInsetMapping.add(output); - - this._sendMessageToWebview({ - type: 'hideOutput', - outputId: outputCache.outputId, - cellId: outputCache.cellInfo.cellId, - }); - } - - clearInsets() { - if (this._disposed) { - return; - } - - this._sendMessageToWebview({ - type: 'clear' - }); - - this.insetMapping = new Map(); - this.reversedInsetMapping = new Map(); - } - - focusWebview() { - if (this._disposed) { - return; - } - - this.webview?.focus(); - } - - focusOutput(cellId: string) { - if (this._disposed) { - return; - } - - this.webview?.focus(); - setTimeout(() => { // Need this, or focus decoration is not shown. No clue. - this._sendMessageToWebview({ - type: 'focus-output', - cellId, - }); - }, 50); - } - - deltaCellOutputContainerClassNames(cellId: string, added: string[], removed: string[]) { - this._sendMessageToWebview({ - type: 'decorations', - cellId, - addedClassNames: added, - removedClassNames: removed - }); - - } - - async updateKernelPreloads(extensionLocations: URI[], preloads: URI[]) { - if (this._disposed) { - return; - } - - await this._loaded; - - const resources: IPreloadResource[] = []; - for (const preload of preloads) { - const uri = this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https') - ? preload : asWebviewUri(this.environmentService, this.id, preload); - - if (!this._preloadsCache.has(uri.toString())) { - resources.push({ uri: uri.toString(), originalUri: preload.toString() }); - this._preloadsCache.add(uri.toString()); - } - } - - if (!resources.length) { - return; - } - - this.kernelRootsCache = [...extensionLocations, ...this.kernelRootsCache]; - this._updatePreloads(resources, 'kernel'); - } - - async updateRendererPreloads(renderers: Iterable) { - if (this._disposed) { - return []; - } - - await this._loaded; - - const requiredPreloads: IPreloadResource[] = []; - const resources: IPreloadResource[] = []; - const extensionLocations: URI[] = []; - for (const rendererInfo of renderers) { - extensionLocations.push(rendererInfo.extensionLocation); - for (const preload of [rendererInfo.entrypoint, ...rendererInfo.preloads]) { - const uri = asWebviewUri(this.environmentService, this.id, preload); - const resource: IPreloadResource = { uri: uri.toString(), originalUri: preload.toString() }; - requiredPreloads.push(resource); - - if (!this._preloadsCache.has(uri.toString())) { - resources.push(resource); - this._preloadsCache.add(uri.toString()); - } - } - } - - if (!resources.length) { - return requiredPreloads; - } - - this.rendererRootsCache = extensionLocations; - this._updatePreloads(resources, 'renderer'); - return requiredPreloads; - } - - private _updatePreloads(resources: IPreloadResource[], source: 'renderer' | 'kernel') { - if (!this.webview) { - return; - } - - const mixedResourceRoots = [...(this.localResourceRootsCache || []), ...this.rendererRootsCache, ...this.kernelRootsCache]; - - this.webview.localResourcesRoot = mixedResourceRoots; - - this._sendMessageToWebview({ - type: 'preload', - resources: resources, - source: source - }); - } - - private _sendMessageToWebview(message: ToWebviewMessage) { - if (this._disposed) { - return; - } - - this.webview?.postMessage(message); - } - - clearPreloadsCache() { - this._preloadsCache.clear(); - } - - dispose() { - this._disposed = true; - this.webview?.dispose(); - super.dispose(); - } -} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 98f32e0af59..0963288f036 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -38,11 +38,11 @@ import { IDiffChange } from 'vs/base/common/diff/diff'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { SequencerByKey } from 'vs/base/common/async'; -import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/diff/backLayerWebview2'; import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; +import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; const $ = DOM.$; From 86838823e3b919095d19dcfec53ae8f4a1142639 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 16:17:47 -0800 Subject: [PATCH 1051/1837] move genericTypes into notebookBrowser --- .../contrib/notebook/browser/diff/common.ts | 3 +- .../browser/diff/diffElementViewModel.ts | 3 +- .../browser/diff/diffNestedCellViewModel.ts | 3 +- .../browser/diff/notebookTextDiffEditor.ts | 3 +- .../contrib/notebook/browser/genericTypes.ts | 40 ------------------- .../notebook/browser/notebookBrowser.ts | 36 ++++++++++++++++- .../notebook/browser/notebookEditorWidget.ts | 3 +- .../view/renderers/backLayerWebView.ts | 3 +- .../notebook/test/testNotebookEditor.ts | 3 +- 9 files changed, 42 insertions(+), 55 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/genericTypes.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index 9d7b73aeb6c..e8a45767398 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisplayOutputViewModel, IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { Event } from 'vs/base/common/event'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; @@ -14,7 +14,6 @@ import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; -import { ICommonCellInfo, ICommonNotebookEditor, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface IDiffCellInfo extends ICommonCellInfo { diffElement: DiffElementViewModelBase; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 464e55126eb..cfb29fecca0 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -7,7 +7,7 @@ import { NotebookDiffEditorEventDispatcher } from 'vs/workbench/contrib/notebook import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IGenericCellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { hash } from 'vs/base/common/hash'; @@ -16,7 +16,6 @@ import { applyEdits } from 'vs/base/common/jsonEdit'; import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { URI } from 'vs/base/common/uri'; -import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export enum PropertyFoldingState { Expanded, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts index 050b6feb951..f5bdbfc8037 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel.ts @@ -8,8 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { generateUuid } from 'vs/base/common/uuid'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IDiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/common'; -import { IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; -import { CellViewModelStateChangeEvent, ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellViewModelStateChangeEvent, ICellOutputViewModel, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 0963288f036..f19a874b806 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; -import { IDisplayOutputViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/common'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -41,7 +41,6 @@ import { SequencerByKey } from 'vs/base/common/async'; import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; -import { IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; const $ = DOM.$; diff --git a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts b/src/vs/workbench/contrib/notebook/browser/genericTypes.ts deleted file mode 100644 index 80261d31163..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/genericTypes.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; -import { URI } from 'vs/base/common/uri'; -import { ICellOutputViewModel, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; - -export interface IGenericCellViewModel { - id: string; - handle: number; - uri: URI; - metadata: NotebookCellMetadata | undefined; - outputIsHovered: boolean; - outputsViewModels: ICellOutputViewModel[]; - getOutputOffset(index: number): number; - updateOutputHeight(index: number, height: number): void; -} - -export interface IDisplayOutputLayoutUpdateRequest { - output: IDisplayOutputViewModel; - cellTop: number; - outputOffset: number; -} - -export interface ICommonCellInfo { - cellId: string; - cellHandle: number; - cellUri: URI; -} - -export interface ICommonNotebookEditor { - triggerScroll(event: IMouseWheelEvent): void; - getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; - focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; - focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; -} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 744c663361f..024bdb5aa2c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -31,7 +31,6 @@ import { EditorOptions } from 'vs/workbench/common/editor'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; -import { ICommonCellInfo, ICommonNotebookEditor, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); @@ -67,6 +66,41 @@ export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; export const NOTEBOOK_HAS_MULTIPLE_KERNELS = new RawContextKey('notebookHasMultipleKernels', false); + +// These are types shared by the Notebook Editor and Notebook Diff Editor + +export interface IGenericCellViewModel { + id: string; + handle: number; + uri: URI; + metadata: NotebookCellMetadata | undefined; + outputIsHovered: boolean; + outputsViewModels: ICellOutputViewModel[]; + getOutputOffset(index: number): number; + updateOutputHeight(index: number, height: number): void; +} + +export interface IDisplayOutputLayoutUpdateRequest { + output: IDisplayOutputViewModel; + cellTop: number; + outputOffset: number; +} + +export interface ICommonCellInfo { + cellId: string; + cellHandle: number; + cellUri: URI; +} + +export interface ICommonNotebookEditor { + triggerScroll(event: IMouseWheelEvent): void; + getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; + focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; + focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; +} + + export interface NotebookLayoutInfo { width: number; height: number; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 880ba066d17..b69f21df8bb 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -42,7 +42,7 @@ import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, IDisplayOutputViewModel, IInsetRenderOutput, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IInsetRenderOutput, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -62,7 +62,6 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { ICommonCellInfo, IDisplayOutputLayoutUpdateRequest } from 'vs/workbench/contrib/notebook/browser/genericTypes'; const $ = DOM.$; 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 4dab3eba4d3..c70ac956800 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; -import { IDisplayOutputViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview'; @@ -25,7 +25,6 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { getExtensionForMimeType } from 'vs/base/common/mime'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export interface WebviewIntialized { __vscode_notebook_message: boolean; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index dacce8299ae..c624881feb9 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -12,7 +12,7 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { Range } from 'vs/editor/common/core/range'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { EditorModel } from 'vs/workbench/common/editor'; -import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput, IDisplayOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput, IDisplayOutputViewModel, ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; @@ -36,7 +36,6 @@ import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService import { ScrollEvent } from 'vs/base/common/scrollable'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; -import { ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/genericTypes'; export class TestCell extends NotebookCellTextModel { constructor( From f6a796b66935124037a903ab4b5031331b73e57c Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 16:22:04 -0800 Subject: [PATCH 1052/1837] grouping types in notebookBrowser --- .../notebook/browser/notebookBrowser.ts | 118 +++++++++--------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 024bdb5aa2c..6707689f601 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -32,6 +32,7 @@ import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; +//#region Context Keys export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); // Is Notebook @@ -57,17 +58,73 @@ export const NOTEBOOK_CELL_RUN_STATE = new RawContextKey('notebookCellRu export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey('notebookCellHasOutputs', false); // bool export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey('notebookCellInputIsCollapsed', false); // bool export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebookCellOutputIsCollapsed', false); // bool +// Kernels +export const NOTEBOOK_HAS_MULTIPLE_KERNELS = new RawContextKey('notebookHasMultipleKernels', false); -// Shared commands +//#endregion + +//#region Shared commands export const EXPAND_CELL_CONTENT_COMMAND_ID = 'notebook.cell.expandCellContent'; export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; -// Kernels +//#endregion -export const NOTEBOOK_HAS_MULTIPLE_KERNELS = new RawContextKey('notebookHasMultipleKernels', false); +//#region Output related types +export const enum RenderOutputType { + None, + Html, + Extension +} + +export interface IRenderNoOutput { + type: RenderOutputType.None; + hasDynamicHeight: boolean; +} + +export interface IRenderPlainHtmlOutput { + type: RenderOutputType.Html; + source: IDisplayOutputViewModel; + htmlContent: string; + hasDynamicHeight: boolean; +} + +export interface IRenderOutputViaExtension { + type: RenderOutputType.Extension; + source: IDisplayOutputViewModel; + mimeType: string; + renderer: INotebookRendererInfo; +} + +export type IInsetRenderOutput = IRenderPlainHtmlOutput | IRenderOutputViaExtension; +export type IRenderOutput = IRenderNoOutput | IInsetRenderOutput; + +export const outputHasDynamicHeight = (o: IRenderOutput) => o.type !== RenderOutputType.Extension && o.hasDynamicHeight; -// These are types shared by the Notebook Editor and Notebook Diff Editor +export interface ICellOutputViewModel { + model: IProcessedOutput; + isDisplayOutput(): this is IDisplayOutputViewModel; + isErrorOutput(): this is IErrorOutputViewModel; + isStreamOutput(): this is IStreamOutputViewModel; +} + +export interface IDisplayOutputViewModel extends ICellOutputViewModel { + model: ITransformedDisplayOutputDto; + resolveMimeTypes(textModel: NotebookTextModel): [readonly IOrderedMimeType[], number]; + pickedMimeType: number; +} + +export interface IErrorOutputViewModel extends ICellOutputViewModel { + model: IErrorOutput; +} + +export interface IStreamOutputViewModel extends ICellOutputViewModel { + model: IStreamOutput; +} + +//#endregion + +//#region Shared types between the Notebook Editor and Notebook Diff Editor, they are mostly used for output rendering export interface IGenericCellViewModel { id: string; @@ -100,6 +157,7 @@ export interface ICommonNotebookEditor { updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; } +//#endregion export interface NotebookLayoutInfo { width: number; @@ -157,58 +215,6 @@ export interface MarkdownCellLayoutChangeEvent { totalHeight?: number; } -export const enum RenderOutputType { - None, - Html, - Extension -} - -export interface IRenderNoOutput { - type: RenderOutputType.None; - hasDynamicHeight: boolean; -} - -export interface IRenderPlainHtmlOutput { - type: RenderOutputType.Html; - source: IDisplayOutputViewModel; - htmlContent: string; - hasDynamicHeight: boolean; -} - -export interface IRenderOutputViaExtension { - type: RenderOutputType.Extension; - source: IDisplayOutputViewModel; - mimeType: string; - renderer: INotebookRendererInfo; -} - -export type IInsetRenderOutput = IRenderPlainHtmlOutput | IRenderOutputViaExtension; -export type IRenderOutput = IRenderNoOutput | IInsetRenderOutput; - -export const outputHasDynamicHeight = (o: IRenderOutput) => o.type !== RenderOutputType.Extension && o.hasDynamicHeight; - - -export interface ICellOutputViewModel { - model: IProcessedOutput; - isDisplayOutput(): this is IDisplayOutputViewModel; - isErrorOutput(): this is IErrorOutputViewModel; - isStreamOutput(): this is IStreamOutputViewModel; -} - -export interface IDisplayOutputViewModel extends ICellOutputViewModel { - model: ITransformedDisplayOutputDto; - resolveMimeTypes(textModel: NotebookTextModel): [readonly IOrderedMimeType[], number]; - pickedMimeType: number; -} - -export interface IErrorOutputViewModel extends ICellOutputViewModel { - model: IErrorOutput; -} - -export interface IStreamOutputViewModel extends ICellOutputViewModel { - model: IStreamOutput; -} - export interface ICellViewModel extends IGenericCellViewModel { readonly model: NotebookCellTextModel; readonly id: string; From 03c528450f34942b00c97c3e0366260ce7ece0f4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 14 Dec 2020 14:31:22 -0800 Subject: [PATCH 1053/1837] Small formatting cleanup --- src/vs/workbench/api/browser/mainThreadWebviewPanels.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts index 6428e6f488c..ed502732d0b 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts @@ -181,7 +181,6 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc webview.setName(value); } - public $setIconPath(handle: extHostProtocol.WebviewHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void { const webview = this.getWebviewInput(handle); webview.iconPath = reviveWebviewIcon(value); @@ -199,8 +198,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc } } - public $registerSerializer(viewType: string) - : void { + public $registerSerializer(viewType: string): void { if (this._revivers.has(viewType)) { throw new Error(`Reviver for ${viewType} already registered`); } @@ -216,7 +214,6 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc return; } - const handle = webviewInput.id; this.addWebviewInput(handle, webviewInput); From 542670762fdb231309ebc8fe3c38bd17e51a6cb5 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 14 Dec 2020 14:41:25 -0800 Subject: [PATCH 1054/1837] Make sure we dispose of webview revivers when the main thread extension host is disposed of --- src/vs/workbench/api/browser/mainThreadWebviewPanels.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts index ed502732d0b..7aa6907722d 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts @@ -129,6 +129,9 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc dispose(this._editorProviders.values()); this._editorProviders.clear(); + + dispose(this._revivers.values()); + this._revivers.clear(); } public get webviewInputs(): Iterable { return this._webviewInputs; } From 6d3c2e683553ba6cc6be89e5b7223a9fea8e4d02 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 15 Dec 2020 16:15:15 -0800 Subject: [PATCH 1055/1837] Adding proposed external uri opener API For #109277 --- src/vs/platform/opener/common/opener.ts | 4 +- src/vs/vscode.proposed.d.ts | 46 +++++++++ .../api/browser/extensionHost.contribution.ts | 1 + .../api/browser/mainThreadUriOpeners.ts | 63 ++++++++++++ .../workbench/api/common/extHost.api.impl.ts | 8 +- .../workbench/api/common/extHost.protocol.ts | 11 +++ .../workbench/api/common/extHostUriOpener.ts | 98 +++++++++++++++++++ 7 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 src/vs/workbench/api/browser/mainThreadUriOpeners.ts create mode 100644 src/vs/workbench/api/common/extHostUriOpener.ts diff --git a/src/vs/platform/opener/common/opener.ts b/src/vs/platform/opener/common/opener.ts index d82651f93be..84601bcf48e 100644 --- a/src/vs/platform/opener/common/opener.ts +++ b/src/vs/platform/opener/common/opener.ts @@ -11,7 +11,7 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor'; export const IOpenerService = createDecorator('openerService'); -type OpenInternalOptions = { +export type OpenInternalOptions = { /** * Signals that the intent is to open an editor to the side @@ -31,7 +31,7 @@ type OpenInternalOptions = { readonly fromUserGesture?: boolean; }; -type OpenExternalOptions = { readonly openExternal?: boolean; readonly allowTunneling?: boolean }; +export type OpenExternalOptions = { readonly openExternal?: boolean; readonly allowTunneling?: boolean }; export type OpenOptions = OpenInternalOptions & OpenExternalOptions; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 2a960c7821b..f40d195d03b 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Command } from 'vscode'; + /** * This is the place for API experiments and proposals. * These API are NOT stable and subject to change. They are only available in the Insiders @@ -2297,4 +2299,48 @@ declare module 'vscode' { location?: Location; } //#endregion + + //#region Opener service (https://github.com/microsoft/vscode/issues/109277) + + /** + * Handles opening external uris. + * + * An extension can use this to open a `http` link to a webserver inside of VS Code instead of + * having the link be opened by the webbrowser. + * + * Currently openers may only be registered for `http` and `https` uris. + */ + export interface ExternalUriOpener { + + /** + * Try to open a given uri. + * + * @param uri The uri being opened. + * @param ctx Additional metadata about how the open was triggered. + * @param token Cancellation token. + * + * @return Optional command that opens the uri. If no command is returned, VS Code will + * continue checking to see if any other openers are available. + * + * If multiple openers are available for a given uri, then the `Command.title` is shown in the UI. + */ + openExternalUri(uri: Uri, ctx: {}, token: CancellationToken): ProviderResult; + } + + namespace window { + /** + * Register a new `ExternalUriOpener`. + * + * When a uri is about to be opened, a `onUriOpen:SCHEME` activation event is fired. + * + * @param schemes List of uri schemes the opener is triggered for. Currently only `http` + * and `https` are supported. + * @param opener Opener to register. + * + * @returns Disposable that unregisters the opener. + */ + export function registerExternalUriOpener(schemes: readonly string[], opener: ExternalUriOpener,): Disposable; + } + + //#endregion } diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 3b4c8a66c27..a69945ffec0 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -54,6 +54,7 @@ import './mainThreadTheming'; import './mainThreadTreeViews'; import './mainThreadDownloadService'; import './mainThreadUrls'; +import './mainThreadUriOpeners'; import './mainThreadWindow'; import './mainThreadWebviewManager'; import './mainThreadWorkspace'; diff --git a/src/vs/workbench/api/browser/mainThreadUriOpeners.ts b/src/vs/workbench/api/browser/mainThreadUriOpeners.ts new file mode 100644 index 00000000000..c15a654f74d --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadUriOpeners.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Schemas } from 'vs/base/common/network'; +import { URI } from 'vs/base/common/uri'; +import { IOpener, IOpenerService, OpenExternalOptions, OpenInternalOptions } from 'vs/platform/opener/common/opener'; +import { ExtHostContext, ExtHostUriOpenersShape, IExtHostContext, MainContext, MainThreadUriOpenersShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { extHostNamedCustomer } from '../common/extHostCustomers'; + + +@extHostNamedCustomer(MainContext.MainThreadUriOpeners) +export class MainThreadUriOpeners implements MainThreadUriOpenersShape, IOpener { + + private readonly proxy: ExtHostUriOpenersShape; + private readonly handlers = new Set(); + + constructor( + context: IExtHostContext, + @IOpenerService private readonly openerService: IOpenerService, + @IExtensionService private readonly extensionService: IExtensionService, + ) { + this.proxy = context.getProxy(ExtHostContext.ExtHostUriOpeners); + + this.openerService.registerOpener(this); + } + + async open( + target: string | URI, + options?: OpenInternalOptions | OpenExternalOptions + ): Promise { + const targetUri = typeof target === 'string' ? URI.parse(target) : target; + + // Currently we only allow openers for http and https urls + if (targetUri.scheme !== Schemas.http && targetUri.scheme !== Schemas.https) { + return false; + } + + await this.extensionService.activateByEvent(`onUriOpen:${targetUri.scheme}`); + + // No handlers so no point in making a rount trip + if (!this.handlers.size) { + return false; + } + + return await this.proxy.$openUri(targetUri, CancellationToken.None); + } + + async $registerUriOpener(handle: number): Promise { + this.handlers.add(handle); + } + + async $unregisterUriOpener(handle: number): Promise { + this.handlers.delete(handle); + } + + dispose(): void { + this.handlers.clear(); + } +} diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b7ec8703834..00564b6db78 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -82,6 +82,7 @@ import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPane import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits'; import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo'; import { ExtHostTesting } from 'vs/workbench/api/common/extHostTesting'; +import { ExtHostUriOpeners } from 'vs/workbench/api/common/extHostUriOpener'; export interface IExtensionApiFactory { (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; @@ -154,6 +155,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels)); const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews)); const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol, extHostDocumentsAndEditors, extHostWorkspace)); + const extHostUriOpeners = rpcProtocol.set(ExtHostContext.ExtHostUriOpeners, new ExtHostUriOpeners(rpcProtocol, extHostCommands, extHostQuickOpen)); // Check that no named customers are missing const expected: ProxyIdentifier[] = values(ExtHostContext); @@ -691,7 +693,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I showNotebookDocument(document, options?) { checkProposedApiEnabled(extension); return extHostNotebook.showNotebookDocument(document, options); - } + }, + registerExternalUriOpener(schemes: readonly string[], opener: vscode.ExternalUriOpener) { + checkProposedApiEnabled(extension); + return extHostUriOpeners.registerUriOpener(extension.identifier, schemes, opener); + }, }; // namespace: workspace diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 733bd6f3971..ee9054a3055 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -788,6 +788,15 @@ export interface ExtHostUrlsShape { $handleExternalUri(handle: number, uri: UriComponents): Promise; } +export interface MainThreadUriOpenersShape extends IDisposable { + $registerUriOpener(handle: number): Promise; + $unregisterUriOpener(handle: number): Promise; +} + +export interface ExtHostUriOpenersShape { + $openUri(uri: UriComponents, token: CancellationToken): Promise; +} + export interface ITextSearchComplete { limitHit?: boolean; } @@ -1821,6 +1830,7 @@ export const MainContext = { MainThreadWebviewViews: createMainId('MainThreadWebviewViews'), MainThreadCustomEditors: createMainId('MainThreadCustomEditors'), MainThreadUrls: createMainId('MainThreadUrls'), + MainThreadUriOpeners: createMainId('MainThreadUriOpeners'), MainThreadWorkspace: createMainId('MainThreadWorkspace'), MainThreadFileSystem: createMainId('MainThreadFileSystem'), MainThreadExtensionService: createMainId('MainThreadExtensionService'), @@ -1870,6 +1880,7 @@ export const ExtHostContext = { ExtHostComments: createMainId('ExtHostComments'), ExtHostStorage: createMainId('ExtHostStorage'), ExtHostUrls: createExtId('ExtHostUrls'), + ExtHostUriOpeners: createExtId('ExtHostUriOpeners'), ExtHostOutputService: createMainId('ExtHostOutputService'), ExtHosLabelService: createMainId('ExtHostLabelService'), ExtHostNotebook: createMainId('ExtHostNotebook'), diff --git a/src/vs/workbench/api/common/extHostUriOpener.ts b/src/vs/workbench/api/common/extHostUriOpener.ts new file mode 100644 index 00000000000..b0260552e30 --- /dev/null +++ b/src/vs/workbench/api/common/extHostUriOpener.ts @@ -0,0 +1,98 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { coalesce } from 'vs/base/common/arrays'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { toDisposable } from 'vs/base/common/lifecycle'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; +import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen'; +import type * as vscode from 'vscode'; +import { ExtHostUriOpenersShape, IMainContext, MainContext, MainThreadUriOpenersShape } from './extHost.protocol'; + +export class ExtHostUriOpeners implements ExtHostUriOpenersShape { + + private static HandlePool = 0; + + private readonly _proxy: MainThreadUriOpenersShape; + private readonly _commands: ExtHostCommands; + private readonly _quickOpen: ExtHostQuickOpen; + + private readonly _openers = new Map, opener: vscode.ExternalUriOpener }>(); + + constructor( + mainContext: IMainContext, + commands: ExtHostCommands, + quickOpen: ExtHostQuickOpen, + ) { + this._proxy = mainContext.getProxy(MainContext.MainThreadUriOpeners); + this._commands = commands; + this._quickOpen = quickOpen; + } + + registerUriOpener( + extensionId: ExtensionIdentifier, + schemes: readonly string[], + opener: vscode.ExternalUriOpener, + ): vscode.Disposable { + + const handle = ExtHostUriOpeners.HandlePool++; + + this._openers.set(handle, { opener, schemes: new Set(schemes) }); + this._proxy.$registerUriOpener(handle); + + return toDisposable(() => { + this._openers.delete(handle); + this._proxy.$unregisterUriOpener(handle); + }); + } + + async $openUri(uriComponents: UriComponents, token: CancellationToken): Promise { + const uri = URI.revive(uriComponents); + + const promises = Array.from(this._openers.values()).map(async ({ schemes, opener }): Promise => { + if (!schemes.has(uri.scheme)) { + return undefined; + } + + try { + const result = await opener.openExternalUri(uri, {}, token); + if (result) { + return result; + } + } catch (e) { + // noop + } + return undefined; + }); + + const results = coalesce(await Promise.all(promises)); + + if (results.length === 0) { + return false; + } else if (results.length === 1) { + const [command] = results; + await this._commands.executeCommand(command.command, ...(command.arguments ?? [])); + return true; + } else { + type PickItem = vscode.QuickPickItem & { index: number }; + const items = results.map((command, i): PickItem => { + return { + label: command.title, + index: i + }; + }); + const picked = await this._quickOpen.showQuickPick(items, false, {}); + if (picked) { + const command = results[(picked as PickItem).index]; + await this._commands.executeCommand(command.command, ...(command.arguments ?? [])); + return true; + } + + return false; + } + } +} From 03081f5a3a8299274dedf0c8fda0e0b77ac0f82d Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 15 Dec 2020 10:52:35 -0800 Subject: [PATCH 1056/1837] Polish skip location --- .../welcome/gettingStarted/browser/gettingStarted.css | 10 +--------- .../welcome/gettingStarted/browser/gettingStarted.ts | 2 ++ .../browser/vs_code_editor_getting_started.ts | 7 ------- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 7eebbcbb7c7..3498196cba1 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -17,7 +17,7 @@ } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories { - height: calc(100% - 50px); + height: calc(100% - 10px); display: flex; flex-direction: column; overflow: hidden; @@ -253,14 +253,6 @@ padding: 0; } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .footer { - position: absolute; - text-align: center; - bottom: 0; - width: calc(100% - 40px); - margin-bottom: 10px; -} - .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.next { left: 100%; opacity: 0; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 817d7d4fdef..6cc77d9ed7e 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -222,6 +222,8 @@ export class GettingStartedPage extends Disposable { }); categoryScrollContainer.appendChild(categoriesContainer); + categoryScrollContainer.appendChild($('.footer', {}, $('a.skip', { 'x-dispatch': 'skip' }, localize('gettingStarted.skip', "Skip")))); + this.scrollbar = this._register(new DomScrollableElement(categoryScrollContainer, {})); categoriesSlide.appendChild(this.scrollbar.getDomNode()); categoriesSlide.appendChild($('.gap')); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index 92221ba66c4..245f36dc2ca 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -28,13 +28,6 @@ export default () => `
-
`.replace(/\|/g, '`'); - - -//
-//
From 01b04218586c6e17297a3452943fafea9dbec740 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 15 Dec 2020 14:39:23 -0800 Subject: [PATCH 1057/1837] Take ownership of workbench-welcome --- .github/classifier.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/classifier.json b/.github/classifier.json index 6fd9eb6d4eb..96b58771393 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -172,7 +172,7 @@ "workbench-tabs": {"assign": ["bpasero"]}, "workbench-touchbar": {"assign": ["bpasero"]}, "workbench-views": {"assign": ["sbatten"]}, - "workbench-welcome": {"assign": ["chrmarti"]}, + "workbench-welcome": {"assign": ["JacksonKearl"]}, "workbench-window": {"assign": ["bpasero"]}, "workbench-zen": {"assign": ["isidorn"]}, "workspace-edit": {"assign": ["jrieken"]}, From f91b8f2e7aee636060a6b8e957b82268ac51fb07 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 15 Dec 2020 16:46:26 -0800 Subject: [PATCH 1058/1837] More scrolling in getting started --- .../gettingStarted/browser/gettingStarted.css | 47 ++++++++++++++----- .../gettingStarted/browser/gettingStarted.ts | 44 ++++++++++++----- .../browser/vs_code_editor_getting_started.ts | 2 +- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 3498196cba1..5f15d3d1bcc 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -14,10 +14,10 @@ position: absolute; transition: left 0.25s, opacity 0.25s; left: 0; + top: 0; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.categories { - height: calc(100% - 10px); display: flex; flex-direction: column; overflow: hidden; @@ -82,21 +82,30 @@ font-size: 32px; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .gap { + flex: 150px 0 1000 +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category { width: 330px; display: flex; - padding: 40px 0 20px 12px; + padding: 10px 0 20px 12px; margin: 0; min-height: auto; } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .gap { - flex: 150px 1 1 +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-columns .gap { + flex: 150px 1 1000 } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-media { min-height: 300px; - flex: 40% 1 10 } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-category .codicon { @@ -106,9 +115,9 @@ .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-columns { display: flex; - height: calc(100% - 98px); justify-content: flex-start; - padding: 44px; + padding: 20px 20px 0; + max-height: calc(100% - 20px); } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .getting-started-task { @@ -174,14 +183,25 @@ min-width: 330px; width: 40%; max-width: 400px; + display: flex; + flex-direction: column; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail .full-height-scrollable { + height: 100%; +} + +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-container { + height: 100%; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-right { display: flex; - align-items: baseline; + align-items: center; + justify-content: center; width: 66%; - text-align: center; - padding: 52px 0 0 44px; + min-height: 300px; + padding: 0px 0 20px 44px; min-width: 400px; max-width: 800px; } @@ -193,8 +213,8 @@ padding: 16px; } -.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:not(:first-child) { - margin-top: 12px; +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button { + margin-bottom: 12px; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer button:hover { @@ -207,7 +227,8 @@ .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button { position: absolute; - left: 0; + left: -2px; + top: -10px; font-size: 12pt; margin: 10px; } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 6cc77d9ed7e..59f4f80c2e3 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -45,7 +45,9 @@ export class GettingStartedPage extends Disposable { private gettingStartedCategories: IGettingStartedCategoryWithProgress[]; private currentCategory: IGettingStartedCategoryWithProgress | undefined; - private scrollbar: DomScrollableElement | undefined; + private categoriesScrollbar: DomScrollableElement | undefined; + private detailsScrollbar: DomScrollableElement | undefined; + private detailImageScrollbar: DomScrollableElement | undefined; constructor( initialState: { selectedCategory?: string, selectedTask?: string }, @@ -95,11 +97,11 @@ export class GettingStartedPage extends Disposable { const badgeelement = assertIsDefined(document.getElementById('done-task-' + task.id)); if (task.done) { badgeelement.classList.remove('codicon-circle-large-outline'); - badgeelement.classList.add('codicon-pass-filled'); + badgeelement.classList.add('codicon-pass-filled', 'complete'); } else { badgeelement.classList.add('codicon-circle-large-outline'); - badgeelement.classList.remove('codicon-pass-filled'); + badgeelement.classList.remove('codicon-pass-filled', 'complete'); } } this.updateCategoryProgress(); @@ -189,6 +191,8 @@ export class GettingStartedPage extends Disposable { mediaElement.setAttribute('src', ''); mediaElement.setAttribute('alt', ''); } + this.detailsScrollbar?.scanDomNode(); + this.detailImageScrollbar?.scanDomNode(); } private onReady(container: HTMLElement) { @@ -212,6 +216,14 @@ export class GettingStartedPage extends Disposable { const categoriesSlide = assertIsDefined(document.getElementById('gettingStartedSlideCategory')); const tasksSlide = assertIsDefined(document.getElementById('gettingStartedSlideDetails')); + const tasksContent = assertIsDefined(document.getElementById('getting-started-detail-columns')); + tasksContent.remove(); + if (this.detailImageScrollbar) { this.detailImageScrollbar.dispose(); } + this.detailImageScrollbar = this._register(new DomScrollableElement(tasksContent, {})); + tasksSlide.appendChild(this.detailImageScrollbar.getDomNode()); + tasksSlide.appendChild($('.gap')); + this.detailImageScrollbar.scanDomNode(); + const rightColumn = assertIsDefined(container.querySelector('#getting-started-detail-right')); rightColumn.appendChild($('img#getting-started-media')); @@ -224,10 +236,11 @@ export class GettingStartedPage extends Disposable { categoryScrollContainer.appendChild(categoriesContainer); categoryScrollContainer.appendChild($('.footer', {}, $('a.skip', { 'x-dispatch': 'skip' }, localize('gettingStarted.skip', "Skip")))); - this.scrollbar = this._register(new DomScrollableElement(categoryScrollContainer, {})); - categoriesSlide.appendChild(this.scrollbar.getDomNode()); + if (this.categoriesScrollbar) { this.categoriesScrollbar.dispose(); } + this.categoriesScrollbar = this._register(new DomScrollableElement(categoryScrollContainer, {})); + categoriesSlide.appendChild(this.categoriesScrollbar.getDomNode()); categoriesSlide.appendChild($('.gap')); - this.scrollbar.scanDomNode(); + this.categoriesScrollbar.scanDomNode(); this.updateCategoryProgress(); @@ -248,14 +261,16 @@ export class GettingStartedPage extends Disposable { } private layout() { - this.scrollbar?.scanDomNode(); + this.categoriesScrollbar?.scanDomNode(); + this.detailsScrollbar?.scanDomNode(); + this.detailImageScrollbar?.scanDomNode(); } private updateCategoryProgress() { document.querySelectorAll('.category-progress').forEach(element => { const categoryID = element.getAttribute('x-data-category-id'); const category = this.gettingStartedCategories.find(category => category.id === categoryID); - if (!category) { throw Error('Could not find c=ategory with ID ' + categoryID); } + if (!category) { throw Error('Could not find category with ID ' + categoryID); } if (category.content.type !== 'items') { throw Error('Category with ID ' + categoryID + ' is not of items type'); } const numDone = category.content.items.filter(task => task.done).length; const numTotal = category.content.items.length; @@ -293,6 +308,7 @@ export class GettingStartedPage extends Disposable { if (!category) { throw Error('could not find category with ID ' + categoryID); } if (category.content.type !== 'items') { throw Error('category with ID ' + categoryID + ' is not of items type'); } + const leftColumn = assertIsDefined(document.getElementById('getting-started-detail-left')); const detailTitle = assertIsDefined(document.getElementById('getting-started-detail-title')); detailTitle.appendChild( $('.getting-started-category', @@ -305,7 +321,7 @@ export class GettingStartedPage extends Disposable { const categoryElements = category.content.items.map( (task, i, arr) => $('button.getting-started-task', { 'x-dispatch': 'selectTask:' + task.id, id: 'getting-started-task-' + task.id }, - $('.codicon' + (task.done ? '.codicon-pass-filled' : '.codicon-circle-large-outline'), { id: 'done-task-' + task.id }), + $('.codicon' + (task.done ? '.complete.codicon-pass-filled' : '.codicon-circle-large-outline'), { id: 'done-task-' + task.id }), $('.task-description-container', {}, $('h3.task-title', {}, task.title), $('.task-description.description', {}, task.description), @@ -325,17 +341,21 @@ export class GettingStartedPage extends Disposable { )) ))); - const detailContainer = assertIsDefined(document.getElementById('getting-started-detail-container')); + const detailContainer = $('#getting-started-detail-container'); + if (this.detailsScrollbar) { this.detailsScrollbar.getDomNode().remove(); this.detailsScrollbar.dispose(); } + this.detailsScrollbar = this._register(new DomScrollableElement(detailContainer, { className: 'full-height-scrollable' })); categoryElements.forEach(element => detailContainer.appendChild(element)); + leftColumn.appendChild(this.detailsScrollbar.getDomNode()); const toExpand = category.content.items.find(item => !item.done) ?? category.content.items[0]; this.selectTask(selectedItem ?? toExpand.id); + this.detailsScrollbar.scanDomNode(); this.registerDispatchListeners(container); } private clearDetialView() { - const detailContainer = assertIsDefined(document.getElementById('getting-started-detail-container')); - while (detailContainer.firstChild) { detailContainer.removeChild(detailContainer.firstChild); } + const detailContainer = (document.getElementById('getting-started-detail-container')); + detailContainer?.remove(); const detailTitle = assertIsDefined(document.getElementById('getting-started-detail-title')); while (detailTitle.firstChild) { detailTitle.removeChild(detailTitle.firstChild); } } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index 245f36dc2ca..73cf66eb70c 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -18,11 +18,11 @@ export default () => `
Back +
-
From d2aebcd2c58c626f9927c95c64c4d501ae105e92 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 16:55:49 -0800 Subject: [PATCH 1059/1837] absolute positioned borders elements --- .../contrib/notebook/browser/diff/common.ts | 12 +++++++++-- .../notebook/browser/diff/diffComponents.ts | 7 +++++++ .../notebook/browser/diff/notebookDiff.css | 20 ++++++++++++++++++ .../browser/diff/notebookTextDiffEditor.ts | 5 ++++- .../browser/diff/notebookTextDiffList.ts | 21 +++++++++++++++++++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/common.ts b/src/vs/workbench/contrib/notebook/browser/diff/common.ts index e8a45767398..987772ddd3d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/common.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/common.ts @@ -42,7 +42,14 @@ export interface IDiffNestedCellViewModel { } -export interface CellDiffSingleSideRenderTemplate { +export interface CellDiffCommonRenderTemplate { + readonly leftBorder: HTMLElement; + readonly rightBorder: HTMLElement; + readonly topBorder: HTMLElement; + readonly bottomBorder: HTMLElement; +} + +export interface CellDiffSingleSideRenderTemplate extends CellDiffCommonRenderTemplate { readonly container: HTMLElement; readonly body: HTMLElement; readonly diffEditorContainer: HTMLElement; @@ -53,10 +60,11 @@ export interface CellDiffSingleSideRenderTemplate { readonly metadataInfoContainer: HTMLElement; readonly outputHeaderContainer: HTMLElement; readonly outputInfoContainer: HTMLElement; + } -export interface CellDiffSideBySideRenderTemplate { +export interface CellDiffSideBySideRenderTemplate extends CellDiffCommonRenderTemplate { readonly container: HTMLElement; readonly body: HTMLElement; readonly diffEditorContainer: HTMLElement; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 2771f8b135b..3d2c5c1176b 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -258,6 +258,7 @@ abstract class AbstractElementRenderer extends Disposable { this._outputEditorDisposeStore = new DisposableStore(); this._register(this._metadataEditorDisposeStore); this._register(cell.onDidLayoutChange(e => this.layout(e))); + this._register(cell.onDidLayoutChange(e => this.updateBorders())); this.buildBody(); } @@ -595,6 +596,12 @@ abstract class AbstractElementRenderer extends Disposable { ); } + updateBorders() { + this.templateData.leftBorder.style.height = `${this.cell.totalHeight - 32}px`; + this.templateData.rightBorder.style.height = `${this.cell.totalHeight - 32}px`; + this.templateData.bottomBorder.style.top = `${this.cell.totalHeight - 32}px`; + } + dispose() { this._isDisposed = true; super.dispose(); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css index ba600aa00c7..687e8282be2 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css @@ -21,6 +21,26 @@ flex-direction: row; } +.notebook-text-diff-editor .cell-body .border-container { + position: absolute; + width: calc(100% - 32px); +} + +.notebook-text-diff-editor .cell-body .border-container .top-border, +.notebook-text-diff-editor .cell-body .border-container .bottom-border { + position: absolute; + width: 100%; +} + +.notebook-text-diff-editor .cell-body .border-container .left-border, +.notebook-text-diff-editor .cell-body .border-container .right-border { + position: absolute; +} + +.notebook-text-diff-editor .cell-body .border-container .right-border { + left: 100%; +} + .notebook-text-diff-editor .cell-body.right { flex-direction: row-reverse; } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index f19a874b806..67c1697c55e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -593,7 +593,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD registerThemingParticipant((theme, collector) => { const cellBorderColor = theme.getColor(notebookCellBorder); if (cellBorderColor) { - collector.addRule(`.notebook-text-diff-editor .cell-body { border: 1px solid ${cellBorderColor};}`); + collector.addRule(`.notebook-text-diff-editor .cell-body .border-container .top-border { border-top: 1px solid ${cellBorderColor};}`); + collector.addRule(`.notebook-text-diff-editor .cell-body .border-container .bottom-border { border-top: 1px solid ${cellBorderColor};}`); + collector.addRule(`.notebook-text-diff-editor .cell-body .border-container .left-border { border-left: 1px solid ${cellBorderColor};}`); + collector.addRule(`.notebook-text-diff-editor .cell-body .border-container .right-border { border-right: 1px solid ${cellBorderColor};}`); collector.addRule(`.notebook-text-diff-editor .cell-diff-editor-container .output-header-container, .notebook-text-diff-editor .cell-diff-editor-container .metadata-header-container { border-top: 1px solid ${cellBorderColor}; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index a879142635a..464e6f083ef 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -148,6 +148,12 @@ export class CellDiffSingleSideRenderer implements IListRenderer Date: Tue, 15 Dec 2020 16:56:18 -0800 Subject: [PATCH 1060/1837] :guard: --- .../contrib/notebook/browser/view/renderers/webviewPreloads.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 6565898f513..a79a6da2443 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -20,7 +20,7 @@ declare module globalThis { }); } -declare var acquireVsCodeApi: () => ({ +declare let acquireVsCodeApi: () => ({ getState(): { [key: string]: unknown; }; setState(data: { [key: string]: unknown; }): void; postMessage: (msg: unknown) => void; From fec4672c27af221bae64904b9e1a1e1a12c75750 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 17:01:22 -0800 Subject: [PATCH 1061/1837] output diff container css class clearing --- .../contrib/notebook/browser/diff/diffComponents.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 3d2c5c1176b..8e87cb20574 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -814,6 +814,10 @@ export class DeletedElement extends SingleSideDiffElement { }); } + if (this._diagonalFill) { + this._diagonalFill.style.height = `${this.cell.totalHeight - 32}px`; + } + this.layoutNotebookCell(); }); } @@ -967,6 +971,7 @@ export class ModifiedElement extends AbstractElementRenderer { buildBody() { const body = this.templateData.body; this._diffEditorContainer = this.templateData.diffEditorContainer; + body.classList.remove('left', 'right', 'full'); switch (this.style) { case 'left': body.classList.add('left'); From 2118388b0e1f4de16f4fc6b9a35efe6bc3f9bef8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 17:12:34 -0800 Subject: [PATCH 1062/1837] two webviews --- .../notebook/browser/diff/diffComponents.ts | 19 ++-- .../browser/diff/notebookTextDiffEditor.ts | 102 ++++++++++-------- .../notebook/browser/notebookEditorWidget.ts | 2 + .../view/renderers/backLayerWebView.ts | 1 - 4 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 8e87cb20574..1b7f3d406de 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -823,17 +823,18 @@ export class DeletedElement extends SingleSideDiffElement { } _buildOutputContainer() { - // this._outputView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell.modified!, this._outputViewContainer!); - // this._outputView.render(); - // this.layout({ outputView: true }); + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, false, this._outputViewContainer!); + this._outputLeftView.render(); + this.cell.layoutChange(); } _showOutputs() { - + this._outputLeftView?.render(); + this.cell.layoutChange(); } _hideOutputs() { - + this._outputLeftView?.hideOutputs(); } } @@ -895,18 +896,18 @@ export class InsertElement extends SingleSideDiffElement { } _buildOutputContainer() { - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputViewContainer!); - this._outputLeftView.render(); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputViewContainer!); + this._outputRightView.render(); this.cell.layoutChange(); } _showOutputs() { - this._outputLeftView?.render(); + this._outputRightView?.render(); this.cell.layoutChange(); } _hideOutputs() { - this._outputLeftView?.hideOutputs(); + this._outputRightView?.hideOutputs(); } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 67c1697c55e..940d1f3dd8e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -57,6 +57,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // private _diffElementViewModels: DiffElementViewModelBase[] = []; private _list!: NotebookTextDiffList; private _modifiedWebview: BackLayerWebView | null = null; + private _originalWebview: BackLayerWebView | null = null; private _webviewTransparentCover: HTMLElement | null = null; private _fontInfo: BareFontInfo | undefined; @@ -206,55 +207,53 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const scrollTop = this._list.scrollTop; const scrollHeight = this._list.scrollHeight; - if (!this._modifiedWebview) { - return; - } + if (this._modifiedWebview) { + this._modifiedWebview!.element.style.height = `${scrollHeight}px`; - this._modifiedWebview!.element.style.height = `${scrollHeight}px`; - - if (this._modifiedWebview?.insetMapping) { - const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; - const removedItems: IDisplayOutputViewModel[] = []; - this._modifiedWebview?.insetMapping.forEach((value, key) => { - const cell = value.cellInfo.diffElement.modified; - if (!cell) { - return; - } - - const viewIndex = this._list.indexOf(value.cellInfo.diffElement); - - if (viewIndex === undefined) { - return; - } - - if (cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId) < 0) { - // output is already gone - removedItems.push(key); - } - - const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); - if (this._modifiedWebview!.shouldUpdateInset(cell, key, cellTop)) { - // TODO: why? does it mean, we create new output view model every time? - const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); - let outputOffset = 0; - if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(false, outputIndex); - } else { - outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + if (this._modifiedWebview?.insetMapping) { + const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; + const removedItems: IDisplayOutputViewModel[] = []; + this._modifiedWebview?.insetMapping.forEach((value, key) => { + const cell = value.cellInfo.diffElement.modified; + if (!cell) { + return; } - updateItems.push({ - output: key, - cellTop: cellTop, - outputOffset: outputOffset - }); + const viewIndex = this._list.indexOf(value.cellInfo.diffElement); + + if (viewIndex === undefined) { + return; + } + + if (cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId) < 0) { + // output is already gone + removedItems.push(key); + } + + const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); + if (this._modifiedWebview!.shouldUpdateInset(cell, key, cellTop)) { + // TODO: why? does it mean, we create new output view model every time? + const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); + let outputOffset = 0; + if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(false, outputIndex); + } else { + outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } + + updateItems.push({ + output: key, + cellTop: cellTop, + outputOffset: outputOffset + }); + } + }); + + removedItems.forEach(output => this._modifiedWebview?.removeInset(output)); + + if (updateItems.length) { + this._modifiedWebview?.updateViewScrollTop(-scrollTop, false, updateItems); } - }); - - removedItems.forEach(output => this._modifiedWebview?.removeInset(output)); - - if (updateItems.length) { - this._modifiedWebview?.updateViewScrollTop(-scrollTop, false, updateItems); } } @@ -311,6 +310,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } })); + await this._createOriginalWebview(generateUuid(), this._model.original.resource); await this._createModifiedWebview(generateUuid(), this._model.modified.resource); this._eventDispatcher = new NotebookDiffEditorEventDispatcher(); @@ -322,9 +322,19 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); await this._modifiedWebview.createWebview(); + this._modifiedWebview.element.style.width = `calc(50%)`; this._modifiedWebview.element.style.left = `calc(50%)`; } + private async _createOriginalWebview(id: string, resource: URI): Promise { + this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource) as BackLayerWebView; + // attach the webview container to the DOM tree first + this._list.rowsContainer.insertAdjacentElement('afterbegin', this._originalWebview.element); + await this._originalWebview.createWebview(); + this._originalWebview.element.style.width = `calc(50%)`; + this._originalWebview.element.style.left = `0`; + } + private async _resolveStats(resource: URI) { if (resource.scheme === Schemas.untitled) { return undefined; @@ -507,6 +517,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } + } else { + } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b69f21df8bb..065966363b2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -903,6 +903,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (!this._webview) { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, this.getId(), this.textModel!.uri); + this._webview.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; this._webview.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; // attach the webview container to the DOM tree first @@ -953,6 +954,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private async _createWebview(id: string, resource: URI): Promise { this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource); + this._webview.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; this._webview.element.style.margin = `0px 0 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px`; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element); 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 c70ac956800..61e743d4a45 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -248,7 +248,6 @@ export class BackLayerWebView extends Disposable { this.element = document.createElement('div'); - this.element.style.width = `calc(100% - ${CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER}px)`; this.element.style.height = '1400px'; this.element.style.position = 'absolute'; } From 1741bbf7e6f6b0b02eb3eab4cce71c39832c74c5 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 15 Dec 2020 17:19:19 -0800 Subject: [PATCH 1063/1837] render deleted output --- .../browser/diff/notebookTextDiffEditor.ts | 19 +++++++++++++++++-- .../browser/diff/notebookTextDiffList.ts | 4 ++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 940d1f3dd8e..9f9b201220e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -331,8 +331,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._originalWebview.element); await this._originalWebview.createWebview(); - this._originalWebview.element.style.width = `calc(50%)`; - this._originalWebview.element.style.left = `0`; + this._originalWebview.element.style.width = `calc(50% - 16px)`; + this._originalWebview.element.style.left = `16px`; } private async _resolveStats(resource: URI) { @@ -518,7 +518,22 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } } else { + if (!this._originalWebview!.insetMapping.has(output.source)) { + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + await this._originalWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, offset); + } else { + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + const scrollTop = this._list.scrollTop; + const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); + let outputOffset = 0; + if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(true, outputIndex); + } else { + outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } + this._originalWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); + } } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts index 464e6f083ef..34447188f77 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts @@ -189,6 +189,8 @@ export class CellDiffSingleSideRenderer implements IListRenderer Date: Tue, 15 Dec 2020 17:21:42 -0800 Subject: [PATCH 1064/1837] hide inset and update layout for the left webview. --- .../browser/diff/notebookTextDiffEditor.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 9f9b201220e..58303b87995 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -257,6 +257,56 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } } + if (this._originalWebview) { + this._originalWebview.element.style.height = `${scrollHeight}px`; + + if (this._originalWebview.insetMapping) { + const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; + const removedItems: IDisplayOutputViewModel[] = []; + this._originalWebview.insetMapping.forEach((value, key) => { + const cell = value.cellInfo.diffElement.modified; + if (!cell) { + return; + } + + const viewIndex = this._list.indexOf(value.cellInfo.diffElement); + + if (viewIndex === undefined) { + return; + } + + if (cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId) < 0) { + // output is already gone + removedItems.push(key); + } + + const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); + if (this._originalWebview!.shouldUpdateInset(cell, key, cellTop)) { + // TODO: why? does it mean, we create new output view model every time? + const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); + let outputOffset = 0; + if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { + outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(true, outputIndex); + } else { + outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + } + + updateItems.push({ + output: key, + cellTop: cellTop, + outputOffset: outputOffset + }); + } + }); + + removedItems.forEach(output => this._originalWebview?.removeInset(output)); + + if (updateItems.length) { + this._originalWebview?.updateViewScrollTop(-scrollTop, false, updateItems); + } + } + } + }); })); } @@ -548,6 +598,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IDisplayOutputViewModel) { this._modifiedWebview?.hideInset(output); + this._originalWebview?.hideInset(output); } // private async _resolveWebview(rightEditor: boolean): Promise { From 8a2ec350bd99e059ee9a179c721187f31b503e8b Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 15 Dec 2020 17:44:35 -0800 Subject: [PATCH 1065/1837] Restore terminal UI state and layout when reconnecting to remote terminals Fix microsoft/vscode#109244 Co-authored-by: Megan Rogge --- .../terminal/browser/remoteTerminalService.ts | 22 ++++- .../contrib/terminal/browser/terminal.ts | 16 +++- .../terminal/browser/terminalInstance.ts | 2 + .../browser/terminalProcessManager.ts | 11 ++- .../terminal/browser/terminalService.ts | 94 ++++++++++++++----- .../contrib/terminal/browser/terminalTab.ts | 61 +++++++++--- .../terminal/common/remoteTerminalChannel.ts | 31 +++++- .../contrib/terminal/common/terminal.ts | 28 +++++- 8 files changed, 219 insertions(+), 46 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts index d380061ddaf..b2b5ec36d29 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts @@ -15,7 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ILogService } from 'vs/platform/log/common/log'; import { IRemoteTerminalService, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IRemoteTerminalProcessExecCommandEvent, IShellLaunchConfigDto, RemoteTerminalChannelClient, REMOTE_TERMINAL_CHANNEL_NAME } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; -import { IProcessDataEvent, IRemoteTerminalAttachTarget, IShellLaunchConfig, ITerminalChildProcess, ITerminalConfigHelper, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IProcessDataEvent, IRemoteTerminalAttachTarget, IShellLaunchConfig, ITerminalChildProcess, ITerminalConfigHelper, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById } from 'vs/workbench/contrib/terminal/common/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; export class RemoteTerminalService extends Disposable implements IRemoteTerminalService { @@ -69,6 +69,22 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal }; }); } + + public setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { + if (!this._remoteTerminalChannel) { + throw new Error(`Cannot call setActiveInstanceId when there is no remote`); + } + + return this._remoteTerminalChannel.setTerminalLayoutInfo(layout); + } + + public getTerminalLayoutInfo(): Promise { + if (!this._remoteTerminalChannel) { + throw new Error(`Cannot call getActiveInstanceId when there is no remote`); + } + + return this._remoteTerminalChannel.getTerminalLayoutInfo(); + } } export class RemoteTerminalProcess extends Disposable implements ITerminalChildProcess { @@ -115,7 +131,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP } } - public async start(): Promise { + public async start(): Promise { // Fetch the environment to check shell permissions const env = await this._remoteAgentService.getEnvironment(); if (!env) { @@ -166,7 +182,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP } this._startBarrier.open(); - return undefined; + return { remoteTerminalId: this._remoteTerminalId }; } public shutdown(immediate: boolean): void { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 1f58d65eab4..cdf55b05fb5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -7,7 +7,7 @@ import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; -import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig, IDefaultShellAndArgsRequest, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, ITerminalProcessExtHostProxy, ICommandTracker, INavigationMode, TitleEventSource, ITerminalDimensions, ITerminalLaunchError, ITerminalNativeWindowsDelegate, LinuxDistro, IRemoteTerminalAttachTarget } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig, IDefaultShellAndArgsRequest, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, ITerminalProcessExtHostProxy, ICommandTracker, INavigationMode, TitleEventSource, ITerminalDimensions, ITerminalLaunchError, ITerminalNativeWindowsDelegate, LinuxDistro, IRemoteTerminalAttachTarget, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ITerminalTabLayoutInfoById } from 'vs/workbench/contrib/terminal/common/terminal'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IProcessEnvironment, Platform } from 'vs/base/common/platform'; import { Event } from 'vs/base/common/event'; @@ -58,16 +58,17 @@ export interface ITerminalTab { title: string; onDisposed: Event; onInstancesChanged: Event; - focusPreviousPane(): void; focusNextPane(): void; resizePane(direction: Direction): void; + resizePanes(relativeSizes: number[]): void; setActiveInstanceByIndex(index: number): void; attachToElement(element: HTMLElement): void; setVisible(visible: boolean): void; layout(width: number, height: number): void; addDisposable(disposable: IDisposable): void; split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance; + getLayoutInfo(isActive: boolean): ITerminalTabLayoutInfoById; } export const enum TerminalConnectionState { @@ -186,11 +187,12 @@ export interface ITerminalService { export interface IRemoteTerminalService { readonly _serviceBrand: undefined; - dispose(): void; - listTerminals(isInitialization?: boolean): Promise; createRemoteTerminalProcess(terminalId: number, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, configHelper: ITerminalConfigHelper,): Promise; + + setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise; + getTerminalLayoutInfo(): Promise; } /** @@ -261,6 +263,12 @@ export interface ITerminalInstance { */ processId: number | undefined; + /** + * The id of a terminal on the remote server. Defined if this is a terminal created + * by the RemoteTerminalService. + */ + readonly remoteTerminalId: number | undefined; + /** * An event that fires when the terminal instance's title changes. */ diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 9303f7bdb70..8ef61e3bbe0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -369,6 +369,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return TerminalInstance._lastKnownCanvasDimensions; } + public get remoteTerminalId(): number | undefined { return this._processManager.remoteTerminalId; } + private async _getXtermConstructor(): Promise { if (xtermConstructor) { return xtermConstructor; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 5fbf29637ba..043a6e04af7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -83,6 +83,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce public get onEnvironmentVariableInfoChanged(): Event { return this._onEnvironmentVariableInfoChange.event; } public get environmentVariableInfo(): IEnvironmentVariableInfo | undefined { return this._environmentVariableInfo; } + private _remoteTerminalId: number | undefined; + public get remoteTerminalId(): number | undefined { return this._remoteTerminalId; } constructor( private readonly _terminalId: number, @@ -208,9 +210,12 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } }, LAUNCHING_DURATION); - const error = await this._process.start(); - if (error) { - return error; + const result = await this._process.start(); + if (result && 'remoteTerminalId' in result) { + this._remoteTerminalId = result.remoteTerminalId; + } else if (result) { + // Error + return result; } return undefined; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 83b4cf26c03..6290797c7dc 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { timeout } from 'vs/base/common/async'; +import { debounce } from 'vs/base/common/decorators'; import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { basename } from 'vs/base/common/path'; @@ -17,14 +18,13 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IPickOptions, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { TerminalConnectionState, IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalTab, TerminalShellType, WindowsShellType } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView'; -import { IAvailableShellsRequest, IRemoteTerminalAttachTarget, IShellDefinition, IShellLaunchConfig, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalLaunchError, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, LinuxDistro, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IAvailableShellsRequest, IRemoteTerminalAttachTarget, IShellDefinition, IShellLaunchConfig, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalLaunchError, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, ITerminalsLayoutInfoById, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, LinuxDistro, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -117,8 +117,7 @@ export class TerminalService implements ITerminalService { @IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, @IRemoteTerminalService private readonly _remoteTerminalService: IRemoteTerminalService, - @ITelemetryService private readonly _telemetryService: ITelemetryService, - @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService + @ITelemetryService private readonly _telemetryService: ITelemetryService ) { this._activeTabIndex = 0; this._isShuttingDown = false; @@ -135,7 +134,6 @@ export class TerminalService implements ITerminalService { this._onActiveInstanceChanged.fire(instance ? instance : undefined); }); this.onInstanceLinksReady(instance => this._setInstanceLinkProviders(instance)); - this._handleInstanceContextKeys(); this._processSupportContextKey = KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED.bindTo(this._contextKeyService); this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null); @@ -147,36 +145,74 @@ export class TerminalService implements ITerminalService { this._connectionState = TerminalConnectionState.Connecting; } else { this._connectionState = TerminalConnectionState.Connected; + this.attachRemoteListeners(); } } private async _reconnectToRemoteTerminals(): Promise { - const remoteTerms = await this._remoteTerminalService.listTerminals(true); - const workspace = this._workspaceContextService.getWorkspace(); - const unattachedWorkspaceRemoteTerms = remoteTerms - .filter(term => term.workspaceId === workspace.id) - .filter(term => !this.isAttachedToTerminal(term)); - + // Reattach to all remote terminals + const layoutInfo = await this._remoteTerminalService.getTerminalLayoutInfo(); + let reconnectCounter = 0; + let activeTab: ITerminalTab | undefined; + if (layoutInfo) { + layoutInfo.tabs.forEach((tabLayout) => { + const terminalLayouts = tabLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan); + if (terminalLayouts.length) { + reconnectCounter += terminalLayouts.length; + let terminalInstance: ITerminalInstance | undefined; + let tab: ITerminalTab | undefined; + terminalLayouts.forEach((terminalLayout) => { + if (!terminalInstance) { + // create tab and terminal + terminalInstance = this.createTerminal({ remoteAttach: terminalLayout.terminal! }); + tab = this._getTabForInstance(terminalInstance); + if (tabLayout.isActive) { + activeTab = tab; + } + } else { + // add split terminals to this tab + this.splitInstance(terminalInstance, { remoteAttach: terminalLayout.terminal! }); + } + }); + const activeInstance = this.terminalInstances.find(t => t.shellLaunchConfig.remoteAttach?.pid === tabLayout.activeTerminalProcessId); + if (activeInstance) { + this.setActiveInstance(activeInstance); + } + tab?.resizePanes(tabLayout.terminals.map(terminal => terminal.relativeSize)); + } + }); + if (layoutInfo.tabs.length) { + this.setActiveTabByIndex(activeTab ? this.terminalTabs.indexOf(activeTab) : 0); + } + } /* __GDPR__ "terminalReconnection" : { "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ const data = { - count: unattachedWorkspaceRemoteTerms.length + count: reconnectCounter }; this._telemetryService.publicLog('terminalReconnection', data); - if (unattachedWorkspaceRemoteTerms.length > 0) { - // Reattach to all remote terminals - for (let term of unattachedWorkspaceRemoteTerms) { - this.createTerminal({ remoteAttach: term }); - } - } - this._connectionState = TerminalConnectionState.Connected; + // now that terminals have been restored, + // attach listeners to update remote when terminals are changed + this.attachRemoteListeners(); this._onDidChangeConnectionState.fire(); } + private attachRemoteListeners(): void { + this.onActiveTabChanged(() => { + this._updateRemoteState(); + }); + this.onActiveInstanceChanged(() => { + this._updateRemoteState(); + }); + this.onInstancesChanged(() => { + this._updateRemoteState(); + }); + } + public setNativeWindowsDelegate(delegate: ITerminalNativeWindowsDelegate): void { this._nativeWindowsDelegate = delegate; } @@ -253,7 +289,7 @@ export class TerminalService implements ITerminalService { } private async _onBeforeShutdownAsync(): Promise { - // veto if configured to show confirmation and the user choosed not to exit + // veto if configured to show confirmation and the user chose not to exit const veto = await this._showTerminalCloseConfirmation(); if (!veto) { this._isShuttingDown = true; @@ -274,6 +310,16 @@ export class TerminalService implements ITerminalService { return this._findState; } + @debounce(500) + private _updateRemoteState(): void { + if (!!this._environmentService.remoteAuthority) { + const state: ITerminalsLayoutInfoById = { + tabs: this.terminalTabs.map(t => t.getLayoutInfo(t === this.getActiveTab())) + }; + this._remoteTerminalService.setTerminalLayoutInfo(state); + } + } + private _removeTab(tab: ITerminalTab): void { // Get the index of the tab and remove it from the list const index = this._terminalTabs.indexOf(tab); @@ -467,6 +513,7 @@ export class TerminalService implements ITerminalService { } const instance = tab.split(shellLaunchConfig); + this._initInstanceListeners(instance); this._onInstancesChanged.fire(); @@ -479,7 +526,10 @@ export class TerminalService implements ITerminalService { instance.addDisposable(instance.onTitleChanged(this._onInstanceTitleChanged.fire, this._onInstanceTitleChanged)); instance.addDisposable(instance.onProcessIdReady(this._onInstanceProcessIdReady.fire, this._onInstanceProcessIdReady)); instance.addDisposable(instance.onLinksReady(this._onInstanceLinksReady.fire, this._onInstanceLinksReady)); - instance.addDisposable(instance.onDimensionsChanged(() => this._onInstanceDimensionsChanged.fire(instance))); + instance.addDisposable(instance.onDimensionsChanged(() => { + this._onInstanceDimensionsChanged.fire(instance); + this._updateRemoteState(); + })); instance.addDisposable(instance.onMaximumDimensionsChanged(() => this._onInstanceMaximumDimensionsChanged.fire(instance))); instance.addDisposable(instance.onFocus(this._onActiveInstanceChanged.fire, this._onActiveInstanceChanged)); } @@ -746,7 +796,7 @@ export class TerminalService implements ITerminalService { } } - public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { + public async setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): Promise { this._configHelper.panelContainer = panelContainer; this._terminalContainer = terminalContainer; this._terminalTabs.forEach(tab => tab.attachToElement(terminalContainer)); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts index 6e8e1f58dad..740a03e3662 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IShellLaunchConfig, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalTabLayoutInfoById, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview'; @@ -100,6 +100,22 @@ class SplitPaneContainer extends Disposable { } } + public resizePanes(relativeSizes: number[]): void { + if (this._children.length <= 1) { + return; + } + + // assign any extra size to last terminal + relativeSizes[relativeSizes.length - 1] += 1 - relativeSizes.reduce((totalValue, currentValue) => totalValue + currentValue, 0); + let totalSize = 0; + for (let i = 0; i < this._splitView.length; i++) { + totalSize += this._splitView.getViewSize(i); + } + for (let i = 0; i < this._splitView.length; i++) { + this._splitView.resizeView(i, totalSize * relativeSizes[i]); + } + } + private _addChild(instance: ITerminalInstance, index: number): void { const child = new SplitPane(instance, this.orientation === Orientation.HORIZONTAL ? this._height : this._width); child.orientation = this.orientation; @@ -212,6 +228,7 @@ class SplitPane implements IView { export class TerminalTab extends Disposable implements ITerminalTab { private _terminalInstances: ITerminalInstance[] = []; private _splitPaneContainer: SplitPaneContainer | undefined; + private get splitPaneContainer(): SplitPaneContainer | undefined { return this._splitPaneContainer; } private _tabElement: HTMLElement | undefined; private _panelPosition: Position = Position.BOTTOM; private _terminalLocation: ViewContainerLocation = ViewContainerLocation.Panel; @@ -221,11 +238,12 @@ export class TerminalTab extends Disposable implements ITerminalTab { public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } + private _initialRelativeSizes: number[] | undefined; + private readonly _onDisposed: Emitter = this._register(new Emitter()); public readonly onDisposed: Event = this._onDisposed.event; private readonly _onInstancesChanged: Emitter = this._register(new Emitter()); public readonly onInstancesChanged: Event = this._onInstancesChanged.event; - constructor( private _container: HTMLElement | undefined, shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance | undefined, @@ -235,13 +253,10 @@ export class TerminalTab extends Disposable implements ITerminalTab { @IInstantiationService private readonly _instantiationService: IInstantiationService ) { super(); - if (shellLaunchConfigOrInstance) { this.addInstance(shellLaunchConfigOrInstance); } - this._activeInstanceIndex = 0; - if (this._container) { this.attachToElement(this._container); } @@ -281,6 +296,22 @@ export class TerminalTab extends Disposable implements ITerminalTab { return this._terminalInstances[this._activeInstanceIndex]; } + public getLayoutInfo(isActive: boolean): ITerminalTabLayoutInfoById { + const isHorizontal = this.splitPaneContainer?.orientation === Orientation.HORIZONTAL; + const remoteInstances = this.terminalInstances.filter(instance => typeof instance.remoteTerminalId === 'number'); + const totalSize = remoteInstances.map(instance => isHorizontal ? instance.cols : instance.rows).reduce((totalValue, currentValue) => totalValue + currentValue, 0); + return { + isActive: isActive, + activeTerminalProcessId: this.activeInstance?.processId || 0, + terminals: remoteInstances.map(t => { + return { + relativeSize: isHorizontal ? t.cols / totalSize : t.rows / totalSize, + terminal: t.remoteTerminalId! + }; + }) + }; + } + private _initInstanceListeners(instance: ITerminalInstance): void { instance.addDisposable(instance.onDisposed(instance => this._onInstanceDisposed(instance))); instance.addDisposable(instance.onFocused(instance => this._setActiveInstance(instance))); @@ -366,7 +397,6 @@ export class TerminalTab extends Disposable implements ITerminalTab { this._splitPaneContainer = newLocal; this.terminalInstances.forEach(instance => this._splitPaneContainer!.split(instance)); } - this.setVisible(this._isVisible); } @@ -389,10 +419,6 @@ export class TerminalTab extends Disposable implements ITerminalTab { } public split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { - if (!this._container) { - throw new Error('Cannot split terminal that has not been attached'); - } - const instance = this._terminalService.createInstance(undefined, shellLaunchConfig); this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance); this._initInstanceListeners(instance); @@ -415,15 +441,17 @@ export class TerminalTab extends Disposable implements ITerminalTab { const newPanelPosition = this._layoutService.getPanelPosition(); const newTerminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID)!; const terminalPositionChanged = newPanelPosition !== this._panelPosition || newTerminalLocation !== this._terminalLocation; - if (terminalPositionChanged) { const newOrientation = newTerminalLocation === ViewContainerLocation.Panel && newPanelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL; this._splitPaneContainer.setOrientation(newOrientation); this._panelPosition = newPanelPosition; this._terminalLocation = newTerminalLocation; } - this._splitPaneContainer.layout(width, height); + if (this._initialRelativeSizes && height > 0 && width > 0) { + this.resizePanes(this._initialRelativeSizes); + this._initialRelativeSizes = undefined; + } } } @@ -450,4 +478,13 @@ export class TerminalTab extends Disposable implements ITerminalTab { this._splitPaneContainer.resizePane(this._activeInstanceIndex, direction, amount); } } + + public resizePanes(relativeSizes: number[]): void { + if (!this._splitPaneContainer) { + this._initialRelativeSizes = relativeSizes; + return; + } + + this._splitPaneContainer.resizePanes(relativeSizes); + } } diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index d25b3982fcc..af860fc269f 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -13,7 +13,7 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared'; -import { ITerminalConfiguration, ITerminalEnvironment, ITerminalLaunchError, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IRawTerminalTabLayoutInfo, ITerminalConfiguration, ITerminalEnvironment, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ITerminalTabLayoutInfoById, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { SideBySideEditor, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -128,6 +128,15 @@ export interface IListTerminalsArgs { isInitialization: boolean; } +export interface ISetTerminalLayoutInfoArgs { + workspaceId: string; + tabs: ITerminalTabLayoutInfoById[]; +} + +export interface IGetTerminalLayoutInfoArgs { + workspaceId: string; +} + export interface IRemoteTerminalDescriptionDto { id: number; pid: number; @@ -135,8 +144,11 @@ export interface IRemoteTerminalDescriptionDto { cwd: string; workspaceId: string; workspaceName: string; + isOrphan: boolean; } +export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo; + export interface ITriggerTerminalDataReplayArguments { id: number; } @@ -362,4 +374,21 @@ export class RemoteTerminalChannelClient { }; return this._channel.call('$listTerminals', args); } + + public setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { + const workspace = this._workspaceContextService.getWorkspace(); + const args: ISetTerminalLayoutInfoArgs = { + workspaceId: workspace.id, + tabs: layout.tabs + }; + return this._channel.call('$setTerminalLayoutInfo', args); + } + + public getTerminalLayoutInfo(): Promise { + const workspace = this._workspaceContextService.getWorkspace(); + const args: IGetTerminalLayoutInfoArgs = { + workspaceId: workspace.id, + }; + return this._channel.call('$getTerminalLayoutInfo', args); + } } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index c852d4e7306..f7768934872 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -180,8 +180,33 @@ export interface IRemoteTerminalAttachTarget { cwd: string; workspaceId: string; workspaceName: string; + isOrphan: boolean; } +export interface IRawTerminalInstanceLayoutInfo { + relativeSize: number; + terminal: T; +} + +export type ITerminalInstanceLayoutInfoById = IRawTerminalInstanceLayoutInfo; +export type ITerminalInstanceLayoutInfo = IRawTerminalInstanceLayoutInfo; + +export interface IRawTerminalTabLayoutInfo { + isActive: boolean; + activeTerminalProcessId: number; + terminals: IRawTerminalInstanceLayoutInfo[]; +} + +export type ITerminalTabLayoutInfoById = IRawTerminalTabLayoutInfo; +export type ITerminalTabLayoutInfo = IRawTerminalTabLayoutInfo; + +export interface IRawTerminalsLayoutInfo { + tabs: IRawTerminalTabLayoutInfo[]; +} + +export type ITerminalsLayoutInfo = IRawTerminalsLayoutInfo; +export type ITerminalsLayoutInfoById = IRawTerminalsLayoutInfo; + export interface IShellLaunchConfig { /** * The name of the terminal, if this is not set the name of the process will be used. @@ -339,6 +364,7 @@ export interface ITerminalProcessManager extends IDisposable { readonly os: OperatingSystem | undefined; readonly userHome: string | undefined; readonly environmentVariableInfo: IEnvironmentVariableInfo | undefined; + readonly remoteTerminalId: number | undefined; readonly onProcessReady: Event; readonly onBeforeProcessData: Event; @@ -469,7 +495,7 @@ export interface ITerminalChildProcess { * @returns undefined when the process was successfully started, otherwise an object containing * information on what went wrong. */ - start(): Promise; + start(): Promise; /** * Shutdown the terminal process. From ede8d447025f8b9324ac763993f1bb83c244199f Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 15 Dec 2020 17:46:35 -0800 Subject: [PATCH 1066/1837] Bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2cfa4597017..f068244ef7e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "76f83677fb51b70361bf5d0e77f18a09ed4be467", + "distro": "7c432813adc9777bc766d47b318dc1e7fff5b91a", "author": { "name": "Microsoft Corporation" }, From 083d38475c9b464a93a25ea71632fc9095f98ed1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 16 Dec 2020 07:55:43 +0100 Subject: [PATCH 1067/1837] Tab bar not rendered on first load of only a welcome editor (fix #112618) --- .../browser/parts/editor/tabsTitleControl.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 556e4ffecbe..151a462bd75 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1276,22 +1276,21 @@ export class TabsTitleControl extends TitleControl { layout(dimensions: ITitleControlDimensions): Dimension { this.dimensions = dimensions; - // We need an opened editor and dimensions to layout the title - // Otherwise quickly return from the layout algorithm - const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; - if (!activeTabAndIndex || dimensions.container === Dimension.None || dimensions.available === Dimension.None) { - return Dimension.None; - } - // The layout of tabs can be an expensive operation because we access DOM properties // that can result in the browser doing a full page layout to validate them. To buffer // this a little bit we try at least to schedule this work on the next animation frame. if (!this.layoutScheduled.value) { - this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { - this.doLayout(this.dimensions); - this.layoutScheduled.clear(); - }); + // We need an opened editor and dimensions to layout the title, + // otherwise we skip the layout call until we have opened editors + const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; + if (activeTabAndIndex && dimensions.container !== Dimension.None && dimensions.available !== Dimension.None) { + this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { + this.doLayout(this.dimensions); + + this.layoutScheduled.clear(); + }); + } } return new Dimension(dimensions.container.width, this.getDimensions().height); From 3229991032ca6fb0aeeb9e3afeb98db98fdb9fb3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 16 Dec 2020 08:09:18 +0100 Subject: [PATCH 1068/1837] :lipstick: --- .../browser/parts/editor/tabsTitleControl.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 151a462bd75..d732fc3e77f 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1280,17 +1280,11 @@ export class TabsTitleControl extends TitleControl { // that can result in the browser doing a full page layout to validate them. To buffer // this a little bit we try at least to schedule this work on the next animation frame. if (!this.layoutScheduled.value) { + this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { + this.doLayout(this.dimensions); - // We need an opened editor and dimensions to layout the title, - // otherwise we skip the layout call until we have opened editors - const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; - if (activeTabAndIndex && dimensions.container !== Dimension.None && dimensions.available !== Dimension.None) { - this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { - this.doLayout(this.dimensions); - - this.layoutScheduled.clear(); - }); - } + this.layoutScheduled.clear(); + }); } return new Dimension(dimensions.container.width, this.getDimensions().height); @@ -1298,8 +1292,8 @@ export class TabsTitleControl extends TitleControl { private doLayout(dimensions: ITitleControlDimensions): void { const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined; - if (!activeTabAndIndex) { - return; // nothing to do if not editor opened + if (!activeTabAndIndex || dimensions.container === Dimension.None || dimensions.available === Dimension.None) { + return; // nothing to do if not editor opened or we got no dimensions yet } // Breadcrumbs From d833f8bc10dcec87a9a71e1c602c55975792f721 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 16 Dec 2020 08:46:04 +0100 Subject: [PATCH 1069/1837] quick pick - use Alt as modifier to open to side --- .../codeEditor/browser/quickaccess/gotoLineQuickAccess.ts | 4 ++-- .../codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts | 4 ++-- .../workbench/contrib/search/browser/anythingQuickAccess.ts | 4 ++-- src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index 67115614768..99417655a68 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -44,12 +44,12 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use - if ((options.keyMods.ctrlCmd || (this.configuration.openEditorPinned && options.keyMods.alt) || options.forceSideBySide) && this.editorService.activeEditor) { + if ((options.keyMods.alt || (this.configuration.openEditorPinned && options.keyMods.ctrlCmd) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor this.editorService.openEditor(this.editorService.activeEditor, { selection: options.range, - pinned: options.keyMods.alt || this.configuration.openEditorPinned, + pinned: options.keyMods.ctrlCmd || this.configuration.openEditorPinned, preserveFocus: options.preserveFocus }, SIDE_GROUP); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 6a3c2d9b1f0..427116923a6 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -67,12 +67,12 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void { // Check for sideBySide use - if ((options.keyMods.ctrlCmd || (this.configuration.openEditorPinned && options.keyMods.alt) || options.forceSideBySide) && this.editorService.activeEditor) { + if ((options.keyMods.alt || (this.configuration.openEditorPinned && options.keyMods.ctrlCmd) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor this.editorService.openEditor(this.editorService.activeEditor, { selection: options.range, - pinned: options.keyMods.alt || this.configuration.openEditorPinned, + pinned: options.keyMods.ctrlCmd || this.configuration.openEditorPinned, preserveFocus: options.preserveFocus }, SIDE_GROUP); } diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 28ac3519150..4bf8fee7aeb 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -932,11 +932,11 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { const editorOptions: ITextEditorOptions = { preserveFocus: options.preserveFocus, - pinned: options.keyMods?.alt || options.forcePinned || this.configuration.openEditorPinned, + pinned: options.keyMods?.ctrlCmd || options.forcePinned || this.configuration.openEditorPinned, selection: options.range ? Range.collapseToStart(options.range) : undefined }; - const targetGroup = options.keyMods?.ctrlCmd || (this.configuration.openEditorPinned && options.keyMods?.alt) || options.forceOpenSideBySide ? SIDE_GROUP : ACTIVE_GROUP; + const targetGroup = options.keyMods?.alt || (this.configuration.openEditorPinned && options.keyMods?.ctrlCmd) || options.forceOpenSideBySide ? SIDE_GROUP : ACTIVE_GROUP; // Restore any view state if the target is the side group if (targetGroup === SIDE_GROUP) { diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index 3038dd70630..e55526fa230 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -248,10 +248,10 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider Date: Wed, 16 Dec 2020 09:22:04 +0100 Subject: [PATCH 1070/1837] debug: preserve focus in editor when integrated terminal is shown so match debug console behavior and to make sense for accessibility fyi @weinand --- src/vs/workbench/api/node/extHostDebugService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index ff76f109b68..992c637770b 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -104,7 +104,7 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase { cwdForPrepareCommand = args.cwd; } - terminal.show(); + terminal.show(true); const shellProcessId = await terminal.processId; From 20920160792a10b8aa0328af598b23c923293028 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 10:00:42 +0100 Subject: [PATCH 1071/1837] don't show loader stats in perf view editor anymore --- .../performance/browser/perfviewEditor.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index fe06a15dfe7..93974d117c3 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -132,8 +132,8 @@ class PerfModelContentProvider implements ITextModelContentProvider { md.blank(); this._addRawPerfMarks(md); md.blank(); - this._addLoaderStats(md, stats); - md.blank(); + // this._addLoaderStats(md, stats); + // md.blank(); this._addCachedDataStats(md); this._model.setValue(md.value); @@ -238,20 +238,20 @@ class PerfModelContentProvider implements ITextModelContentProvider { } } - private _addLoaderStats(md: MarkdownBuilder, stats: LoaderStats): void { - md.heading(2, 'Loader Stats'); - md.heading(3, 'Load AMD-module'); - md.table(['Module', 'Duration'], stats.amdLoad); - md.blank(); - md.heading(3, 'Load commonjs-module'); - md.table(['Module', 'Duration'], stats.nodeRequire); - md.blank(); - md.heading(3, 'Invoke AMD-module factory'); - md.table(['Module', 'Duration'], stats.amdInvoke); - md.blank(); - md.heading(3, 'Invoke commonjs-module'); - md.table(['Module', 'Duration'], stats.nodeEval); - } + // private _addLoaderStats(md: MarkdownBuilder, stats: LoaderStats): void { + // md.heading(2, 'Loader Stats'); + // md.heading(3, 'Load AMD-module'); + // md.table(['Module', 'Duration'], stats.amdLoad); + // md.blank(); + // md.heading(3, 'Load commonjs-module'); + // md.table(['Module', 'Duration'], stats.nodeRequire); + // md.blank(); + // md.heading(3, 'Invoke AMD-module factory'); + // md.table(['Module', 'Duration'], stats.amdInvoke); + // md.blank(); + // md.heading(3, 'Invoke commonjs-module'); + // md.table(['Module', 'Duration'], stats.nodeEval); + // } private _addCachedDataStats(md: MarkdownBuilder): void { From 2f8dee4d87cf215fd2ece45aa4ecfb097b345788 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 16 Dec 2020 10:27:52 +0100 Subject: [PATCH 1072/1837] Add logging for calls of `process.exit` in the extension host --- .../api/common/extHostExtensionService.ts | 8 +++++++- .../extensions/common/extensionHostMain.ts | 19 +++++++++++++------ .../node/extensionHostProcessSetup.ts | 14 +++++++------- .../extensions/worker/extensionHostWorker.ts | 6 +++--- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 812a850c7e5..d606324e05a 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -51,7 +51,7 @@ export const IHostUtils = createDecorator('IHostUtils'); export interface IHostUtils { readonly _serviceBrand: undefined; - exit(code?: number): void; + exit(code: number): void; exists(path: string): Promise; realpath(path: string): Promise; } @@ -610,11 +610,17 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } private _testRunnerExit(code: number): void { + this._logService.info(`extension host terminating: test runner requested exit with code ${code}`); + this._logService.flush(); + // wait at most 5000ms for the renderer to confirm our exit request and for the renderer socket to drain // (this is to ensure all outstanding messages reach the renderer) const exitPromise = this._mainThreadExtensionsProxy.$onExtensionHostExit(code); const drainPromise = this._extHostContext.drain(); Promise.race([Promise.all([exitPromise, drainPromise]), timeout(5000)]).then(() => { + this._logService.info(`exiting with code ${code}`); + this._logService.flush(); + this._hostUtils.exit(code); }); } diff --git a/src/vs/workbench/services/extensions/common/extensionHostMain.ts b/src/vs/workbench/services/extensions/common/extensionHostMain.ts index 3590d05969f..1f338fd0142 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostMain.ts @@ -37,6 +37,7 @@ export class ExtensionHostMain { private _isTerminating: boolean; private readonly _hostUtils: IHostUtils; private readonly _extensionService: IExtHostExtensionService; + private readonly _logService: ILogService; private readonly _disposables = new DisposableStore(); constructor( @@ -65,12 +66,11 @@ export class ExtensionHostMain { const terminalService = instaService.invokeFunction(accessor => accessor.get(IExtHostTerminalService)); this._disposables.add(terminalService); - const logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); - this._disposables.add(logService); + this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); performance.mark(`extHost/didCreateServices`); - logService.info('extension host started'); - logService.trace('initData', initData); + this._logService.info('extension host started'); + this._logService.trace('initData', initData); // ugly self - inject // must call initialize *after* creating the extension service @@ -112,12 +112,14 @@ export class ExtensionHostMain { }); } - terminate(): void { + terminate(reason: string): void { if (this._isTerminating) { // we are already shutting down... return; } this._isTerminating = true; + this._logService.info(`extension host terminating: ${reason}`); + this._logService.flush(); this._disposables.dispose(); @@ -129,7 +131,12 @@ export class ExtensionHostMain { // Give extensions 1 second to wrap up any async dispose, then exit in at most 4 seconds setTimeout(() => { - Promise.race([timeout(4000), extensionsDeactivated]).finally(() => this._hostUtils.exit()); + Promise.race([timeout(4000), extensionsDeactivated]).finally(() => { + this._logService.info(`exiting with code 0`); + this._logService.flush(); + this._logService.dispose(); + this._hostUtils.exit(0); + }); }, 1000); } diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index 0e5e8e3d23f..dc41f93c46c 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -93,7 +93,7 @@ interface IRendererConnection { // This calls exit directly in case the initialization is not finished and we need to exit // Otherwise, if initialization completed we go to extensionHostMain.terminate() -let onTerminate = function () { +let onTerminate = function (reason: string) { nativeExit(); }; @@ -110,8 +110,8 @@ function _createExtHostProtocol(): Promise { const reconnectionGraceTime = ProtocolConstants.ReconnectionGraceTime; const reconnectionShortGraceTime = ProtocolConstants.ReconnectionShortGraceTime; - const disconnectRunner1 = new RunOnceScheduler(() => onTerminate(), reconnectionGraceTime); - const disconnectRunner2 = new RunOnceScheduler(() => onTerminate(), reconnectionShortGraceTime); + const disconnectRunner1 = new RunOnceScheduler(() => onTerminate('renderer disconnected for too long (1)'), reconnectionGraceTime); + const disconnectRunner2 = new RunOnceScheduler(() => onTerminate('renderer disconnected for too long (2)'), reconnectionShortGraceTime); process.on('message', (msg: IExtHostSocketMessage | IExtHostReduceGraceTimeMessage, handle: net.Socket) => { if (msg && msg.type === 'VSCODE_EXTHOST_IPC_SOCKET') { @@ -131,7 +131,7 @@ function _createExtHostProtocol(): Promise { } else { clearTimeout(timer); protocol = new PersistentProtocol(socket, initialDataChunk); - protocol.onDidDispose(() => onTerminate()); + protocol.onDidDispose(() => onTerminate('renderer disconnected')); resolve(protocol); // Wait for rich client to reconnect @@ -192,7 +192,7 @@ async function createExtHostProtocol(): Promise { protocol.onMessage((msg) => { if (isMessageOfType(msg, MessageType.Terminate)) { this._terminating = true; - onTerminate(); + onTerminate('received terminate message from renderer'); } else { this._onMessage.fire(msg); } @@ -268,7 +268,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise { ); // rewrite onTerminate-function to be a proper shutdown - onTerminate = () => extensionHostMain.terminate(); + onTerminate = (reason: string) => extensionHostMain.terminate(reason); } diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 72607f084db..1c71288b6fb 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -111,7 +111,7 @@ class ExtensionWorker { if (isMessageOfType(msg, MessageType.Terminate)) { // handle terminate-message right here terminating = true; - onTerminate(); + onTerminate('received terminate message from renderer'); return; } @@ -147,7 +147,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise nativeClose(); (function create(): void { const res = new ExtensionWorker(); @@ -161,6 +161,6 @@ let onTerminate = nativeClose; null, ); - onTerminate = () => extHostMain.terminate(); + onTerminate = (reason: string) => extHostMain.terminate(reason); }); })(); From 77221e5f604222acef4a6c31ba42440c7206701c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 10:53:43 +0100 Subject: [PATCH 1073/1837] Allow strings as host name for port forwarding --- .../workbench/services/remote/common/remoteExplorerService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index ceddc7e961e..4bdcfa8befb 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -58,7 +58,7 @@ export function makeAddress(host: string, port: number): string { } export function parseAddress(address: string): { host: string, port: number } | undefined { - const matches = address.match(/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\:|localhost:)?([0-9]+)$/); + const matches = address.match(/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\:|localhost:|[a-zA-Z]+:)?([0-9]+)$/); if (!matches) { return undefined; } From 1100f276812e188daccc1f77ea0acb78a062046f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 11:18:28 +0100 Subject: [PATCH 1074/1837] fix build --- build/azure-pipelines/darwin/product-build-darwin.yml | 8 +++++++- build/azure-pipelines/linux/product-build-linux.yml | 6 ++++++ build/azure-pipelines/win32/product-build-win32.yml | 7 +++++++ test/integration/browser/package.json | 4 ++-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 8d778087cdb..aac5eb41eef 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -173,6 +173,12 @@ steps: displayName: Run unit tests (Browser) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + yarn --cwd test/integration/browser compile + displayName: Compile integration tests + condition: and(succeeded(), eq(variables['CacheRestored'], 'true'), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | # Figure out the full absolute path of the product we just built # including the remote server and configure the integration tests @@ -184,7 +190,7 @@ steps: VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \ ./scripts/test-integration.sh --build --tfs "Integration Tests" displayName: Run integration tests (Electron) - condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index ca269dc460f..7c2aaf2ac4b 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -153,6 +153,12 @@ steps: displayName: Run unit tests (Browser) condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | + set -e + yarn --cwd test/integration/browser compile + displayName: Compile integration tests + condition: and(succeeded(), eq(variables['CacheRestored'], 'true'), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | # Figure out the full absolute path of the product we just built # including the remote server and configure the integration tests diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index b52165a07a3..6f7380e737a 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -147,6 +147,13 @@ steps: displayName: Run unit tests (Browser) condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn --cwd test/integration/browser compile } + displayName: Compile integration tests + condition: and(succeeded(), eq(variables['CacheRestored'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) + - powershell: | # Figure out the full absolute path of the product we just built # including the remote server and configure the integration tests diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json index beb4142c55d..f71102e23d5 100644 --- a/test/integration/browser/package.json +++ b/test/integration/browser/package.json @@ -3,8 +3,8 @@ "version": "0.1.0", "main": "./index.js", "scripts": { - "postinstall": "npm run compile", - "compile": "yarn tsc" + "postinstall": "tsc", + "compile": "tsc" }, "devDependencies": { "@types/mkdirp": "0.5.1", From ac7eb534b820cc9169bf3c0235773b48d1f0a16d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 16 Dec 2020 11:01:52 +0100 Subject: [PATCH 1075/1837] Increase web worker extension host timeout from 10s to 60s --- .../workbench/services/extensions/browser/extensionService.ts | 4 ++-- .../services/extensions/browser/webWorkerExtensionHost.ts | 4 ++-- .../services/extensions/common/extensionHostProtocol.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index c6eb782943a..983bee9a7c2 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -84,10 +84,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _onExtensionHostCrashed(extensionHost: ExtensionHostManager, code: number, signal: string | null): void { super._onExtensionHostCrashed(extensionHost, code, signal); if (extensionHost.kind === ExtensionHostKind.LocalWebWorker) { - if (code === ExtensionHostExitCode.StartTimeout10s) { + if (code === ExtensionHostExitCode.StartTimeout60s) { this._notificationService.prompt( Severity.Error, - nls.localize('extensionService.startTimeout', "The Web Worker Extension Host did not start in 10s."), + nls.localize('extensionService.startTimeout', "The Web Worker Extension Host did not start in 60s."), [] ); return; diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 32a3d8ac92f..a061c8b9454 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -166,8 +166,8 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost }; startTimeout = setTimeout(() => { - rejectBarrier(ExtensionHostExitCode.StartTimeout10s, new Error('The Web Worker Extension Host did not start in 10s')); - }, 10000); + rejectBarrier(ExtensionHostExitCode.StartTimeout60s, new Error('The Web Worker Extension Host did not start in 60s')); + }, 60000); this._register(dom.addDisposableListener(window, 'message', (event) => { if (event.source !== iframe.contentWindow) { diff --git a/src/vs/workbench/services/extensions/common/extensionHostProtocol.ts b/src/vs/workbench/services/extensions/common/extensionHostProtocol.ts index c60299a9a42..df53b4709d3 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostProtocol.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostProtocol.ts @@ -8,7 +8,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; export const enum ExtensionHostExitCode { // nodejs uses codes 1-13 and exit codes >128 are signal exits VersionMismatch = 55, - StartTimeout10s = 56, + StartTimeout60s = 56, UnexpectedError = 81, } From ec2d8d677255575a7c9f0559683f8de2b5832d11 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 16 Dec 2020 11:15:41 +0100 Subject: [PATCH 1076/1837] Try to give a good stack trace in case loading code fails --- .../api/worker/extHostExtensionService.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index e69e48b0b8d..82a203344cc 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -71,7 +71,19 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { // Here we append #vscode-extension to serve as a marker, such that source maps // can be adjusted for the extra wrapping function. const sourceURL = `${module.toString(true)}#vscode-extension`; - const initFn = new Function('module', 'exports', 'require', `${source}\n//# sourceURL=${sourceURL}`); + let initFn: Function; + try { + initFn = new Function('module', 'exports', 'require', `${source}\n//# sourceURL=${sourceURL}`); + } catch (err) { + if (extensionId) { + console.error(`Loading code for extension ${extensionId.value} failed: ${err.message}`); + } else { + console.error(`Loading code failed: ${err.message}`); + } + console.error(`${module.toString(true)}${typeof err.line === 'number' ? ` line ${err.line}` : ''}${typeof err.column === 'number' ? ` column ${err.column}` : ''}`); + console.error(err); + throw err; + } // define commonjs globals: `module`, `exports`, and `require` const _exports = {}; From 8fbe27ae9aae81c50e7af949ff5d8ec893f65b86 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 16 Dec 2020 11:28:50 +0100 Subject: [PATCH 1077/1837] Do not touch the perf marks names --- .../api/common/extHostExtensionService.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index d606324e05a..76c554108e0 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -463,22 +463,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme private _activateAllStartupFinished(): void { // startup is considered finished - const marks = performance.getMarks().map((entry) => { - if (entry.name.startsWith('fork/')) { - return { - name: `extHost/` + entry.name.substr('fork/'.length), - startTime: entry.startTime - }; - } - if (entry.name.startsWith('code/')) { - return { - name: `extHost/` + entry.name.substr('code/'.length), - startTime: entry.startTime - }; - } - return entry; - }); - this._mainThreadExtensionsProxy.$setPerformanceMarks(marks); + this._mainThreadExtensionsProxy.$setPerformanceMarks(performance.getMarks()); for (const desc of this._registry.getAllExtensionDescriptions()) { if (desc.activationEvents) { From f75e0388adcbf643d2af3093089eda22a8df1e08 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 16 Dec 2020 11:30:42 +0100 Subject: [PATCH 1078/1837] remove passing user target --- src/vs/workbench/browser/actions/layoutActions.ts | 4 ++-- src/vs/workbench/browser/actions/windowActions.ts | 4 ++-- .../workbench/contrib/codeEditor/browser/diffEditorHelper.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 41eb6d4362c..cdde4b650bf 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -8,7 +8,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor, MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions, CATEGORIES } from 'vs/workbench/common/actions'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; @@ -433,7 +433,7 @@ export class ToggleMenuBarAction extends Action { newVisibilityValue = (isWeb && currentVisibilityValue === 'hidden') ? 'compact' : 'default'; } - return this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue, ConfigurationTarget.USER); + return this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue); } } diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index e5fdcdbca0a..a65ee1a9e52 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -33,7 +33,7 @@ import { ResourceMap } from 'vs/base/common/map'; import { Codicon } from 'vs/base/common/codicons'; import { isHTMLElement } from 'vs/base/browser/dom'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export const inRecentFilesPickerContextKey = 'inRecentFilesPicker'; @@ -405,7 +405,7 @@ CommandsRegistry.registerCommand('workbench.action.toggleConfirmBeforeClose', ac const configurationService = accessor.get(IConfigurationService); const setting = configurationService.inspect<'always' | 'keyboardOnly' | 'never'>('window.confirmBeforeClose').userValue; - return configurationService.updateValue('window.confirmBeforeClose', setting === 'never' ? 'keyboardOnly' : 'never', ConfigurationTarget.USER); + return configurationService.updateValue('window.confirmBeforeClose', setting === 'never' ? 'keyboardOnly' : 'never'); }); // --- Menu Registration diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts index c3ede411a52..bbeba186b93 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -11,7 +11,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets'; import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; const enum WidgetState { @@ -94,7 +94,7 @@ class DiffEditorHelperContribution extends Disposable implements IDiffEditorCont private _onDidClickHelperWidget(): void { if (this._state === WidgetState.HintWhitespace) { - this._configurationService.updateValue('diffEditor.ignoreTrimWhitespace', false, ConfigurationTarget.USER); + this._configurationService.updateValue('diffEditor.ignoreTrimWhitespace', false); } } From 78fc9abd92e25677cbe1fd996164a8f73e6cffc0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 11:43:53 +0100 Subject: [PATCH 1079/1837] explain why ::after "inherits" italic rendering --- src/vs/base/browser/ui/iconLabel/iconlabel.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index da6e0ec421c..a5b9fa1c1f3 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -64,6 +64,11 @@ font-style: italic; } +/* make sure apply italic font style to decorations as well */ +.monaco-icon-label.italic::after { + font-style: italic; +} + .monaco-icon-label.strikethrough > .monaco-icon-label-container > .monaco-icon-name-container > .label-name, .monaco-icon-label.strikethrough > .monaco-icon-label-container > .monaco-icon-description-container > .label-description { text-decoration: line-through; @@ -77,10 +82,6 @@ text-align: center; } -.monaco-icon-label.italic::after { - font-style: italic; -} - /* make sure selection color wins when a label is being selected */ .monaco-list:focus .selected .monaco-icon-label, /* list */ .monaco-list:focus .selected .monaco-icon-label::after From 6f08397de0f630ff6d0489844c370b90d2800e0f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 11:52:02 +0100 Subject: [PATCH 1080/1837] Enable fileWorkspaceFolder variable for remote tasks Fixes #112514 --- src/vs/workbench/api/node/extHostTask.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 9d5951b84de..85e9a1e520f 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -121,7 +121,7 @@ export class ExtHostTask extends ExtHostTaskBase { private async getVariableResolver(workspaceFolders: vscode.WorkspaceFolder[]): Promise { if (this._variableResolver === undefined) { const configProvider = await this._configurationService.getConfigProvider(); - this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, process.env as IProcessEnvironment); + this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, process.env as IProcessEnvironment, this.workspaceService); } return this._variableResolver; } From aaf73920aeae171096d205efb2c58804a32b6846 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 12:02:05 +0100 Subject: [PATCH 1081/1837] Ensure task executions get cleaned up Fixes #112247 --- src/vs/workbench/api/browser/mainThreadTask.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTask.ts b/src/vs/workbench/api/browser/mainThreadTask.ts index 2f4cb073c9f..3cc31f08607 100644 --- a/src/vs/workbench/api/browser/mainThreadTask.ts +++ b/src/vs/workbench/api/browser/mainThreadTask.ts @@ -567,13 +567,19 @@ export class MainThreadTask implements MainThreadTaskShape { if (!task) { reject(new Error('Task not found')); } else { - this._taskService.run(task).then(undefined, reason => { - // eat the error, it has already been surfaced to the user and we don't care about it here - }); const result: TaskExecutionDTO = { id: value.id, task: TaskDTO.from(task) }; + this._taskService.run(task).then(summary => { + // Ensure that the task execution gets cleaned up if the exit code is undefined + // This can happen when the task has dependent tasks and one of them failed + if ((summary?.exitCode === undefined) || (summary.exitCode !== 0)) { + this._proxy.$OnDidEndTask(result); + } + }, reason => { + // eat the error, it has already been surfaced to the user and we don't care about it here + }); resolve(result); } }, (_error) => { From 39bd9df739ffd09ce5631757bb12daa14b77c403 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 16 Dec 2020 12:16:08 +0100 Subject: [PATCH 1082/1837] Show a clear dialog on web when the remote connection fails --- src/vs/platform/remote/common/remoteHosts.ts | 2 +- .../remote/browser/remoteAgentServiceImpl.ts | 68 ++++++++++++++++++- .../common/abstractRemoteAgentService.ts | 27 +------- .../remoteAgentServiceImpl.ts | 48 ++++++++++++- 4 files changed, 116 insertions(+), 29 deletions(-) diff --git a/src/vs/platform/remote/common/remoteHosts.ts b/src/vs/platform/remote/common/remoteHosts.ts index 1f3ab36f303..86f2c4f26ec 100644 --- a/src/vs/platform/remote/common/remoteHosts.ts +++ b/src/vs/platform/remote/common/remoteHosts.ts @@ -19,7 +19,7 @@ export function getRemoteName(authority: string | undefined): string | undefined } const pos = authority.indexOf('+'); if (pos < 0) { - // funky? bad authority? + // e.g. localhost:8000 return authority; } return authority.substr(0, pos); diff --git a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts index 5a9684c38a1..e3406ca12fa 100644 --- a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts @@ -3,14 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { AbstractRemoteAgentService } from 'vs/workbench/services/remote/common/abstractRemoteAgentService'; import { IProductService } from 'vs/platform/product/common/productService'; import { IWebSocketFactory, BrowserSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory'; import { ISignService } from 'vs/platform/sign/common/sign'; import { ILogService } from 'vs/platform/log/common/log'; +import { Severity } from 'vs/platform/notification/common/notification'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions'; +import { IHostService } from 'vs/workbench/services/host/browser/host'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService { @@ -25,3 +34,60 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR super(new BrowserSocketFactory(webSocketFactory), environmentService, productService, remoteAuthorityResolverService, signService, logService); } } + +class RemoteConnectionFailureNotificationContribution implements IWorkbenchContribution { + + constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, + @IDialogService private readonly _dialogService: IDialogService, + @IHostService private readonly _hostService: IHostService, + @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + @ITelemetryService private readonly _telemetryService: ITelemetryService, + ) { + // Let's cover the case where connecting to fetch the remote extension info fails + remoteAgentService.getRawEnvironment() + .then(undefined, (err) => { + + type RemoteConnectionFailureClassification = { + web: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + remoteName: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + message: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + }; + type RemoteConnectionFailureEvent = { + web: boolean; + remoteName: string | undefined; + message: string; + }; + this._telemetryService.publicLog2('remoteConnectionFailure', { + web: true, + remoteName: getRemoteName(this._environmentService.remoteAuthority), + message: err ? err.message : '' + }); + + if (!RemoteAuthorityResolverError.isHandled(err)) { + this._presentConnectionError(err); + } + }); + } + + private async _presentConnectionError(err: any): Promise { + const res = await this._dialogService.show( + Severity.Error, + nls.localize('connectionError', "An unexpected error occurred that requires a reload of this page."), + [ + nls.localize('reload', "Reload") + ], + { + detail: nls.localize('connectionErrorDetail', "The workbench failed to connect to the server (Error: {0})", err ? err.message : '') + } + ); + + if (res.choice === 0) { + this._hostService.reload(); + } + } + +} + +const workbenchRegistry = Registry.as(Extensions.Workbench); +workbenchRegistry.registerWorkbenchContribution(RemoteConnectionFailureNotificationContribution, LifecyclePhase.Ready); diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index 5fbc58f2a05..9440bcf7af2 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -3,20 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { Disposable } from 'vs/base/common/lifecycle'; import { IChannel, IServerChannel, getDelayedChannel, IPCLogger } from 'vs/base/parts/ipc/common/ipc'; import { Client } from 'vs/base/parts/ipc/common/ipc.net'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { connectRemoteAgentManagement, IConnectionOptions, ISocketFactory, PersistentConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection'; import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver'; -import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { RemoteAgentConnectionContext, IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; -import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions'; -import { Registry } from 'vs/platform/registry/common/platform'; import { RemoteExtensionEnvironmentChannelClient } from 'vs/workbench/services/remote/common/remoteAgentEnvironmentChannel'; -import { INotificationService } from 'vs/platform/notification/common/notification'; import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics'; import { Emitter } from 'vs/base/common/event'; import { ISignService } from 'vs/platform/sign/common/sign'; @@ -205,23 +200,3 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon return connection.client; } } - -class RemoteConnectionFailureNotificationContribution implements IWorkbenchContribution { - - constructor( - @IRemoteAgentService remoteAgentService: IRemoteAgentService, - @INotificationService notificationService: INotificationService, - ) { - // Let's cover the case where connecting to fetch the remote extension info fails - remoteAgentService.getRawEnvironment() - .then(undefined, err => { - if (!RemoteAuthorityResolverError.isHandled(err)) { - notificationService.error(nls.localize('connectionError', "Failed to connect to the remote extension host server (Error: {0})", err ? err.message : '')); - } - }); - } - -} - -const workbenchRegistry = Registry.as(Extensions.Workbench); -workbenchRegistry.registerWorkbenchContribution(RemoteConnectionFailureNotificationContribution, LifecyclePhase.Ready); diff --git a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts index a0cc5572f4e..dd99a414f14 100644 --- a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts @@ -4,13 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IProductService } from 'vs/platform/product/common/productService'; import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; import { AbstractRemoteAgentService } from 'vs/workbench/services/remote/common/abstractRemoteAgentService'; import { ISignService } from 'vs/platform/sign/common/sign'; import { ILogService } from 'vs/platform/log/common/log'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import * as nls from 'vs/nls'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService { constructor( @@ -23,3 +30,42 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR super(nodeSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService, logService); } } + +class RemoteConnectionFailureNotificationContribution implements IWorkbenchContribution { + + constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, + @INotificationService notificationService: INotificationService, + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @ITelemetryService telemetryService: ITelemetryService, + ) { + // Let's cover the case where connecting to fetch the remote extension info fails + remoteAgentService.getRawEnvironment() + .then(undefined, err => { + + type RemoteConnectionFailureClassification = { + web: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + remoteName: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + message: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; + }; + type RemoteConnectionFailureEvent = { + web: boolean; + remoteName: string | undefined; + message: string; + }; + telemetryService.publicLog2('remoteConnectionFailure', { + web: false, + remoteName: getRemoteName(environmentService.remoteAuthority), + message: err ? err.message : '', + }); + + if (!RemoteAuthorityResolverError.isHandled(err)) { + notificationService.error(nls.localize('connectionError', "Failed to connect to the remote extension host server (Error: {0})", err ? err.message : '')); + } + }); + } + +} + +const workbenchRegistry = Registry.as(Extensions.Workbench); +workbenchRegistry.registerWorkbenchContribution(RemoteConnectionFailureNotificationContribution, LifecyclePhase.Ready); From 1abefb9be2a9e33a78f4e9bacda722095d342a23 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Wed, 16 Dec 2020 13:54:06 +0100 Subject: [PATCH 1083/1837] Fixes #112652: A disposed IPC channel should reject all requests with a canceled error, not resolve them --- src/vs/base/parts/ipc/common/ipc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index b459b90de71..535502f3efd 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -527,13 +527,13 @@ export class ChannelClient implements IChannelClient, IDisposable { return { call(command: string, arg?: any, cancellationToken?: CancellationToken) { if (that.isDisposed) { - return Promise.resolve(errors.canceled()); + return Promise.reject(errors.canceled()); } return that.requestPromise(channelName, command, arg, cancellationToken); }, listen(event: string, arg: any) { if (that.isDisposed) { - return Promise.resolve(errors.canceled()); + return Promise.reject(errors.canceled()); } return that.requestEvent(channelName, event, arg); } From a1b6de93363cc5d3f4a343b17f8ace585762fd2d Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 13:55:11 +0100 Subject: [PATCH 1084/1837] Fix markdown span style filter Fixes #112606 --- src/vs/base/browser/markdownRenderer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 71248b11b0e..72a8ac0b5ca 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -298,8 +298,8 @@ function getInsaneOptions(options: { readonly isTrusted?: boolean }): InsaneOpti 'td': ['align'] }, filter(token: { tag: string; attrs: { readonly [key: string]: string; }; }): boolean { - if (token.tag === 'span' && options.isTrusted && (Object.keys(token.attrs).length === 1)) { - if (token.attrs['style']) { + if (token.tag === 'span' && options.isTrusted) { + if (token.attrs['style'] && (Object.keys(token.attrs).length === 1)) { return !!token.attrs['style'].match(/^(color\:#[0-9a-fA-F]+;)?(background-color\:#[0-9a-fA-F]+;)?$/); } else if (token.attrs['class']) { // The class should match codicon rendering in src\vs\base\common\codicons.ts From 6260e655bc606e204ad51ce5b1cb34216cd36dd3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 16 Dec 2020 12:37:52 +0100 Subject: [PATCH 1085/1837] codicons -> iconLabels --- src/vs/base/browser/markdownRenderer.ts | 8 +- src/vs/base/browser/ui/button/button.ts | 10 +- .../ui/highlightedlabel/highlightedLabel.ts | 10 +- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 12 +- .../iconLabel/iconLabels.ts} | 26 ++- .../simpleIconLabel.ts} | 6 +- src/vs/base/browser/ui/menu/menu.ts | 5 +- src/vs/base/common/codicon.ts | 135 --------------- src/vs/base/common/codicons.ts | 45 ++--- src/vs/base/common/htmlContent.ts | 4 +- src/vs/base/common/iconLabels.ts | 161 ++++++++++++++++++ .../parts/quickinput/browser/quickInput.ts | 8 +- .../quickinput/browser/quickInputList.ts | 14 +- .../{codicons.test.ts => iconLabels.test.ts} | 28 +-- src/vs/base/test/common/codicon.test.ts | 78 --------- src/vs/base/test/common/iconLabels.test.ts | 74 ++++++++ .../issue/issueReporterMain.ts | 6 +- .../editor/contrib/codelens/codelensWidget.ts | 4 +- .../quickAccess/commandsQuickAccess.ts | 4 +- .../contrib/suggest/suggestWidgetRenderer.ts | 2 +- src/vs/platform/theme/common/iconRegistry.ts | 3 +- .../browser/parts/statusbar/statusbarPart.ts | 11 +- .../workbench/browser/parts/views/viewPane.ts | 2 +- .../contrib/debug/browser/debugToolBar.ts | 15 -- .../abstractRuntimeExtensionsEditor.ts | 12 +- .../notebook/browser/diff/cellComponents.ts | 7 +- .../browser/view/renderers/cellActionView.ts | 4 +- .../browser/view/renderers/cellRenderer.ts | 9 +- .../browser/view/renderers/cellWidgets.ts | 8 +- .../browser/view/renderers/markdownCell.ts | 7 +- .../preferences/browser/settingsTree.ts | 4 +- .../browser/commandsQuickAccess.ts | 5 +- src/vs/workbench/contrib/scm/browser/util.ts | 4 +- .../search/browser/anythingQuickAccess.ts | 5 +- .../contrib/timeline/browser/timelinePane.ts | 2 +- .../electron-sandbox/contextmenuService.ts | 6 +- 36 files changed, 373 insertions(+), 371 deletions(-) rename src/vs/base/browser/{codicons.ts => ui/iconLabel/iconLabels.ts} (50%) rename src/vs/base/browser/ui/{codicons/codiconLabel.ts => iconLabel/simpleIconLabel.ts} (76%) delete mode 100644 src/vs/base/common/codicon.ts create mode 100644 src/vs/base/common/iconLabels.ts rename src/vs/base/test/browser/{codicons.test.ts => iconLabels.test.ts} (64%) delete mode 100644 src/vs/base/test/common/codicon.test.ts create mode 100644 src/vs/base/test/common/iconLabels.test.ts diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 72a8ac0b5ca..6293b732999 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -15,10 +15,10 @@ import { cloneAndChange } from 'vs/base/common/objects'; import { escape } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { markdownEscapeEscapedCodicons } from 'vs/base/common/codicons'; +import { markdownEscapeEscapedIcons } from 'vs/base/common/iconLabels'; import { resolvePath } from 'vs/base/common/resources'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { Event } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; @@ -156,7 +156,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende }; renderer.paragraph = (text): string => { if (markdown.supportThemeIcons) { - const elements = renderCodicons(text); + const elements = renderLabelWithIcons(text); text = elements.map(e => typeof e === 'string' ? e : e.outerHTML).join(''); } return `

${text}

`; @@ -233,7 +233,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende } // escape theme icons if (markdown.supportThemeIcons) { - value = markdownEscapeEscapedCodicons(value); + value = markdownEscapeEscapedIcons(value); } const renderedMarkdown = marked.parse(value, markedOptions); diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index b3697f9bf25..aeba7819d81 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -11,7 +11,7 @@ import { mixin } from 'vs/base/common/objects'; import { Event as BaseEvent, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom'; import { IContextMenuProvider } from 'vs/base/browser/contextmenu'; import { IAction, IActionRunner } from 'vs/base/common/actions'; @@ -19,7 +19,7 @@ import { CSSIcon, Codicon } from 'vs/base/common/codicons'; export interface IButtonOptions extends IButtonStyles { readonly title?: boolean | string; - readonly supportCodicons?: boolean; + readonly supportIcons?: boolean; readonly secondary?: boolean; } @@ -190,8 +190,8 @@ export class Button extends Disposable implements IButton { set label(value: string) { this._element.classList.add('monaco-text-button'); - if (this.options.supportCodicons) { - reset(this._element, ...renderCodicons(value)); + if (this.options.supportIcons) { + reset(this._element, ...renderLabelWithIcons(value)); } else { this._element.textContent = value; } @@ -255,7 +255,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.button = this._register(new Button(this.element, options)); this.onDidClick = this.button.onDidClick; - this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportCodicons: true })); + this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportIcons: true })); this.dropdownButton.element.classList.add('monaco-dropdown-button'); this.dropdownButton.icon = Codicon.dropDownButton; this._register(this.dropdownButton.onDidClick(() => { diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index c6b9850857e..552f1e57d18 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -5,7 +5,7 @@ import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; export interface IHighlight { start: number; @@ -21,7 +21,7 @@ export class HighlightedLabel { private highlights: IHighlight[] = []; private didEverRender: boolean = false; - constructor(container: HTMLElement, private supportCodicons: boolean) { + constructor(container: HTMLElement, private supportIcons: boolean) { this.domNode = document.createElement('span'); this.domNode.className = 'monaco-highlighted-label'; @@ -61,12 +61,12 @@ export class HighlightedLabel { } if (pos < highlight.start) { const substring = this.text.substring(pos, highlight.start); - children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring])); + children.push(dom.$('span', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring])); pos = highlight.end; } const substring = this.text.substring(highlight.start, highlight.end); - const element = dom.$('span.highlight', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring]); + const element = dom.$('span.highlight', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]); if (highlight.extraClasses) { element.classList.add(highlight.extraClasses); } @@ -76,7 +76,7 @@ export class HighlightedLabel { if (pos < this.text.length) { const substring = this.text.substring(pos,); - children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring])); + children.push(dom.$('span', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring])); } dom.reset(this.domNode, ...children); diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 50274475e84..81da73bdb0d 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -20,7 +20,7 @@ import { domEvent } from 'vs/base/browser/event'; export interface IIconLabelCreationOptions { supportHighlights?: boolean; supportDescriptionHighlights?: boolean; - supportCodicons?: boolean; + supportIcons?: boolean; hoverDelegate?: IHoverDelegate; } @@ -114,13 +114,13 @@ export class IconLabel extends Disposable { this.descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container')))); if (options?.supportHighlights) { - this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportCodicons); + this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportIcons); } else { this.nameNode = new Label(nameContainer); } if (options?.supportDescriptionHighlights) { - this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), !!options.supportCodicons); + this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), !!options.supportIcons); } else { this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.descriptionContainer.element, dom.$('span.label-description')))); } @@ -337,7 +337,7 @@ class LabelWithHighlights { private singleLabel: HighlightedLabel | undefined = undefined; private options: IIconLabelValueOptions | undefined; - constructor(private container: HTMLElement, private supportCodicons: boolean) { } + constructor(private container: HTMLElement, private supportIcons: boolean) { } setLabel(label: string | string[], options?: IIconLabelValueOptions): void { if (this.label === label && equals(this.options, options)) { @@ -351,7 +351,7 @@ class LabelWithHighlights { if (!this.singleLabel) { this.container.innerText = ''; this.container.classList.remove('multiple'); - this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), this.supportCodicons); + this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), this.supportIcons); } this.singleLabel.set(label, options?.matches, undefined, options?.labelEscapeNewLines); @@ -369,7 +369,7 @@ class LabelWithHighlights { const id = options?.domId && `${options?.domId}_${i}`; const name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' }); - const highlightedLabel = new HighlightedLabel(dom.append(this.container, name), this.supportCodicons); + const highlightedLabel = new HighlightedLabel(dom.append(this.container, name), this.supportIcons); highlightedLabel.set(l, m, undefined, options?.labelEscapeNewLines); if (i < label.length - 1) { diff --git a/src/vs/base/browser/codicons.ts b/src/vs/base/browser/ui/iconLabel/iconLabels.ts similarity index 50% rename from src/vs/base/browser/codicons.ts rename to src/vs/base/browser/ui/iconLabel/iconLabels.ts index 5793a73b66c..8c56bfb54cb 100644 --- a/src/vs/base/browser/codicons.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabels.ts @@ -4,21 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import * as dom from 'vs/base/browser/dom'; +import { Codicon, getClassNamesArray } from 'vs/base/common/codicons'; -const renderCodiconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi; +const labelWithIconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi; -export function renderCodicons(text: string): Array { +export function renderLabelWithIcons(text: string): Array { const elements = new Array(); let match: RegExpMatchArray | null; let textStart = 0, textStop = 0; - while ((match = renderCodiconsRegex.exec(text)) !== null) { + while ((match = labelWithIconsRegex.exec(text)) !== null) { textStop = match.index || 0; elements.push(text.substring(textStart, textStop)); textStart = (match.index || 0) + match[0].length; const [, escaped, codicon, name, modifier] = match; - elements.push(escaped ? `$(${codicon})` : renderCodicon(name, modifier)); + elements.push(escaped ? `$(${codicon})` : doRender(name, modifier)); } if (textStart < text.length) { @@ -27,6 +28,19 @@ export function renderCodicons(text: string): Array { return elements; } -export function renderCodicon(name: string, modifier: string): HTMLSpanElement { - return dom.$(`span.codicon.codicon-${name}${modifier ? `.codicon-modifier-${modifier}` : ''}`); +export const iconIdRegex = /^(codicon\/)?([a-z-]+)(~[a-z]+)?$/i; + +export function renderIcon(icon: { id: string }): HTMLSpanElement { + const match = iconIdRegex.exec(icon.id); + if (!match) { + return renderIcon(Codicon.error); + } + let [, , name, modifier] = match; + return doRender(name, modifier); +} + +function doRender(name: string, modifier?: string): HTMLSpanElement { + const node = dom.$(`span`); + node.classList.add(...getClassNamesArray(name, modifier)); + return node; } diff --git a/src/vs/base/browser/ui/codicons/codiconLabel.ts b/src/vs/base/browser/ui/iconLabel/simpleIconLabel.ts similarity index 76% rename from src/vs/base/browser/ui/codicons/codiconLabel.ts rename to src/vs/base/browser/ui/iconLabel/simpleIconLabel.ts index e21eb2381a4..659572d4ff8 100644 --- a/src/vs/base/browser/ui/codicons/codiconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/simpleIconLabel.ts @@ -4,16 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import { reset } from 'vs/base/browser/dom'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; -export class CodiconLabel { +export class SimpleIconLabel { constructor( private readonly _container: HTMLElement ) { } set text(text: string) { - reset(this._container, ...renderCodicons(text ?? '')); + reset(this._container, ...renderLabelWithIcons(text ?? '')); } set title(title: string) { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index fc129fef580..947ba2708b0 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -18,11 +18,12 @@ import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; import { Event } from 'vs/base/common/event'; import { AnchorAlignment, layout, LayoutAnchorPosition } from 'vs/base/browser/ui/contextview/contextview'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; -import { Codicon, registerCodicon, stripCodicons } from 'vs/base/common/codicons'; +import { Codicon, registerCodicon } from 'vs/base/common/codicons'; import { BaseActionViewItem, ActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles'; import { isFirefox } from 'vs/base/browser/browser'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { stripIcons } from 'vs/base/common/iconLabels'; export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/; export const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\s&])/g; @@ -532,7 +533,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem { if (this.options.label) { clearNode(this.label); - let label = stripCodicons(this.getAction().label); + let label = stripIcons(this.getAction().label); if (label) { const cleanLabel = cleanMnemonic(label); if (!this.options.enableMnemonics) { diff --git a/src/vs/base/common/codicon.ts b/src/vs/base/common/codicon.ts deleted file mode 100644 index 5b3541125e0..00000000000 --- a/src/vs/base/common/codicon.ts +++ /dev/null @@ -1,135 +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 { matchesFuzzy, IMatch } from 'vs/base/common/filters'; -import { ltrim } from 'vs/base/common/strings'; - -export const codiconStartMarker = '$('; - -export interface IParsedCodicons { - readonly text: string; - readonly codiconOffsets?: readonly number[]; -} - -export function parseCodicons(text: string): IParsedCodicons { - const firstCodiconIndex = text.indexOf(codiconStartMarker); - if (firstCodiconIndex === -1) { - return { text }; // return early if the word does not include an codicon - } - - return doParseCodicons(text, firstCodiconIndex); -} - -function doParseCodicons(text: string, firstCodiconIndex: number): IParsedCodicons { - const codiconOffsets: number[] = []; - let textWithoutCodicons: string = ''; - - function appendChars(chars: string) { - if (chars) { - textWithoutCodicons += chars; - - for (const _ of chars) { - codiconOffsets.push(codiconsOffset); // make sure to fill in codicon offsets - } - } - } - - let currentCodiconStart = -1; - let currentCodiconValue: string = ''; - let codiconsOffset = 0; - - let char: string; - let nextChar: string; - - let offset = firstCodiconIndex; - const length = text.length; - - // Append all characters until the first codicon - appendChars(text.substr(0, firstCodiconIndex)); - - // example: $(file-symlink-file) my cool $(other-codicon) entry - while (offset < length) { - char = text[offset]; - nextChar = text[offset + 1]; - - // beginning of codicon: some value $( <-- - if (char === codiconStartMarker[0] && nextChar === codiconStartMarker[1]) { - currentCodiconStart = offset; - - // if we had a previous potential codicon value without - // the closing ')', it was actually not an codicon and - // so we have to add it to the actual value - appendChars(currentCodiconValue); - - currentCodiconValue = codiconStartMarker; - - offset++; // jump over '(' - } - - // end of codicon: some value $(some-codicon) <-- - else if (char === ')' && currentCodiconStart !== -1) { - const currentCodiconLength = offset - currentCodiconStart + 1; // +1 to include the closing ')' - codiconsOffset += currentCodiconLength; - currentCodiconStart = -1; - currentCodiconValue = ''; - } - - // within codicon - else if (currentCodiconStart !== -1) { - // Make sure this is a real codicon name - if (/^[a-z0-9\-]$/i.test(char)) { - currentCodiconValue += char; - } else { - // This is not a real codicon, treat it as text - appendChars(currentCodiconValue); - - currentCodiconStart = -1; - currentCodiconValue = ''; - } - } - - // any value outside of codicons - else { - appendChars(char); - } - - offset++; - } - - // if we had a previous potential codicon value without - // the closing ')', it was actually not an codicon and - // so we have to add it to the actual value - appendChars(currentCodiconValue); - - return { text: textWithoutCodicons, codiconOffsets }; -} - -export function matchesFuzzyCodiconAware(query: string, target: IParsedCodicons, enableSeparateSubstringMatching = false): IMatch[] | null { - const { text, codiconOffsets } = target; - - // Return early if there are no codicon markers in the word to match against - if (!codiconOffsets || codiconOffsets.length === 0) { - return matchesFuzzy(query, text, enableSeparateSubstringMatching); - } - - // Trim the word to match against because it could have leading - // whitespace now if the word started with an codicon - const wordToMatchAgainstWithoutCodiconsTrimmed = ltrim(text, ' '); - const leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutCodiconsTrimmed.length; - - // match on value without codicons - const matches = matchesFuzzy(query, wordToMatchAgainstWithoutCodiconsTrimmed, enableSeparateSubstringMatching); - - // Map matches back to offsets with codicons and trimming - if (matches) { - for (const match of matches) { - const codiconOffset = codiconOffsets[match.start + leadingWhitespaceOffset] /* codicon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */; - match.start += codiconOffset; - match.end += codiconOffset; - } - } - - return matches; -} diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index 8681df3231f..5d61f9603ba 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -3,9 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codiconStartMarker } from 'vs/base/common/codicon'; import { Emitter, Event } from 'vs/base/common/event'; -import { localize } from 'vs/nls'; export interface IIconRegistry { readonly all: IterableIterator; @@ -47,8 +45,8 @@ const _registry = new Registry(); export const iconRegistry: IIconRegistry = _registry; -export function registerCodicon(id: string, def: Codicon, description?: string): Codicon { - return new Codicon(id, def, description); +export function registerCodicon(id: string, def: Codicon): Codicon { + return new Codicon(id, def); } export class Codicon implements CSSIcon { @@ -61,6 +59,14 @@ export class Codicon implements CSSIcon { public get cssSelector() { return '.codicon.codicon-' + this.id; } } +export function getClassNamesArray(id: string, modifier?: string) { + const classNames = ['codicon', 'codicon-' + id]; + if (modifier) { + classNames.push('codicon-modifier-' + modifier); + } + return classNames; +} + export interface CSSIcon { readonly classNames: string; } @@ -498,35 +504,6 @@ export namespace Codicon { export const circleLargeFilled = new Codicon('circle-large-filled', { character: '\\ebb4' }); export const circleLargeOutline = new Codicon('circle-large-outline', { character: '\\ebb5' }); - export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition, localize('dropDownButton', 'Icon for drop down buttons.')); + export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition); } -// common icons - - - - -const escapeCodiconsRegex = /(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi; -export function escapeCodicons(text: string): string { - return text.replace(escapeCodiconsRegex, (match, escaped) => escaped ? match : `\\${match}`); -} - -const markdownEscapedCodiconsRegex = /\\\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi; -export function markdownEscapeEscapedCodicons(text: string): string { - // Need to add an extra \ for escaping in markdown - return text.replace(markdownEscapedCodiconsRegex, match => `\\${match}`); -} - -const markdownUnescapeCodiconsRegex = /(\\)?\$\\\(([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?)\\\)/gi; -export function markdownUnescapeCodicons(text: string): string { - return text.replace(markdownUnescapeCodiconsRegex, (match, escaped, codicon) => escaped ? match : `$(${codicon})`); -} - -const stripCodiconsRegex = /(\s)?(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)(\s)?/gi; -export function stripCodicons(text: string): string { - if (text.indexOf(codiconStartMarker) === -1) { - return text; - } - - return text.replace(stripCodiconsRegex, (match, preWhitespace, escaped, postWhitespace) => escaped ? match : preWhitespace || postWhitespace || ''); -} diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index 829a3480092..6062c1b520d 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -5,7 +5,7 @@ import { equals } from 'vs/base/common/arrays'; import { UriComponents } from 'vs/base/common/uri'; -import { escapeCodicons } from 'vs/base/common/codicons'; +import { escapeIcons } from 'vs/base/common/iconLabels'; import { illegalArgument } from 'vs/base/common/errors'; export interface IMarkdownString { @@ -47,7 +47,7 @@ export class MarkdownString implements IMarkdownString { appendText(value: string, newlineStyle: MarkdownStringTextNewlineStyle = MarkdownStringTextNewlineStyle.Paragraph): MarkdownString { // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash - this.value += (this.supportThemeIcons ? escapeCodicons(value) : value) + this.value += (this.supportThemeIcons ? escapeIcons(value) : value) .replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') .replace(/([ \t]+)/g, (_match, g1) => ' '.repeat(g1.length)) .replace(/^>/gm, '\\>') diff --git a/src/vs/base/common/iconLabels.ts b/src/vs/base/common/iconLabels.ts new file mode 100644 index 00000000000..8ad65bee767 --- /dev/null +++ b/src/vs/base/common/iconLabels.ts @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { matchesFuzzy, IMatch } from 'vs/base/common/filters'; +import { ltrim } from 'vs/base/common/strings'; + +export const iconStartMarker = '$('; + +const escapeIconsRegex = /(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi; +export function escapeIcons(text: string): string { + return text.replace(escapeIconsRegex, (match, escaped) => escaped ? match : `\\${match}`); +} + +const markdownEscapedIconsRegex = /\\\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi; +export function markdownEscapeEscapedIcons(text: string): string { + // Need to add an extra \ for escaping in markdown + return text.replace(markdownEscapedIconsRegex, match => `\\${match}`); +} + +const markdownUnescapeIconsRegex = /(\\)?\$\\\(([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?)\\\)/gi; +export function markdownUnescapeIcons(text: string): string { + return text.replace(markdownUnescapeIconsRegex, (match, escaped, iconId) => escaped ? match : `$(${iconId})`); +} + +const stripIconsRegex = /(\s)?(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)(\s)?/gi; +export function stripIcons(text: string): string { + if (text.indexOf(iconStartMarker) === -1) { + return text; + } + + return text.replace(stripIconsRegex, (match, preWhitespace, escaped, postWhitespace) => escaped ? match : preWhitespace || postWhitespace || ''); +} + + +export interface IParsedLabelWithIcons { + readonly text: string; + readonly iconOffsets?: readonly number[]; +} + +export function parseLabelWithIcons(text: string): IParsedLabelWithIcons { + const firstIconIndex = text.indexOf(iconStartMarker); + if (firstIconIndex === -1) { + return { text }; // return early if the word does not include an icon + } + + return doParseLabelWithIcons(text, firstIconIndex); +} + +function doParseLabelWithIcons(text: string, firstIconIndex: number): IParsedLabelWithIcons { + const iconOffsets: number[] = []; + let textWithoutIcons: string = ''; + + function appendChars(chars: string) { + if (chars) { + textWithoutIcons += chars; + + for (const _ of chars) { + iconOffsets.push(iconsOffset); // make sure to fill in icon offsets + } + } + } + + let currentIconStart = -1; + let currentIconValue: string = ''; + let iconsOffset = 0; + + let char: string; + let nextChar: string; + + let offset = firstIconIndex; + const length = text.length; + + // Append all characters until the first icon + appendChars(text.substr(0, firstIconIndex)); + + // example: $(file-symlink-file) my cool $(other-icon) entry + while (offset < length) { + char = text[offset]; + nextChar = text[offset + 1]; + + // beginning of icon: some value $( <-- + if (char === iconStartMarker[0] && nextChar === iconStartMarker[1]) { + currentIconStart = offset; + + // if we had a previous potential icon value without + // the closing ')', it was actually not an icon and + // so we have to add it to the actual value + appendChars(currentIconValue); + + currentIconValue = iconStartMarker; + + offset++; // jump over '(' + } + + // end of icon: some value $(some-icon) <-- + else if (char === ')' && currentIconStart !== -1) { + const currentIconLength = offset - currentIconStart + 1; // +1 to include the closing ')' + iconsOffset += currentIconLength; + currentIconStart = -1; + currentIconValue = ''; + } + + // within icon + else if (currentIconStart !== -1) { + // Make sure this is a real icon name + if (/^[a-z0-9\-]$/i.test(char)) { + currentIconValue += char; + } else { + // This is not a real icon, treat it as text + appendChars(currentIconValue); + + currentIconStart = -1; + currentIconValue = ''; + } + } + + // any value outside of icon + else { + appendChars(char); + } + + offset++; + } + + // if we had a previous potential icon value without + // the closing ')', it was actually not an icon and + // so we have to add it to the actual value + appendChars(currentIconValue); + + return { text: textWithoutIcons, iconOffsets }; +} + +export function matchesFuzzyIconAware(query: string, target: IParsedLabelWithIcons, enableSeparateSubstringMatching = false): IMatch[] | null { + const { text, iconOffsets } = target; + + // Return early if there are no icon markers in the word to match against + if (!iconOffsets || iconOffsets.length === 0) { + return matchesFuzzy(query, text, enableSeparateSubstringMatching); + } + + // Trim the word to match against because it could have leading + // whitespace now if the word started with an icon + const wordToMatchAgainstWithoutIconsTrimmed = ltrim(text, ' '); + const leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutIconsTrimmed.length; + + // match on value without icon + const matches = matchesFuzzy(query, wordToMatchAgainstWithoutIconsTrimmed, enableSeparateSubstringMatching); + + // Map matches back to offsets with icon and trimming + if (matches) { + for (const match of matches) { + const iconOffset = iconOffsets[match.start + leadingWhitespaceOffset] /* icon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */; + match.start += iconOffset; + match.end += iconOffset; + } + } + + return matches; +} diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index bddbd8a6eb9..038816012f3 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -30,7 +30,7 @@ import { Color } from 'vs/base/common/color'; import { registerCodicon, Codicon } from 'vs/base/common/codicons'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { escape } from 'vs/base/common/strings'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; export interface IQuickInputOptions { idPrefix: string; @@ -72,7 +72,7 @@ const $ = dom.$; type Writeable = { -readonly [P in keyof T]: T[P] }; -const backButtonIcon = registerCodicon('quick-input-back', Codicon.arrowLeft, localize('backButtonIcon', 'Icon for the back button in the quick input dialog.')); +const backButtonIcon = registerCodicon('quick-input-back', Codicon.arrowLeft); const backButton = { iconClass: backButtonIcon.classNames, @@ -967,7 +967,7 @@ class QuickPick extends QuickInput implements IQuickPi const validationMessage = this.validationMessage || ''; if (this._lastValidationMessage !== validationMessage) { this._lastValidationMessage = validationMessage; - dom.reset(this.ui.message, ...renderCodicons(escape(validationMessage))); + dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage))); this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore); } this.ui.customButton.label = this.customLabel || ''; @@ -1103,7 +1103,7 @@ class InputBox extends QuickInput implements IInputBox { const validationMessage = this.validationMessage || this.noValidationMessage; if (this._lastValidationMessage !== validationMessage) { this._lastValidationMessage = validationMessage; - dom.reset(this.ui.message, ...renderCodicons(validationMessage)); + dom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage)); this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore); } } diff --git a/src/vs/base/parts/quickinput/browser/quickInputList.ts b/src/vs/base/parts/quickinput/browser/quickInputList.ts index 0973f0c1446..056daff0784 100644 --- a/src/vs/base/parts/quickinput/browser/quickInputList.ts +++ b/src/vs/base/parts/quickinput/browser/quickInputList.ts @@ -9,7 +9,7 @@ import * as dom from 'vs/base/browser/dom'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator } from 'vs/base/parts/quickinput/common/quickInput'; import { IMatch } from 'vs/base/common/filters'; -import { matchesFuzzyCodiconAware, parseCodicons } from 'vs/base/common/codicon'; +import { matchesFuzzyIconAware, parseLabelWithIcons } from 'vs/base/common/iconLabels'; import { compareAnything } from 'vs/base/common/comparers'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -127,7 +127,7 @@ class ListElementRenderer implements IListRenderer s && parseCodicons(s).text) + .map(s => s && parseLabelWithIcons(s).text) .filter(s => !!s) .join(', '); @@ -596,12 +596,12 @@ export class QuickInputList { }); } - // Filter by value (since we support codicons, use codicon aware fuzzy matching) + // Filter by value (since we support icons in labels, use $(..) aware fuzzy matching) else { this.elements.forEach(element => { - const labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesFuzzyCodiconAware(query, parseCodicons(element.saneLabel))) : undefined; - const descriptionHighlights = this.matchOnDescription ? withNullAsUndefined(matchesFuzzyCodiconAware(query, parseCodicons(element.saneDescription || ''))) : undefined; - const detailHighlights = this.matchOnDetail ? withNullAsUndefined(matchesFuzzyCodiconAware(query, parseCodicons(element.saneDetail || ''))) : undefined; + const labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneLabel))) : undefined; + const descriptionHighlights = this.matchOnDescription ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDescription || ''))) : undefined; + const detailHighlights = this.matchOnDetail ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDetail || ''))) : undefined; if (labelHighlights || descriptionHighlights || detailHighlights) { element.labelHighlights = labelHighlights; diff --git a/src/vs/base/test/browser/codicons.test.ts b/src/vs/base/test/browser/iconLabels.test.ts similarity index 64% rename from src/vs/base/test/browser/codicons.test.ts rename to src/vs/base/test/browser/iconLabels.test.ts index bd9e432921d..db81e37a514 100644 --- a/src/vs/base/test/browser/codicons.test.ts +++ b/src/vs/base/test/browser/iconLabels.test.ts @@ -3,43 +3,43 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import * as assert from 'assert'; -suite('renderCodicons', () => { +suite('renderLabelWithIcons', () => { - test('no codicons', () => { - const result = renderCodicons(' hello World .'); + test('no icons', () => { + const result = renderLabelWithIcons(' hello World .'); assert.equal(elementsToString(result), ' hello World .'); }); - test('codicon only', () => { - const result = renderCodicons('$(alert)'); + test('icons only', () => { + const result = renderLabelWithIcons('$(alert)'); assert.equal(elementsToString(result), ''); }); - test('codicon and non-codicon strings', () => { - const result = renderCodicons(` $(alert) Unresponsive`); + test('icon and non-icon strings', () => { + const result = renderLabelWithIcons(` $(alert) Unresponsive`); assert.equal(elementsToString(result), ' Unresponsive'); }); - test('multiple codicons', () => { - const result = renderCodicons('$(check)$(error)'); + test('multiple icons', () => { + const result = renderLabelWithIcons('$(check)$(error)'); assert.equal(elementsToString(result), ''); }); - test('escaped codicon', () => { - const result = renderCodicons('\\$(escaped)'); + test('escaped icons', () => { + const result = renderLabelWithIcons('\\$(escaped)'); assert.equal(elementsToString(result), '$(escaped)'); }); - test('codicon with animation', () => { - const result = renderCodicons('$(zip~anim)'); + test('icon with animation', () => { + const result = renderLabelWithIcons('$(zip~anim)'); assert.equal(elementsToString(result), ''); }); diff --git a/src/vs/base/test/common/codicon.test.ts b/src/vs/base/test/common/codicon.test.ts deleted file mode 100644 index 8d974ea0ad4..00000000000 --- a/src/vs/base/test/common/codicon.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { IMatch } from 'vs/base/common/filters'; -import { matchesFuzzyCodiconAware, parseCodicons, IParsedCodicons } from 'vs/base/common/codicon'; -import { stripCodicons } from 'vs/base/common/codicons'; - -export interface ICodiconFilter { - // Returns null if word doesn't match. - (query: string, target: IParsedCodicons): IMatch[] | null; -} - -function filterOk(filter: ICodiconFilter, word: string, target: IParsedCodicons, highlights?: { start: number; end: number; }[]) { - let r = filter(word, target); - assert(r); - if (highlights) { - assert.deepEqual(r, highlights); - } -} - -suite('Codicon', () => { - test('matchesFuzzzyCodiconAware', () => { - - // Camel Case - - filterOk(matchesFuzzyCodiconAware, 'ccr', parseCodicons('$(codicon)CamelCaseRocks$(codicon)'), [ - { start: 10, end: 11 }, - { start: 15, end: 16 }, - { start: 19, end: 20 } - ]); - - filterOk(matchesFuzzyCodiconAware, 'ccr', parseCodicons('$(codicon) CamelCaseRocks $(codicon)'), [ - { start: 11, end: 12 }, - { start: 16, end: 17 }, - { start: 20, end: 21 } - ]); - - filterOk(matchesFuzzyCodiconAware, 'iut', parseCodicons('$(codicon) Indent $(octico) Using $(octic) Tpaces'), [ - { start: 11, end: 12 }, - { start: 28, end: 29 }, - { start: 43, end: 44 }, - ]); - - // Prefix - - filterOk(matchesFuzzyCodiconAware, 'using', parseCodicons('$(codicon) Indent Using Spaces'), [ - { start: 18, end: 23 }, - ]); - - // Broken Codicon - - filterOk(matchesFuzzyCodiconAware, 'codicon', parseCodicons('This $(codicon Indent Using Spaces'), [ - { start: 7, end: 14 }, - ]); - - filterOk(matchesFuzzyCodiconAware, 'indent', parseCodicons('This $codicon Indent Using Spaces'), [ - { start: 14, end: 20 }, - ]); - - // Testing #59343 - filterOk(matchesFuzzyCodiconAware, 'unt', parseCodicons('$(primitive-dot) $(file-text) Untitled-1'), [ - { start: 30, end: 33 }, - ]); - }); -}); - -suite('Codicons', () => { - - test('stripCodicons', () => { - assert.equal(stripCodicons('Hello World'), 'Hello World'); - assert.equal(stripCodicons('$(Hello World'), '$(Hello World'); - assert.equal(stripCodicons('$(Hello) World'), ' World'); - assert.equal(stripCodicons('$(Hello) W$(oi)rld'), ' Wrld'); - }); -}); diff --git a/src/vs/base/test/common/iconLabels.test.ts b/src/vs/base/test/common/iconLabels.test.ts new file mode 100644 index 00000000000..998c6897176 --- /dev/null +++ b/src/vs/base/test/common/iconLabels.test.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IMatch } from 'vs/base/common/filters'; +import { matchesFuzzyIconAware, parseLabelWithIcons, IParsedLabelWithIcons, stripIcons } from 'vs/base/common/iconLabels'; + +export interface IIconFilter { + // Returns null if word doesn't match. + (query: string, target: IParsedLabelWithIcons): IMatch[] | null; +} + +function filterOk(filter: IIconFilter, word: string, target: IParsedLabelWithIcons, highlights?: { start: number; end: number; }[]) { + let r = filter(word, target); + assert(r); + if (highlights) { + assert.deepEqual(r, highlights); + } +} + +suite('Icon Labels', () => { + test('matchesFuzzyIconAware', () => { + + // Camel Case + + filterOk(matchesFuzzyIconAware, 'ccr', parseLabelWithIcons('$(codicon)CamelCaseRocks$(codicon)'), [ + { start: 10, end: 11 }, + { start: 15, end: 16 }, + { start: 19, end: 20 } + ]); + + filterOk(matchesFuzzyIconAware, 'ccr', parseLabelWithIcons('$(codicon) CamelCaseRocks $(codicon)'), [ + { start: 11, end: 12 }, + { start: 16, end: 17 }, + { start: 20, end: 21 } + ]); + + filterOk(matchesFuzzyIconAware, 'iut', parseLabelWithIcons('$(codicon) Indent $(octico) Using $(octic) Tpaces'), [ + { start: 11, end: 12 }, + { start: 28, end: 29 }, + { start: 43, end: 44 }, + ]); + + // Prefix + + filterOk(matchesFuzzyIconAware, 'using', parseLabelWithIcons('$(codicon) Indent Using Spaces'), [ + { start: 18, end: 23 }, + ]); + + // Broken Codicon + + filterOk(matchesFuzzyIconAware, 'codicon', parseLabelWithIcons('This $(codicon Indent Using Spaces'), [ + { start: 7, end: 14 }, + ]); + + filterOk(matchesFuzzyIconAware, 'indent', parseLabelWithIcons('This $codicon Indent Using Spaces'), [ + { start: 14, end: 20 }, + ]); + + // Testing #59343 + filterOk(matchesFuzzyIconAware, 'unt', parseLabelWithIcons('$(primitive-dot) $(file-text) Untitled-1'), [ + { start: 30, end: 33 }, + ]); + }); + + test('stripIcons', () => { + assert.equal(stripIcons('Hello World'), 'Hello World'); + assert.equal(stripIcons('$(Hello World'), '$(Hello World'); + assert.equal(stripIcons('$(Hello) World'), ' World'); + assert.equal(stripIcons('$(Hello) W$(oi)rld'), ' Wrld'); + }); +}); diff --git a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts index 252260a5754..f2dae0f632c 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts @@ -11,7 +11,6 @@ import { ipcRenderer, process } from 'vs/base/parts/sandbox/electron-sandbox/glo import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window'; import { $, reset, safeInnerHtml, windowOpenNoOpener } from 'vs/base/browser/dom'; import { Button } from 'vs/base/browser/ui/button/button'; -import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; import * as collections from 'vs/base/common/collections'; import { debounce } from 'vs/base/common/decorators'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -26,6 +25,8 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { Codicon } from 'vs/base/common/codicons'; +import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; const MAX_URL_LENGTH = 2045; @@ -598,8 +599,7 @@ export class IssueReporter extends Disposable { issueState = $('span.issue-state'); const issueIcon = $('span.issue-icon'); - const codicon = new CodiconLabel(issueIcon); - codicon.text = issue.state === 'open' ? '$(issue-opened)' : '$(issue-closed)'; + issueIcon.appendChild(renderIcon(issue.state === 'open' ? Codicon.issueOpened : Codicon.issueClosed)); const issueStateLabel = $('span.issue-state.label'); issueStateLabel.textContent = issue.state === 'open' ? localize('open', "Open") : localize('closed', "Closed"); diff --git a/src/vs/editor/contrib/codelens/codelensWidget.ts b/src/vs/editor/contrib/codelens/codelensWidget.ts index f77b2dfc5b4..9014c904a2a 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.ts +++ b/src/vs/editor/contrib/codelens/codelensWidget.ts @@ -14,7 +14,7 @@ import { editorCodeLensForeground } from 'vs/editor/common/view/editorColorRegis import { CodeLensItem } from 'vs/editor/contrib/codelens/codelens'; import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; class CodeLensViewZone implements IViewZone { @@ -88,7 +88,7 @@ class CodeLensContentWidget implements IContentWidget { } hasSymbol = true; if (lens.command) { - const title = renderCodicons(lens.command.title.trim()); + const title = renderLabelWithIcons(lens.command.title.trim()); if (lens.command.id) { children.push(dom.$('a', { id: String(i) }, ...title)); this._commands.set(String(i), lens.command); diff --git a/src/vs/editor/contrib/quickAccess/commandsQuickAccess.ts b/src/vs/editor/contrib/quickAccess/commandsQuickAccess.ts index 7db794fa83e..ec7d2ab922e 100644 --- a/src/vs/editor/contrib/quickAccess/commandsQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/commandsQuickAccess.ts @@ -10,7 +10,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { stripCodicons } from 'vs/base/common/codicons'; +import { stripIcons } from 'vs/base/common/iconLabels'; export abstract class AbstractEditorCommandsQuickAccessProvider extends AbstractCommandsQuickAccessProvider { @@ -41,7 +41,7 @@ export abstract class AbstractEditorCommandsQuickAccessProvider extends Abstract editorCommandPicks.push({ commandId: editorAction.id, commandAlias: editorAction.alias, - label: stripCodicons(editorAction.label) || editorAction.id, + label: stripIcons(editorAction.label) || editorAction.id, }); } diff --git a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts index 26cdc77ae04..71098fe0628 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts @@ -117,7 +117,7 @@ export class ItemRenderer implements IListRenderer { this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href }); diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 8f62ac8d999..01f318e9aa6 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -375,21 +375,6 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestart)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestartFrame)} { color: ${debugIconRestartColor} !important; }`); } - const debugIconStepOverColor = theme.getColor(debugIconStepOverForeground); - if (debugIconStepOverColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOver)} { color: ${debugIconStepOverColor} !important; }`); - } - - const debugIconStepIntoColor = theme.getColor(debugIconStepIntoForeground); - if (debugIconStepIntoColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepInto)} { color: ${debugIconStepIntoColor} !important; }`); - } - - const debugIconStepOutColor = theme.getColor(debugIconStepOutForeground); - if (debugIconStepOutColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOut)} { color: ${debugIconStepOutColor} !important; }`); - } - const debugIconContinueColor = theme.getColor(debugIconContinueForeground); if (debugIconContinueColor) { collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugContinue)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugReverseContinue)} { color: ${debugIconContinueColor} !important; }`); diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index 96c54f0a83a..8e0a3cea178 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -27,7 +27,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati 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 { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -346,28 +346,28 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { clearNode(data.msgContainer); if (this._getUnresponsiveProfile(element.description.identifier)) { - const el = $('span', undefined, ...renderCodicons(` $(alert) Unresponsive`)); + const el = $('span', undefined, ...renderLabelWithIcons(` $(alert) Unresponsive`)); el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze."); data.msgContainer.appendChild(el); } if (isNonEmptyArray(element.status.runtimeErrors)) { - const el = $('span', undefined, ...renderCodicons(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`)); + const el = $('span', undefined, ...renderLabelWithIcons(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`)); data.msgContainer.appendChild(el); } if (element.status.messages && element.status.messages.length > 0) { - const el = $('span', undefined, ...renderCodicons(`$(alert) ${element.status.messages[0].message}`)); + const el = $('span', undefined, ...renderLabelWithIcons(`$(alert) ${element.status.messages[0].message}`)); data.msgContainer.appendChild(el); } if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { - const el = $('span', undefined, ...renderCodicons(`$(remote) ${element.description.extensionLocation.authority}`)); + const el = $('span', undefined, ...renderLabelWithIcons(`$(remote) ${element.description.extensionLocation.authority}`)); data.msgContainer.appendChild(el); const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); if (hostLabel) { - reset(el, ...renderCodicons(`$(remote) ${hostLabel}`)); + reset(el, ...renderLabelWithIcons(`$(remote) ${hostLabel}`)); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index a6c71a531c6..4b498bf5e78 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -29,9 +29,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Delayer } from 'vs/base/common/async'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; const fixedEditorOptions: IEditorOptions = { padding: { @@ -203,9 +202,9 @@ class PropertyHeader extends Disposable { private _updateFoldingIcon() { if (this.accessor.getFoldingState(this.cell) === PropertyFoldingState.Collapsed) { - DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(collapsedIcon))); + DOM.reset(this._foldingIndicator, renderIcon(collapsedIcon)); } else { - DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(expandedIcon))); + DOM.reset(this._foldingIndicator, renderIcon(expandedIcon)); } } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts index 3ded6bb42b2..886a0e942c9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellActionView.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import * as DOM from 'vs/base/browser/dom'; import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Action, IAction, Separator } from 'vs/base/common/actions'; @@ -91,7 +91,7 @@ export class CodiconActionViewItem extends MenuEntryActionViewItem { } updateLabel(): void { if (this.options.label && this.label) { - DOM.reset(this.label, ...renderCodicons(this._commandAction.label ?? '')); + DOM.reset(this.label, ...renderLabelWithIcons(this._commandAction.label ?? '')); } } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index ba8b9bb81b1..e912f94e816 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -10,7 +10,7 @@ import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/lis import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IAction } from 'vs/base/common/actions'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -51,6 +51,7 @@ import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, Not import { CodiconActionViewItem, createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { errorStateIcon, successStateIcon, unfoldIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { syncing } from 'vs/platform/theme/common/iconRegistry'; const $ = DOM.$; @@ -1052,11 +1053,11 @@ export class RunStateRenderer { } if (runState === NotebookCellRunState.Success) { - DOM.reset(this.element, ...renderCodicons(ThemeIcon.asCodiconLabel(successStateIcon))); + DOM.reset(this.element, renderIcon(successStateIcon)); } else if (runState === NotebookCellRunState.Error) { - DOM.reset(this.element, ...renderCodicons(ThemeIcon.asCodiconLabel(errorStateIcon))); + DOM.reset(this.element, renderIcon(errorStateIcon)); } else if (runState === NotebookCellRunState.Running) { - DOM.reset(this.element, ...renderCodicons('$(sync~spin)')); + DOM.reset(this.element, renderIcon(syncing)); this.spinnerTimer = setTimeout(() => { this.spinnerTimer = undefined; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index 6be1604eea1..bf8ff332dab 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -5,9 +5,9 @@ import * as DOM from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; +import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel'; import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; -import { stripCodicons } from 'vs/base/common/codicons'; +import { stripIcons } from 'vs/base/common/iconLabels'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -160,7 +160,7 @@ class CellStatusBarItem extends Disposable { @INotificationService private readonly notificationService: INotificationService ) { super(); - new CodiconLabel(this.container).text = this._itemModel.text; + new SimpleIconLabel(this.container).text = this._itemModel.text; if (this._itemModel.opacity) { this.container.style.opacity = this._itemModel.opacity; @@ -172,7 +172,7 @@ class CellStatusBarItem extends Disposable { ariaLabel = this._itemModel.accessibilityInformation.label; role = this._itemModel.accessibilityInformation.role; } else { - ariaLabel = this._itemModel.text ? stripCodicons(this._itemModel.text).trim() : ''; + ariaLabel = this._itemModel.text ? stripIcons(this._itemModel.text).trim() : ''; } if (ariaLabel) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index da2e04bc65c..7ca17c7b555 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -21,9 +21,8 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { getExecuteCellPlaceholder, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; export class StatefulMarkdownCell extends Disposable { @@ -355,10 +354,10 @@ export class StatefulMarkdownCell extends Disposable { this.templateData.foldingIndicator.innerText = ''; break; case CellFoldingState.Collapsed: - DOM.reset(this.templateData.foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(collapsedIcon))); + DOM.reset(this.templateData.foldingIndicator, renderIcon(collapsedIcon)); break; case CellFoldingState.Expanded: - DOM.reset(this.templateData.foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(expandedIcon))); + DOM.reset(this.templateData.foldingIndicator, renderIcon(expandedIcon)); break; default: diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 3b26e64a130..6a74b8a95c8 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -49,7 +49,7 @@ import { ISetting, ISettingsGroup, SettingValueType } from 'vs/workbench/service import { getDefaultIgnoredSettings, IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; import { getInvalidTypeError } from 'vs/workbench/services/preferences/common/preferencesValidation'; import { Codicon } from 'vs/base/common/codicons'; -import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; +import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { IList } from 'vs/base/browser/ui/tree/indexTreeModel'; import { IListService, WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; @@ -552,7 +552,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre protected createSyncIgnoredElement(container: HTMLElement): HTMLElement { const syncIgnoredElement = DOM.append(container, $('span.setting-item-ignored')); - const syncIgnoredLabel = new CodiconLabel(syncIgnoredElement); + const syncIgnoredLabel = new SimpleIconLabel(syncIgnoredElement); syncIgnoredLabel.text = `($(sync-ignored) ${localize('extensionSyncIgnoredLabel', 'Sync: Ignored')})`; return syncIgnoredElement; diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index d742a1d2821..54129ffb298 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -22,7 +22,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess'; -import { Codicon, stripCodicons } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -30,6 +30,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { stripIcons } from 'vs/base/common/iconLabels'; export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider { @@ -136,7 +137,7 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce globalCommandPicks.push({ commandId: action.item.id, commandAlias, - label: stripCodicons(label) + label: stripIcons(label) }); } diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index 1c0d1e0e3ad..664dea50728 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -11,7 +11,7 @@ import { Action, IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { equals } from 'vs/base/common/arrays'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; -import { renderCodicons } from 'vs/base/browser/codicons'; +import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { Command } from 'vs/editor/common/modes'; import { basename } from 'vs/base/common/resources'; @@ -104,7 +104,7 @@ export class StatusBarActionViewItem extends ActionViewItem { updateLabel(): void { if (this.options.label && this.label) { - reset(this.label, ...renderCodicons(this.getAction().label)); + reset(this.label, ...renderLabelWithIcons(this.getAction().label)); } } } diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 4bf8fee7aeb..9ea5ebd262a 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -48,8 +48,9 @@ import { once } from 'vs/base/common/functional'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { getIEditor } from 'vs/editor/browser/editorBrowser'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { Codicon, stripCodicons } from 'vs/base/common/codicons'; +import { Codicon } from 'vs/base/common/codicons'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { stripIcons } from 'vs/base/common/iconLabels'; interface IAnythingQuickPickItem extends IPickerQuickAccessItem, IQuickPickItemWithResource { } @@ -815,7 +816,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider Date: Wed, 16 Dec 2020 14:16:35 +0100 Subject: [PATCH 1086/1837] empty From 3b5cdf3a0ebe0ae332499cfa8b058b468a784dfc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 16 Dec 2020 14:37:32 +0100 Subject: [PATCH 1087/1837] backup - move progress reporting into place where save actually happens --- .../backup/electron-sandbox/backupTracker.ts | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts index 60a54808e43..86cf5ff2378 100644 --- a/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts @@ -90,19 +90,8 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont // and then check again for dirty copies if (this.filesConfigurationService.getAutoSaveMode() !== AutoSaveMode.OFF) { - // Save all files but show progress and allow to cancel - // (https://github.com/microsoft/vscode/issues/112278) - const cts = new CancellationTokenSource(); - await this.progressService.withProgress({ - location: ProgressLocation.Notification, - cancellable: true, - delay: 800, // delay notification so that it only appears when saving takes a long time - title: localize('saveBeforeShutdown', "Waiting for dirty editors to save...") - }, () => { - const autoSavePromise = this.doSaveAllBeforeShutdown(false /* not untitled */, SaveReason.AUTO); - - return raceCancellation(autoSavePromise, cts.token); - }, () => cts.dispose(true)); + // Save all files + await this.doSaveAllBeforeShutdown(false /* not untitled */, SaveReason.AUTO); // If we still have dirty working copies, we either have untitled ones or working copies that cannot be saved const remainingDirtyWorkingCopies = this.workingCopyService.dirtyWorkingCopies; @@ -248,9 +237,9 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont return true; // veto (user canceled) } - private async doSaveAllBeforeShutdown(workingCopies: IWorkingCopy[], reason: SaveReason): Promise; - private async doSaveAllBeforeShutdown(includeUntitled: boolean, reason: SaveReason): Promise; - private async doSaveAllBeforeShutdown(arg1: IWorkingCopy[] | boolean, reason: SaveReason): Promise { + private doSaveAllBeforeShutdown(workingCopies: IWorkingCopy[], reason: SaveReason): Promise; + private doSaveAllBeforeShutdown(includeUntitled: boolean, reason: SaveReason): Promise; + private doSaveAllBeforeShutdown(arg1: IWorkingCopy[] | boolean, reason: SaveReason): Promise { const workingCopies = Array.isArray(arg1) ? arg1 : this.workingCopyService.dirtyWorkingCopies.filter(workingCopy => { if (arg1 === false && (workingCopy.capabilities & WorkingCopyCapabilities.Untitled)) { return false; // skip untitled unless explicitly included @@ -259,21 +248,34 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont return true; }); - // Skip save participants on shutdown for performance reasons - const saveOptions = { skipSaveParticipants: true, reason }; + const cts = new CancellationTokenSource(); + return this.progressService.withProgress({ + location: ProgressLocation.Notification, + cancellable: true, // for https://github.com/microsoft/vscode/issues/112278 + delay: 800, // delay notification so that it only appears when saving takes a long time + title: localize('saveBeforeShutdown', "Waiting for dirty editors to save...") + }, () => { + const saveAllPromise = (async () => { - // First save through the editor service if we save all to benefit - // from some extras like switching to untitled dirty editors before saving. - let result: boolean | undefined = undefined; - if (typeof arg1 === 'boolean' || workingCopies.length === this.workingCopyService.dirtyCount) { - result = await this.editorService.saveAll({ includeUntitled: typeof arg1 === 'boolean' ? arg1 : true, ...saveOptions }); - } + // Skip save participants on shutdown for performance reasons + const saveOptions = { skipSaveParticipants: true, reason }; - // If we still have dirty working copies, save those directly - // unless the save was not successful (e.g. cancelled) - if (result !== false) { - await Promise.all(workingCopies.map(workingCopy => workingCopy.isDirty() ? workingCopy.save(saveOptions) : true)); - } + // First save through the editor service if we save all to benefit + // from some extras like switching to untitled dirty editors before saving. + let result: boolean | undefined = undefined; + if (typeof arg1 === 'boolean' || workingCopies.length === this.workingCopyService.dirtyCount) { + result = await this.editorService.saveAll({ includeUntitled: typeof arg1 === 'boolean' ? arg1 : true, ...saveOptions }); + } + + // If we still have dirty working copies, save those directly + // unless the save was not successful (e.g. cancelled) + if (result !== false) { + await Promise.all(workingCopies.map(workingCopy => workingCopy.isDirty() ? workingCopy.save(saveOptions) : true)); + } + })(); + + return raceCancellation(saveAllPromise, cts.token); + }, () => cts.dispose(true)); } private async doRevertAllBeforeShutdown(workingCopies: IWorkingCopy[]): Promise { From 018b924fee2b2eff2d803c55faf54d30f1293c15 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 16 Dec 2020 14:55:51 +0100 Subject: [PATCH 1088/1837] add logging for #112649 --- .../contrib/files/test/browser/textFileEditor.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts b/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts index 9b346315b6c..5577b01eb9b 100644 --- a/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts +++ b/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts @@ -27,6 +27,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; +import { raceTimeout } from 'vs/base/common/async'; suite('Files - TextFileEditor', () => { @@ -73,7 +74,7 @@ suite('Files - TextFileEditor', () => { const accessor = instantiationService.createInstance(TestServiceAccessor); - await part.whenRestored; + await raceTimeout(part.whenRestored, 2000, () => assert.fail('textFileEditor.test.ts: Unexpected long time to wait for part to restore (#112649)')); return [part, accessor, instantiationService, editorService]; } From a780c7d4515315d9741c72b318023695bb9fa30c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 14:57:30 +0100 Subject: [PATCH 1089/1837] spell out GDPR types instead of using mapped types --- src/vs/workbench/services/timer/browser/timerService.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 52e7a9bf8a1..59e035f6734 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -465,7 +465,12 @@ export abstract class AbstractTimerService implements ITimerService { // defines the start for (const [source, marks] of this.getPerformanceMarks()) { type Mark = { source: string; name: string; relativeStartTime: number; startTime: number }; - type MarkClassification = { [K in keyof Mark]: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' } }; + type MarkClassification = { + source: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }, + name: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }, + relativeStartTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }, + startTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }, + }; let lastMark: perf.PerformanceMark = marks[0]; for (const mark of marks) { From ce1ffe0e7f891f886b6e7b36b86591f11430e2c8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 15:12:05 +0100 Subject: [PATCH 1090/1837] link webkit issue for missing timeOrigin support --- src/vs/base/common/performance.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index ceb864ebf24..ac8c2cdb714 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -56,6 +56,7 @@ function _define() { let timeOrigin = performance.timeOrigin; if (typeof timeOrigin !== 'number') { // safari: there is no timerOrigin but in renderers there is the timing-property + // see https://bugs.webkit.org/show_bug.cgi?id=174862 timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart; } const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; From 7db8e3b08c08b8170ae4c4a56781f06aad077fb7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 15:34:04 +0100 Subject: [PATCH 1091/1837] fix https://github.com/microsoft/vscode/issues/112418 --- src/vs/editor/contrib/gotoSymbol/referencesModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/gotoSymbol/referencesModel.ts b/src/vs/editor/contrib/gotoSymbol/referencesModel.ts index 334928f3cf5..63f6b95274b 100644 --- a/src/vs/editor/contrib/gotoSymbol/referencesModel.ts +++ b/src/vs/editor/contrib/gotoSymbol/referencesModel.ts @@ -51,7 +51,7 @@ export class OneReference { ); } else { return localize( - 'aria.oneReference.preview', "symbol in {0} on line {1} at column {2}, {3}", + { key: 'aria.oneReference.preview', comment: ['Placeholders are: 0: filename, 1:line number, 2: column number, 3: preview snippet of source code'] }, "symbol in {0} on line {1} at column {2}, {3}", basename(this.uri), this.range.startLineNumber, this.range.startColumn, preview.value ); } From d5a632e6fcfe56036faa6da7bf7f6b58772765d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 15:48:12 +0100 Subject: [PATCH 1092/1837] empty From b4b8bcda47998afa5d867d6f7a855b5fe155fb08 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 16:03:06 +0100 Subject: [PATCH 1093/1837] tweak padding-right for decorations --- src/vs/workbench/browser/parts/editor/media/titlecontrol.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css index e26475babd3..97accf43c74 100644 --- a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css @@ -26,7 +26,9 @@ cursor: pointer; } -.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::after { +/* By defalut the icon label has a padding right and this isn't wanted when not showing tabs and not showing breadcrumbs */ +.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .monaco-icon-label::after, +.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs .monaco-icon-label::after { padding-right: 0; } From ad362089bea798b2ebc204d23b8534367e1d5e5c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 16:15:32 +0100 Subject: [PATCH 1094/1837] add proposal of CancellationError, https://github.com/microsoft/vscode/issues/93686 --- src/vs/base/common/errors.ts | 9 +++++++++ src/vs/vscode.proposed.d.ts | 19 +++++++++++++++++++ .../workbench/api/common/extHost.api.impl.ts | 3 +++ 3 files changed, 31 insertions(+) diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index f6d4f5cf893..8c8e874e853 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -142,6 +142,15 @@ export function isPromiseCanceledError(error: any): boolean { return error instanceof Error && error.name === canceledName && error.message === canceledName; } +// !!!IMPORTANT!!! +// Do NOT change this class because it is also used as an API-type. +export class CancellationError extends Error { + constructor() { + super(canceledName); + this.name = this.message; + } +} + /** * Returns an error that signals cancellation. */ diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index f40d195d03b..71ebc8f4990 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -18,6 +18,25 @@ import { Command } from 'vscode'; declare module 'vscode' { + //#region https://github.com/microsoft/vscode/issues/93686 + + /** + * An error type should be used to signal cancellation of an operation. + * + * This type can be used in response to a cancellation token or when an + * operation is being cancelled by the executor of that operation. + */ + export class CancellationError extends Error { + + /** + * Creates a new cancellation error. + */ + constructor(); + } + + + //#endregion + // #region auth provider: https://github.com/microsoft/vscode/issues/88309 /** diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 00564b6db78..6d6bdd4bd2d 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1212,6 +1212,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ViewColumn: extHostTypes.ViewColumn, WorkspaceEdit: extHostTypes.WorkspaceEdit, // proposed api types + get CancellationError() { + return errors.CancellationError; + }, get RemoteAuthorityResolverError() { // checkProposedApiEnabled(extension); return extHostTypes.RemoteAuthorityResolverError; From 6236a5bf8b5a461e115bed0feda8cac93ba4d7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 16:19:36 +0100 Subject: [PATCH 1095/1837] compile: use artifacts instead of cache --- .artifactignore | 3 ++ .../linux/product-build-linux.yml | 18 ++------ build/azure-pipelines/product-compile.yml | 45 ++++--------------- 3 files changed, 15 insertions(+), 51 deletions(-) create mode 100644 .artifactignore diff --git a/.artifactignore b/.artifactignore new file mode 100644 index 00000000000..bd76fdab400 --- /dev/null +++ b/.artifactignore @@ -0,0 +1,3 @@ +**/* +!.build/** +!out-*/** \ No newline at end of file diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 5b258aec975..567512e07c2 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,18 +1,7 @@ steps: - - script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - echo -n $ENABLE_TERRAPIN > .build/terrapin - displayName: Prepare compilation cache flags - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" - vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" + - download: current + artifact: CompilationOutput + path: $(System.DefaultWorkingDirectory) - script: | set -e @@ -59,6 +48,7 @@ steps: - script: | echo -n $(VSCODE_ARCH) > .build/arch + echo -n $ENABLE_TERRAPIN > .build/terrapin displayName: Prepare yarn cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index f72cf0151b0..ba6deeec43c 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -1,36 +1,17 @@ steps: - - script: | - mkdir -p .build - echo -n $BUILD_SOURCEVERSION > .build/commit - echo -n $VSCODE_QUALITY > .build/quality - echo -n $ENABLE_TERRAPIN > .build/terrapin - displayName: Prepare compilation cache flag - - - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" - vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" - dryRun: true - - task: NodeTool@0 inputs: versionSpec: "12.18.3" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.x" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" inputs: azureSubscription: "vscode-builds-subscription" KeyVaultName: vscode - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -43,22 +24,21 @@ steps: git config user.email "vscode@microsoft.com" git config user.name "VSCode" displayName: Prepare tooling - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") displayName: Merge distro - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | npx https://aka.ms/enablesecurefeed standAlone displayName: Switch to Terrapin packages timeoutInMinutes: 5 - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true')) + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | echo -n $(VSCODE_ARCH) > .build/arch + echo -n $ENABLE_TERRAPIN > .build/terrapin displayName: Prepare yarn cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 @@ -66,7 +46,6 @@ steps: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -87,21 +66,20 @@ steps: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 displayName: Install dependencies - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 inputs: keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock" targetfolder: "**/node_modules, !**/node_modules/**/node_modules" vstsFeed: "npm-vscode" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) # Mixin must run before optimize, because the CSS loader will inline small SVGs - script: | set -e node build/azure-pipelines/mixin displayName: Mix in quality - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e @@ -111,14 +89,13 @@ steps: yarn gulp minify-vscode-reh yarn gulp minify-vscode-reh-web displayName: Compile - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) - script: | set -e AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ node build/azure-pipelines/upload-sourcemaps displayName: Upload sourcemaps - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | set -e @@ -126,13 +103,7 @@ steps: AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ node build/azure-pipelines/common/createBuild.js $VERSION displayName: Create build - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false')) + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - inputs: - keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin" - targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min" - vstsFeed: "npm-vscode" - platformIndependent: true - alias: "Compilation" - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true')) + - publish: $(System.DefaultWorkingDirectory) + artifact: CompilationOutput From d14fb9da0fbeb1f659e8e4b22cafc9825817f216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 16:23:12 +0100 Subject: [PATCH 1096/1837] fix build --- build/azure-pipelines/linux/product-build-linux.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 567512e07c2..6b8664e0dae 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,7 +1,8 @@ steps: - - download: current - artifact: CompilationOutput - path: $(System.DefaultWorkingDirectory) + - task: DownloadPipelineArtifact@2 + inputs: + artifact: CompilationOutput + path: $(System.DefaultWorkingDirectory) - script: | set -e From cda701edbd76681a34d4dfa2fb8a95e93d1f5a6b Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 16 Dec 2020 13:45:39 +0100 Subject: [PATCH 1097/1837] debug: move colors to debugColors.ts from debugToolBar --- .../contrib/debug/browser/debugColors.ts | 128 +++++++++++++++++- .../contrib/debug/browser/debugToolBar.ts | 116 +--------------- .../notebook/browser/notebookEditorWidget.ts | 2 +- 3 files changed, 131 insertions(+), 115 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugColors.ts b/src/vs/workbench/contrib/debug/browser/debugColors.ts index df54038d02c..476f8571e72 100644 --- a/src/vs/workbench/contrib/debug/browser/debugColors.ts +++ b/src/vs/workbench/contrib/debug/browser/debugColors.ts @@ -4,8 +4,28 @@ *--------------------------------------------------------------------------------------------*/ import { registerColor, foreground, editorInfoForeground, editorWarningForeground, errorForeground, badgeBackground, badgeForeground, listDeemphasizedForeground, contrastBorder, inputBorder } from 'vs/platform/theme/common/colorRegistry'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; +import { localize } from 'vs/nls'; +import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; + +export const debugToolBarBackground = registerColor('debugToolBar.background', { + dark: '#333333', + light: '#F3F3F3', + hc: '#000000' +}, localize('debugToolBarBackground', "Debug toolbar background color.")); + +export const debugToolBarBorder = registerColor('debugToolBar.border', { + dark: null, + light: null, + hc: null +}, localize('debugToolBarBorder', "Debug toolbar border color.")); + +export const debugIconStartForeground = registerColor('debugIcon.startForeground', { + dark: '#89D185', + light: '#388A34', + hc: '#89D185' +}, localize('debugIcon.startForeground', "Debug toolbar icon for start debugging.")); export function registerColors() { @@ -28,6 +48,62 @@ export function registerColors() { const debugConsoleSourceForeground = registerColor('debugConsole.sourceForeground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for source filenames in debug REPL console.'); const debugConsoleInputIconForeground = registerColor('debugConsoleInputIcon.foreground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for debug console input marker icon.'); + + + const debugIconPauseForeground = registerColor('debugIcon.pauseForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.pauseForeground', "Debug toolbar icon for pause.")); + + const debugIconStopForeground = registerColor('debugIcon.stopForeground', { + dark: '#F48771', + light: '#A1260D', + hc: '#F48771' + }, localize('debugIcon.stopForeground', "Debug toolbar icon for stop.")); + + const debugIconDisconnectForeground = registerColor('debugIcon.disconnectForeground', { + dark: '#F48771', + light: '#A1260D', + hc: '#F48771' + }, localize('debugIcon.disconnectForeground', "Debug toolbar icon for disconnect.")); + + const debugIconRestartForeground = registerColor('debugIcon.restartForeground', { + dark: '#89D185', + light: '#388A34', + hc: '#89D185' + }, localize('debugIcon.restartForeground', "Debug toolbar icon for restart.")); + + const debugIconStepOverForeground = registerColor('debugIcon.stepOverForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.stepOverForeground', "Debug toolbar icon for step over.")); + + const debugIconStepIntoForeground = registerColor('debugIcon.stepIntoForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.stepIntoForeground', "Debug toolbar icon for step into.")); + + const debugIconStepOutForeground = registerColor('debugIcon.stepOutForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.stepOutForeground', "Debug toolbar icon for step over.")); + + const debugIconContinueForeground = registerColor('debugIcon.continueForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.continueForeground', "Debug toolbar icon for continue.")); + + const debugIconStepBackForeground = registerColor('debugIcon.stepBackForeground', { + dark: '#75BEFF', + light: '#007ACC', + hc: '#75BEFF' + }, localize('debugIcon.stepBackForeground', "Debug toolbar icon for step back.")); + registerThemingParticipant((theme, collector) => { // All these colours provide a default value so they will never be undefined, hence the `!` const badgeBackgroundColor = theme.getColor(badgeBackground)!; @@ -186,5 +262,55 @@ export function registerColors() { } `); } + + const debugIconStartColor = theme.getColor(debugIconStartForeground); + if (debugIconStartColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStart)} { color: ${debugIconStartColor} !important; }`); + } + + const debugIconPauseColor = theme.getColor(debugIconPauseForeground); + if (debugIconPauseColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugPause)} { color: ${debugIconPauseColor} !important; }`); + } + + const debugIconStopColor = theme.getColor(debugIconStopForeground); + if (debugIconStopColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStop)} { color: ${debugIconStopColor} !important; }`); + } + + const debugIconDisconnectColor = theme.getColor(debugIconDisconnectForeground); + if (debugIconDisconnectColor) { + collector.addRule(`.monaco-workbench .debug-view-content ${ThemeIcon.asCSSSelector(icons.debugDisconnect)}, .monaco-workbench .debug-toolbar ${ThemeIcon.asCSSSelector(icons.debugDisconnect)} { color: ${debugIconDisconnectColor} !important; }`); + } + + const debugIconRestartColor = theme.getColor(debugIconRestartForeground); + if (debugIconRestartColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestart)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestartFrame)} { color: ${debugIconRestartColor} !important; }`); + } + + const debugIconStepOverColor = theme.getColor(debugIconStepOverForeground); + if (debugIconStepOverColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOver)} { color: ${debugIconStepOverColor} !important; }`); + } + + const debugIconStepIntoColor = theme.getColor(debugIconStepIntoForeground); + if (debugIconStepIntoColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepInto)} { color: ${debugIconStepIntoColor} !important; }`); + } + + const debugIconStepOutColor = theme.getColor(debugIconStepOutForeground); + if (debugIconStepOutColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepOut)} { color: ${debugIconStepOutColor} !important; }`); + } + + const debugIconContinueColor = theme.getColor(debugIconContinueForeground); + if (debugIconContinueColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugContinue)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugReverseContinue)} { color: ${debugIconContinueColor} !important; }`); + } + + const debugIconStepBackColor = theme.getColor(debugIconStepBackForeground); + if (debugIconStepBackColor) { + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepBack)} { color: ${debugIconStepBackColor} !important; }`); + } }); } diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 01f318e9aa6..21e873243a3 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -18,9 +18,8 @@ import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/d import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { registerThemingParticipant, IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { registerColor, contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; -import { localize } from 'vs/nls'; +import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -30,6 +29,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -275,113 +275,3 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { } } } - -export const debugToolBarBackground = registerColor('debugToolBar.background', { - dark: '#333333', - light: '#F3F3F3', - hc: '#000000' -}, localize('debugToolBarBackground', "Debug toolbar background color.")); - -export const debugToolBarBorder = registerColor('debugToolBar.border', { - dark: null, - light: null, - hc: null -}, localize('debugToolBarBorder', "Debug toolbar border color.")); - -export const debugIconStartForeground = registerColor('debugIcon.startForeground', { - dark: '#89D185', - light: '#388A34', - hc: '#89D185' -}, localize('debugIcon.startForeground', "Debug toolbar icon for start debugging.")); - -export const debugIconPauseForeground = registerColor('debugIcon.pauseForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.pauseForeground', "Debug toolbar icon for pause.")); - -export const debugIconStopForeground = registerColor('debugIcon.stopForeground', { - dark: '#F48771', - light: '#A1260D', - hc: '#F48771' -}, localize('debugIcon.stopForeground', "Debug toolbar icon for stop.")); - -export const debugIconDisconnectForeground = registerColor('debugIcon.disconnectForeground', { - dark: '#F48771', - light: '#A1260D', - hc: '#F48771' -}, localize('debugIcon.disconnectForeground', "Debug toolbar icon for disconnect.")); - -export const debugIconRestartForeground = registerColor('debugIcon.restartForeground', { - dark: '#89D185', - light: '#388A34', - hc: '#89D185' -}, localize('debugIcon.restartForeground', "Debug toolbar icon for restart.")); - -export const debugIconStepOverForeground = registerColor('debugIcon.stepOverForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.stepOverForeground', "Debug toolbar icon for step over.")); - -export const debugIconStepIntoForeground = registerColor('debugIcon.stepIntoForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.stepIntoForeground', "Debug toolbar icon for step into.")); - -export const debugIconStepOutForeground = registerColor('debugIcon.stepOutForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.stepOutForeground', "Debug toolbar icon for step over.")); - -export const debugIconContinueForeground = registerColor('debugIcon.continueForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.continueForeground', "Debug toolbar icon for continue.")); - -export const debugIconStepBackForeground = registerColor('debugIcon.stepBackForeground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' -}, localize('debugIcon.stepBackForeground', "Debug toolbar icon for step back.")); - -registerThemingParticipant((theme, collector) => { - - const debugIconStartColor = theme.getColor(debugIconStartForeground); - if (debugIconStartColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStart)} { color: ${debugIconStartColor} !important; }`); - } - - const debugIconPauseColor = theme.getColor(debugIconPauseForeground); - if (debugIconPauseColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugPause)} { color: ${debugIconPauseColor} !important; }`); - } - - const debugIconStopColor = theme.getColor(debugIconStopForeground); - if (debugIconStopColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStop)} { color: ${debugIconStopColor} !important; }`); - } - - const debugIconDisconnectColor = theme.getColor(debugIconDisconnectForeground); - if (debugIconDisconnectColor) { - collector.addRule(`.monaco-workbench .debug-view-content ${ThemeIcon.asCSSSelector(icons.debugDisconnect)}, .monaco-workbench .debug-toolbar ${ThemeIcon.asCSSSelector(icons.debugDisconnect)} { color: ${debugIconDisconnectColor} !important; }`); - } - - const debugIconRestartColor = theme.getColor(debugIconRestartForeground); - if (debugIconRestartColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestart)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugRestartFrame)} { color: ${debugIconRestartColor} !important; }`); - } - - const debugIconContinueColor = theme.getColor(debugIconContinueForeground); - if (debugIconContinueColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugContinue)}, .monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugReverseContinue)} { color: ${debugIconContinueColor} !important; }`); - } - - const debugIconStepBackColor = theme.getColor(debugIconStepBackForeground); - if (debugIconStepBackColor) { - collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icons.debugStepBack)} { color: ${debugIconStepBackColor} !important; }`); - } -}); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 2b4a41c1747..e34a31ca5a2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -40,7 +40,6 @@ import { EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorMemento } from 'vs/workbench/common/editor'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; -import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellViewModel, INotebookCellList, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; @@ -62,6 +61,7 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors'; const $ = DOM.$; From 24a98f06442b432d3fc009649fb9f6005eb0bf7b Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 16 Dec 2020 16:23:43 +0100 Subject: [PATCH 1098/1837] debug viewlet: use registerAction2 and restructure the whole debug toolbar #92038 --- .../contrib/debug/browser/breakpointsView.ts | 4 +- .../debug/browser/debug.contribution.ts | 50 +--- .../contrib/debug/browser/debugActions.ts | 108 +------- .../contrib/debug/browser/debugCommands.ts | 25 ++ .../contrib/debug/browser/debugService.ts | 4 +- .../contrib/debug/browser/debugToolBar.ts | 87 +++--- .../contrib/debug/browser/debugViewlet.ts | 250 ++++++++++-------- .../contrib/debug/browser/welcomeView.ts | 8 +- .../workbench/contrib/debug/common/debug.ts | 1 + .../contrib/debug/common/debugViewModel.ts | 10 +- 10 files changed, 252 insertions(+), 295 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index e941ae8fd55..0f125e52f7d 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -888,11 +888,11 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: }; } -export const functionBreakpointCommandId = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; +export const FUNCTION_BREAKPOINT_COMMAND_ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; registerAction2(class extends Action2 { constructor() { super({ - id: functionBreakpointCommandId, + id: FUNCTION_BREAKPOINT_COMMAND_ID, title: localize('addFunctionBreakpoint', "Add Function Breakpoint"), f1: true, icon: icons.watchExpressionsAddFuncBreakpoint, diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index cae1daa5206..2a72c696ea0 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -12,17 +12,17 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions, CATEGORIES } from 'vs/workbench/common/actions'; -import { BreakpointsView, removeAllBreakpointsCommand, functionBreakpointCommandId } from 'vs/workbench/contrib/debug/browser/breakpointsView'; +import { BreakpointsView, removeAllBreakpointsCommand, FUNCTION_BREAKPOINT_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IDebugService, VIEWLET_ID, DEBUG_PANEL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA, - CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, + CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, } from 'vs/workbench/contrib/debug/common/debug'; -import { StartAction, ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { StartAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RunAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { DebugService } from 'vs/workbench/contrib/debug/browser/debugService'; -import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; @@ -38,8 +38,7 @@ import { VariablesView, SET_VARIABLE_ID, COPY_VALUE_ID, BREAK_WHEN_VALUE_CHANGES import { Repl } from 'vs/workbench/contrib/debug/browser/repl'; import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { DebugViewPaneContainer, OpenDebugConsoleAction, OpenDebugViewletAction } from 'vs/workbench/contrib/debug/browser/debugViewlet'; +import { DebugViewPaneContainer, OpenDebugViewletAction, DEBUG_CONFIGURE_COMMAND_ID, OPEN_REPL_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugViewlet'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { CallStackEditorContribution } from 'vs/workbench/contrib/debug/browser/callStackEditorContribution'; import { BreakpointEditorContribution } from 'vs/workbench/contrib/debug/browser/breakpointEditorContribution'; @@ -102,11 +101,9 @@ function regsiterEditorContributions(): void { function registerCommandsAndActions(): void { - registry.registerWorkbenchAction(SyncActionDescriptor.from(ConfigureAction), 'Debug: Open launch.json', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); registry.registerWorkbenchAction(SyncActionDescriptor.from(ReapplyBreakpointsAction), 'Debug: Reapply All Breakpoints', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); registry.registerWorkbenchAction(SyncActionDescriptor.from(EnableAllBreakpointsAction), 'Debug: Enable All Breakpoints', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); registry.registerWorkbenchAction(SyncActionDescriptor.from(DisableAllBreakpointsAction), 'Debug: Disable All Breakpoints', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); - registry.registerWorkbenchAction(SyncActionDescriptor.from(SelectAndStartAction), 'Debug: Select and Start Debugging', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); const registerDebugCommandPaletteItem = (id: string, title: string, when?: ContextKeyExpression, precondition?: ContextKeyExpression) => { MenuRegistry.appendMenuItem(MenuId.CommandPalette, { @@ -134,33 +131,6 @@ function registerCommandsAndActions(): void { registerDebugCommandPaletteItem(RunToCursorAction.ID, RunToCursorAction.LABEL, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); registerDebugCommandPaletteItem(TOGGLE_INLINE_BREAKPOINT_ID, nls.localize('inlineBreakpoint', "Inline Breakpoint")); - // Debug toolbar - - const registerDebugToolBarItem = (id: string, title: string, order: number, icon: { light?: URI, dark?: URI } | ThemeIcon, when?: ContextKeyExpression, precondition?: ContextKeyExpression) => { - MenuRegistry.appendMenuItem(MenuId.DebugToolBar, { - group: 'navigation', - when, - order, - command: { - id, - title, - icon, - precondition - } - }); - }; - - registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, icons.debugContinue, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, icons.debugPause, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); - registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); - registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH); - registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, icons.debugStepOver, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, icons.debugStepInto, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, icons.debugStepOut, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, icons.debugRestart); - registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, icons.debugStepBack, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, icons.debugReverseContinue, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); - // Debug callstack context menu const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, order: number, when?: ContextKeyExpression, precondition?: ContextKeyExpression, group = 'navigation') => { MenuRegistry.appendMenuItem(menuId, { @@ -234,7 +204,7 @@ function registerDebugMenu(): void { MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { group: '4_panels', command: { - id: OpenDebugConsoleAction.ID, + id: OPEN_REPL_COMMAND_ID, title: nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console") }, order: 2 @@ -288,7 +258,7 @@ function registerDebugMenu(): void { MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { group: '2_configuration', command: { - id: ConfigureAction.ID, + id: DEBUG_CONFIGURE_COMMAND_ID, title: nls.localize({ key: 'miOpenConfigurations', comment: ['&& denotes a mnemonic'] }, "Open &&Configurations") }, order: 1, @@ -384,7 +354,7 @@ function registerDebugMenu(): void { MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, { group: '1_breakpoints', command: { - id: functionBreakpointCommandId, + id: FUNCTION_BREAKPOINT_COMMAND_ID, title: nls.localize({ key: 'miFunctionBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Function Breakpoint...") }, order: 3, @@ -460,7 +430,7 @@ function registerDebugPanel(): void { icon: icons.debugConsoleViewIcon, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: DEBUG_PANEL_ID, - focusCommand: { id: OpenDebugConsoleAction.ID }, + focusCommand: { id: OPEN_REPL_COMMAND_ID }, order: 2, hideIfEmpty: true }, ViewContainerLocation.Panel); @@ -474,8 +444,6 @@ function registerDebugPanel(): void { when: CONTEXT_DEBUGGERS_AVAILABLE, ctorDescriptor: new SyncDescriptor(Repl), }], VIEW_CONTAINER); - - registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenDebugConsoleAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y }), 'View: Debug Console', CATEGORIES.View.value, CONTEXT_DEBUGGERS_AVAILABLE); } diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 07bf716f1d4..b2c43870f59 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -6,16 +6,11 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IDebugService, State, IEnablement, IBreakpoint, IDebugSession, ILaunch } from 'vs/workbench/contrib/debug/common/debug'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IDebugService, State, IEnablement, IBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { Variable, Breakpoint, FunctionBreakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { INotificationService } from 'vs/platform/notification/common/notification'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { deepClone } from 'vs/base/common/objects'; -import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export abstract class AbstractDebugAction extends Action { @@ -55,67 +50,6 @@ export abstract class AbstractDebugAction extends Action { } } -export class ConfigureAction extends AbstractDebugAction { - static readonly ID = 'workbench.action.debug.configure'; - static readonly LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); - - constructor(id: string, label: string, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - @INotificationService private readonly notificationService: INotificationService, - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IQuickInputService private readonly quickInputService: IQuickInputService - ) { - super(id, label, 'debug-action ' + ThemeIcon.asClassName(icons.debugConfigure), debugService, keybindingService); - this._register(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass())); - this.updateClass(); - } - - get tooltip(): string { - if (this.debugService.getConfigurationManager().selectedConfiguration.name) { - return ConfigureAction.LABEL; - } - - return nls.localize('launchJsonNeedsConfigurtion', "Configure or Fix 'launch.json'"); - } - - private updateClass(): void { - const configurationManager = this.debugService.getConfigurationManager(); - this.class = configurationManager.selectedConfiguration.name ? 'debug-action' + ThemeIcon.asClassName(icons.debugConfigure) : 'debug-action ' + ThemeIcon.asClassName(icons.debugConfigure) + ' notification'; - } - - async run(): Promise { - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY || this.contextService.getWorkspace().folders.length === 0) { - this.notificationService.info(nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); - return; - } - - const configurationManager = this.debugService.getConfigurationManager(); - let launch: ILaunch | undefined; - if (configurationManager.selectedConfiguration.name) { - launch = configurationManager.selectedConfiguration.launch; - } else { - const launches = configurationManager.getLaunches().filter(l => !l.hidden); - if (launches.length === 1) { - launch = launches[0]; - } else { - const picks = launches.map(l => ({ label: l.name, launch: l })); - const picked = await this.quickInputService.pick<{ label: string, launch: ILaunch }>(picks, { - activeItem: picks[0], - placeHolder: nls.localize({ key: 'selectWorkspaceFolder', comment: ['User picks a workspace folder or a workspace configuration file here. Workspace configuration files can contain settings and thus a launch.json configuration can be written into one.'] }, "Select a workspace folder to create a launch.json file in or add it to the workspace config file") - }); - if (picked) { - launch = picked.launch; - } - } - } - - if (launch) { - return launch.openConfigFile(false); - } - } -} - export class StartAction extends AbstractDebugAction { static ID = 'workbench.action.debug.start'; static LABEL = nls.localize('startDebug', "Start Debugging"); @@ -176,23 +110,6 @@ export class RunAction extends StartAction { } } -export class SelectAndStartAction extends AbstractDebugAction { - static readonly ID = 'workbench.action.debug.selectandstart'; - static readonly LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); - - constructor(id: string, label: string, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - @IQuickInputService private readonly quickInputService: IQuickInputService - ) { - super(id, label, '', debugService, keybindingService); - } - - async run(): Promise { - this.quickInputService.quickAccess.show('debug '); - } -} - export class RemoveBreakpointAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.removeBreakpoint'; static readonly LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint"); @@ -265,27 +182,6 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction { } } -export class FocusSessionAction extends AbstractDebugAction { - static readonly ID = 'workbench.action.debug.focusProcess'; - static readonly LABEL = nls.localize('focusSession', "Focus Session"); - - constructor(id: string, label: string, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - @IEditorService private readonly editorService: IEditorService - ) { - super(id, label, '', debugService, keybindingService); - } - - async run(session: IDebugSession): Promise { - await this.debugService.focusStackFrame(undefined, undefined, session, true); - const stackFrame = this.debugService.getViewModel().focusedStackFrame; - if (stackFrame) { - await stackFrame.openInEditor(this.editorService, true); - } - } -} - export class CopyValueAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.copyValue'; static readonly LABEL = nls.localize('copyValue', "Copy Value"); diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 47aaedfb960..720ba1a4e64 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -47,6 +47,8 @@ export const RESTART_FRAME_ID = 'workbench.action.debug.restartFrame'; export const CONTINUE_ID = 'workbench.action.debug.continue'; export const FOCUS_REPL_ID = 'workbench.debug.action.focusRepl'; export const JUMP_TO_CURSOR_ID = 'debug.jumpToCursor'; +export const FOCUS_SESSION_ID = 'workbench.action.debug.focusProcess'; +export const SELECT_AND_START_ID = 'workbench.action.debug.selectandstart'; export const RESTART_LABEL = nls.localize('restartDebug', "Restart"); export const STEP_OVER_LABEL = nls.localize('stepOverDebug', "Step Over"); @@ -56,6 +58,8 @@ export const PAUSE_LABEL = nls.localize('pauseDebug', "Pause"); export const DISCONNECT_LABEL = nls.localize('disconnect', "Disconnect"); export const STOP_LABEL = nls.localize('stop', "Stop"); export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); +export const FOCUS_SESSION_LABEL = nls.localize('focusSession', "Focus Session"); +export const SELECT_AND_START_LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); interface CallStackContext { sessionId: string; @@ -346,6 +350,27 @@ export function registerCommands(): void { } }); + CommandsRegistry.registerCommand({ + id: FOCUS_SESSION_ID, + handler: async (accessor: ServicesAccessor, session: IDebugSession) => { + const debugService = accessor.get(IDebugService); + const editorService = accessor.get(IEditorService); + await debugService.focusStackFrame(undefined, undefined, session, true); + const stackFrame = debugService.getViewModel().focusedStackFrame; + if (stackFrame) { + await stackFrame.openInEditor(editorService, true); + } + } + }); + + CommandsRegistry.registerCommand({ + id: SELECT_AND_START_ID, + handler: async (accessor: ServicesAccessor) => { + const quickInputService = accessor.get(IQuickInputService); + quickInputService.quickAccess.show('debug '); + } + }); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'debug.toggleBreakpoint', weight: KeybindingWeight.WorkbenchContrib + 5, diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index cca24fe1fc9..9b6789a9357 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -17,7 +17,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/files/common/files'; import { DebugModel, FunctionBreakpoint, Breakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel'; import { ViewModel } from 'vs/workbench/contrib/debug/common/debugViewModel'; -import * as debugactions from 'vs/workbench/contrib/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager'; import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/contrib/files/common/files'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -50,6 +49,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager'; import { ITextModel } from 'vs/editor/common/model'; +import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugViewlet'; export class DebugService implements IDebugService { declare readonly _serviceBrand: undefined; @@ -778,7 +778,7 @@ export class DebugService implements IDebugService { } private async showError(message: string, errorActions: ReadonlyArray = []): Promise { - const configureAction = this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL); + const configureAction = new Action(DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL, undefined, true, () => this.commandService.executeCommand(DEBUG_CONFIGURE_COMMAND_ID)); const actions = [...errorActions, configureAction]; const { choice } = await this.dialogService.show(severity.Error, message, actions.map(a => a.label).concat(nls.localize('cancel', "Cancel")), { cancelId: actions.length }); if (choice < actions.length) { diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index 21e873243a3..af79b513e47 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -8,14 +8,15 @@ import * as errors from 'vs/base/common/errors'; import * as browser from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; +import { localize } from 'vs/nls'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions'; +import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG } from 'vs/workbench/contrib/debug/common/debug'; import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; -import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -24,12 +25,13 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { IContextKeyService, ContextKeyExpression, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; +import { URI } from 'vs/base/common/uri'; +import { CONTINUE_LABEL, CONTINUE_ID, PAUSE_ID, STOP_ID, DISCONNECT_ID, STEP_OVER_ID, STEP_INTO_ID, RESTART_SESSION_ID, STEP_OUT_ID, STEP_BACK_ID, REVERSE_CONTINUE_ID, RESTART_LABEL, STEP_OUT_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, DISCONNECT_LABEL, STOP_LABEL, PAUSE_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -75,7 +77,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { this.actionBar = this._register(new ActionBar(actionBarContainer, { orientation: ActionsOrientation.HORIZONTAL, actionViewItemProvider: (action: IAction) => { - if (action.id === FocusSessionAction.ID) { + if (action.id === FOCUS_SESSION_ID) { return this.instantiationService.createInstance(FocusSessionActionViewItem, action, undefined); } else if (action instanceof MenuItemAction) { return this.instantiationService.createInstance(MenuEntryActionViewItem, action); @@ -94,7 +96,8 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { return this.hide(); } - const { actions, disposable } = DebugToolBar.getActions(this.debugToolBarMenu, this.debugService, this.instantiationService); + const actions: IAction[] = []; + const disposable = createAndFillInActionBarActions(this.debugToolBarMenu, undefined, actions, () => false); if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id && first.enabled === second.enabled)) { this.actionBar.clear(); this.actionBar.push(actions, { icon: true, label: false }); @@ -115,9 +118,11 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { private registerListeners(): void { this._register(this.debugService.onDidChangeState(() => this.updateScheduler.schedule())); - this._register(this.debugService.getViewModel().onDidFocusSession(() => this.updateScheduler.schedule())); - this._register(this.debugService.onDidNewSession(() => this.updateScheduler.schedule())); - this._register(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e))); + this._register(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('debug.toolBarLocation')) { + this.updateScheduler.schedule(); + } + })); this._register(this.debugToolBarMenu.onDidChange(() => this.updateScheduler.schedule())); this._register(this.actionBar.actionRunner.onDidRun((e: IRunEvent) => { // check for error @@ -225,12 +230,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { } } - private onDidConfigurationChange(event: IConfigurationChangeEvent): void { - if (event.affectsConfiguration('debug.hideActionBar') || event.affectsConfiguration('debug.toolBarLocation')) { - this.updateScheduler.schedule(); - } - } - private show(): void { if (this.isVisible) { this.setCoordinates(); @@ -251,19 +250,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { dom.hide(this.$el); } - static getActions(menu: IMenu, debugService: IDebugService, instantiationService: IInstantiationService): { actions: IAction[], disposable: IDisposable } { - const actions: IAction[] = []; - const disposable = createAndFillInActionBarActions(menu, undefined, actions, () => false); - if (debugService.getViewModel().isMultiSessionView()) { - actions.push(instantiationService.createInstance(FocusSessionAction, FocusSessionAction.ID, FocusSessionAction.LABEL)); - } - - return { - actions: actions.filter(a => !(a instanceof Separator)), // do not render separators for now - disposable - }; - } - dispose(): void { super.dispose(); @@ -275,3 +261,44 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { } } } + +// Debug toolbar + +const registerDebugToolBarItem = (id: string, title: string, order: number, icon?: { light?: URI, dark?: URI } | ThemeIcon, when?: ContextKeyExpression, precondition?: ContextKeyExpression) => { + MenuRegistry.appendMenuItem(MenuId.DebugToolBar, { + group: 'navigation', + when, + order, + command: { + id, + title, + icon, + precondition + } + }); + + // Register actions in debug viewlet when toolbar is docked + MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { + group: 'navigation', + when: ContextKeyExpr.and(when, CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')), + order, + command: { + id, + title, + icon, + precondition + } + }); +}; + +registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, icons.debugContinue, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, icons.debugPause, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'), CONTEXT_DEBUG_STATE.isEqualTo('running')); +registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, icons.debugStop, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated()); +registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, icons.debugDisconnect, CONTEXT_FOCUSED_SESSION_IS_ATTACH); +registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, icons.debugStepOver, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, icons.debugStepInto, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, icons.debugStepOut, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, icons.debugRestart); +registerDebugToolBarItem(STEP_BACK_ID, localize('stepBackDebug', "Step Back"), 50, icons.debugStepBack, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(REVERSE_CONTINUE_ID, localize('reverseContinue', "Reverse"), 60, icons.debugReverseContinue, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped')); +registerDebugToolBarItem(FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, 100, undefined, CONTEXT_MULTI_SESSION_DEBUG); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index cd4038aab03..2978210dd43 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -6,35 +6,37 @@ import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; import { IAction, IActionViewItem } from 'vs/base/common/actions'; -import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; -import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch } from 'vs/workbench/contrib/debug/common/debug'; +import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IProgressService } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { memoize } from 'vs/base/common/decorators'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; -import { IMenu, MenuId, IMenuService, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { MenuId, MenuItemAction, SubmenuItemAction, registerAction2, Action2, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { IContextKeyService, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; -import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { RunOnceScheduler } from 'vs/base/common/async'; import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { debugConsole } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { debugConfigure, debugConsole } from 'vs/workbench/contrib/debug/browser/debugIcons'; +import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; +import { FOCUS_SESSION_ID, SELECT_AND_START_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -42,9 +44,6 @@ export class DebugViewPaneContainer extends ViewPaneContainer { private progressResolve: (() => void) | undefined; private breakpointView: ViewPane | undefined; private paneListeners = new Map(); - private debugToolBarMenu: IMenu | undefined; - private disposeOnTitleUpdate: IDisposable | undefined; - private updateToolBarScheduler: RunOnceScheduler; constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @@ -59,22 +58,13 @@ export class DebugViewPaneContainer extends ViewPaneContainer { @IExtensionService extensionService: IExtensionService, @IConfigurationService configurationService: IConfigurationService, @IContextViewService private readonly contextViewService: IContextViewService, - @IMenuService private readonly menuService: IMenuService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IViewDescriptorService viewDescriptorService: IViewDescriptorService ) { super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); - this.updateToolBarScheduler = this._register(new RunOnceScheduler(() => { - if (this.configurationService.getValue('debug').toolBarLocation === 'docked') { - this.updateTitleArea(); - } - }, 20)); - // When there are potential updates to the docked debug toolbar we need to update it this._register(this.debugService.onDidChangeState(state => this.onDebugServiceStateChange(state))); - this._register(this.debugService.onDidNewSession(() => this.updateToolBarScheduler.schedule())); - this._register(this.debugService.getViewModel().onDidFocusSession(() => this.updateToolBarScheduler.schedule())); this._register(this.contextKeyService.onDidChangeContext(e => { if (e.affectsSome(new Set([CONTEXT_DEBUG_UX_KEY]))) { @@ -105,74 +95,12 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } } - @memoize - private get startAction(): StartAction { - return this._register(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL)); - } - - @memoize - private get configureAction(): ConfigureAction { - return this._register(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL)); - } - - @memoize - private get toggleReplAction(): OpenDebugConsoleAction { - return this._register(this.instantiationService.createInstance(OpenDebugConsoleAction, OpenDebugConsoleAction.ID, OpenDebugConsoleAction.LABEL)); - } - - @memoize - private get selectAndStartAction(): SelectAndStartAction { - return this._register(this.instantiationService.createInstance(SelectAndStartAction, SelectAndStartAction.ID, nls.localize('startAdditionalSession', "Start Additional Session"))); - } - - getActions(): IAction[] { - if (CONTEXT_DEBUG_UX.getValue(this.contextKeyService) === 'simple') { - return []; - } - - if (!this.showInitialDebugActions) { - - if (!this.debugToolBarMenu) { - this.debugToolBarMenu = this.menuService.createMenu(MenuId.DebugToolBar, this.contextKeyService); - this._register(this.debugToolBarMenu); - this._register(this.debugToolBarMenu.onDidChange(() => this.updateToolBarScheduler.schedule())); - } - - const { actions, disposable } = DebugToolBar.getActions(this.debugToolBarMenu, this.debugService, this.instantiationService); - if (this.disposeOnTitleUpdate) { - dispose(this.disposeOnTitleUpdate); - } - this.disposeOnTitleUpdate = disposable; - - return actions; - } - - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { - return [this.toggleReplAction]; - } - - return [this.startAction, this.configureAction, this.toggleReplAction]; - } - - get showInitialDebugActions(): boolean { - const state = this.debugService.state; - return state === State.Inactive || this.configurationService.getValue('debug').toolBarLocation !== 'docked'; - } - - getSecondaryActions(): IAction[] { - if (this.showInitialDebugActions) { - return []; - } - - return [this.selectAndStartAction, this.configureAction, this.toggleReplAction]; - } - getActionViewItem(action: IAction): IActionViewItem | undefined { - if (action.id === StartAction.ID) { + if (action.id === 'debug.start') { this.startDebugActionViewItem = this.instantiationService.createInstance(StartDebugActionViewItem, null, action); return this.startDebugActionViewItem; } - if (action.id === FocusSessionAction.ID) { + if (action.id === FOCUS_SESSION_ID) { return new FocusSessionActionViewItem(action, undefined, this.debugService, this.themeService, this.contextViewService, this.configurationService); } if (action instanceof MenuItemAction) { @@ -202,8 +130,6 @@ export class DebugViewPaneContainer extends ViewPaneContainer { return new Promise(resolve => this.progressResolve = resolve); }); } - - this.updateToolBarScheduler.schedule(); } addPanes(panes: { pane: ViewPane, size: number, index?: number }[]): void { @@ -237,22 +163,6 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } } -export class OpenDebugConsoleAction extends ToggleViewAction { - public static readonly ID = 'workbench.debug.action.toggleRepl'; - public static readonly LABEL = nls.localize('toggleDebugPanel', "Debug Console"); - - constructor( - id: string, - label: string, - @IViewsService viewsService: IViewsService, - @IViewDescriptorService viewDescriptorService: IViewDescriptorService, - @IContextKeyService contextKeyService: IContextKeyService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService - ) { - super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, ThemeIcon.asClassName(debugConsole)); - } -} - export class OpenDebugViewletAction extends ShowViewletAction { public static readonly ID = VIEWLET_ID; public static readonly LABEL = nls.localize('toggleDebugViewlet', "Show Run and Debug"); @@ -267,3 +177,131 @@ export class OpenDebugViewletAction extends ShowViewletAction { super(id, label, VIEWLET_ID, viewletService, editorGroupService, layoutService); } } + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'debug.start', + title: StartAction.LABEL, + f1: false, + precondition: ContextKeyExpr.and(CONTEXT_DEBUG_STATE.notEqualsTo('initializing'), CONTEXT_DEBUG_UX.notEqualsTo('simple')), + menu: { + id: MenuId.ViewContainerTitle, + group: 'navigation', + order: 10, + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_UX.notEqualsTo('simple'), WorkbenchStateContext.notEqualsTo('empty'), + ContextKeyExpr.or(CONTEXT_DEBUG_STATE.isEqualTo('inactive'), ContextKeyExpr.notEquals('config.debug.toolBarLocation', 'docked'))) + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const instantiationService = accessor.get(IInstantiationService); + const startAction = instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL); + await startAction.run(); + } +}); + +export const DEBUG_CONFIGURE_COMMAND_ID = 'workbench.action.debug.configure'; +export const DEBUG_CONFIGURE_LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); +registerAction2(class extends Action2 { + constructor() { + super({ + id: DEBUG_CONFIGURE_COMMAND_ID, + title: DEBUG_CONFIGURE_LABEL, + f1: true, + icon: debugConfigure, + precondition: CONTEXT_DEBUG_UX.notEqualsTo('simple'), + menu: [{ + id: MenuId.ViewContainerTitle, + group: 'navigation', + order: 20, + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_UX.notEqualsTo('simple'), WorkbenchStateContext.notEqualsTo('empty'), + ContextKeyExpr.or(CONTEXT_DEBUG_STATE.isEqualTo('inactive'), ContextKeyExpr.notEquals('config.debug.toolBarLocation', 'docked'))) + }, { + id: MenuId.ViewContainerTitle, + order: 20, + // Show in debug viewlet secondary actions when debugging and debug toolbar is docked + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')) + }] + }); + } + + async run(accessor: ServicesAccessor): Promise { + const debugService = accessor.get(IDebugService); + const quickInputService = accessor.get(IQuickInputService); + const configurationManager = debugService.getConfigurationManager(); + let launch: ILaunch | undefined; + if (configurationManager.selectedConfiguration.name) { + launch = configurationManager.selectedConfiguration.launch; + } else { + const launches = configurationManager.getLaunches().filter(l => !l.hidden); + if (launches.length === 1) { + launch = launches[0]; + } else { + const picks = launches.map(l => ({ label: l.name, launch: l })); + const picked = await quickInputService.pick<{ label: string, launch: ILaunch }>(picks, { + activeItem: picks[0], + placeHolder: nls.localize({ key: 'selectWorkspaceFolder', comment: ['User picks a workspace folder or a workspace configuration file here. Workspace configuration files can contain settings and thus a launch.json configuration can be written into one.'] }, "Select a workspace folder to create a launch.json file in or add it to the workspace config file") + }); + if (picked) { + launch = picked.launch; + } + } + } + + if (launch) { + await launch.openConfigFile(false); + } + } +}); + +export const OPEN_REPL_COMMAND_ID = 'workbench.debug.action.toggleRepl'; +registerAction2(class extends Action2 { + constructor() { + super({ + id: OPEN_REPL_COMMAND_ID, + title: nls.localize('toggleDebugPanel', "Debug Console"), + f1: true, + keybinding: { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y, + weight: KeybindingWeight.WorkbenchContrib + }, + icon: debugConsole, + precondition: CONTEXT_DEBUG_UX.notEqualsTo('simple'), + menu: [{ + id: MenuId.ViewContainerTitle, + group: 'navigation', + order: 30, + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_UX.notEqualsTo('simple'), WorkbenchStateContext.notEqualsTo('empty'), + ContextKeyExpr.or(CONTEXT_DEBUG_STATE.isEqualTo('inactive'), ContextKeyExpr.notEquals('config.debug.toolBarLocation', 'docked'))) + }, { + id: MenuId.ViewContainerTitle, + order: 30, + // Show in debug viewlet secondary actions when debugging and debug toolbar is docked + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')) + }] + }); + } + + async run(accessor: ServicesAccessor): Promise { + const viewsService = accessor.get(IViewsService); + const viewDescriptorService = accessor.get(IViewDescriptorService); + const contextKeyService = accessor.get(IContextKeyService); + const layoutService = accessor.get(IWorkbenchLayoutService); + return new class extends ToggleViewAction { + constructor() { + super(OPEN_REPL_COMMAND_ID, 'Debug Console', REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); + } + }().run(); + } +}); + +MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')), + order: 10, + command: { + id: SELECT_AND_START_ID, + title: nls.localize('startAdditionalSession', "Start Additional Session"), + } +}); diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index 8129475f305..2dfa11afe60 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -10,7 +10,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService, RawContextKey, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; -import { StartAction, ConfigureAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; @@ -25,6 +25,8 @@ import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugViewlet'; +import { SELECT_AND_START_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; const debugStartLanguageKey = 'debugStartLanguage'; const CONTEXT_DEBUG_START_LANGUAGE = new RawContextKey(debugStartLanguageKey, undefined); @@ -123,7 +125,7 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { content: localize({ key: 'detectThenRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] }, - "[Show](command:{0}) all automatic debug configurations.", SelectAndStartAction.ID), + "[Show](command:{0}) all automatic debug configurations.", SELECT_AND_START_ID), when: CONTEXT_DEBUGGERS_AVAILABLE, group: ViewContentGroups.Debug, order: 10 @@ -131,7 +133,7 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { content: localize({ key: 'customizeRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] }, - "To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID), + "To customize Run and Debug [create a launch.json file](command:{0}).", DEBUG_CONFIGURE_COMMAND_ID), when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty')), group: ViewContentGroups.Debug }); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 8912ce6c0bf..1463e58ad80 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -67,6 +67,7 @@ export const CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED = new RawContextKey('variableEvaluateNamePresent', false); export const CONTEXT_EXCEPTION_WIDGET_VISIBLE = new RawContextKey('exceptionWidgetVisible', false); export const CONTEXT_MULTI_SESSION_REPL = new RawContextKey('multiSessionRepl', false); +export const CONTEXT_MULTI_SESSION_DEBUG = new RawContextKey('multiSessionDebug', false); export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug'; export const BREAKPOINT_EDITOR_CONTRIBUTION_ID = 'editor.contrib.breakpoint'; diff --git a/src/vs/workbench/contrib/debug/common/debugViewModel.ts b/src/vs/workbench/contrib/debug/common/debugViewModel.ts index e7541cd89e7..3ff9f675cc5 100644 --- a/src/vs/workbench/contrib/debug/common/debugViewModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugViewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, IExceptionBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; +import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, IExceptionBreakpoint, CONTEXT_MULTI_SESSION_DEBUG } from 'vs/workbench/contrib/debug/common/debug'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils'; @@ -21,7 +21,6 @@ export class ViewModel implements IViewModel { private readonly _onDidFocusStackFrame = new Emitter<{ stackFrame: IStackFrame | undefined, explicit: boolean }>(); private readonly _onDidSelectExpression = new Emitter(); private readonly _onWillUpdateViews = new Emitter(); - private multiSessionView: boolean; private expressionSelectedContextKey!: IContextKey; private breakpointSelectedContextKey!: IContextKey; private loadedScriptsSupportedContextKey!: IContextKey; @@ -31,9 +30,9 @@ export class ViewModel implements IViewModel { private stepIntoTargetsSupported!: IContextKey; private jumpToCursorSupported!: IContextKey; private setVariableSupported!: IContextKey; + private multiSessionDebug!: IContextKey; constructor(private contextKeyService: IContextKeyService) { - this.multiSessionView = false; contextKeyService.bufferChangeEvents(() => { this.expressionSelectedContextKey = CONTEXT_EXPRESSION_SELECTED.bindTo(contextKeyService); this.breakpointSelectedContextKey = CONTEXT_BREAKPOINT_SELECTED.bindTo(contextKeyService); @@ -44,6 +43,7 @@ export class ViewModel implements IViewModel { this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService); this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService); this.setVariableSupported = CONTEXT_SET_VARIABLE_SUPPORTED.bindTo(contextKeyService); + this.multiSessionDebug = CONTEXT_MULTI_SESSION_DEBUG.bindTo(contextKeyService); }); } @@ -130,10 +130,10 @@ export class ViewModel implements IViewModel { } isMultiSessionView(): boolean { - return this.multiSessionView; + return !!this.multiSessionDebug.get(); } setMultiSessionView(isMultiSessionView: boolean): void { - this.multiSessionView = isMultiSessionView; + this.multiSessionDebug.set(isMultiSessionView); } } From df0eda5adbb53121362ef1bf9a28df0598692364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 16:25:38 +0100 Subject: [PATCH 1099/1837] build --- .../linux/product-build-linux.yml | 17 ++++++----------- build/azure-pipelines/product-compile.yml | 7 +++++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 6b8664e0dae..93b4651492b 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,15 +1,4 @@ steps: - - task: DownloadPipelineArtifact@2 - inputs: - artifact: CompilationOutput - path: $(System.DefaultWorkingDirectory) - - - script: | - set -e - exit 1 - displayName: Check RestoreCache - condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) - - task: NodeTool@0 inputs: versionSpec: "12.18.3" @@ -24,6 +13,12 @@ steps: azureSubscription: "vscode-builds-subscription" KeyVaultName: vscode + - task: DownloadPipelineArtifact@2 + inputs: + artifact: CompilationOutput + path: $(System.DefaultWorkingDirectory) + displayName: Download Compilation Output + - script: | set -e cat << EOF > ~/.netrc diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index ba6deeec43c..9f1dc1a5b81 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -105,5 +105,8 @@ steps: displayName: Create build condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - - publish: $(System.DefaultWorkingDirectory) - artifact: CompilationOutput + - task: PublishPipelineArtifact@1 + inputs: + targetPath: $(System.DefaultWorkingDirectory) + artifactName: CompilationOutput + displayName: Publish Compilation Output From fb2a5e18bb29966271e136790a5c0b7ca4f891d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 16:31:54 +0100 Subject: [PATCH 1100/1837] fix build --- build/azure-pipelines/product-compile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 9f1dc1a5b81..c52490e3835 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -37,6 +37,7 @@ steps: condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) - script: | + mkdir -p .build echo -n $(VSCODE_ARCH) > .build/arch echo -n $ENABLE_TERRAPIN > .build/terrapin displayName: Prepare yarn cache flags From 7d0d3835e6ebc15fd4eb937c56c28c7310f27ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 16 Dec 2020 16:33:03 +0100 Subject: [PATCH 1101/1837] cleanup hygien --- build/azure-pipelines/product-hygiene.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index df73b27b6a6..4f634314b4d 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -1,9 +1,4 @@ steps: - - script: | - mkdir -p .build - echo -n $ENABLE_TERRAPIN > .build/terrapin - displayName: Prepare compilation cache flag - - task: NodeTool@0 inputs: versionSpec: "12.18.3" @@ -36,7 +31,9 @@ steps: displayName: Merge distro - script: | + mkdir -p .build echo -n $(VSCODE_ARCH) > .build/arch + echo -n $ENABLE_TERRAPIN > .build/terrapin displayName: Prepare yarn cache flags - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 From 3776ba6be2f987feed4424386be14b6662d5cce2 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 16:36:16 +0100 Subject: [PATCH 1102/1837] Fix activity badge on ports view not going away --- src/vs/workbench/contrib/remote/browser/remoteExplorer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index a57e54b14ad..f8ef14edc09 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -123,12 +123,12 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu } private async updateActivityBadge() { - if (this._activityBadge) { - this._activityBadge.dispose(); - } if (!(await this.usePanelTreatment())) { return; } + if (this._activityBadge) { + this._activityBadge.dispose(); + } if (this.remoteExplorerService.tunnelModel.forwarded.size > 0) { const viewContainer = this.viewDescriptorService.getViewContainerByViewId(TUNNEL_VIEW_ID); if (viewContainer) { From c78bc56460424ee67e0b4e62387d52fd17a1f874 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 16:55:24 +0100 Subject: [PATCH 1103/1837] update references viewlet --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index d819b68c2aa..d78d5024e10 100644 --- a/product.json +++ b/product.json @@ -61,7 +61,7 @@ }, { "name": "ms-vscode.references-view", - "version": "0.0.75", + "version": "0.0.76", "repo": "https://github.com/microsoft/vscode-reference-view", "metadata": { "id": "dc489f46-520d-4556-ae85-1f9eab3c412d", From e5e25a027e38438c3ede6ebd2c6bc923043ffd33 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 16:56:39 +0100 Subject: [PATCH 1104/1837] Update src/vs/workbench/browser/parts/editor/media/titlecontrol.css Co-authored-by: Benjamin Pasero --- src/vs/workbench/browser/parts/editor/media/titlecontrol.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css index 97accf43c74..05fe5934019 100644 --- a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css @@ -26,7 +26,7 @@ cursor: pointer; } -/* By defalut the icon label has a padding right and this isn't wanted when not showing tabs and not showing breadcrumbs */ +/* By default the icon label has a padding right and this isn't wanted when not showing tabs and not showing breadcrumbs */ .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .monaco-icon-label::after, .monaco-workbench .part.editor > .content .editor-group-container > .title.tabs .monaco-icon-label::after { padding-right: 0; From fc6bf56844ad7f9768fb878a08281c251175e796 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 16 Dec 2020 17:01:36 +0100 Subject: [PATCH 1105/1837] Fix executeTask for composite tasks Fixes #112545 --- src/vs/workbench/api/node/extHostTask.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 85e9a1e520f..260ace16bd9 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -50,11 +50,12 @@ export class ExtHostTask extends ExtHostTaskBase { } public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise { - if (!task.execution) { + const tTask = (task as types.Task); + + if (!task.execution && (tTask._id === undefined)) { throw new Error('Tasks to execute must include an execution'); } - const tTask = (task as types.Task); // We have a preserved ID. So the task didn't change. if (tTask._id !== undefined) { // Always get the task execution first to prevent timing issues when retrieving it later From b8ddffe7b413b52fd9bae16a2e4245a7136a5ff8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 17:03:30 +0100 Subject: [PATCH 1106/1837] rename setting --- .../workbench/browser/parts/editor/noTabsTitleControl.ts | 6 +++--- src/vs/workbench/browser/parts/editor/tabsTitleControl.ts | 4 ++-- src/vs/workbench/browser/workbench.contribution.ts | 8 ++++---- src/vs/workbench/common/editor.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 8c043a69be2..2760fd20c3a 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -189,7 +189,7 @@ export class NoTabsTitleControl extends TitleControl { } updateOptions(oldOptions: IEditorPartOptions, newOptions: IEditorPartOptions): void { - if (oldOptions.labelFormat !== newOptions.labelFormat || !equals(oldOptions.tabDecorations, newOptions.tabDecorations)) { + if (oldOptions.labelFormat !== newOptions.labelFormat || !equals(oldOptions.decorations, newOptions.decorations)) { this.redraw(); } } @@ -295,8 +295,8 @@ export class NoTabsTitleControl extends TitleControl { italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'], fileDecorations: { - colors: Boolean(options.tabDecorations?.colors), - badges: Boolean(options.tabDecorations?.badges) + colors: Boolean(options.decorations?.colors), + badges: Boolean(options.decorations?.badges) }, } ); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 722e0ccd98e..ead79b7a776 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -561,7 +561,7 @@ export class TabsTitleControl extends TitleControl { oldOptions.showIcons !== newOptions.showIcons || oldOptions.hasIcons !== newOptions.hasIcons || oldOptions.highlightModifiedTabs !== newOptions.highlightModifiedTabs || - !equals(oldOptions.tabDecorations, newOptions.tabDecorations) + !equals(oldOptions.decorations, newOptions.decorations) ) { this.redraw(); } @@ -1146,7 +1146,7 @@ export class TabsTitleControl extends TitleControl { // Label tabLabelWidget.setResource( { name, description, resource: EditorResourceAccessor.getOriginalUri(editor, { supportSideBySide: SideBySideEditor.BOTH }) }, - { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel, fileDecorations: { colors: Boolean(options.tabDecorations?.colors), badges: Boolean(options.tabDecorations?.badges) } } + { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel, fileDecorations: { colors: Boolean(options.decorations?.colors), badges: Boolean(options.decorations?.badges) } } ); // Tests helper diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index e460395c045..d5ea96380a9 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -43,14 +43,14 @@ import { isStandalone } from 'vs/base/browser/browser'; 'markdownDescription': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not. This value is ignored when `#workbench.editor.showTabs#` is disabled."), 'default': false }, - 'workbench.editor.tabDecorations.badges': { + 'workbench.editor.decorations.badges': { 'type': 'boolean', - 'markdownDescription': nls.localize('tabDecorations.badges', "Controls whether editor file decorations should use badges."), + 'markdownDescription': nls.localize('decorations.badges', "Controls whether editor file decorations should use badges."), 'default': true }, - 'workbench.editor.tabDecorations.colors': { + 'workbench.editor.decorations.colors': { 'type': 'boolean', - 'markdownDescription': nls.localize('tabDecorations.colors', "Controls whether editor file decorations should use colors."), + 'markdownDescription': nls.localize('decorations.colors', "Controls whether editor file decorations should use colors."), 'default': true }, 'workbench.editor.labelFormat': { diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 6e71546682b..db82863b0a6 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1291,7 +1291,7 @@ interface IEditorPartConfiguration { value?: number; perEditorGroup?: boolean; }; - tabDecorations?: { + decorations?: { badges?: boolean; colors?: boolean; } From cee8cbd9f299afbd81e6bc5c5d42b4c04df6813c Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 16 Dec 2020 17:10:58 +0100 Subject: [PATCH 1107/1837] fix cyclic dependency --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 4 ++-- src/vs/workbench/contrib/debug/browser/debugCommands.ts | 2 ++ src/vs/workbench/contrib/debug/browser/debugService.ts | 2 +- src/vs/workbench/contrib/debug/browser/debugViewlet.ts | 4 +--- src/vs/workbench/contrib/debug/browser/welcomeView.ts | 3 +-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 2a72c696ea0..32410b328ca 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -22,7 +22,7 @@ import { import { StartAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RunAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { DebugService } from 'vs/workbench/contrib/debug/browser/debugService'; -import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; @@ -38,7 +38,7 @@ import { VariablesView, SET_VARIABLE_ID, COPY_VALUE_ID, BREAK_WHEN_VALUE_CHANGES import { Repl } from 'vs/workbench/contrib/debug/browser/repl'; import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; -import { DebugViewPaneContainer, OpenDebugViewletAction, DEBUG_CONFIGURE_COMMAND_ID, OPEN_REPL_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugViewlet'; +import { DebugViewPaneContainer, OpenDebugViewletAction, OPEN_REPL_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugViewlet'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { CallStackEditorContribution } from 'vs/workbench/contrib/debug/browser/callStackEditorContribution'; import { BreakpointEditorContribution } from 'vs/workbench/contrib/debug/browser/breakpointEditorContribution'; diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 720ba1a4e64..a39c94ee18c 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -49,6 +49,7 @@ export const FOCUS_REPL_ID = 'workbench.debug.action.focusRepl'; export const JUMP_TO_CURSOR_ID = 'debug.jumpToCursor'; export const FOCUS_SESSION_ID = 'workbench.action.debug.focusProcess'; export const SELECT_AND_START_ID = 'workbench.action.debug.selectandstart'; +export const DEBUG_CONFIGURE_COMMAND_ID = 'workbench.action.debug.configure'; export const RESTART_LABEL = nls.localize('restartDebug', "Restart"); export const STEP_OVER_LABEL = nls.localize('stepOverDebug', "Step Over"); @@ -60,6 +61,7 @@ export const STOP_LABEL = nls.localize('stop', "Stop"); export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); export const FOCUS_SESSION_LABEL = nls.localize('focusSession', "Focus Session"); export const SELECT_AND_START_LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); +export const DEBUG_CONFIGURE_LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); interface CallStackContext { sessionId: string; diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 9b6789a9357..7dab649d0c3 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -49,7 +49,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager'; import { ITextModel } from 'vs/editor/common/model'; -import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugViewlet'; +import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; export class DebugService implements IDebugService { declare readonly _serviceBrand: undefined; diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 2978210dd43..2371e1a0706 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -36,7 +36,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { FOCUS_SESSION_ID, SELECT_AND_START_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { FOCUS_SESSION_ID, SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -202,8 +202,6 @@ registerAction2(class extends Action2 { } }); -export const DEBUG_CONFIGURE_COMMAND_ID = 'workbench.action.debug.configure'; -export const DEBUG_CONFIGURE_LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); registerAction2(class extends Action2 { constructor() { super({ diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index 2dfa11afe60..e073a168921 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -25,8 +25,7 @@ import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugViewlet'; -import { SELECT_AND_START_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; const debugStartLanguageKey = 'debugStartLanguage'; const CONTEXT_DEBUG_START_LANGUAGE = new RawContextKey(debugStartLanguageKey, undefined); From 6a342fe0a47dddf075f8a3d13458107e3afe736a Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 16 Dec 2020 08:22:13 -0800 Subject: [PATCH 1108/1837] update original webview based on original text model. --- .../browser/diff/notebookTextDiffEditor.ts | 17 ++++++++++++++++- .../browser/view/renderers/backLayerWebView.ts | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 58303b87995..cc9a8753c53 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -76,6 +76,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _revealFirst: boolean; private readonly _insetModifyQueueByOutputId = new SequencerByKey(); + private _isDisposed: boolean = false; + + get isDisposed() { + return this._isDisposed; + } + constructor( @IInstantiationService readonly instantiationService: IInstantiationService, @IThemeService readonly themeService: IThemeService, @@ -204,6 +210,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._register(this._list.onDidChangeContentHeight(() => { DOM.scheduleAtNextAnimationFrame(() => { + if (this._isDisposed) { + return; + } + const scrollTop = this._list.scrollTop; const scrollHeight = this._list.scrollHeight; @@ -264,7 +274,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const updateItems: IDisplayOutputLayoutUpdateRequest[] = []; const removedItems: IDisplayOutputViewModel[] = []; this._originalWebview.insetMapping.forEach((value, key) => { - const cell = value.cellInfo.diffElement.modified; + const cell = value.cellInfo.diffElement.original; if (!cell) { return; } @@ -666,6 +676,11 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); } + + dispose() { + this._isDisposed = true; + super.dispose(); + } } registerThemingParticipant((theme, collector) => { 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 61e743d4a45..faa02519988 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -10,7 +10,7 @@ import { isWeb } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; -import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputKind, IDisplayOutput, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; From af7edd782e127b06a1a2aa54c1d9da2bbe740a3f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 16 Dec 2020 17:46:24 +0100 Subject: [PATCH 1109/1837] move progress and cancellation of file operation participants into its only customer so that progress stop when applying a workspace edit and showing its preview --- .../mainThreadFileSystemEventService.ts | 62 ++++++++++++++++--- .../workingCopyFileOperationParticipant.ts | 54 +++------------- .../common/workingCopyFileService.ts | 4 +- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index b875404549b..fc119e251bd 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -4,15 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { DisposableStore } from 'vs/base/common/lifecycle'; -import { FileChangeType, IFileService } from 'vs/platform/files/common/files'; +import { FileChangeType, FileOperation, IFileService } from 'vs/platform/files/common/files'; import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/extHost.protocol'; import { localize } from 'vs/nls'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, SourceTargetPair } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { reviveWorkspaceEditDto2 } from 'vs/workbench/api/browser/mainThreadEditors'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; +import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; +import { raceCancellation } from 'vs/base/common/async'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; @extHostCustomer export class MainThreadFileSystemEventService { @@ -23,7 +26,8 @@ export class MainThreadFileSystemEventService { extHostContext: IExtHostContext, @IFileService fileService: IFileService, @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, - @IBulkEditService bulkEditService: IBulkEditService + @IBulkEditService bulkEditService: IBulkEditService, + @IProgressService progressService: IProgressService ) { const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService); @@ -56,13 +60,38 @@ export class MainThreadFileSystemEventService { })); - // BEFORE file operation - this._listener.add(workingCopyFileService.addFileOperationParticipant({ - participate: async (files, operation, undoRedoGroupId, isUndoing, _progress, timeout, token) => { + const fileOperationParticipant = new class implements IWorkingCopyFileOperationParticipant { + async participate(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, timeout: number, token: CancellationToken) { if (isUndoing) { return; } - const data = await proxy.$onWillRunFileOperation(operation, files, timeout, token); + + const cts = new CancellationTokenSource(token); + const timer = setTimeout(() => cts.cancel(), timeout); + + const data = await progressService.withProgress({ + location: ProgressLocation.Notification, + title: this._progressLabel(operation), + cancellable: true, + delay: Math.min(timeout / 2, 3000) + }, () => { + // race extension host event delivery against timeout AND user-cancel + const onWillEvent = proxy.$onWillRunFileOperation(operation, files, timeout, token); + return raceCancellation(onWillEvent, cts.token); + }, () => { + // user-cancel + cts.cancel(); + + }).finally(() => { + cts.dispose(); + clearTimeout(timer); + }); + + if (!data) { + // cancelled or no reply + return; + } + const edit = reviveWorkspaceEditDto2(data); await bulkEditService.apply(edit, { undoRedoGroupId, @@ -71,7 +100,22 @@ export class MainThreadFileSystemEventService { suppressPreview: true }); } - })); + private _progressLabel(operation: FileOperation): string { + switch (operation) { + case FileOperation.CREATE: + return localize('msg-create', "Running 'File Create' participants..."); + case FileOperation.MOVE: + return localize('msg-rename', "Running 'File Rename' participants..."); + case FileOperation.COPY: + return localize('msg-copy', "Running 'File Copy' participants..."); + case FileOperation.DELETE: + return localize('msg-delete', "Running 'File Delete' participants..."); + } + } + }; + + // BEFORE file operation + this._listener.add(workingCopyFileService.addFileOperationParticipant(fileOperationParticipant)); // AFTER file operation this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.files))); @@ -80,6 +124,8 @@ export class MainThreadFileSystemEventService { dispose(): void { this._listener.dispose(); } + + } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index f4b04294ed3..31fda6475fe 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -3,11 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localize } from 'vs/nls'; -import { raceCancellation } from 'vs/base/common/async'; -import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; -import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IWorkingCopyFileOperationParticipant } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { URI } from 'vs/base/common/uri'; @@ -20,7 +17,6 @@ export class WorkingCopyFileOperationParticipant extends Disposable { private readonly participants = new LinkedList(); constructor( - @IProgressService private readonly progressService: IProgressService, @ILogService private readonly logService: ILogService, @IConfigurationService private readonly configurationService: IConfigurationService ) { @@ -38,49 +34,13 @@ export class WorkingCopyFileOperationParticipant extends Disposable { return; // disabled } - const cts = new CancellationTokenSource(token); - const timer = setTimeout(() => cts.cancel(), timeout); - - return this.progressService.withProgress({ - location: ProgressLocation.Notification, - title: this.progressLabel(operation), - cancellable: true, - delay: Math.min(timeout / 2, 3000) - }, async progress => { - - // For each participant - for (const participant of this.participants) { - if (cts.token.isCancellationRequested) { - break; - } - try { - const promise = participant.participate(files, operation, undoRedoGroupId, isUndoing, progress, timeout, cts.token); - await raceCancellation(promise, cts.token); - } catch (err) { - this.logService.warn(err); - } + // For each participant + for (const participant of this.participants) { + try { + await participant.participate(files, operation, undoRedoGroupId, isUndoing, timeout, token ?? CancellationToken.None); + } catch (err) { + this.logService.warn(err); } - }, () => { - // user cancel - cts.cancel(); - - }).finally(() => { - // cleanup - cts.dispose(); - clearTimeout(timer); - }); - } - - private progressLabel(operation: FileOperation): string { - switch (operation) { - case FileOperation.CREATE: - return localize('msg-create', "Running 'File Create' participants..."); - case FileOperation.MOVE: - return localize('msg-rename', "Running 'File Rename' participants..."); - case FileOperation.COPY: - return localize('msg-copy', "Running 'File Copy' participants..."); - case FileOperation.DELETE: - return localize('msg-delete', "Running 'File Delete' participants..."); } } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 0e78557503d..922c722741a 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -13,13 +13,12 @@ import { IFileService, FileOperation, IFileStatWithMetadata } from 'vs/platform/ import { CancellationToken } from 'vs/base/common/cancellation'; import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress'; import { WorkingCopyFileOperationParticipant } from 'vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant'; import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; export const IWorkingCopyFileService = createDecorator('workingCopyFileService'); -interface SourceTargetPair { +export interface SourceTargetPair { /** * The source resource that is defined for move operations. @@ -62,7 +61,6 @@ export interface IWorkingCopyFileOperationParticipant { operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, - progress: IProgress, timeout: number, token: CancellationToken ): Promise; From 9f27d99af0146e45a4027a7ae622c944b21e1089 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Tue, 15 Dec 2020 15:30:44 -0800 Subject: [PATCH 1110/1837] Update isVSO check with new remote authority --- src/vs/workbench/api/browser/mainThreadAuthentication.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index c39650404a0..ffc57d866fa 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -416,7 +416,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu const remoteConnection = this.remoteAgentService.getConnection(); const isVSO = remoteConnection !== null - ? remoteConnection.remoteAuthority.startsWith('vsonline') + ? remoteConnection.remoteAuthority.startsWith('vsonline') || remoteConnection.remoteAuthority.startsWith('codespaces') : isWeb; if (isVSO && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) { From bffa4045489af467053ee5176e3e7bbbea590cfb Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Wed, 16 Dec 2020 09:01:06 -0800 Subject: [PATCH 1111/1837] Have TentativeBoundary trigger rollback (#112510) * have TentativeBoundary trigger rollback * add test * simplify test * add additional test --- .../browser/terminalTypeAheadAddon.ts | 3 +- .../test/browser/terminalTypeahead.test.ts | 51 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts index 5a9b02d8e04..a2e80c4b6be 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts @@ -330,7 +330,8 @@ class TentativeBoundary implements IPrediction { return ''; } - public rollback() { + public rollback(cursor: Cursor) { + this.inner.rollback(cursor); return ''; } diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts index 0814572f0d2..5f963dc0c82 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { Terminal } from 'xterm'; +import { IBuffer, Terminal } from 'xterm'; import { SinonStub, stub, useFakeTimers } from 'sinon'; import { Emitter } from 'vs/base/common/event'; import { CharPredictState, IPrediction, PredictionStats, TypeAheadAddon } from 'vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon'; @@ -14,6 +14,11 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; const CSI = `\x1b[`; +const enum CursorMoveDirection { + Back = 'D', + Forwards = 'C', +} + suite('Workbench - Terminal Typeahead', () => { suite('PredictionStats', () => { let stats: PredictionStats; @@ -139,6 +144,42 @@ suite('Workbench - Terminal Typeahead', () => { assert.strictEqual(addon.stats?.accuracy, 0); }); + test('handles left arrow when we hit the boundary', () => { + const t = createMockTerminal({ lines: ['|'] }); + addon.activate(t.terminal); + addon.unlockLeftNavigating(); + + const cursorXBefore = addon.getCursor(t.terminal.buffer.active)?.x!; + t.onData(`${CSI}${CursorMoveDirection.Back}`); + t.expectWritten(''); + + // Trigger rollback because we don't expect this data + onBeforeProcessData.fire({ data: 'xy' }); + + assert.strictEqual( + addon.getCursor(t.terminal.buffer.active)?.x, + // The cursor should not have changed because we've hit the + // boundary (start of prompt) + cursorXBefore); + }); + + test('internal cursor state is reset when all predictions are undone', () => { + const t = createMockTerminal({ lines: ['|'] }); + addon.activate(t.terminal); + addon.unlockLeftNavigating(); + + const cursorXBefore = addon.getCursor(t.terminal.buffer.active)?.x!; + t.onData(`${CSI}${CursorMoveDirection.Back}`); + t.expectWritten(''); + addon.undoAllPredictions(); + + assert.strictEqual( + addon.getCursor(t.terminal.buffer.active)?.x, + // The cursor should not have changed because we've hit the + // boundary (start of prompt) + cursorXBefore); + }); + test('restores cursor graphics mode', () => { const t = createMockTerminal({ lines: ['hello|'], @@ -296,6 +337,14 @@ class TestTypeAheadAddon extends TypeAheadAddon { public get isShowing() { return !!this.timeline?.isShowingPredictions; } + + public undoAllPredictions() { + this.timeline?.undoAllPredictions(); + } + + public getCursor(buffer: IBuffer) { + return this.timeline?.getCursor(buffer); + } } function upcastPartial(v: Partial): T { From 9474102e7b27a48de7b5f11691ff4c1b593e0b73 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 16 Dec 2020 18:17:25 +0100 Subject: [PATCH 1112/1837] debug: more transition to commands, get rid of StartAction --- .../debug/browser/debug.contribution.ts | 20 +++--- .../contrib/debug/browser/debugActions.ts | 62 ------------------- .../contrib/debug/browser/debugCommands.ts | 35 ++++++++++- .../contrib/debug/browser/debugViewlet.ts | 34 +++------- .../contrib/debug/browser/welcomeView.ts | 7 +-- .../contrib/watermark/browser/watermark.ts | 4 +- 6 files changed, 58 insertions(+), 104 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 32410b328ca..dcc0e815366 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -17,12 +17,12 @@ import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView' import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IDebugService, VIEWLET_ID, DEBUG_PANEL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA, - CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, + CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, BREAKPOINT_EDITOR_CONTRIBUTION_ID, REPL_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, EDITOR_CONTRIBUTION_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT, getStateLabel, State, } from 'vs/workbench/contrib/debug/common/debug'; -import { StartAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RunAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { DisableAllBreakpointsAction, EnableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { DebugService } from 'vs/workbench/contrib/debug/browser/debugService'; -import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID, DEBUG_RUN_LABEL, DEBUG_RUN_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; @@ -55,7 +55,6 @@ import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); const debugCategory = nls.localize('debugCategory', "Debug"); -const runCategroy = nls.localize('runCategory', "Run"); registerWorkbenchContributions(); registerColors(); registerCommandsAndActions(); @@ -63,8 +62,6 @@ registerDebugMenu(); registerEditorActions(); registerCommands(); registerDebugPanel(); -registry.registerWorkbenchAction(SyncActionDescriptor.from(StartAction, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE.toNegated()), 'Debug: Start Debugging', debugCategory, CONTEXT_DEBUGGERS_AVAILABLE); -registry.registerWorkbenchAction(SyncActionDescriptor.from(RunAction, { primary: KeyMod.CtrlCmd | KeyCode.F5, mac: { primary: KeyMod.WinCtrl | KeyCode.F5 } }), 'Run: Start Without Debugging', runCategroy, CONTEXT_DEBUGGERS_AVAILABLE); registerSingleton(IDebugService, DebugService, true); registerDebugView(); @@ -108,6 +105,7 @@ function registerCommandsAndActions(): void { const registerDebugCommandPaletteItem = (id: string, title: string, when?: ContextKeyExpression, precondition?: ContextKeyExpression) => { MenuRegistry.appendMenuItem(MenuId.CommandPalette, { when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, when), + group: debugCategory, command: { id, title: `Debug: ${title}`, @@ -130,6 +128,8 @@ function registerCommandsAndActions(): void { registerDebugCommandPaletteItem(JUMP_TO_CURSOR_ID, nls.localize('SetNextStatement', "Set Next Statement"), CONTEXT_JUMP_TO_CURSOR_SUPPORTED); registerDebugCommandPaletteItem(RunToCursorAction.ID, RunToCursorAction.LABEL, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); registerDebugCommandPaletteItem(TOGGLE_INLINE_BREAKPOINT_ID, nls.localize('inlineBreakpoint', "Inline Breakpoint")); + registerDebugCommandPaletteItem(DEBUG_START_COMMAND_ID, DEBUG_START_LABEL, ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing)))); + registerDebugCommandPaletteItem(DEBUG_RUN_COMMAND_ID, DEBUG_RUN_LABEL, ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing)))); // Debug callstack context menu const registerDebugViewMenuItem = (menuId: MenuId, id: string, title: string, order: number, when?: ContextKeyExpression, precondition?: ContextKeyExpression, group = 'navigation') => { @@ -177,8 +177,8 @@ function registerCommandsAndActions(): void { }); }; - registerTouchBarEntry(StartAction.ID, StartAction.LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/continue-tb.png', require)); - registerTouchBarEntry(RunAction.ID, RunAction.LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/continue-without-debugging-tb.png', require)); + registerTouchBarEntry(DEBUG_START_COMMAND_ID, DEBUG_START_LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/continue-tb.png', require)); + registerTouchBarEntry(DEBUG_RUN_COMMAND_ID, DEBUG_RUN_LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/continue-without-debugging-tb.png', require)); registerTouchBarEntry(CONTINUE_ID, CONTINUE_LABEL, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/continue-tb.png', require)); registerTouchBarEntry(PAUSE_ID, PAUSE_LABEL, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/pause-tb.png', require)); registerTouchBarEntry(STEP_OVER_ID, STEP_OVER_LABEL, 2, CONTEXT_IN_DEBUG_MODE, FileAccess.asFileUri('vs/workbench/contrib/debug/browser/media/stepover-tb.png', require)); @@ -215,7 +215,7 @@ function registerDebugMenu(): void { MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { group: '1_debug', command: { - id: StartAction.ID, + id: DEBUG_START_COMMAND_ID, title: nls.localize({ key: 'miStartDebugging', comment: ['&& denotes a mnemonic'] }, "&&Start Debugging") }, order: 1, @@ -225,7 +225,7 @@ function registerDebugMenu(): void { MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { group: '1_debug', command: { - id: RunAction.ID, + id: DEBUG_RUN_COMMAND_ID, title: nls.localize({ key: 'miRun', comment: ['&& denotes a mnemonic'] }, "Run &&Without Debugging") }, order: 2, diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index b2c43870f59..1650c4479e0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -6,11 +6,9 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDebugService, State, IEnablement, IBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { Variable, Breakpoint, FunctionBreakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { deepClone } from 'vs/base/common/objects'; export abstract class AbstractDebugAction extends Action { @@ -50,66 +48,6 @@ export abstract class AbstractDebugAction extends Action { } } -export class StartAction extends AbstractDebugAction { - static ID = 'workbench.action.debug.start'; - static LABEL = nls.localize('startDebug', "Start Debugging"); - - constructor(id: string, label: string, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - ) { - super(id, label, 'debug-action start', debugService, keybindingService); - - this._register(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement())); - this._register(this.debugService.onDidNewSession(() => this.updateEnablement())); - this._register(this.debugService.onDidEndSession(() => this.updateEnablement())); - this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement())); - } - - async run(): Promise { - let { launch, name, getConfig } = this.debugService.getConfigurationManager().selectedConfiguration; - const config = await getConfig(); - const clonedConfig = deepClone(config); - return this.debugService.startDebugging(launch, clonedConfig || name, { noDebug: this.isNoDebug() }); - } - - protected isNoDebug(): boolean { - return false; - } - - static isEnabled(debugService: IDebugService) { - const sessions = debugService.getModel().getSessions(); - - if (debugService.state === State.Initializing) { - return false; - } - let { name, launch } = debugService.getConfigurationManager().selectedConfiguration; - let nameToStart = name; - - if (sessions.some(s => s.configuration.name === nameToStart && s.root === launch?.workspace)) { - // There is already a debug session running and we do not have any launch configuration selected - return false; - } - - return true; - } - - // Disabled if the launch drop down shows the launch config that is already running. - protected isEnabled(): boolean { - return StartAction.isEnabled(this.debugService); - } -} - -export class RunAction extends StartAction { - static readonly ID = 'workbench.action.debug.run'; - static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging"); - - protected isNoDebug(): boolean { - return true; - } -} - export class RemoveBreakpointAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.removeBreakpoint'; static readonly LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint"); diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index a39c94ee18c..355e65bed1a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -9,7 +9,7 @@ import { List } from 'vs/base/browser/ui/list/listWidget'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IListService } from 'vs/platform/list/browser/listService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, IDebugConfiguration, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, IDebugConfiguration, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, REPL_VIEW_ID, CONTEXT_DEBUGGERS_AVAILABLE, State, getStateLabel } from 'vs/workbench/contrib/debug/common/debug'; import { Expression, Variable, Breakpoint, FunctionBreakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel'; import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -23,12 +23,13 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { InputFocusedContext } from 'vs/platform/contextkey/common/contextkeys'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { PanelFocusContext } from 'vs/workbench/common/panel'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IViewsService } from 'vs/workbench/common/views'; +import { deepClone } from 'vs/base/common/objects'; export const ADD_CONFIGURATION_ID = 'debug.addConfiguration'; export const TOGGLE_INLINE_BREAKPOINT_ID = 'editor.debug.action.toggleInlineBreakpoint'; @@ -50,6 +51,8 @@ export const JUMP_TO_CURSOR_ID = 'debug.jumpToCursor'; export const FOCUS_SESSION_ID = 'workbench.action.debug.focusProcess'; export const SELECT_AND_START_ID = 'workbench.action.debug.selectandstart'; export const DEBUG_CONFIGURE_COMMAND_ID = 'workbench.action.debug.configure'; +export const DEBUG_START_COMMAND_ID = 'workbench.action.debug.start'; +export const DEBUG_RUN_COMMAND_ID = 'workbench.action.debug.run'; export const RESTART_LABEL = nls.localize('restartDebug', "Restart"); export const STEP_OVER_LABEL = nls.localize('stepOverDebug', "Step Over"); @@ -62,6 +65,8 @@ export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); export const FOCUS_SESSION_LABEL = nls.localize('focusSession', "Focus Session"); export const SELECT_AND_START_LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); export const DEBUG_CONFIGURE_LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); +export const DEBUG_START_LABEL = nls.localize('startDebug', "Start Debugging"); +export const DEBUG_RUN_LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging"); interface CallStackContext { sessionId: string; @@ -373,6 +378,32 @@ export function registerCommands(): void { } }); + KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: DEBUG_START_COMMAND_ID, + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyCode.F5, + when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing))), + handler: async (accessor: ServicesAccessor, debugStartOptions?: { noDebug: boolean }) => { + const debugService = accessor.get(IDebugService); + let { launch, name, getConfig } = debugService.getConfigurationManager().selectedConfiguration; + const config = await getConfig(); + const clonedConfig = deepClone(config); + await debugService.startDebugging(launch, clonedConfig || name, { noDebug: debugStartOptions && debugStartOptions.noDebug }); + } + }); + + KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: DEBUG_RUN_COMMAND_ID, + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyMod.CtrlCmd | KeyCode.F5, + mac: { primary: KeyMod.WinCtrl | KeyCode.F5 }, + when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing))), + handler: async (accessor: ServicesAccessor) => { + const commandService = accessor.get(ICommandService); + await commandService.executeCommand(DEBUG_START_COMMAND_ID, { noDebug: true }); + } + }); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'debug.toggleBreakpoint', weight: KeybindingWeight.WorkbenchContrib + 5, diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 2371e1a0706..c0e955c6288 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -7,7 +7,6 @@ import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; import { IAction, IActionViewItem } from 'vs/base/common/actions'; import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch } from 'vs/workbench/contrib/debug/common/debug'; -import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -36,7 +35,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { FOCUS_SESSION_ID, SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { FOCUS_SESSION_ID, SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -96,7 +95,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } getActionViewItem(action: IAction): IActionViewItem | undefined { - if (action.id === 'debug.start') { + if (action.id === DEBUG_START_COMMAND_ID) { this.startDebugActionViewItem = this.instantiationService.createInstance(StartDebugActionViewItem, null, action); return this.startDebugActionViewItem; } @@ -178,27 +177,14 @@ export class OpenDebugViewletAction extends ShowViewletAction { } } -registerAction2(class extends Action2 { - constructor() { - super({ - id: 'debug.start', - title: StartAction.LABEL, - f1: false, - precondition: ContextKeyExpr.and(CONTEXT_DEBUG_STATE.notEqualsTo('initializing'), CONTEXT_DEBUG_UX.notEqualsTo('simple')), - menu: { - id: MenuId.ViewContainerTitle, - group: 'navigation', - order: 10, - when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_UX.notEqualsTo('simple'), WorkbenchStateContext.notEqualsTo('empty'), - ContextKeyExpr.or(CONTEXT_DEBUG_STATE.isEqualTo('inactive'), ContextKeyExpr.notEquals('config.debug.toolBarLocation', 'docked'))) - } - }); - } - - async run(accessor: ServicesAccessor): Promise { - const instantiationService = accessor.get(IInstantiationService); - const startAction = instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL); - await startAction.run(); +MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_UX.notEqualsTo('simple'), WorkbenchStateContext.notEqualsTo('empty'), + ContextKeyExpr.or(CONTEXT_DEBUG_STATE.isEqualTo('inactive'), ContextKeyExpr.notEquals('config.debug.toolBarLocation', 'docked'))), + order: 10, + group: 'navigation', + command: { + id: DEBUG_START_COMMAND_ID, + title: DEBUG_START_LABEL } }); diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index e073a168921..e33671e73e8 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -10,7 +10,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService, RawContextKey, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; -import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; @@ -25,7 +24,7 @@ import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { SELECT_AND_START_ID, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_START_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; const debugStartLanguageKey = 'debugStartLanguage'; const CONTEXT_DEBUG_START_LANGUAGE = new RawContextKey(debugStartLanguageKey, undefined); @@ -97,7 +96,7 @@ export class WelcomeView extends ViewPane { })); setContextKey(); - const debugKeybinding = this.keybindingService.lookupKeybinding(StartAction.ID); + const debugKeybinding = this.keybindingService.lookupKeybinding(DEBUG_START_COMMAND_ID); debugKeybindingLabel = debugKeybinding ? ` (${debugKeybinding.getLabel()})` : ''; } @@ -117,7 +116,7 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { let debugKeybindingLabel = ''; viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, { content: localize({ key: 'runAndDebugAction', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] }, - "[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID), + "[Run and Debug{0}](command:{1})", debugKeybindingLabel, DEBUG_START_COMMAND_ID), when: CONTEXT_DEBUGGERS_AVAILABLE, group: ViewContentGroups.Debug }); diff --git a/src/vs/workbench/contrib/watermark/browser/watermark.ts b/src/vs/workbench/contrib/watermark/browser/watermark.ts index 30340ca4663..f08bda7c8fc 100644 --- a/src/vs/workbench/contrib/watermark/browser/watermark.ts +++ b/src/vs/workbench/contrib/watermark/browser/watermark.ts @@ -17,7 +17,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { OpenFolderAction, OpenFileFolderAction, OpenFileAction } from 'vs/workbench/browser/actions/workspaceActions'; import { ShowAllCommandsAction } from 'vs/workbench/contrib/quickaccess/browser/commandsQuickAccess'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { FindInFilesActionId } from 'vs/workbench/contrib/search/common/constants'; import * as dom from 'vs/base/browser/dom'; import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; @@ -27,6 +26,7 @@ import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/termin import { assertIsDefined } from 'vs/base/common/types'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; import { NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { DEBUG_START_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; const $ = dom.$; @@ -46,7 +46,7 @@ const newUntitledFile: WatermarkEntry = { text: nls.localize('watermark.newUntit const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile); const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: TERMINAL_COMMAND_ID.TOGGLE }; const findInFiles: WatermarkEntry = { text: nls.localize('watermark.findInFiles', "Find in Files"), id: FindInFilesActionId }; -const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: StartAction.ID }; +const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: DEBUG_START_COMMAND_ID }; const noFolderEntries = [ showCommands, From 41f450129ff9f9ec41b051859aa23c9e630797be Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Thu, 17 Dec 2020 02:01:52 +0800 Subject: [PATCH 1113/1837] fix: hover link encode unnecessarily --- src/vs/editor/contrib/links/links.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 04e8b8aa037..17573b46ecd 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -57,7 +57,7 @@ function getHoverMessage(link: Link, useMetaKey: boolean): MarkdownString { nativeLabel = ` "${nativeLabelText}"`; } } - const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()}${nativeLabel}) (${kb})`); + const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString(true)}${nativeLabel}) (${kb})`); return hoverMessage; } else { return new MarkdownString().appendText(`${label} (${kb})`); From 2156931d38bc48f490ffef25a50ed410e19a6bae Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 16 Dec 2020 10:16:10 -0800 Subject: [PATCH 1114/1837] Better side scrolling --- .../gettingStarted/browser/gettingStarted.css | 7 +++++++ .../gettingStarted/browser/gettingStarted.ts | 5 ++--- .../browser/vs_code_editor_getting_started.ts | 13 ++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 5f15d3d1bcc..4a882d18248 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -195,6 +195,12 @@ height: 100%; } +.monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #gettingStartedDetailsContent { + height: 100%; + display: flex; + flex-direction: column; +} + .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .gettingStartedSlide.detail #getting-started-detail-right { display: flex; align-items: center; @@ -231,6 +237,7 @@ top: -10px; font-size: 12pt; margin: 10px; + z-index: 1; } .monaco-workbench .part.editor > .content .walkThroughContent .gettingStartedContainer .prev-button:hover { diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 59f4f80c2e3..166cf511fdd 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -216,12 +216,11 @@ export class GettingStartedPage extends Disposable { const categoriesSlide = assertIsDefined(document.getElementById('gettingStartedSlideCategory')); const tasksSlide = assertIsDefined(document.getElementById('gettingStartedSlideDetails')); - const tasksContent = assertIsDefined(document.getElementById('getting-started-detail-columns')); + const tasksContent = assertIsDefined(document.getElementById('gettingStartedDetailsContent')); tasksContent.remove(); if (this.detailImageScrollbar) { this.detailImageScrollbar.dispose(); } - this.detailImageScrollbar = this._register(new DomScrollableElement(tasksContent, {})); + this.detailImageScrollbar = this._register(new DomScrollableElement(tasksContent, { className: 'full-height-scrollable' })); tasksSlide.appendChild(this.detailImageScrollbar.getDomNode()); - tasksSlide.appendChild($('.gap')); this.detailImageScrollbar.scanDomNode(); const rightColumn = assertIsDefined(container.querySelector('#getting-started-detail-right')); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts index 73cf66eb70c..1c2733696e3 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/vs_code_editor_getting_started.ts @@ -18,13 +18,16 @@ export default () => `
Back -
-
+
-
-
+
+
+
+
+
+
+
-
From 483bd40550d660c24f49e153dc8aa689d64db78a Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 16 Dec 2020 10:20:57 -0800 Subject: [PATCH 1115/1837] Update several Emmet commands (#112597) For match tag, update tag, and balance in/out, we now have the following: - vscode-html-languageservice parse is being used to speed up file parse times - Balance balance-in after balance-out behaviour is now more consistent - These commands now work in markup files with unclosed tags - Implemented a cache for these commands to prevent multiple document parses on the same version of the document --- extensions/emmet/src/balance.ts | 84 ++++++++-------- extensions/emmet/src/emmetCommon.ts | 17 +++- extensions/emmet/src/matchTag.ts | 32 ++++--- extensions/emmet/src/parseMarkupDocument.ts | 43 +++++++++ extensions/emmet/src/splitJoinTag.ts | 49 +++++----- extensions/emmet/src/updateTag.ts | 55 ++++++----- extensions/emmet/src/util.ts | 101 +++++++++++++++++++- 7 files changed, 273 insertions(+), 108 deletions(-) create mode 100644 extensions/emmet/src/parseMarkupDocument.ts diff --git a/extensions/emmet/src/balance.ts b/extensions/emmet/src/balance.ts index 21ac3027d5e..0862b20a60f 100644 --- a/extensions/emmet/src/balance.ts +++ b/extensions/emmet/src/balance.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { HtmlNode } from 'EmmetNode'; -import { getHtmlNode, parseDocument, validate } from './util'; +import { getHtmlNodeLS, offsetRangeToSelection, toLSTextDocument, validate } from './util'; +import { parseMarkupDocument } from './parseMarkupDocument'; +import { TextDocument as LSTextDocument } from 'vscode-html-languageservice'; let balanceOutStack: Array = []; -let lastOut = false; let lastBalancedSelections: vscode.Selection[] = []; export function balanceOut() { @@ -24,53 +24,50 @@ function balance(out: boolean) { return; } const editor = vscode.window.activeTextEditor; - let rootNode = parseDocument(editor.document); - if (!rootNode) { + const document = toLSTextDocument(editor.document); + const htmlDocument = parseMarkupDocument(document); + if (!htmlDocument) { return; } - let getRangeFunction = out ? getRangeToBalanceOut : getRangeToBalanceIn; + const rangeFn = out ? getRangeToBalanceOut : getRangeToBalanceIn; let newSelections: vscode.Selection[] = []; editor.selections.forEach(selection => { - let range = getRangeFunction(editor.document, selection, rootNode); + const range = rangeFn(document, selection); newSelections.push(range); }); - if (areSameSelections(newSelections, editor.selections)) { - return; - } - + // check whether we are starting a balance elsewhere if (areSameSelections(lastBalancedSelections, editor.selections)) { + // we are not starting elsewhere, so use the stack as-is if (out) { - if (!balanceOutStack.length) { + // make sure we are able to expand outwards + if (!areSameSelections(editor.selections, newSelections)) { balanceOutStack.push(editor.selections); } - balanceOutStack.push(newSelections); - } else { - if (lastOut) { - balanceOutStack.pop(); - } - newSelections = balanceOutStack.pop() || newSelections; + } else if (balanceOutStack.length) { + newSelections = balanceOutStack.pop()!; } } else { - balanceOutStack = out ? [editor.selections, newSelections] : []; + // we are starting elsewhere, so reset the stack + balanceOutStack = out ? [editor.selections] : []; } - lastOut = out; - lastBalancedSelections = editor.selections = newSelections; + editor.selections = newSelections; + lastBalancedSelections = editor.selections; } -function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection { - let nodeToBalance = getHtmlNode(document, rootNode, selection.start, false); +function getRangeToBalanceOut(document: LSTextDocument, selection: vscode.Selection): vscode.Selection { + const nodeToBalance = getHtmlNodeLS(document, selection.start, false); if (!nodeToBalance) { return selection; } - if (!nodeToBalance.close) { - return new vscode.Selection(nodeToBalance.start, nodeToBalance.end); + if (!nodeToBalance.endTagStart || !nodeToBalance.startTagEnd) { + return offsetRangeToSelection(document, nodeToBalance.start, nodeToBalance.end); } - let innerSelection = new vscode.Selection(nodeToBalance.open.end, nodeToBalance.close.start); - let outerSelection = new vscode.Selection(nodeToBalance.start, nodeToBalance.end); + const innerSelection = offsetRangeToSelection(document, nodeToBalance.startTagEnd, nodeToBalance.endTagStart); + const outerSelection = offsetRangeToSelection(document, nodeToBalance.start, nodeToBalance.end); if (innerSelection.contains(selection) && !innerSelection.isEqual(selection)) { return innerSelection; @@ -81,34 +78,37 @@ function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.S return selection; } -function getRangeToBalanceIn(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection { - let nodeToBalance = getHtmlNode(document, rootNode, selection.start, true); +function getRangeToBalanceIn(document: LSTextDocument, selection: vscode.Selection): vscode.Selection { + const nodeToBalance = getHtmlNodeLS(document, selection.start, true); if (!nodeToBalance) { return selection; } - if (nodeToBalance.close) { - const entireNodeSelected = selection.start.isEqual(nodeToBalance.start) && selection.end.isEqual(nodeToBalance.end); - const startInOpenTag = selection.start.isAfter(nodeToBalance.open.start) && selection.start.isBefore(nodeToBalance.open.end); - const startInCloseTag = selection.start.isAfter(nodeToBalance.close.start) && selection.start.isBefore(nodeToBalance.close.end); + const selectionStart = document.offsetAt(selection.start); + const selectionEnd = document.offsetAt(selection.end); + if (nodeToBalance.endTagStart !== undefined && nodeToBalance.startTagEnd !== undefined) { + const entireNodeSelected = selectionStart === nodeToBalance.start && selectionEnd === nodeToBalance.end; + const startInOpenTag = selectionStart > nodeToBalance.start && selectionStart < nodeToBalance.startTagEnd; + const startInCloseTag = selectionStart > nodeToBalance.endTagStart && selectionStart < nodeToBalance.end; if (entireNodeSelected || startInOpenTag || startInCloseTag) { - return new vscode.Selection(nodeToBalance.open.end, nodeToBalance.close.start); + return offsetRangeToSelection(document, nodeToBalance.startTagEnd, nodeToBalance.endTagStart); } } - if (!nodeToBalance.firstChild) { + if (!nodeToBalance.children.length) { return selection; } - if (selection.start.isEqual(nodeToBalance.firstChild.start) - && selection.end.isEqual(nodeToBalance.firstChild.end) - && nodeToBalance.firstChild.close) { - return new vscode.Selection(nodeToBalance.firstChild.open.end, nodeToBalance.firstChild.close.start); + const firstChild = nodeToBalance.children[0]; + if (selectionStart === firstChild.start + && selectionEnd === firstChild.end + && firstChild.endTagStart !== undefined + && firstChild.startTagEnd !== undefined) { + return offsetRangeToSelection(document, firstChild.startTagEnd, firstChild.endTagStart); } - return new vscode.Selection(nodeToBalance.firstChild.start, nodeToBalance.firstChild.end); - + return offsetRangeToSelection(document, firstChild.start, firstChild.end); } function areSameSelections(a: vscode.Selection[], b: vscode.Selection[]): boolean { @@ -121,4 +121,4 @@ function areSameSelections(a: vscode.Selection[], b: vscode.Selection[]): boolea } } return true; -} \ No newline at end of file +} diff --git a/extensions/emmet/src/emmetCommon.ts b/extensions/emmet/src/emmetCommon.ts index e768b03afd6..56e02a3b1aa 100644 --- a/extensions/emmet/src/emmetCommon.ts +++ b/extensions/emmet/src/emmetCommon.ts @@ -17,8 +17,9 @@ import { fetchEditPoint } from './editPoint'; import { fetchSelectItem } from './selectItem'; import { evaluateMathExpression } from './evaluateMathExpression'; import { incrementDecrement } from './incrementDecrement'; -import { LANGUAGE_MODES, getMappingForIncludedLanguages, updateEmmetExtensionsPath, getPathBaseName } from './util'; +import { LANGUAGE_MODES, getMappingForIncludedLanguages, updateEmmetExtensionsPath, getPathBaseName, toLSTextDocument, getSyntaxes, getEmmetMode } from './util'; import { reflectCssValue } from './reflectCssValue'; +import { addFileToMarkupParseCache, removeFileFromMarkupParseCache } from './parseMarkupDocument'; export function activateEmmetExtension(context: vscode.ExtensionContext) { registerCompletionProviders(context); @@ -145,6 +146,20 @@ export function activateEmmetExtension(context: vscode.ExtensionContext) { updateEmmetExtensionsPath(true); } })); + + context.subscriptions.push(vscode.workspace.onDidOpenTextDocument((e) => { + const emmetMode = getEmmetMode(e.languageId, []) ?? ''; + if (getSyntaxes().markup.includes(emmetMode)) { + addFileToMarkupParseCache(toLSTextDocument(e)); + } + })); + + context.subscriptions.push(vscode.workspace.onDidCloseTextDocument((e) => { + const emmetMode = getEmmetMode(e.languageId, []) ?? ''; + if (getSyntaxes().markup.includes(emmetMode)) { + removeFileFromMarkupParseCache(toLSTextDocument(e)); + } + })); } /** diff --git a/extensions/emmet/src/matchTag.ts b/extensions/emmet/src/matchTag.ts index 1e5ead3fb87..f2b707d4457 100644 --- a/extensions/emmet/src/matchTag.ts +++ b/extensions/emmet/src/matchTag.ts @@ -4,9 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { HtmlNode } from 'EmmetNode'; -import { getHtmlNode, parseDocument, validate } from './util'; - +import { toLSTextDocument, validate, getHtmlNodeLS, offsetRangeToSelection } from './util'; +import { TextDocument as LSTextDocument } from 'vscode-html-languageservice'; export function matchTag() { if (!validate(false) || !vscode.window.activeTextEditor) { @@ -14,32 +13,37 @@ export function matchTag() { } const editor = vscode.window.activeTextEditor; - let rootNode: HtmlNode = parseDocument(editor.document); - if (!rootNode) { return; } + const document = toLSTextDocument(editor.document); let updatedSelections: vscode.Selection[] = []; editor.selections.forEach(selection => { - let updatedSelection = getUpdatedSelections(editor, selection.start, rootNode); + const updatedSelection = getUpdatedSelections(document, selection.start); if (updatedSelection) { updatedSelections.push(updatedSelection); } }); - if (updatedSelections.length > 0) { + if (updatedSelections.length) { editor.selections = updatedSelections; editor.revealRange(editor.selections[updatedSelections.length - 1]); } } -function getUpdatedSelections(editor: vscode.TextEditor, position: vscode.Position, rootNode: HtmlNode): vscode.Selection | undefined { - let currentNode = getHtmlNode(editor.document, rootNode, position, true); - if (!currentNode) { return; } +function getUpdatedSelections(document: LSTextDocument, position: vscode.Position): vscode.Selection | undefined { + const currentNode = getHtmlNodeLS(document, position, true); + if (!currentNode) { + return; + } + + const offset = document.offsetAt(position); // If no closing tag or cursor is between open and close tag, then no-op - if (!currentNode.close || (position.isAfter(currentNode.open.end) && position.isBefore(currentNode.close.start))) { + if (currentNode.endTagStart === undefined + || currentNode.startTagEnd === undefined + || (offset > currentNode.startTagEnd && offset < currentNode.endTagStart)) { return; } // Place cursor inside the close tag if cursor is inside the open tag, else place it inside the open tag - let finalPosition = position.isBeforeOrEqual(currentNode.open.end) ? currentNode.close.start.translate(0, 2) : currentNode.open.start.translate(0, 1); - return new vscode.Selection(finalPosition, finalPosition); -} \ No newline at end of file + const finalOffset = (offset <= currentNode.startTagEnd) ? currentNode.endTagStart + 2 : currentNode.start + 1; + return offsetRangeToSelection(document, finalOffset, finalOffset); +} diff --git a/extensions/emmet/src/parseMarkupDocument.ts b/extensions/emmet/src/parseMarkupDocument.ts new file mode 100644 index 00000000000..a1e526056c8 --- /dev/null +++ b/extensions/emmet/src/parseMarkupDocument.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { HTMLDocument, TextDocument as LSTextDocument } from 'vscode-html-languageservice'; +import { getLanguageService } from './util'; + +type Pair = { + key: K; + value: V; +}; + +// Map(filename, Pair(fileVersion, parsedContent)) +const _parseCache = new Map | undefined>(); + +export function parseMarkupDocument(document: LSTextDocument, useCache: boolean = true): HTMLDocument { + const languageService = getLanguageService(); + const key = document.uri; + const result = _parseCache.get(key); + const documentVersion = document.version; + if (useCache && result) { + if (documentVersion === result.key) { + return result.value; + } + } + + const parsedDocument = languageService.parseHTMLDocument(document); + if (useCache) { + _parseCache.set(key, { key: documentVersion, value: parsedDocument }); + } + return parsedDocument; +} + +export function addFileToMarkupParseCache(document: LSTextDocument) { + const filename = document.uri; + _parseCache.set(filename, undefined); +} + +export function removeFileFromMarkupParseCache(document: LSTextDocument) { + const filename = document.uri; + _parseCache.delete(filename); +} diff --git a/extensions/emmet/src/splitJoinTag.ts b/extensions/emmet/src/splitJoinTag.ts index a5f1d255c85..d2df5d65078 100644 --- a/extensions/emmet/src/splitJoinTag.ts +++ b/extensions/emmet/src/splitJoinTag.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { HtmlNode } from 'EmmetNode'; -import { getHtmlNode, parseDocument, validate, getEmmetMode, getEmmetConfiguration } from './util'; +import { validate, getEmmetMode, getEmmetConfiguration, toLSTextDocument, getHtmlNodeLS, offsetRangeToVsRange } from './util'; +import { Node as LSNode, TextDocument as LSTextDocument } from 'vscode-html-languageservice'; export function splitJoinTag() { if (!validate(false) || !vscode.window.activeTextEditor) { @@ -13,40 +13,42 @@ export function splitJoinTag() { } const editor = vscode.window.activeTextEditor; - let rootNode = parseDocument(editor.document); - if (!rootNode) { - return; - } - + const document = toLSTextDocument(editor.document); return editor.edit(editBuilder => { editor.selections.reverse().forEach(selection => { - let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start, true); + const nodeToUpdate = getHtmlNodeLS(document, selection.start, true); if (nodeToUpdate) { - let textEdit = getRangesToReplace(editor.document, nodeToUpdate); - editBuilder.replace(textEdit.range, textEdit.newText); + const textEdit = getRangesToReplace(document, nodeToUpdate); + if (textEdit) { + editBuilder.replace(textEdit.range, textEdit.newText); + } } }); }); } -function getRangesToReplace(document: vscode.TextDocument, nodeToUpdate: HtmlNode): vscode.TextEdit { +function getRangesToReplace(document: LSTextDocument, nodeToUpdate: LSNode): vscode.TextEdit | undefined { let rangeToReplace: vscode.Range; let textToReplaceWith: string; - if (!nodeToUpdate.close) { - // Split Tag - let nodeText = document.getText(new vscode.Range(nodeToUpdate.start, nodeToUpdate.end)); - let m = nodeText.match(/(\s*\/)?>$/); - let end = nodeToUpdate.end; - let start = m ? end.translate(0, -m[0].length) : end; + if (!nodeToUpdate?.tag) { + return; + } - rangeToReplace = new vscode.Range(start, end); - textToReplaceWith = `>`; + if (nodeToUpdate.endTagStart === undefined || nodeToUpdate.startTagEnd === undefined) { + // Split Tag + const nodeText = document.getText().substring(nodeToUpdate.start, nodeToUpdate.end); + const m = nodeText.match(/(\s*\/)?>$/); + const end = nodeToUpdate.end; + const start = m ? end - m[0].length : end; + + rangeToReplace = offsetRangeToVsRange(document, start, end); + textToReplaceWith = `>`; } else { // Join Tag - let start = (nodeToUpdate.open.end).translate(0, -1); - let end = nodeToUpdate.end; - rangeToReplace = new vscode.Range(start, end); + const start = nodeToUpdate.startTagEnd - 1; + const end = nodeToUpdate.end; + rangeToReplace = offsetRangeToVsRange(document, start, end); textToReplaceWith = '/>'; const emmetMode = getEmmetMode(document.languageId, []) || ''; @@ -55,8 +57,7 @@ function getRangesToReplace(document: vscode.TextDocument, nodeToUpdate: HtmlNod (emmetConfig.syntaxProfiles[emmetMode]['selfClosingStyle'] === 'xhtml' || emmetConfig.syntaxProfiles[emmetMode]['self_closing_tag'] === 'xhtml')) { textToReplaceWith = ' ' + textToReplaceWith; } - } return new vscode.TextEdit(rangeToReplace, textToReplaceWith); -} \ No newline at end of file +} diff --git a/extensions/emmet/src/updateTag.ts b/extensions/emmet/src/updateTag.ts index b8f568e9e52..a2f9b5a66e0 100644 --- a/extensions/emmet/src/updateTag.ts +++ b/extensions/emmet/src/updateTag.ts @@ -4,23 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { HtmlNode } from 'EmmetNode'; -import { getHtmlNode, parseDocument, validate } from './util'; +import { getHtmlNodeLS, toLSTextDocument, validate } from './util'; +import { TextDocument as LSTextDocument, Node as LSNode } from 'vscode-html-languageservice'; export function updateTag(tagName: string): Thenable | undefined { if (!validate(false) || !vscode.window.activeTextEditor) { return; } - let editor = vscode.window.activeTextEditor; - let rootNode = parseDocument(editor.document); - if (!rootNode) { - return; - } - let rangesToUpdate: vscode.Range[] = []; - editor.selections.reverse().forEach(selection => { - rangesToUpdate = rangesToUpdate.concat(getRangesToUpdate(editor, selection, rootNode)); - }); + const editor = vscode.window.activeTextEditor; + const rangesToUpdate = editor.selections.reverse() + .reduce((prev, selection) => + prev.concat(getRangesToUpdate(editor, selection)), []); return editor.edit(editBuilder => { rangesToUpdate.forEach(range => { @@ -29,22 +24,36 @@ export function updateTag(tagName: string): Thenable | undefined { }); } -function getRangesToUpdate(editor: vscode.TextEditor, selection: vscode.Selection, rootNode: HtmlNode): vscode.Range[] { - let nodeToUpdate = getHtmlNode(editor.document, rootNode, selection.start, true); - if (!nodeToUpdate) { - return []; +function getPositionFromOffset(offset: number | undefined, document: LSTextDocument): vscode.Position | undefined { + if (offset === undefined) { + return undefined; } + const pos = document.positionAt(offset); + return new vscode.Position(pos.line, pos.character); +} - let openStart = nodeToUpdate.open.start.translate(0, 1); - let openEnd = openStart.translate(0, nodeToUpdate.name.length); +function getRangesFromNode(node: LSNode, document: LSTextDocument): vscode.Range[] { + const start = getPositionFromOffset(node.start, document)!; + const startTagEnd = getPositionFromOffset(node.startTagEnd, document); + const end = getPositionFromOffset(node.end, document)!; + const endTagStart = getPositionFromOffset(node.endTagStart, document); - let ranges = [new vscode.Range(openStart, openEnd)]; - if (nodeToUpdate.close) { - let closeStart = nodeToUpdate.close.start.translate(0, 2); - let closeEnd = nodeToUpdate.close.end.translate(0, -1); - ranges.push(new vscode.Range(closeStart, closeEnd)); + let ranges: vscode.Range[] = []; + if (startTagEnd) { + ranges.push(new vscode.Range(start.translate(0, 1), + start.translate(0, 1).translate(0, node.tag!.length ?? 0))); + } + if (endTagStart) { + ranges.push(new vscode.Range(endTagStart.translate(0, 2), end.translate(0, -1))); } return ranges; } - +function getRangesToUpdate(editor: vscode.TextEditor, selection: vscode.Selection): vscode.Range[] { + const document = toLSTextDocument(editor.document); + const nodeToUpdate = getHtmlNodeLS(document, selection.start, true); + if (!nodeToUpdate) { + return []; + } + return getRangesFromNode(nodeToUpdate, document); +} diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index f2b72548a5f..259a30292d8 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -9,9 +9,11 @@ import parseStylesheet from '@emmetio/css-parser'; import { Node, HtmlNode, CssToken, Property, Rule, Stylesheet } from 'EmmetNode'; import { DocumentStreamReader } from './bufferStream'; import * as EmmetHelper from 'vscode-emmet-helper'; -import { TextDocument as LSTextDocument } from 'vscode-html-languageservice'; +import { Position as LSPosition, getLanguageService as getLanguageServiceInternal, LanguageService, LanguageServiceOptions, TextDocument as LSTextDocument, Node as LSNode } from 'vscode-html-languageservice'; +import { parseMarkupDocument } from './parseMarkupDocument'; let _emmetHelper: typeof EmmetHelper; +let _languageService: LanguageService; let _currentExtensionsPath: string | undefined = undefined; let _homeDir: vscode.Uri | undefined; @@ -21,7 +23,6 @@ export function setHomeDir(homeDir: vscode.Uri) { _homeDir = homeDir; } - export function getEmmetHelper() { // Lazy load vscode-emmet-helper instead of importing it // directly to reduce the start-up time of the extension @@ -32,6 +33,16 @@ export function getEmmetHelper() { return _emmetHelper; } +export function getLanguageService(options?: LanguageServiceOptions): LanguageService { + if (!options) { + if (!_languageService) { + _languageService = getLanguageServiceInternal(); + } + return _languageService; + } + return getLanguageServiceInternal(options); +} + /** * Update Emmet Helper to use user snippets from the extensionsPath setting */ @@ -130,8 +141,8 @@ export function getEmmetMode(language: string, excludedLanguages: string[]): str if (language === 'jade') { return 'pug'; } - const emmetModes = ['html', 'pug', 'slim', 'haml', 'xml', 'xsl', 'jsx', 'css', 'scss', 'sass', 'less', 'stylus']; - if (emmetModes.indexOf(language) > -1) { + const syntaxes = getSyntaxes(); + if (syntaxes.markup.includes(language) || syntaxes.stylesheet.includes(language)) { return language; } return; @@ -366,6 +377,78 @@ export function getHtmlNode(document: vscode.TextDocument, root: Node | undefine return currentNode; } +/** + * Finds the HTML node within an HTML document at a given position + */ +export function getHtmlNodeLS(document: LSTextDocument, position: vscode.Position, includeNodeBoundary: boolean): LSNode | undefined { + const documentText = document.getText(); + const offset = document.offsetAt(position); + let selectionStartOffset = offset; + if (includeNodeBoundary && documentText.charAt(offset) === '<') { + selectionStartOffset++; + } + else if (includeNodeBoundary && documentText.charAt(offset) === '>') { + selectionStartOffset--; + } + return getHtmlNodeLSInternal(document, selectionStartOffset); +} + +function getHtmlNodeLSInternal(document: LSTextDocument, offset: number, isInTemplateNode: boolean = false): LSNode | undefined { + const useCache = !isInTemplateNode; + const parsedDocument = parseMarkupDocument(document, useCache); + + const currentNode: LSNode = parsedDocument.findNodeAt(offset); + if (!currentNode.tag) { return; } + + const isTemplateScript = isNodeTemplateScriptLS(currentNode); + if (isTemplateScript + && currentNode.startTagEnd + && offset > currentNode.startTagEnd + && (!currentNode.endTagStart || offset < currentNode.endTagStart)) { + // blank out the rest of the document and search for the node within + const documentText = document.getText(); + const beforePadding = ' '.repeat(currentNode.startTagEnd); + const scriptBodyText = beforePadding + documentText.substring(currentNode.startTagEnd, currentNode.endTagStart ?? currentNode.end); + const scriptBodyDocument = LSTextDocument.create(document.uri, document.languageId, document.version, scriptBodyText); + const scriptBodyNode = getHtmlNodeLSInternal(scriptBodyDocument, offset, true); + if (scriptBodyNode) { + scriptBodyNode.parent = currentNode; + currentNode.children.push(scriptBodyNode); + return scriptBodyNode; + } + } + return currentNode; +} + +/** + * Returns whether the node is a `; From e0498f0cdd38ee1755482e20d5ce3f0d2cf22929 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 20:58:11 +0100 Subject: [PATCH 1184/1837] Share typescript node module (#112718) --- extensions/github-authentication/package.json | 3 +-- extensions/github-authentication/yarn.lock | 5 ----- extensions/markdown-language-features/package.json | 1 - extensions/markdown-language-features/yarn.lock | 5 ----- extensions/microsoft-authentication/package.json | 3 +-- extensions/microsoft-authentication/yarn.lock | 5 ----- extensions/vscode-api-tests/package.json | 1 - extensions/vscode-api-tests/yarn.lock | 5 ----- extensions/vscode-notebook-tests/package.json | 1 - extensions/vscode-notebook-tests/yarn.lock | 5 ----- 10 files changed, 2 insertions(+), 32 deletions(-) diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index b74a91843a3..b7626df85f8 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -61,7 +61,6 @@ "@types/keytar": "^4.4.2", "@types/node": "^10.12.21", "@types/node-fetch": "2.5.7", - "@types/uuid": "8.0.0", - "typescript": "^3.7.5" + "@types/uuid": "8.0.0" } } diff --git a/extensions/github-authentication/yarn.lock b/extensions/github-authentication/yarn.lock index 08604b972ee..e808558aeb3 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -518,11 +518,6 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -typescript@^3.7.5: - version "3.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" - integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 440697d1dba..1bd856ab46d 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -336,7 +336,6 @@ "@types/markdown-it": "0.0.2", "@types/node": "^12.11.7", "lodash.throttle": "^4.1.1", - "typescript": "^3.7.3", "vscode": "^1.1.10" } } diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 33b80569a82..edd32557f3e 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -1916,11 +1916,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -typescript@^3.7.3: - version "3.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" - integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== - uc.micro@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 64becb50468..061a222fd3e 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -43,8 +43,7 @@ "@types/node-fetch": "^2.5.7", "@types/randombytes": "^2.0.0", "@types/sha.js": "^2.4.0", - "@types/uuid": "^8.0.0", - "typescript": "^3.7.4" + "@types/uuid": "^8.0.0" }, "dependencies": { "buffer": "^5.6.0", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index df970ce40d8..75893ec149b 100644 --- a/extensions/microsoft-authentication/yarn.lock +++ b/extensions/microsoft-authentication/yarn.lock @@ -561,11 +561,6 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -typescript@^3.7.4: - version "3.7.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19" - integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index b735042deb2..7269bd3af2e 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -115,7 +115,6 @@ "devDependencies": { "@types/mocha": "2.2.43", "@types/node": "^12.11.7", - "typescript": "^1.6.2", "vscode": "1.1.5" } } diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index 5a61c09721d..14e5281e11d 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -1786,11 +1786,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -typescript@^1.6.2: - version "1.8.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e" - integrity sha1-tHXW4N/wv1DyluXKbvn7tccyDx4= - unique-stream@^2.0.2: version "2.2.1" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index 96eae024344..c5ab339f4d7 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -19,7 +19,6 @@ }, "dependencies": {}, "devDependencies": { - "typescript": "^3.8.3", "@types/node": "^12.11.7", "vscode": "~1.1.36" }, diff --git a/extensions/vscode-notebook-tests/yarn.lock b/extensions/vscode-notebook-tests/yarn.lock index 21c92a6df84..5ec22bc1fc7 100644 --- a/extensions/vscode-notebook-tests/yarn.lock +++ b/extensions/vscode-notebook-tests/yarn.lock @@ -546,11 +546,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -typescript@^3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" From c5d42b277220bc535d6723fa33db3d3ec37b4408 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 12:38:05 -0800 Subject: [PATCH 1185/1837] renderers layout update --- .../notebook/browser/diff/diffComponents.ts | 24 ++++++++++++-- .../browser/diff/diffElementOutputs.ts | 2 +- .../browser/diff/notebookDiffEditorBrowser.ts | 6 ++-- .../browser/diff/notebookTextDiffEditor.ts | 33 +++++++++++++------ .../notebook/browser/notebookBrowser.ts | 4 +-- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../view/renderers/backLayerWebView.ts | 11 ++++++- .../browser/view/renderers/webviewPreloads.ts | 1 + .../notebook/test/testNotebookEditor.ts | 2 +- 9 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 549aaeccc82..9fe8b05ff56 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -933,7 +933,6 @@ export class InsertElement extends SingleSideDiffElement { }); } - this.layoutNotebookCell(); if (this._diagonalFill) { @@ -1071,15 +1070,36 @@ export class ModifiedElement extends AbstractElementRenderer { this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputRightContainer!); this._outputRightView.render(); + const originalOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.original.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(true, this.cell.original.id, ['nb-cellDeleted'], []); + originalOutputRenderListener.dispose(); + } + }); + + const modifiedOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.modified.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(false, this.cell.modified.id, ['nb-cellAdded'], []); + modifiedOutputRenderListener.dispose(); + } + }); + + this._decorate(); this.cell.layoutChange(); } _showOutputs() { this._outputLeftView?.render(); this._outputRightView?.render(); + this._decorate(); this.cell.layoutChange(); } + _decorate() { + this.notebookEditor.deltaCellOutputContainerClassNames(true, this.cell.original.id, ['nb-cellDeleted'], []); + this.notebookEditor.deltaCellOutputContainerClassNames(false, this.cell.modified.id, ['nb-cellAdded'], []); + } + _hideOutputs() { this._outputLeftView?.hideOutputs(); this._outputRightView?.hideOutputs(); @@ -1179,8 +1199,6 @@ export class ModifiedElement extends AbstractElementRenderer { this.cell.editorHeight = contentHeight; } - - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 47351651b0b..c6507df68b1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -85,7 +85,7 @@ export class OutputElement extends Disposable { this._diffElementViewModel, this._nestedCell, result, - this.getOutputOffsetInCell(index), + () => this.getOutputOffsetInCell(index), this._diffElementViewModel instanceof SideBySideDiffElementViewModel ? this._modified : this._diffElementViewModel.type === 'insert' diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index 987772ddd3d..a78970d4475 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -22,11 +22,12 @@ export interface IDiffCellInfo extends ICommonCellInfo { export interface INotebookTextDiffEditor extends ICommonNotebookEditor { readonly textModel?: NotebookTextModel; onMouseUp: Event<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>; + onDidDynamicOutputRendered: Event<{ cell: IGenericCellViewModel, output: IDisplayOutputViewModel }>; getOverflowContainerDomNode(): HTMLElement; getLayoutInfo(): NotebookLayoutInfo; layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; - createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void; + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, rightEditor: boolean): void; hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IDisplayOutputViewModel): void; /** * Trigger the editor to scroll from scroll event programmatically @@ -35,7 +36,8 @@ export interface INotebookTextDiffEditor extends ICommonNotebookEditor { getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number, isInit: boolean): void; + deltaCellOutputContainerClassNames(original: boolean, cellId: string, added: string[], removed: string[]): void; } export interface IDiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 88693033af3..d975eb351f1 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -76,6 +76,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD private _revealFirst: boolean; private readonly _insetModifyQueueByOutputId = new SequencerByKey(); + protected _onDidDynamicOutputRendered = new Emitter<{ cell: IGenericCellViewModel, output: IDisplayOutputViewModel }>(); + onDidDynamicOutputRendered = this._onDidDynamicOutputRendered.event; + + private _isDisposed: boolean = false; get isDisposed() { @@ -111,7 +115,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // throw new Error('Method not implemented.'); } - updateOutputHeight(cellInfo: IDiffCellInfo, output: IDisplayOutputViewModel, outputHeight: number): void { + updateOutputHeight(cellInfo: IDiffCellInfo, output: IDisplayOutputViewModel, outputHeight: number, isInit: boolean): void { const diffElement = cellInfo.diffElement; const cell = this.getCellByInfo(cellInfo); const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.model as ITransformedDisplayOutputDto).outputId); @@ -126,6 +130,10 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } else { (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); } + + if (isInit) { + this._onDidDynamicOutputRendered.fire({ cell, output }); + } } protected createEditor(parent: HTMLElement): void { @@ -219,17 +227,14 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return; } - const scrollTop = this._list.scrollTop; - const scrollHeight = this._list.scrollHeight; - if (this._modifiedWebview) { - this._updateOutputsOffsetsInWebview(scrollTop, scrollHeight, this._modifiedWebview, (diffElement: DiffElementViewModelBase) => { + this._updateOutputsOffsetsInWebview(this._list.scrollTop, this._list.scrollHeight, this._modifiedWebview, (diffElement: DiffElementViewModelBase) => { return diffElement.modified; }, false); } if (this._originalWebview) { - this._updateOutputsOffsetsInWebview(scrollTop, scrollHeight, this._originalWebview, (diffElement: DiffElementViewModelBase) => { + this._updateOutputsOffsetsInWebview(this._list.scrollTop, this._list.scrollHeight, this._originalWebview, (diffElement: DiffElementViewModelBase) => { return diffElement.original; }, true); } @@ -524,12 +529,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._list.triggerScrollFromMouseWheelEvent(event); } - createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, offset: number, rightEditor: boolean): void { - this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, rightEditor: boolean): void { + this._insetModifyQueueByOutputId.queue(output.source.model.outputId + (rightEditor ? '-right' : 'left'), async () => { if (rightEditor) { if (!this._modifiedWebview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._modifiedWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, offset); + await this._modifiedWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); } else { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; @@ -546,7 +551,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } else { if (!this._originalWebview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._originalWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, offset); + await this._originalWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); } else { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; @@ -614,6 +619,14 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return this._outputRenderer; } + deltaCellOutputContainerClassNames(original: boolean, cellId: string, added: string[], removed: string[]) { + if (original) { + this._originalWebview?.deltaCellOutputContainerClassNames(cellId, added, removed); + } else { + this._modifiedWebview?.deltaCellOutputContainerClassNames(cellId, added, removed); + } + } + getLayoutInfo(): NotebookLayoutInfo { if (!this._list) { throw new Error('Editor is not initalized successfully'); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index f9360dc25ab..a7031ca27e8 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -162,7 +162,7 @@ export interface ICommonNotebookEditor { getCellByInfo(cellInfo: ICommonCellInfo): IGenericCellViewModel; focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number, isInit: boolean): void; } //#endregion @@ -582,7 +582,7 @@ export interface INotebookEditor extends IEditor, ICommonNotebookEditor { getContribution(id: string): T; getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel; - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void; + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number, isInit: boolean): void; } export interface INotebookCellList { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 40cdf985b20..f755014de6e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1968,7 +1968,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return this.viewModel?.viewCells.find(vc => vc.handle === cellHandle) as CodeCellViewModel; } - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, outputHeight: number): void { + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, outputHeight: number, isInit: boolean): void { const cell = this.viewModel?.viewCells.find(vc => vc.handle === cellInfo.cellHandle); if (cell && cell instanceof CodeCellViewModel) { const outputIndex = cell.outputsViewModels.indexOf(output); 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 18d1c33c037..e5b7bc40023 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -35,6 +35,7 @@ export interface IDimensionMessage { __vscode_notebook_message: boolean; type: 'dimension'; id: string; + init: boolean; data: DOM.Dimension; } @@ -269,6 +270,14 @@ export class BackLayerWebView extends Disposable { background-color: var(--vscode-notebook-symbolHighlightBackground); } + #container > div.nb-cellDeleted > div { + background-color: var(--vscode-diffEditor-removedTextBackground); + } + + #container > div.nb-cellAdded > div { + background-color: var(--vscode-diffEditor-insertedTextBackground); + } + #container > div > div > div { overflow-x: scroll; } @@ -452,7 +461,7 @@ var requirejs = (function() { const resolvedResult = this.resolveOutputId(data.id); if (resolvedResult) { const { cellInfo, output } = resolvedResult; - this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight); + this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight, !!data.init); } } else if (data.type === 'mouseenter') { const resolvedResult = this.resolveOutputId(data.id); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index a79a6da2443..d13b052b189 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -474,6 +474,7 @@ function webviewPreloads() { __vscode_notebook_message: true, type: 'dimension', id: outputId, + init: true, data: { height: outputNode.clientHeight } diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index c624881feb9..0cf9e2612af 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -72,7 +72,7 @@ export class TestNotebookEditor implements INotebookEditor { getCellByInfo(cellInfo: ICommonCellInfo): ICellViewModel { throw new Error('Method not implemented.'); } - updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number): void { + updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number, isInit: boolean): void { throw new Error('Method not implemented.'); } async beginComputeContributedKernels(): Promise { From 7ca71e763d6bb669fefba51c336b03af2c1a5ac4 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 21:40:14 +0100 Subject: [PATCH 1186/1837] Move away from deprecated 'vscode' node module (#112718) --- extensions/emmet/package.json | 3 +- extensions/emmet/src/test/index.ts | 33 +- extensions/emmet/yarn.lock | 2312 ----------------- extensions/git/package.json | 3 +- extensions/git/src/test/index.ts | 2 +- extensions/git/yarn.lock | 594 ----- .../markdown-language-features/package.json | 3 +- .../src/test/index.ts | 2 +- .../markdown-language-features/yarn.lock | 1980 +------------- .../typescript-language-features/package.json | 3 +- .../src/test/index.ts | 2 +- .../typescript-language-features/yarn.lock | 207 +- extensions/vscode-api-tests/package.json | 3 +- .../src/singlefolder-tests/index.ts | 2 +- .../src/workspace-tests/index.ts | 2 +- extensions/vscode-api-tests/yarn.lock | 1929 -------------- extensions/vscode-colorize-tests/package.json | 3 +- extensions/vscode-colorize-tests/src/index.ts | 2 +- extensions/vscode-colorize-tests/yarn.lock | 1929 -------------- .../vscode-custom-editor-tests/package.json | 3 +- .../src/test/index.ts | 2 +- .../vscode-custom-editor-tests/yarn.lock | 294 --- extensions/vscode-notebook-tests/package.json | 3 +- extensions/vscode-notebook-tests/src/index.ts | 2 +- extensions/vscode-notebook-tests/yarn.lock | 594 ----- extensions/vscode-test-resolver/package.json | 3 +- extensions/vscode-test-resolver/yarn.lock | 1871 ------------- package.json | 1 + test/integration/electron/testrunner.js | 48 + yarn.lock | 14 + 30 files changed, 117 insertions(+), 11732 deletions(-) create mode 100644 test/integration/electron/testrunner.js diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 72eb3224c5d..82b4e1fea69 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -430,8 +430,7 @@ "deps": "yarn add vscode-emmet-helper" }, "devDependencies": { - "@types/node": "^12.11.7", - "vscode": "1.0.1" + "@types/node": "^12.11.7" }, "dependencies": { "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", diff --git a/extensions/emmet/src/test/index.ts b/extensions/emmet/src/test/index.ts index 3aeda9dfa42..7d5667439cb 100644 --- a/extensions/emmet/src/test/index.ts +++ b/extensions/emmet/src/test/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', @@ -38,3 +38,34 @@ if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { testRunner.configure(options); export = testRunner; + +// import * as path from 'path'; +// import * as Mocha from 'mocha'; +// import * as glob from 'glob'; + +// export function run(testsRoot: string, cb: (error: any, failures?: number) => void): void { +// // Create the mocha test +// const mocha = new Mocha({ +// ui: 'tdd' +// }); +// mocha.useColors(true); + +// glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { +// if (err) { +// return cb(err); +// } + +// // Add files to the test suite +// files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); + +// try { +// // Run the mocha test +// mocha.run(failures => { +// cb(null, failures); +// }); +// } catch (err) { +// console.error(err); +// cb(err); +// } +// }); +// } diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 11cdaaeb1ad..3bb7f3316d5 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -58,369 +58,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46" integrity sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w== -ajv@^6.12.3: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^0.2.0, ansi-regex@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" - integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" - integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" - integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= - dependencies: - ansi-styles "^1.1.0" - escape-string-regexp "^1.0.0" - has-ansi "^0.1.0" - strip-ansi "^0.3.0" - supports-color "^0.2.0" - -chalk@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1, clone-stats@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -cloneable-readable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" - integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" - integrity sha1-+mihT2qUXVTbvlDYzbMyDp47GgY= - -commander@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" - integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM= - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.1.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^1.0.7-1.2.3: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= - dependencies: - ms "0.7.1" - -decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@^0.1.1, duplexer@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -duplexify@^3.2.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - emmet@^2.1.5: version "2.1.6" resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.1.6.tgz#425e0bcef6bf6e5eb758610f3e8d49f86a6fe877" @@ -429,1909 +66,16 @@ emmet@^2.1.5: "@emmetio/abbreviation" "^2.0.2" "@emmetio/css-abbreviation" "^2.1.2" -end-of-stream@^1.0.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escape-string-regexp@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" - integrity sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE= - -escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -event-stream@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -event-stream@^3.3.1: - version "3.3.5" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" - integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== - dependencies: - duplexer "^0.1.1" - from "^0.1.7" - map-stream "0.0.7" - pause-stream "^0.0.11" - split "^1.0.1" - stream-combiner "^0.2.2" - through "^2.3.8" - -event-stream@~3.1.5: - version "3.1.7" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.1.7.tgz#b4c540012d0fe1498420f3d8946008db6393c37a" - integrity sha1-tMVAAS0P4UmEIPPYlGAI22OTw3o= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.2" - stream-combiner "~0.0.4" - through "~2.3.1" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fancy-log@^1.1.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -from@^0.1.7, from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@~0.1.28: - version "0.1.31" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-0.1.31.tgz#7337f058fbbbbefa8c9f561a28cab0849202c988" - integrity sha1-czfwWPu7vvqMn1YaKMqwhJICyYg= - dependencies: - graceful-fs "~3.0.2" - inherits "~2.0.0" - mkdirp "0.5" - rimraf "2" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - integrity sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0= - dependencies: - inherits "2" - minimatch "0.3" - -glob@^5.0.15, glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -graceful-fs@~3.0.2: - version "3.0.12" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.12.tgz#0034947ce9ed695ec8ab0b854bc919e82b1ffaef" - integrity sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg== - dependencies: - natives "^1.1.3" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - -gulp-chmod@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-1.3.0.tgz#8bb6e8c11895dcbf9b42520c874347a5022bcb0d" - integrity sha1-i7bowRiV3L+bQlIMh0NHpQIryw0= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-4.0.0.tgz#395f58a256c559cdb9e0d157f1caaf5248a38dcb" - integrity sha1-OV9YolbFWc254NFX8cqvUkijjcs= - dependencies: - gulp-util "^3.0.6" - multimatch "^2.0.0" - streamfilter "^1.0.5" - -gulp-gunzip@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" - integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.0: - version "0.4.4" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.4.tgz#4a4d18fac0ffedde94a7855953de90db00a1d1b1" - integrity sha512-mo7lGgZmNXyTbcUzfjSnUVkx1pnqqiwv/pPaIrYdTO77hq0WNTxXLAzQdoYOnyJ0mfVLNmNl9AGqWLiAzTPMMA== - dependencies: - event-stream "3.3.4" - node.extend "~1.1.2" - request "^2.88.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.1.tgz#b0a6df3d43a0537165946ab8e38c1b7080a66fac" - integrity sha512-UHd3MokfIN7SrFdsbV5uZTwzBpL0ZSTu7iq98fuDqBGZ0dlHxgbQBJwfd6qjCW83snkQ3Hz9IY4sMRMz2iTq7w== - dependencies: - event-stream "3.3.4" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.4.tgz#635cc7d67d3d48aec0dbc69822623fc7c33f7d37" - integrity sha1-Y1zH1n09SK7A28aYImI/x8M/fTc= - dependencies: - event-stream "~3.1.5" - gulp-util "~2.2.14" - streamifier "~0.1.0" - tar "~0.1.19" - through2 "~0.4.1" - -gulp-util@^3.0.6: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-util@~2.2.14: - version "2.2.20" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" - integrity sha1-1xRuVyiRC9jwR6awseVJvCLb1kw= - dependencies: - chalk "^0.5.0" - dateformat "^1.0.7-1.2.3" - lodash._reinterpolate "^2.4.1" - lodash.template "^2.4.1" - minimist "^0.2.0" - multipipe "^0.1.0" - through2 "^0.5.0" - vinyl "^0.2.1" - -gulp-vinyl-zip@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" - integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= - dependencies: - event-stream "^3.3.1" - queue "^3.0.10" - through2 "^0.6.3" - vinyl "^0.4.6" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -has-ansi@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" - integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= - dependencies: - ansi-regex "^0.2.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - image-size@^0.5.2: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-core-module@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" - integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== - dependencies: - has "^1.0.3" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" - integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jade@0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" - integrity sha1-jxDXl32NefL2/4YqgbBRPMslaGw= - dependencies: - commander "0.6.1" - mkdirp "0.3.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - jsonc-parser@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342" integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._escapehtmlchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" - integrity sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0= - dependencies: - lodash._htmlescapes "~2.4.1" - -lodash._escapestringchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" - integrity sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._htmlescapes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" - integrity sha1-MtFL8IRLbeb4tioFG09nwii2JMs= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._isnative@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" - integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw= - -lodash._objecttypes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" - integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" - integrity sha1-TxInqlqHEfxjL1sHofRgequLMiI= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._reunescapedhtml@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" - integrity sha1-dHxPxAED6zu4oJduVx96JlnpO6c= - dependencies: - lodash._htmlescapes "~2.4.1" - lodash.keys "~2.4.1" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash._shimkeys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" - integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM= - dependencies: - lodash._objecttypes "~2.4.1" - -lodash.defaults@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" - integrity sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ= - dependencies: - lodash._objecttypes "~2.4.1" - lodash.keys "~2.4.1" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.escape@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" - integrity sha1-LOEsXghNsKV92l5dHu659dF1o7Q= - dependencies: - lodash._escapehtmlchar "~2.4.1" - lodash._reunescapedhtml "~2.4.1" - lodash.keys "~2.4.1" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.isobject@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" - integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU= - dependencies: - lodash._objecttypes "~2.4.1" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.keys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" - integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc= - dependencies: - lodash._isnative "~2.4.1" - lodash._shimkeys "~2.4.1" - lodash.isobject "~2.4.1" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" - integrity sha1-nmEQB+32KRKal0qzxIuBez4c8g0= - dependencies: - lodash._escapestringchar "~2.4.1" - lodash._reinterpolate "~2.4.1" - lodash.defaults "~2.4.1" - lodash.escape "~2.4.1" - lodash.keys "~2.4.1" - lodash.templatesettings "~2.4.1" - lodash.values "~2.4.1" - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -lodash.templatesettings@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" - integrity sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk= - dependencies: - lodash._reinterpolate "~2.4.1" - lodash.escape "~2.4.1" - -lodash.values@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" - integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ= - dependencies: - lodash.keys "~2.4.1" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI= - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - -meow@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - integrity sha1-J12O2qxPG7MyZHIInnlJyDlGmd0= - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.1.tgz#827ba4e7593464e7c221e8c5bed930904ee2c455" - integrity sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg== - -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= - -mkdirp@0.5, mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^2.3.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" - integrity sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg= - dependencies: - commander "2.3.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.2" - glob "3.2.11" - growl "1.9.2" - jade "0.26.3" - mkdirp "0.5.1" - supports-color "1.2.0" - to-iso-string "0.0.2" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.0, multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -natives@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb" - integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA== - -node.extend@~1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" - integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== - dependencies: - has "^1.0.3" - is "^3.2.1" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0, object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pause-stream@0.0.11, pause-stream@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -queue@^3.0.10, queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.17: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.3.5, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" - integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== - -request@^2.67.0, request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -resolve@^1.10.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== - dependencies: - is-core-module "^2.0.0" - path-parse "^1.0.6" - -rimraf@2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -"semver@2 || 3 || 4 || 5", semver@^5.1.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -source-map-support@^0.3.2: - version "0.3.3" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f" - integrity sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8= - dependencies: - source-map "0.1.32" - -source-map@0.1.32: - version "0.1.32" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266" - integrity sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY= - dependencies: - amdefine ">=0.0.4" - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" - integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== - -split@0.2: - version "0.2.10" - resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" - integrity sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc= - dependencies: - through "2" - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -split@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" - integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= - dependencies: - duplexer "~0.1.1" - through "~2.3.4" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -streamfilter@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" - integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" - integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= - dependencies: - ansi-regex "^0.2.1" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - -supports-color@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" - integrity sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4= - -supports-color@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@~0.1.19: - version "0.1.20" - resolved "https://registry.yarnpkg.com/tar/-/tar-0.1.20.tgz#42940bae5b5f22c74483699126f9f3f27449cb13" - integrity sha1-QpQLrltfIsdEg2mRJvnz8nRJyxM= - dependencies: - block-stream "*" - fstream "~0.1.28" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" - integrity sha1-390BLrnHAOIyP9M084rGIqs3Lac= - dependencies: - readable-stream "~1.0.17" - xtend "~3.0.0" - -through2@^0.6.0, through2@^0.6.3, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through2@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" - integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s= - dependencies: - readable-stream "~1.0.17" - xtend "~2.1.1" - -through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" - -to-iso-string@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" - integrity sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE= - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" - integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= - dependencies: - through2 "^2.0.3" - vinyl "^0.4.3" - -vinyl@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" - integrity sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI= - dependencies: - clone-stats "~0.0.1" - -vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - vscode-emmet-helper@~2.0.0: version "2.0.9" resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.0.9.tgz#16244c087cba4e379116f268384bb644649db6ad" @@ -2378,59 +122,3 @@ vscode-uri@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== - -vscode@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.0.1.tgz#3d161200615fe2af1d92ddc650751159411a513b" - integrity sha1-PRYSAGFf4q8dkt3GUHURWUEaUTs= - dependencies: - glob "^5.0.15" - gulp-chmod "^1.3.0" - gulp-filter "^4.0.0" - gulp-gunzip "0.0.3" - gulp-remote-src "^0.4.0" - gulp-symdest "^1.0.0" - gulp-untar "0.0.4" - gulp-vinyl-zip "^1.1.2" - mocha "^2.3.3" - request "^2.67.0" - semver "^5.1.0" - source-map-support "^0.3.2" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - -xtend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" - integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= - -yauzl@^2.2.1: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yazl@^2.2.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" - integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== - dependencies: - buffer-crc32 "~0.2.3" diff --git a/extensions/git/package.json b/extensions/git/package.json index e6be2f8705b..8cc1a070377 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2321,7 +2321,6 @@ "@types/file-type": "^5.2.1", "@types/mocha": "2.2.43", "@types/node": "^12.12.31", - "@types/which": "^1.0.28", - "vscode": "^1.1.36" + "@types/which": "^1.0.28" } } diff --git a/extensions/git/src/test/index.ts b/extensions/git/src/test/index.ts index 8773f772e62..819850af768 100644 --- a/extensions/git/src/test/index.ts +++ b/extensions/git/src/test/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index e1c2d307c0a..4029d537352 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -36,23 +36,6 @@ resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6" integrity sha1-AW44dim4gXvtZT/jLqtdESecjfY= -agent-base@4, agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - -ajv@^6.5.5: - version "6.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" - integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -62,121 +45,11 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -189,472 +62,31 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - -escape-string-regexp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - file-type@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.2.0.tgz#113cfed52e1d6959ab80248906e2f25a8cdccb74" integrity sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q= -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-proxy-agent@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - iconv-lite-umd@0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - jschardet@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.2.1.tgz#03b0264669a90c7a5c436a68c5a7d4e4cb0c9823" integrity sha512-Ks2JNuUJoc7PGaZ7bVFtSEvOcr0rBq6Q1J5/7+zKWLT+g+4zziL63O0jg7y2jxhzIa1LVsHUbPXrbaWmz9iwDw== -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -mime-db@1.43.0: - version "1.43.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" - integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.26" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" - integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== - dependencies: - mime-db "1.43.0" - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -psl@^1.1.28: - version "1.7.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" - integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -source-map-support@^0.5.0: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -url-parse@^1.4.4: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vscode-extension-telemetry@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" @@ -667,32 +99,11 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== -vscode-test@^0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" - integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== - dependencies: - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - vscode-uri@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.0.tgz#2df704222f72b8a71ff266ba0830ed6c51ac1542" integrity sha512-lWXWofDSYD8r/TIyu64MdwB4FaSirQ608PP/TzUyslyOeHGwQ0eTHUZeJrK1ILOmwUHaJtV693m2JoUYroUDpw== -vscode@^1.1.36: - version "1.1.36" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.36.tgz#5e1a0d1bf4977d0c7bc5159a9a13d5b104d4b1b6" - integrity sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ== - dependencies: - glob "^7.1.2" - mocha "^5.2.0" - request "^2.88.0" - semver "^5.4.1" - source-map-support "^0.5.0" - url-parse "^1.4.4" - vscode-test "^0.4.1" - which@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" @@ -700,11 +111,6 @@ which@^1.3.0: dependencies: isexe "^2.0.0" -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 440697d1dba..c2ce04479be 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -336,7 +336,6 @@ "@types/markdown-it": "0.0.2", "@types/node": "^12.11.7", "lodash.throttle": "^4.1.1", - "typescript": "^3.7.3", - "vscode": "^1.1.10" + "typescript": "^3.7.3" } } diff --git a/extensions/markdown-language-features/src/test/index.ts b/extensions/markdown-language-features/src/test/index.ts index 0eb9bc92487..56ba0dde4b6 100644 --- a/extensions/markdown-language-features/src/test/index.ts +++ b/extensions/markdown-language-features/src/test/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 33b80569a82..5ef6bb1f77b 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -31,52 +31,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -91,317 +45,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== - dependencies: - hoek "4.x.x" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - integrity sha1-cVuW6phBWTzDMGeSP17GDr2k99c= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= - -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - integrity sha1-0hfR6WERjjrJpLi7oyhVU79kfNs= - -cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" - integrity sha1-pikNQT8hemEjL5XkWP84QYz7ARc= - dependencies: - inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= - dependencies: - delayed-stream "~1.0.0" - -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== - -commander@^2.9.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - integrity sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.1.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU= - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4= - dependencies: - boom "5.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -414,754 +57,16 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" - integrity sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fancy-log@^1.1.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - integrity sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM= - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - integrity sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ= - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.2, glob@^7.0.5, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - integrity sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw== - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= - -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" - integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= - dependencies: - multimatch "^2.0.0" - plugin-error "^0.1.2" - streamfilter "^1.0.5" - -gulp-gunzip@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz#15b741145e83a9c6f50886241b57cc5871f151a9" - integrity sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1" - integrity sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE= - dependencies: - event-stream "~3.3.4" - node.extend "~1.1.2" - request "~2.79.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.0.tgz#c165320732d192ce56fd94271ffa123234bf2ae0" - integrity sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA= - dependencies: - event-stream "^3.3.1" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz#24e40685dc05b7149995245099e0590263be8dad" - integrity sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0= - dependencies: - event-stream "^3.3.1" - queue "^4.2.1" - through2 "^2.0.3" - vinyl "^2.0.2" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - integrity sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0= - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - highlight.js@*, 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== -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-my-json-valid@^2.12.4: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" - integrity sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" - integrity sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - linkify-it@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" @@ -1169,120 +74,11 @@ linkify-it@^3.0.1: dependencies: uc.micro "^1.0.1" -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - markdown-it-front-matter@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/markdown-it-front-matter/-/markdown-it-front-matter-0.2.1.tgz#dca49a827bb3cebb0528452c1d87dff276eb28dc" @@ -1304,618 +100,11 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= - dependencies: - mime-db "~1.30.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== - dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" - integrity sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y= - dependencies: - is "^3.1.0" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - integrity sha1-51vV9uJoEioqDgvaYwslUMFmUCw= - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - integrity sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs= - -queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -queue@^4.2.1: - version "4.4.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-4.4.2.tgz#5a9733d9a8b8bd1b36e934bc9c55ab89b28e29c7" - integrity sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ== - dependencies: - inherits "~2.0.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - integrity sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -request@^2.83.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - integrity sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -requires-port@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -rimraf@2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -semver@^5.3.0, semver@^5.4.1: +semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== - dependencies: - hoek "4.x.x" - -source-map-support@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.3.tgz#2b3d5fff298cfa4d1afd7d4352d569e9a0158e76" - integrity sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w== - dependencies: - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamfilter@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" - integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== - dependencies: - has-flag "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - integrity sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - typescript@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" @@ -1931,128 +120,6 @@ uc.micro@^1.0.5: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg== -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - integrity sha1-WqADz76Uxf+GbE59ZouxxNuts2k= - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -url-parse@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - integrity sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw== - dependencies: - querystringify "~1.0.0" - requires-port "~1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.0.0, uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" - integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= - dependencies: - through2 "^2.0.3" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" - integrity sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw= - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - vscode-extension-telemetry@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" @@ -2065,51 +132,6 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== -vscode@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.10.tgz#d1cba378ab24f1d3ddf9cd470d242ee1472dd35b" - integrity sha512-MvFXXSGuhw0Q6GC6dQrnRc0ES+63wpttGIoYGBMQnoS9JFCCNC/rWfX0lBCHJyuKL2Q8CYg0ROsMEHbHVwEtVw== - dependencies: - glob "^7.1.2" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.1" - gulp-gunzip "1.0.0" - gulp-remote-src "^0.4.3" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^2.1.0" - mocha "^4.0.1" - request "^2.83.0" - semver "^5.4.1" - source-map-support "^0.5.0" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -yauzl@^2.2.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" - integrity sha1-qBmB6nCleUYTOIPwKcWCGok1mn8= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.0.1" - -yazl@^2.2.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" - integrity sha1-7CblzIfVYBud+EMtvdPNLlFzoHE= - dependencies: - buffer-crc32 "~0.2.3" - zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 9bb4152c94f..6c2c9499d91 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -28,8 +28,7 @@ "@types/rimraf": "2.0.2", "@types/semver": "^5.5.0", "terser": "^4.8.0", - "typescript-web": "npm:typescript@^4.2.0-dev.20201209", - "vscode": "^1.1.36" + "typescript-web": "npm:typescript@^4.2.0-dev.20201209" }, "scripts": { "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:typescript-language-features", diff --git a/extensions/typescript-language-features/src/test/index.ts b/extensions/typescript-language-features/src/test/index.ts index 1a5f7419059..6ddff532d24 100644 --- a/extensions/typescript-language-features/src/test/index.ts +++ b/extensions/typescript-language-features/src/test/index.ts @@ -15,7 +15,7 @@ // to report the results back to the caller. When the tests are finished, return // a possible error to the callback or null if none. -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); // You can directly control Mocha options by uncommenting the following lines // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 0caf7467fce..1fdba2390f1 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - "@types/glob@*": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -43,20 +38,6 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== -agent-base@4, agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - -agent-base@6: - version "6.0.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" - integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== - dependencies: - debug "4" - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -79,21 +60,11 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -104,27 +75,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -137,46 +87,12 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - -escape-string-regexp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2, glob@^7.1.3: +glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -188,54 +104,6 @@ glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - -https-proxy-agent@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - -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" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -254,52 +122,13 @@ jsonc-parser@^2.2.1: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342" integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2, ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -324,12 +153,12 @@ semver@5.5.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== -semver@^5.3.0, semver@^5.4.1: +semver@^5.3.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -source-map-support@^0.5.0, source-map-support@~0.5.12: +source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -342,13 +171,6 @@ source-map@^0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - terser@^4.8.0: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" @@ -380,27 +202,6 @@ vscode-nls@^4.1.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -vscode-test@^0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" - integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== - dependencies: - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - -vscode@^1.1.36: - version "1.1.37" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.37.tgz#c2a770bee4bb3fff765e2b72c7bcc813b8a6bb0a" - integrity sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg== - dependencies: - glob "^7.1.2" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - mocha "^5.2.0" - semver "^5.4.1" - source-map-support "^0.5.0" - vscode-test "^0.4.1" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index b735042deb2..941f13b7f77 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -115,7 +115,6 @@ "devDependencies": { "@types/mocha": "2.2.43", "@types/node": "^12.11.7", - "typescript": "^1.6.2", - "vscode": "1.1.5" + "typescript": "^1.6.2" } } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/index.ts b/extensions/vscode-api-tests/src/singlefolder-tests/index.ts index ea50f38b1b9..8e0c944f8b2 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/index.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', diff --git a/extensions/vscode-api-tests/src/workspace-tests/index.ts b/extensions/vscode-api-tests/src/workspace-tests/index.ts index 9486d8ed3e5..f636d2fd70b 100644 --- a/extensions/vscode-api-tests/src/workspace-tests/index.ts +++ b/extensions/vscode-api-tests/src/workspace-tests/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index 5a61c09721d..ee687e60794 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -12,1936 +12,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== -ajv@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" - integrity sha1-RBT/dKUIecII7l/cgm4ywwNUnto= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== - dependencies: - hoek "4.x.x" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - integrity sha1-cVuW6phBWTzDMGeSP17GDr2k99c= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= - -cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" - integrity sha1-pikNQT8hemEjL5XkWP84QYz7ARc= - dependencies: - inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= - dependencies: - delayed-stream "~1.0.0" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - -commander@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" - integrity sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU= - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4= - dependencies: - boom "5.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= - dependencies: - ms "2.0.0" - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.2.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" - integrity sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - integrity sha1-epDYM+/abPpurA9JSduw+tOmMgY= - dependencies: - once "^1.4.0" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" - integrity sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg= - dependencies: - chalk "^1.1.1" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - integrity sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM= - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - integrity sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ= - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.5, glob@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" - integrity sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U= - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.0.1.tgz#5d87f662e317e5839ef7650e620e6c9008ff92d0" - integrity sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A== - dependencies: - gulp-util "^3.0.6" - multimatch "^2.0.0" - streamfilter "^1.0.5" - -gulp-gunzip@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" - integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1" - integrity sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE= - dependencies: - event-stream "~3.3.4" - node.extend "~1.1.2" - request "~2.79.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.0.tgz#c165320732d192ce56fd94271ffa123234bf2ae0" - integrity sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA= - dependencies: - event-stream "^3.3.1" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@^3.0.6, gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" - integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= - dependencies: - event-stream "^3.3.1" - queue "^3.0.10" - through2 "^0.6.3" - vinyl "^0.4.6" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - integrity sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0= - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-my-json-valid@^2.12.4: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" - integrity sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" - integrity sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= - dependencies: - mime-db "~1.30.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" - escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" - integrity sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y= - dependencies: - is "^3.1.0" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - integrity sha1-51vV9uJoEioqDgvaYwslUMFmUCw= - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - integrity sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs= - -queue@^3.0.10, queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - integrity sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -request@^2.79.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - integrity sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -requires-port@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -rimraf@2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== - dependencies: - hoek "4.x.x" - -source-map-support@^0.4.11: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamfilter@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.5.tgz#87507111beb8e298451717b511cfed8f002abf53" - integrity sha1-h1BxEb644phFFxe1Ec/tjwAqv1M= - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= - dependencies: - has-flag "^1.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@^0.6.1, through2@^0.6.3, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.1, through2@~2.0.0, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - integrity sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - typescript@^1.6.2: version "1.8.10" resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e" integrity sha1-tHXW4N/wv1DyluXKbvn7tccyDx4= - -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - integrity sha1-WqADz76Uxf+GbE59ZouxxNuts2k= - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -url-parse@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - integrity sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw== - dependencies: - querystringify "~1.0.0" - requires-port "~1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.0.0, uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz#44cbe5108205279deb0c5653c094a2887938b1ab" - integrity sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas= - dependencies: - through2 "^0.6.1" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vscode@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.5.tgz#10eb104001840c3dd0813815fd4a05f8fc882d14" - integrity sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ= - dependencies: - glob "^7.1.1" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.0" - gulp-gunzip "0.0.3" - gulp-remote-src "^0.4.2" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^1.4.0" - mocha "^3.2.0" - request "^2.79.0" - semver "^5.3.0" - source-map-support "^0.4.11" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -yauzl@^2.2.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" - integrity sha1-qBmB6nCleUYTOIPwKcWCGok1mn8= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.0.1" - -yazl@^2.2.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" - integrity sha1-7CblzIfVYBud+EMtvdPNLlFzoHE= - dependencies: - buffer-crc32 "~0.2.3" diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index fc9f924a361..454f983a2a7 100644 --- a/extensions/vscode-colorize-tests/package.json +++ b/extensions/vscode-colorize-tests/package.json @@ -20,8 +20,7 @@ "jsonc-parser": "2.2.1" }, "devDependencies": { - "@types/node": "^12.11.7", - "vscode": "1.1.5" + "@types/node": "^12.11.7" }, "contributes": { "semanticTokenTypes": [ diff --git a/extensions/vscode-colorize-tests/src/index.ts b/extensions/vscode-colorize-tests/src/index.ts index 691ba5c6f07..a6e6e6818f2 100644 --- a/extensions/vscode-colorize-tests/src/index.ts +++ b/extensions/vscode-colorize-tests/src/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../test/integration/electron/testrunner'); const suite = 'Integration Colorize Tests'; diff --git a/extensions/vscode-colorize-tests/yarn.lock b/extensions/vscode-colorize-tests/yarn.lock index d2f44d00cca..f5cad7b6b29 100644 --- a/extensions/vscode-colorize-tests/yarn.lock +++ b/extensions/vscode-colorize-tests/yarn.lock @@ -7,1936 +7,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== -ajv@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" - integrity sha1-RBT/dKUIecII7l/cgm4ywwNUnto= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== - dependencies: - hoek "4.x.x" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - integrity sha1-cVuW6phBWTzDMGeSP17GDr2k99c= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= - -cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" - integrity sha1-pikNQT8hemEjL5XkWP84QYz7ARc= - dependencies: - inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= - dependencies: - delayed-stream "~1.0.0" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - -commander@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" - integrity sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU= - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4= - dependencies: - boom "5.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= - dependencies: - ms "2.0.0" - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.2.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" - integrity sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - integrity sha1-epDYM+/abPpurA9JSduw+tOmMgY= - dependencies: - once "^1.4.0" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" - integrity sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg= - dependencies: - chalk "^1.1.1" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - integrity sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM= - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - integrity sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ= - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.5, glob@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" - integrity sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U= - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.0.1.tgz#5d87f662e317e5839ef7650e620e6c9008ff92d0" - integrity sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A== - dependencies: - gulp-util "^3.0.6" - multimatch "^2.0.0" - streamfilter "^1.0.5" - -gulp-gunzip@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" - integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1" - integrity sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE= - dependencies: - event-stream "~3.3.4" - node.extend "~1.1.2" - request "~2.79.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.0.tgz#c165320732d192ce56fd94271ffa123234bf2ae0" - integrity sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA= - dependencies: - event-stream "^3.3.1" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@^3.0.6, gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" - integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= - dependencies: - event-stream "^3.3.1" - queue "^3.0.10" - through2 "^0.6.3" - vinyl "^0.4.6" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - integrity sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0= - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-my-json-valid@^2.12.4: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" - integrity sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" - integrity sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= - jsonc-parser@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w== - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= - dependencies: - mime-db "~1.30.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" - escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" - integrity sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y= - dependencies: - is "^3.1.0" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - integrity sha1-51vV9uJoEioqDgvaYwslUMFmUCw= - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - integrity sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs= - -queue@^3.0.10, queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - integrity sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -request@^2.79.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - integrity sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -requires-port@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -rimraf@2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== - dependencies: - hoek "4.x.x" - -source-map-support@^0.4.11: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamfilter@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.5.tgz#87507111beb8e298451717b511cfed8f002abf53" - integrity sha1-h1BxEb644phFFxe1Ec/tjwAqv1M= - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= - dependencies: - has-flag "^1.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@^0.6.1, through2@^0.6.3, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.1, through2@~2.0.0, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - integrity sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - integrity sha1-WqADz76Uxf+GbE59ZouxxNuts2k= - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -url-parse@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - integrity sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw== - dependencies: - querystringify "~1.0.0" - requires-port "~1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.0.0, uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz#44cbe5108205279deb0c5653c094a2887938b1ab" - integrity sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas= - dependencies: - through2 "^0.6.1" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vscode@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.5.tgz#10eb104001840c3dd0813815fd4a05f8fc882d14" - integrity sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ= - dependencies: - glob "^7.1.1" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.0" - gulp-gunzip "0.0.3" - gulp-remote-src "^0.4.2" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^1.4.0" - mocha "^3.2.0" - request "^2.79.0" - semver "^5.3.0" - source-map-support "^0.4.11" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -yauzl@^2.2.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" - integrity sha1-qBmB6nCleUYTOIPwKcWCGok1mn8= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.0.1" - -yazl@^2.2.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" - integrity sha1-7CblzIfVYBud+EMtvdPNLlFzoHE= - dependencies: - buffer-crc32 "~0.2.3" diff --git a/extensions/vscode-custom-editor-tests/package.json b/extensions/vscode-custom-editor-tests/package.json index 965fc996c17..e5a7575eefb 100644 --- a/extensions/vscode-custom-editor-tests/package.json +++ b/extensions/vscode-custom-editor-tests/package.json @@ -22,8 +22,7 @@ }, "devDependencies": { "@types/node": "^12.11.7", - "@types/p-limit": "^2.2.0", - "vscode": "^1.1.36" + "@types/p-limit": "^2.2.0" }, "contributes": { "customEditors": [ diff --git a/extensions/vscode-custom-editor-tests/src/test/index.ts b/extensions/vscode-custom-editor-tests/src/test/index.ts index a60622b2f28..c5a810981f8 100644 --- a/extensions/vscode-custom-editor-tests/src/test/index.ts +++ b/extensions/vscode-custom-editor-tests/src/test/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../../test/integration/electron/testrunner'); const suite = 'Custom Editor Tests'; diff --git a/extensions/vscode-custom-editor-tests/yarn.lock b/extensions/vscode-custom-editor-tests/yarn.lock index 875b311ba6f..99746c8e453 100644 --- a/extensions/vscode-custom-editor-tests/yarn.lock +++ b/extensions/vscode-custom-editor-tests/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - "@types/node@^12.11.7": version "12.12.53" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.53.tgz#be0d375933c3d15ef2380dafb3b0350ea7021129" @@ -19,239 +14,6 @@ dependencies: p-limit "*" -agent-base@4, agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - -agent-base@6: - version "6.0.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" - integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== - dependencies: - debug "4" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@4: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - -escape-string-regexp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - -https-proxy-agent@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - -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" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - p-limit@*, p-limit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" @@ -263,59 +25,3 @@ p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -source-map-support@^0.5.0: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - -vscode-test@^0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" - integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== - dependencies: - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - -vscode@^1.1.36: - version "1.1.37" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.37.tgz#c2a770bee4bb3fff765e2b72c7bcc813b8a6bb0a" - integrity sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg== - dependencies: - glob "^7.1.2" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - mocha "^5.2.0" - semver "^5.4.1" - source-map-support "^0.5.0" - vscode-test "^0.4.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index 96eae024344..df17fbb99c7 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -20,8 +20,7 @@ "dependencies": {}, "devDependencies": { "typescript": "^3.8.3", - "@types/node": "^12.11.7", - "vscode": "~1.1.36" + "@types/node": "^12.11.7" }, "contributes": { "commands": [ diff --git a/extensions/vscode-notebook-tests/src/index.ts b/extensions/vscode-notebook-tests/src/index.ts index 293c02db743..27c81a57fb1 100644 --- a/extensions/vscode-notebook-tests/src/index.ts +++ b/extensions/vscode-notebook-tests/src/index.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ const path = require('path'); -const testRunner = require('vscode/lib/testrunner'); +const testRunner = require('../../../test/integration/electron/testrunner'); const options: any = { ui: 'tdd', diff --git a/extensions/vscode-notebook-tests/yarn.lock b/extensions/vscode-notebook-tests/yarn.lock index 21c92a6df84..58c80827086 100644 --- a/extensions/vscode-notebook-tests/yarn.lock +++ b/extensions/vscode-notebook-tests/yarn.lock @@ -7,601 +7,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.37.tgz#cb4782d847f801fa58316da5b4801ca3a59ae790" integrity sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg== -agent-base@4, agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - -ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - -escape-string-regexp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-proxy-agent@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -mime-db@1.43.0: - version "1.43.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" - integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.26" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" - integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== - dependencies: - mime-db "1.43.0" - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -source-map-support@^0.5.0: - version "0.5.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.18.tgz#f5f33489e270bd7f7d7e7b8debf283f3a4066960" - integrity sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - typescript@^3.8.3: version "3.8.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -url-parse@^1.4.4: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vscode-test@^0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" - integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== - dependencies: - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - -vscode@~1.1.36: - version "1.1.36" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.36.tgz#5e1a0d1bf4977d0c7bc5159a9a13d5b104d4b1b6" - integrity sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ== - dependencies: - glob "^7.1.2" - mocha "^5.2.0" - request "^2.88.0" - semver "^5.4.1" - source-map-support "^0.5.0" - url-parse "^1.4.4" - vscode-test "^0.4.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index fd7a9c2f881..47f4eb56156 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -21,8 +21,7 @@ ], "main": "./out/extension", "devDependencies": { - "@types/node": "^12.11.7", - "vscode": "1.1.5" + "@types/node": "^12.11.7" }, "contributes": { "resourceLabelFormatters": [ diff --git a/extensions/vscode-test-resolver/yarn.lock b/extensions/vscode-test-resolver/yarn.lock index 4bc1451096e..40784952b89 100644 --- a/extensions/vscode-test-resolver/yarn.lock +++ b/extensions/vscode-test-resolver/yarn.lock @@ -6,1874 +6,3 @@ version "12.11.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== - -ajv@^6.5.5: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -cloneable-readable@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" - integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== - dependencies: - delayed-stream "~1.0.0" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.1.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= - dependencies: - ms "2.0.0" - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@^0.1.1, duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.2.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -event-stream@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.5" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" - integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== - dependencies: - duplexer "^0.1.1" - from "^0.1.7" - map-stream "0.0.7" - pause-stream "^0.0.11" - split "^1.0.1" - stream-combiner "^0.2.2" - through "^2.3.8" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fancy-log@^1.1.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -from@^0.1.7, from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" - integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= - dependencies: - multimatch "^2.0.0" - plugin-error "^0.1.2" - streamfilter "^1.0.5" - -gulp-gunzip@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" - integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.4.tgz#4a4d18fac0ffedde94a7855953de90db00a1d1b1" - integrity sha512-mo7lGgZmNXyTbcUzfjSnUVkx1pnqqiwv/pPaIrYdTO77hq0WNTxXLAzQdoYOnyJ0mfVLNmNl9AGqWLiAzTPMMA== - dependencies: - event-stream "3.3.4" - node.extend "~1.1.2" - request "^2.88.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.1.tgz#b0a6df3d43a0537165946ab8e38c1b7080a66fac" - integrity sha512-UHd3MokfIN7SrFdsbV5uZTwzBpL0ZSTu7iq98fuDqBGZ0dlHxgbQBJwfd6qjCW83snkQ3Hz9IY4sMRMz2iTq7w== - dependencies: - event-stream "3.3.4" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" - integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= - dependencies: - event-stream "^3.3.1" - queue "^3.0.10" - through2 "^0.6.3" - vinyl "^0.4.6" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.0: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" - integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -map-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.38.0: - version "1.38.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" - integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.22" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" - integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== - dependencies: - mime-db "~1.38.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" - escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" - integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== - dependencies: - has "^1.0.3" - is "^3.2.1" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -pause-stream@0.0.11, pause-stream@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - -psl@^1.1.24: - version "1.1.31" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" - integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -querystringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" - integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== - -queue@^3.0.10, queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.3.5, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -request@^2.79.0, request@^2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -rimraf@2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - -source-map-support@^0.4.11: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -split@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" - integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= - dependencies: - duplexer "~0.1.1" - through "~2.3.4" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamfilter@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" - integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= - dependencies: - has-flag "^1.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@^0.6.3, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -url-parse@^1.1.9: - version "1.4.4" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" - integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== - dependencies: - querystringify "^2.0.0" - requires-port "^1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" - integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= - dependencies: - through2 "^2.0.3" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vscode@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.5.tgz#10eb104001840c3dd0813815fd4a05f8fc882d14" - integrity sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ= - dependencies: - glob "^7.1.1" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.0" - gulp-gunzip "0.0.3" - gulp-remote-src "^0.4.2" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^1.4.0" - mocha "^3.2.0" - request "^2.79.0" - semver "^5.3.0" - source-map-support "^0.4.11" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -yauzl@^2.2.1: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yazl@^2.2.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" - integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== - dependencies: - buffer-crc32 "~0.2.3" diff --git a/package.json b/package.json index c695eb4a263..e45eba2d98a 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,7 @@ "rimraf": "^2.2.8", "sinon": "^1.17.2", "source-map": "^0.4.4", + "source-map-support": "^0.3.2", "style-loader": "^1.0.0", "ts-loader": "^6.2.1", "tsec": "googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1", diff --git a/test/integration/electron/testrunner.js b/test/integration/electron/testrunner.js new file mode 100644 index 00000000000..47007fe8002 --- /dev/null +++ b/test/integration/electron/testrunner.js @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const paths = require('path'); +const glob = require('glob'); +// Linux: prevent a weird NPE when mocha on Linux requires the window size from the TTY +// Since we are not running in a tty environment, we just implementt he method statically +const tty = require('tty'); +if (!tty.getWindowSize) { + tty.getWindowSize = function () { return [80, 75]; }; +} +const Mocha = require('mocha'); + +let mocha = new Mocha({ + ui: 'tdd', + useColors: true +}); + +exports.configure = function configure(opts) { + mocha = new Mocha(opts); +}; + +exports.run = function run(testsRoot, clb) { + // Enable source map support + require('source-map-support').install(); + + // Glob test files + glob('**/**.test.js', { cwd: testsRoot }, function (error, files) { + if (error) { + return clb(error); + } + try { + // Fill into Mocha + files.forEach(function (f) { return mocha.addFile(paths.join(testsRoot, f)); }); + // Run the tests + mocha.run(function (failures) { + clb(null, failures); + }); + } + catch (error) { + return clb(error); + } + }); +}; diff --git a/yarn.lock b/yarn.lock index 4a7f0081f22..b00ee1bd986 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9037,6 +9037,13 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f" + integrity sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8= + dependencies: + source-map "0.1.32" + source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -9050,6 +9057,13 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= +source-map@0.1.32: + version "0.1.32" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266" + integrity sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY= + dependencies: + amdefine ">=0.0.4" + source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" From e461782061e41de3787eef0f90c035c45886e596 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 22:00:45 +0100 Subject: [PATCH 1187/1837] Fix compilation problem --- extensions/git/src/timelineProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index 6e2408366c2..f00302f61ad 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -58,8 +58,8 @@ export class GitTimelineItem extends TimelineItem { } export class GitTimelineProvider implements TimelineProvider { - private _onDidChange = new EventEmitter(); - get onDidChange(): Event { + private _onDidChange = new EventEmitter(); + get onDidChange(): Event { return this._onDidChange.event; } From d03c18661cbcd73e107aa210c20636dfdb8f399c Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 22:44:08 +0100 Subject: [PATCH 1188/1837] Windows CI: Do not cache symbol files --- .github/workflows/ci.yml | 58 +++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd519deb7d1..4c0ec3964a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules4- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -71,8 +71,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -125,8 +125,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -184,8 +184,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -246,8 +246,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -291,8 +291,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -329,8 +329,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -381,8 +381,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -427,8 +427,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules3- + # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules4- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -484,8 +484,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules4- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -540,9 +540,13 @@ jobs: id: cacheNodeModules uses: actions/cache@v2 with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + path: | + **/node_modules + !**/Release/*.pdb + !**/Release/*.ilk + !**/Release/obj/** + key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules4- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -590,8 +594,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules4- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -639,8 +643,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules3-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules3- + key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules4- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From 25cb0d70d4a78348bb969fa14bb23739cce0d4a6 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Thu, 17 Dec 2020 21:52:24 +0000 Subject: [PATCH 1189/1837] Update removeTag command - Handles mixed spacing indents - Affects #104173 --- extensions/emmet/src/removeTag.ts | 74 +++++++------------------------ 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/extensions/emmet/src/removeTag.ts b/extensions/emmet/src/removeTag.ts index 5a10fef9ee7..263aa2248d8 100644 --- a/extensions/emmet/src/removeTag.ts +++ b/extensions/emmet/src/removeTag.ts @@ -11,11 +11,9 @@ export function removeTag() { return; } const editor = vscode.window.activeTextEditor; - - const tabSize: number = +editor.options.tabSize!; let finalRangesToRemove = editor.selections.reverse() .reduce((prev, selection) => - prev.concat(getRangesToRemove(editor.document, selection, tabSize)), []); + prev.concat(getRangesToRemove(editor.document, selection)), []); return editor.edit(editBuilder => { finalRangesToRemove.forEach(range => { @@ -28,9 +26,8 @@ export function removeTag() { * Calculates the ranges to remove, along with what to replace those ranges with. * It finds the node to remove based on the selection's start position * and then removes that node, reindenting the content in between. - * Assumption: The document indents consist of only tabs or only spaces. */ -function getRangesToRemove(document: vscode.TextDocument, selection: vscode.Selection, tabSize: number): vscode.Range[] { +function getRangesToRemove(document: vscode.TextDocument, selection: vscode.Selection): vscode.Range[] { const lsDocument = toLSTextDocument(document); const nodeToUpdate = getHtmlNodeLS(lsDocument, selection.start, true); if (!nodeToUpdate) { @@ -45,7 +42,7 @@ function getRangesToRemove(document: vscode.TextDocument, selection: vscode.Sele let rangesToRemove = [openTagRange]; if (closeTagRange) { - const indentAmountToRemove = calculateIndentAmountToRemove(document, openTagRange, closeTagRange, tabSize); + const indentAmountToRemove = calculateIndentAmountToRemove(document, openTagRange, closeTagRange); for (let i = openTagRange.start.line + 1; i < closeTagRange.start.line; i++) { rangesToRemove.push(new vscode.Range(i, 0, i, indentAmountToRemove)); } @@ -54,71 +51,30 @@ function getRangesToRemove(document: vscode.TextDocument, selection: vscode.Sele return rangesToRemove; } -type IndentInfo = { - indentAmount: number, - tabsOnly: boolean -}; - /** * Calculates the amount of indent to remove for getRangesToRemove. */ -function calculateIndentAmountToRemove(document: vscode.TextDocument, openRange: vscode.Range, closeRange: vscode.Range, tabSize: number): number { +function calculateIndentAmountToRemove(document: vscode.TextDocument, openRange: vscode.Range, closeRange: vscode.Range): number { const startLine = openRange.start.line; const endLine = closeRange.start.line; - const startLineIndent = calculateLineIndentInSpaces(document.lineAt(startLine).text, tabSize); - const endLineIndent = calculateLineIndentInSpaces(document.lineAt(endLine).text, tabSize); + const startLineIndent = document.lineAt(startLine).firstNonWhitespaceCharacterIndex; + const endLineIndent = document.lineAt(endLine).firstNonWhitespaceCharacterIndex; - let contentIndent: IndentInfo | undefined; - for (let i = startLine + 1; i <= endLine - 1; i++) { - const lineContent = document.lineAt(i).text; - const indent = calculateLineIndentInSpaces(lineContent, tabSize); - contentIndent = !contentIndent ? indent : - { - indentAmount: Math.min(contentIndent.indentAmount, indent.indentAmount), - tabsOnly: contentIndent.tabsOnly && indent.tabsOnly - }; + let contentIndent: number | undefined; + for (let i = startLine + 1; i < endLine; i++) { + const lineIndent = document.lineAt(i).firstNonWhitespaceCharacterIndex; + contentIndent = !contentIndent ? lineIndent : Math.min(contentIndent, lineIndent); } - let indentAmountSpaces = 0; - let tabsOnly = startLineIndent.tabsOnly && endLineIndent.tabsOnly; - + let indentAmount = 0; if (contentIndent) { - if (contentIndent.indentAmount < startLineIndent.indentAmount - || contentIndent.indentAmount < endLineIndent.indentAmount) { - indentAmountSpaces = 0; + if (contentIndent < startLineIndent || contentIndent < endLineIndent) { + indentAmount = 0; } else { - indentAmountSpaces = Math.min( - contentIndent.indentAmount - startLineIndent.indentAmount, - contentIndent.indentAmount - endLineIndent.indentAmount - ); + indentAmount = Math.min(contentIndent - startLineIndent, contentIndent - endLineIndent); } - tabsOnly = tabsOnly && contentIndent.tabsOnly; } - return tabsOnly ? Math.trunc(indentAmountSpaces / tabSize) : indentAmountSpaces; -} - -function calculateLineIndentInSpaces(line: string, tabSize: number): IndentInfo { - const whiteSpaceMatch = line.match(/^\s+/); - const whiteSpaceContent = whiteSpaceMatch ? whiteSpaceMatch[0] : ''; - - if (!whiteSpaceContent) { - return { indentAmount: 0, tabsOnly: true }; - } - - let numSpaces = 0; - let numTabs = 0; - let tabsOnly = true; - for (const c of whiteSpaceContent) { - if (c === '\t') { - numTabs++; - } - else { - numSpaces++; - tabsOnly = false; - } - } - - return { indentAmount: numTabs * tabSize + numSpaces, tabsOnly }; + return indentAmount; } From 2292bb0283f436bb9da5381924698fb08e339444 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 17 Dec 2020 14:01:52 -0800 Subject: [PATCH 1190/1837] Make notebook add new cell toolbar visible on hover/focus Fixes #111063 --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index c2b2830c4c9..a7738369eed 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -598,8 +598,9 @@ .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container:focus-within, .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container:hover, -.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container:focus-within, -.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container:hover { +.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .cell-bottom-toolbar-container, +.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list:focus-within > .monaco-scrollable-element > .monaco-list-rows:not(:hover) > .monaco-list-row.focused .cell-bottom-toolbar-container, +.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container:focus-within { opacity: 1; } From e9abb31537a2c0c31410fec665e6e50e65c28faf Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 17 Dec 2020 14:02:32 -0800 Subject: [PATCH 1191/1837] Reduce height of notebook add new cell toolbar Fixes #110274 --- src/vs/workbench/contrib/notebook/browser/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 3232b04744f..ab61c29ec14 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -13,8 +13,8 @@ export const CELL_RUN_GUTTER = 28; export const CODE_CELL_LEFT_MARGIN = 32; export const EDITOR_TOOLBAR_HEIGHT = 0; -export const BOTTOM_CELL_TOOLBAR_GAP = 18; -export const BOTTOM_CELL_TOOLBAR_HEIGHT = 50; +export const BOTTOM_CELL_TOOLBAR_GAP = 16; +export const BOTTOM_CELL_TOOLBAR_HEIGHT = 24; export const CELL_STATUSBAR_HEIGHT = 22; // Margin above editor From e48a21c44bd41c5b0e929789734cd9fe38102e6d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 23:08:04 +0100 Subject: [PATCH 1192/1837] :lipstick: --- src/vs/editor/browser/controller/mouseTarget.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 37c1d8b0525..88815bb8eb0 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -269,11 +269,11 @@ export class HitTestContext { const viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset); if (viewZoneWhitespace) { - let viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2, - lineCount = context.model.getLineCount(), - positionBefore: Position | null = null, - position: Position | null, - positionAfter: Position | null = null; + const viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2; + const lineCount = context.model.getLineCount(); + let positionBefore: Position | null = null; + let position: Position | null; + let positionAfter: Position | null = null; if (viewZoneWhitespace.afterLineNumber !== lineCount) { // There are more lines after this view zone From 681a3e413d0e99e00c009abeabf9a08faab66d80 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 14:24:35 -0800 Subject: [PATCH 1193/1837] :build: --- .../notebook/browser/diff/diffComponents.ts | 30 +++++++++-- .../browser/diff/diffElementViewModel.ts | 14 ++++++ .../browser/diff/notebookDiffActions.ts | 50 ++++++++++++++++++- .../contrib/notebook/browser/notebookIcons.ts | 2 + .../notebook/test/testNotebookEditor.ts | 5 +- 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 9fe8b05ff56..956d050d807 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -33,8 +33,6 @@ import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/brows import { renderCodicons } from 'vs/base/browser/codicons'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/diffElementOutputs'; -const RENDER_RICH_OUTPUT = true; - const fixedEditorOptions: IEditorOptions = { padding: { top: 12, @@ -284,9 +282,15 @@ abstract class AbstractElementRenderer extends Disposable { } } - updateOutputRendering() { + updateOutputRendering(renderRichOutput: boolean = true) { if (this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - if (RENDER_RICH_OUTPUT) { + if (renderRichOutput) { + if (this._outputEditorContainer) { + this._hideOutputs(); + this._outputEditorContainer.style.display = 'none'; + this._outputEditorDisposeStore.clear(); + } + this._outputInfoContainer.style.display = 'block'; if (!this._outputViewContainer) { @@ -297,7 +301,16 @@ abstract class AbstractElementRenderer extends Disposable { this._showOutputs(); // this.cell.layoutChange(); } + + this.cell.layoutChange(); + } else { + if (this._outputInfoContainer) { + this._hideOutputs(); + this._outputInfoContainer.style.display = 'none'; + this._outputEditorDisposeStore.clear(); + } + this._outputInfoContainer.style.display = 'block'; if (!this._outputEditorContainer || !this._outputEditor) { @@ -305,11 +318,14 @@ abstract class AbstractElementRenderer extends Disposable { this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); this._buildOutputEditor(); } else { + this._outputEditorContainer.style.display = 'block'; this.cell.outputHeight = this._outputEditor.getContentHeight(); } + + this.cell.layoutChange(); } } else { - if (RENDER_RICH_OUTPUT) { + if (renderRichOutput) { this._hideOutputs(); this._outputInfoContainer.style.display = 'none'; this._outputEditorDisposeStore.clear(); @@ -963,6 +979,10 @@ export class ModifiedElement extends AbstractElementRenderer { @IContextKeyService protected readonly contextKeyService: IContextKeyService ) { super(notebookEditor, cell, templateData, 'full', instantiationService, modeService, modelService, contextMenuService, keybindingService, notificationService, menuService, contextKeyService); + + this._register(cell.onDidStateChange(() => { + this.updateOutputRendering(this.cell.renderOutput); + })); } styleContainer(container: HTMLElement): void { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 5ffd45089d0..1dd0d4fe179 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -27,6 +27,9 @@ export abstract class DiffElementViewModelBase extends Disposable { public outputFoldingState: PropertyFoldingState; protected _layoutInfoEmitter = new Emitter(); onDidLayoutChange = this._layoutInfoEmitter.event; + protected _stateChangeEmitter = new Emitter<{ renderOutput: boolean; }>(); + onDidStateChange = this._stateChangeEmitter.event; + protected _layoutInfo!: { width: number; @@ -88,6 +91,17 @@ export abstract class DiffElementViewModelBase extends Disposable { return this._layoutInfo.metadataHeight; } + private _renderOutput = true; + + set renderOutput(value: boolean) { + this._renderOutput = value; + this._stateChangeEmitter.fire({ renderOutput: this._renderOutput }); + } + + get renderOutput() { + return this._renderOutput; + } + get totalHeight() { return this._layoutInfo.editorHeight + this._layoutInfo.editorMargin diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index b88069d4fc4..5b3d84c23b8 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -11,7 +11,7 @@ import { ActiveEditorContext, viewColumnToEditorGroup } from 'vs/workbench/commo import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; -import { openAsTextIcon, revertIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { openAsTextIcon, revertIcon, showOutputRawIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -81,6 +81,53 @@ registerAction2(class extends Action2 { } }); +// registerAction2(class extends Action2 { +// constructor() { +// super( +// { +// id: 'notebook.diff.cell.switchOutputRenderingStyle', +// title: localize('notebook.diff.cell.switchOutputRenderingStyle', "Switch Outputs Rendering"), +// icon: renderOutputIcon, +// f1: false, +// menu: { +// id: MenuId.NotebookDiffCellOutputsTitle +// } +// } +// ); +// } +// run(accessor: ServicesAccessor, context?: { cell: DiffElementViewModelBase }) { +// if (!context) { +// return; +// } + +// context.cell.renderOutput = true; +// } +// }); + + +registerAction2(class extends Action2 { + constructor() { + super( + { + id: 'notebook.diff.cell.switchOutputRenderingStyleToText', + title: localize('notebook.diff.cell.switchOutputRenderingStyleToText', "View outputs raw data"), + icon: showOutputRawIcon, + f1: false, + menu: { + id: MenuId.NotebookDiffCellOutputsTitle + }, + } + ); + } + run(accessor: ServicesAccessor, context?: { cell: DiffElementViewModelBase }) { + if (!context) { + return; + } + + context.cell.renderOutput = !context.cell.renderOutput; + } +}); + registerAction2(class extends Action2 { constructor() { super( @@ -111,6 +158,7 @@ registerAction2(class extends Action2 { } }); + registerAction2(class extends Action2 { constructor() { super( diff --git a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts index 6780f1fa93f..ce2b0248ce2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookIcons.ts @@ -29,4 +29,6 @@ export const collapsedIcon = registerIcon('notebook-collapsed', Codicon.chevronR export const expandedIcon = registerIcon('notebook-expanded', Codicon.chevronDown, localize('expandedIcon', 'Icon to annotated a expanded section in notebook editors.')); export const openAsTextIcon = registerIcon('notebook-open-as-text', Codicon.fileCode, localize('openAsTextIcon', 'Icon to open the notebook in a text editor.')); export const revertIcon = registerIcon('notebook-revert', Codicon.discard, localize('revertIcon', 'Icon to revert in notebook editors.')); +export const renderOutputIcon = registerIcon('notebook-render-output', Codicon.preview, localize('renderOutputIcon', 'Icon to render output in diff editor.')); +export const showOutputRawIcon = registerIcon('notebook-show-output-raw', Codicon.fileCode, localize('showOutputRawIcon', 'Icon to show output raw data.')); export const mimetypeIcon = registerIcon('notebook-mimetype', Codicon.code, localize('mimetypeIcon', 'Icon for a mime type in notebook editors.')); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 0cf9e2612af..2efea75e07b 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -12,7 +12,7 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { Range } from 'vs/editor/common/core/range'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { EditorModel } from 'vs/workbench/common/editor'; -import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput, IDisplayOutputViewModel, ICommonCellInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookEditorCreationOptions, NotebookEditorOptions, ICellOutputViewModel, IInsetRenderOutput, IDisplayOutputViewModel, ICommonCellInfo, IGenericCellViewModel, INotebookCellOutputLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; @@ -66,6 +66,9 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + getCellOutputLayoutInfo(cell: IGenericCellViewModel): INotebookCellOutputLayoutInfo { + throw new Error('Method not implemented.'); + } focusNextNotebookCell(cell: ICellViewModel, focus: 'editor' | 'container' | 'output'): void { throw new Error('Method not implemented.'); } From 6dd6d4e513849629ee48d6a17fd2a92b03f81416 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 17 Dec 2020 23:38:43 +0100 Subject: [PATCH 1194/1837] Add `--prof-v8-extensions` flag (see #112393) --- src/vs/platform/environment/common/argv.ts | 1 + src/vs/platform/environment/node/argv.ts | 1 + .../extensions/electron-browser/localProcessExtensionHost.ts | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts index e719e129c60..019410e6a30 100644 --- a/src/vs/platform/environment/common/argv.ts +++ b/src/vs/platform/environment/common/argv.ts @@ -28,6 +28,7 @@ export interface NativeParsedArgs { 'prof-startup'?: boolean; 'prof-startup-prefix'?: string; 'prof-append-timers'?: string; + 'prof-v8-extensions'?: boolean; verbose?: boolean; trace?: boolean; 'trace-category-filter'?: string; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 7263bcbf756..1ec40eea8f0 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -66,6 +66,7 @@ export const OPTIONS: OptionDescriptions> = { 'prof-startup': { type: 'boolean', cat: 't', description: localize('prof-startup', "Run CPU profiler during startup") }, 'prof-append-timers': { type: 'string' }, 'prof-startup-prefix': { type: 'string' }, + 'prof-v8-extensions': { type: 'boolean' }, 'disable-extensions': { type: 'boolean', deprecates: 'disableExtensions', cat: 't', description: localize('disableExtensions', "Disable all installed extensions.") }, 'disable-extension': { type: 'string[]', cat: 't', args: 'extension-id', description: localize('disableExtension', "Disable an extension.") }, 'sync': { type: 'string', cat: 't', description: localize('turn sync', "Turn sync on or off"), args: ['on', 'off'] }, diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 101ece12361..88c6ea7ff99 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -202,6 +202,10 @@ export class LocalProcessExtensionHost implements IExtensionHost { opts.execArgv = ['--inspect-port=0']; } + if (this._environmentService.args['prof-v8-extensions']) { + opts.execArgv.unshift('--prof'); + } + // On linux crash reporter needs to be started on child node processes explicitly if (platform.isLinux) { const crashReporterStartOptions: CrashReporterStartOptions = { From 819161c7bcaf78343f2397a871677b6c72aaa5cd Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 14:42:24 -0800 Subject: [PATCH 1195/1837] DiffSide enum to replace boolean. --- .../notebook/browser/diff/diffComponents.ts | 18 ++++++------- .../browser/diff/diffElementOutputs.ts | 22 ++++++++-------- .../browser/diff/diffElementViewModel.ts | 14 +++++----- .../browser/diff/notebookDiffEditorBrowser.ts | 9 +++++-- .../browser/diff/notebookTextDiffEditor.ts | 26 +++++++++---------- 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 956d050d807..30dfeb6d1ac 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -8,7 +8,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DiffElementViewModelBase, getFormatedMetadataJSON, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; -import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -839,7 +839,7 @@ export class DeletedElement extends SingleSideDiffElement { } _buildOutputContainer() { - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, false, this._outputViewContainer!); + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputViewContainer!); this._outputLeftView.render(); this.cell.layoutChange(); } @@ -912,7 +912,7 @@ export class InsertElement extends SingleSideDiffElement { } _buildOutputContainer() { - this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputViewContainer!); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputViewContainer!); this._outputRightView.render(); this.cell.layoutChange(); } @@ -1085,21 +1085,21 @@ export class ModifiedElement extends AbstractElementRenderer { this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left')); this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right')); // We should use the original text model here - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, false, this._outputLeftContainer!); + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputLeftContainer!); this._outputLeftView.render(); - this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, true, this._outputRightContainer!); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputRightContainer!); this._outputRightView.render(); const originalOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { if (e.cell.uri.toString() === this.cell.original.uri.toString()) { - this.notebookEditor.deltaCellOutputContainerClassNames(true, this.cell.original.id, ['nb-cellDeleted'], []); + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original.id, ['nb-cellDeleted'], []); originalOutputRenderListener.dispose(); } }); const modifiedOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { if (e.cell.uri.toString() === this.cell.modified.uri.toString()) { - this.notebookEditor.deltaCellOutputContainerClassNames(false, this.cell.modified.id, ['nb-cellAdded'], []); + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified.id, ['nb-cellAdded'], []); modifiedOutputRenderListener.dispose(); } }); @@ -1116,8 +1116,8 @@ export class ModifiedElement extends AbstractElementRenderer { } _decorate() { - this.notebookEditor.deltaCellOutputContainerClassNames(true, this.cell.original.id, ['nb-cellDeleted'], []); - this.notebookEditor.deltaCellOutputContainerClassNames(false, this.cell.modified.id, ['nb-cellAdded'], []); + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original.id, ['nb-cellDeleted'], []); + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified.id, ['nb-cellAdded'], []); } _hideOutputs() { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index c6507df68b1..3c2e001525d 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; -import { INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { DiffSide, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; @@ -27,7 +27,7 @@ export class OutputElement extends Disposable { private _notebookTextModel: NotebookTextModel, private _notebookService: INotebookService, private _diffElementViewModel: DiffElementViewModelBase, - private _modified: boolean, + private _diffVersion: DiffSide, private _nestedCell: DiffNestedCellViewModel, private _outputContainer: HTMLElement, @@ -87,8 +87,8 @@ export class OutputElement extends Disposable { result, () => this.getOutputOffsetInCell(index), this._diffElementViewModel instanceof SideBySideDiffElementViewModel - ? this._modified - : this._diffElementViewModel.type === 'insert' + ? this._diffVersion + : this._diffElementViewModel.type === 'insert' ? DiffSide.Modified : DiffSide.Original ); } else { outputItemDiv.classList.add('foreground', 'output-element'); @@ -134,7 +134,7 @@ export class OutputElement extends Disposable { getCellOutputCurrentIndex() { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - if (this._modified) { + if (this._diffVersion === DiffSide.Modified) { return this._diffElementViewModel.modified.outputs.indexOf(this.output.model); } else { return this._diffElementViewModel.original.outputs.indexOf(this.output.model); @@ -146,7 +146,7 @@ export class OutputElement extends Disposable { updateHeight(index: number, height: number) { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - this._diffElementViewModel.updateOutputHeight(!this._modified, index, height); + this._diffElementViewModel.updateOutputHeight(this._diffVersion, index, height); } else { (this._diffElementViewModel as SingleSideDiffElementViewModel).updateOutputHeight(index, height); } @@ -154,7 +154,7 @@ export class OutputElement extends Disposable { getOutputOffsetInContainer(index: number) { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - return this._diffElementViewModel.getOutputOffsetInContainer(!this._modified, index); + return this._diffElementViewModel.getOutputOffsetInContainer(this._diffVersion, index); } else { return (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); } @@ -162,7 +162,7 @@ export class OutputElement extends Disposable { getOutputOffsetInCell(index: number) { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - return this._diffElementViewModel.getOutputOffsetInCell(!this._modified, index); + return this._diffElementViewModel.getOutputOffsetInCell(this._diffVersion, index); } else { return (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(index); } @@ -177,7 +177,7 @@ export class OutputContainer extends Disposable { private _notebookTextModel: NotebookTextModel, private _diffElementViewModel: DiffElementViewModelBase, private _nestedCellViewModel: DiffNestedCellViewModel, - private _modified: boolean, + private _diffVersion: DiffSide, private _outputContainer: HTMLElement, @INotebookService private _notebookService: INotebookService, // @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -198,7 +198,7 @@ export class OutputContainer extends Disposable { const index = _nestedCellViewModel.outputs.indexOf(key.model); if (index >= 0) { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - const top = this._diffElementViewModel.getOutputOffsetInContainer(!this._modified, index); + const top = this._diffElementViewModel.getOutputOffsetInContainer(this._diffVersion, index); value.domNode.style.top = `${top}px`; } else { const top = (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); @@ -229,7 +229,7 @@ export class OutputContainer extends Disposable { private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this._outputEntries.has(currOutput)) { - this._outputEntries.set(currOutput, new OutputElement(this._editor, this._notebookTextModel, this._notebookService, this._diffElementViewModel, this._modified, this._nestedCellViewModel, this._outputContainer, currOutput)); + this._outputEntries.set(currOutput, new OutputElement(this._editor, this._notebookTextModel, this._notebookService, this._diffElementViewModel, this._diffVersion, this._nestedCellViewModel, this._outputContainer, currOutput)); } const renderElement = this._outputEntries.get(currOutput)!; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 1dd0d4fe179..d95720fb199 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -6,7 +6,7 @@ import { NotebookDiffEditorEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { CellDiffViewModelLayoutChangeEvent, DIFF_CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { CellDiffViewModelLayoutChangeEvent, DiffSide, DIFF_CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { IGenericCellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -216,24 +216,24 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { return hash(getFormatedMetadataJSON(this.documentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.documentTextModel, this.modified?.metadata ?? {}, this.modified?.language)); } - updateOutputHeight(original: boolean, index: number, height: number) { - if (original) { + updateOutputHeight(diffSide: DiffSide, index: number, height: number) { + if (diffSide === DiffSide.Original) { this.original.updateOutputHeight(index, height); } else { this.modified.updateOutputHeight(index, height); } } - getOutputOffsetInContainer(original: boolean, index: number) { - if (original) { + getOutputOffsetInContainer(diffSide: DiffSide, index: number) { + if (diffSide === DiffSide.Original) { return this.original.getOutputOffset(index); } else { return this.modified.getOutputOffset(index); } } - getOutputOffsetInCell(original: boolean, index: number) { - const offsetInOutputsContainer = this.getOutputOffsetInContainer(original, index); + getOutputOffsetInCell(diffSide: DiffSide, index: number) { + const offsetInOutputsContainer = this.getOutputOffsetInContainer(diffSide, index); return this._layoutInfo.editorHeight + this._layoutInfo.editorMargin diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index a78970d4475..50e07189d1b 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -15,6 +15,11 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; +export enum DiffSide { + Original = 0, + Modified = 1 +} + export interface IDiffCellInfo extends ICommonCellInfo { diffElement: DiffElementViewModelBase; } @@ -27,7 +32,7 @@ export interface INotebookTextDiffEditor extends ICommonNotebookEditor { getLayoutInfo(): NotebookLayoutInfo; layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; - createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, rightEditor: boolean): void; + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void; hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IDisplayOutputViewModel): void; /** * Trigger the editor to scroll from scroll event programmatically @@ -37,7 +42,7 @@ export interface INotebookTextDiffEditor extends ICommonNotebookEditor { focusNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; focusNextNotebookCell(cell: IGenericCellViewModel, focus: 'editor' | 'container' | 'output'): void; updateOutputHeight(cellInfo: ICommonCellInfo, output: IDisplayOutputViewModel, height: number, isInit: boolean): void; - deltaCellOutputContainerClassNames(original: boolean, cellId: string, added: string[], removed: string[]): void; + deltaCellOutputContainerClassNames(diffSide: DiffSide, cellId: string, added: string[], removed: string[]): void; } export interface IDiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index d975eb351f1..b546e4de0cc 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -24,7 +24,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; import { IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { DiffSide, DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { NotebookDiffEditorEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; @@ -126,7 +126,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return; } - diffElement.updateOutputHeight(info.notebook.toString() === this._model?.original.resource.toString(), outputIndex, outputHeight); + diffElement.updateOutputHeight(info.notebook.toString() === this._model?.original.resource.toString() ? DiffSide.Original : DiffSide.Modified, outputIndex, outputHeight); } else { (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); } @@ -230,19 +230,19 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD if (this._modifiedWebview) { this._updateOutputsOffsetsInWebview(this._list.scrollTop, this._list.scrollHeight, this._modifiedWebview, (diffElement: DiffElementViewModelBase) => { return diffElement.modified; - }, false); + }, DiffSide.Modified); } if (this._originalWebview) { this._updateOutputsOffsetsInWebview(this._list.scrollTop, this._list.scrollHeight, this._originalWebview, (diffElement: DiffElementViewModelBase) => { return diffElement.original; - }, true); + }, DiffSide.Original); } }); })); } - private _updateOutputsOffsetsInWebview(scrollTop: number, scrollHeight: number, activeWebview: BackLayerWebView, getActiveNestedCell: (diffElement: DiffElementViewModelBase) => DiffNestedCellViewModel | undefined, original: boolean) { + private _updateOutputsOffsetsInWebview(scrollTop: number, scrollHeight: number, activeWebview: BackLayerWebView, getActiveNestedCell: (diffElement: DiffElementViewModelBase) => DiffNestedCellViewModel | undefined, diffSide: DiffSide) { activeWebview.element.style.height = `${scrollHeight}px`; if (activeWebview.insetMapping) { @@ -271,7 +271,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(original, outputIndex); + outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex); } else { outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } @@ -529,9 +529,9 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._list.triggerScrollFromMouseWheelEvent(event); } - createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, rightEditor: boolean): void { - this._insetModifyQueueByOutputId.queue(output.source.model.outputId + (rightEditor ? '-right' : 'left'), async () => { - if (rightEditor) { + createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void { + this._insetModifyQueueByOutputId.queue(output.source.model.outputId + (diffSide === DiffSide.Modified ? '-right' : 'left'), async () => { + if (diffSide === DiffSide.Modified) { if (!this._modifiedWebview!.insetMapping.has(output.source)) { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); await this._modifiedWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); @@ -541,7 +541,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(false, outputIndex); + outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); } else { outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } @@ -558,7 +558,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(true, outputIndex); + outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); } else { outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); } @@ -619,8 +619,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return this._outputRenderer; } - deltaCellOutputContainerClassNames(original: boolean, cellId: string, added: string[], removed: string[]) { - if (original) { + deltaCellOutputContainerClassNames(diffSide: DiffSide, cellId: string, added: string[], removed: string[]) { + if (diffSide === DiffSide.Original) { this._originalWebview?.deltaCellOutputContainerClassNames(cellId, added, removed); } else { this._modifiedWebview?.deltaCellOutputContainerClassNames(cellId, added, removed); From 6d378dbadea7e31bb0ab1b9a9a3c3a0484253022 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 14:52:14 -0800 Subject: [PATCH 1196/1837] no more casting for Single/SidebySide diff view model. --- .../browser/diff/diffElementOutputs.ts | 25 +++++-------------- .../browser/diff/diffElementViewModel.ts | 7 ++++-- .../browser/diff/notebookTextDiffEditor.ts | 19 +++----------- 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 3c2e001525d..f5f326cba67 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -27,8 +27,7 @@ export class OutputElement extends Disposable { private _notebookTextModel: NotebookTextModel, private _notebookService: INotebookService, private _diffElementViewModel: DiffElementViewModelBase, - private _diffVersion: DiffSide, - + private _diffSide: DiffSide, private _nestedCell: DiffNestedCellViewModel, private _outputContainer: HTMLElement, readonly output: ICellOutputViewModel @@ -87,7 +86,7 @@ export class OutputElement extends Disposable { result, () => this.getOutputOffsetInCell(index), this._diffElementViewModel instanceof SideBySideDiffElementViewModel - ? this._diffVersion + ? this._diffSide : this._diffElementViewModel.type === 'insert' ? DiffSide.Modified : DiffSide.Original ); } else { @@ -134,7 +133,7 @@ export class OutputElement extends Disposable { getCellOutputCurrentIndex() { if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - if (this._diffVersion === DiffSide.Modified) { + if (this._diffSide === DiffSide.Modified) { return this._diffElementViewModel.modified.outputs.indexOf(this.output.model); } else { return this._diffElementViewModel.original.outputs.indexOf(this.output.model); @@ -145,27 +144,15 @@ export class OutputElement extends Disposable { } updateHeight(index: number, height: number) { - if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - this._diffElementViewModel.updateOutputHeight(this._diffVersion, index, height); - } else { - (this._diffElementViewModel as SingleSideDiffElementViewModel).updateOutputHeight(index, height); - } + this._diffElementViewModel.updateOutputHeight(this._diffSide, index, height); } getOutputOffsetInContainer(index: number) { - if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - return this._diffElementViewModel.getOutputOffsetInContainer(this._diffVersion, index); - } else { - return (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); - } + return this._diffElementViewModel.getOutputOffsetInContainer(this._diffSide, index); } getOutputOffsetInCell(index: number) { - if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - return this._diffElementViewModel.getOutputOffsetInCell(this._diffVersion, index); - } else { - return (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(index); - } + return this._diffElementViewModel.getOutputOffsetInCell(this._diffSide, index); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index d95720fb199..b1cace76689 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -147,6 +147,9 @@ export abstract class DiffElementViewModelBase extends Disposable { abstract checkMetadataIfModified(): boolean; abstract layoutChange(): void; abstract getCellByUri(cellUri: URI): IGenericCellViewModel; + abstract getOutputOffsetInCell(diffSide: DiffSide, index: number): number; + abstract getOutputOffsetInContainer(diffSide: DiffSide, index: number): number; + abstract updateOutputHeight(diffSide: DiffSide, index: number, height: number): void; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -300,7 +303,7 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { return false; } - updateOutputHeight(index: number, height: number) { + updateOutputHeight(diffSide: DiffSide, index: number, height: number) { this.cellViewModel?.updateOutputHeight(index, height); } @@ -308,7 +311,7 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { return this.cellViewModel!.getOutputOffset(index); } - getOutputOffsetInCell(index: number) { + getOutputOffsetInCell(diffSide: DiffSide, index: number) { const offsetInOutputsContainer = this.cellViewModel!.getOutputOffset(index); return this._layoutInfo.editorHeight diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index b546e4de0cc..09556fb7302 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -128,7 +128,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD diffElement.updateOutputHeight(info.notebook.toString() === this._model?.original.resource.toString() ? DiffSide.Original : DiffSide.Modified, outputIndex, outputHeight); } else { - (diffElement as SingleSideDiffElementViewModel).updateOutputHeight(outputIndex, outputHeight); + diffElement.updateOutputHeight(diffElement.type === 'insert' ? DiffSide.Modified : DiffSide.Original, outputIndex, outputHeight); } if (isInit) { @@ -269,12 +269,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD if (activeWebview.shouldUpdateInset(cell, key, cellTop)) { // TODO: why? does it mean, we create new output view model every time? const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); - let outputOffset = 0; - if (value.cellInfo.diffElement instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex); - } else { - outputOffset = cellTop + (value.cellInfo.diffElement as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); - } + const outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex); updateItems.push({ output: key, @@ -543,7 +538,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); } else { - outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); + outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(diffSide, outputIndex); } this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); @@ -556,13 +551,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); - let outputOffset = 0; - if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); - } else { - outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(outputIndex); - } - + const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); this._originalWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } } From 1c2d88e68baa63583c230f65328851134c357df8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 14:58:40 -0800 Subject: [PATCH 1197/1837] fewer weird as cast --- .../browser/diff/diffElementOutputs.ts | 23 ++++--------------- .../browser/diff/diffElementViewModel.ts | 13 +++++++++-- .../browser/diff/notebookTextDiffEditor.ts | 9 ++------ 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index f5f326cba67..55c9d7b4fda 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -132,15 +132,7 @@ export class OutputElement extends Disposable { } getCellOutputCurrentIndex() { - if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - if (this._diffSide === DiffSide.Modified) { - return this._diffElementViewModel.modified.outputs.indexOf(this.output.model); - } else { - return this._diffElementViewModel.original.outputs.indexOf(this.output.model); - } - } else { - return (this._diffElementViewModel as SingleSideDiffElementViewModel).cellViewModel!.outputs.indexOf(this.output.model); - } + return this._diffElementViewModel.getNestedCellViewModel(this._diffSide).outputs.indexOf(this.output.model); } updateHeight(index: number, height: number) { @@ -164,7 +156,7 @@ export class OutputContainer extends Disposable { private _notebookTextModel: NotebookTextModel, private _diffElementViewModel: DiffElementViewModelBase, private _nestedCellViewModel: DiffNestedCellViewModel, - private _diffVersion: DiffSide, + private _diffSide: DiffSide, private _outputContainer: HTMLElement, @INotebookService private _notebookService: INotebookService, // @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -184,13 +176,8 @@ export class OutputContainer extends Disposable { this._outputEntries.forEach((value, key) => { const index = _nestedCellViewModel.outputs.indexOf(key.model); if (index >= 0) { - if (this._diffElementViewModel instanceof SideBySideDiffElementViewModel) { - const top = this._diffElementViewModel.getOutputOffsetInContainer(this._diffVersion, index); - value.domNode.style.top = `${top}px`; - } else { - const top = (this._diffElementViewModel as SingleSideDiffElementViewModel).getOutputOffsetInContainer(index); - value.domNode.style.top = `${top}px`; - } + const top = this._diffElementViewModel.getOutputOffsetInContainer(this._diffSide, index); + value.domNode.style.top = `${top}px`; } }); })); @@ -216,7 +203,7 @@ export class OutputContainer extends Disposable { private _renderOutput(currOutput: ICellOutputViewModel, index: number, beforeElement?: HTMLElement) { if (!this._outputEntries.has(currOutput)) { - this._outputEntries.set(currOutput, new OutputElement(this._editor, this._notebookTextModel, this._notebookService, this._diffElementViewModel, this._diffVersion, this._nestedCellViewModel, this._outputContainer, currOutput)); + this._outputEntries.set(currOutput, new OutputElement(this._editor, this._notebookTextModel, this._notebookService, this._diffElementViewModel, this._diffSide, this._nestedCellViewModel, this._outputContainer, currOutput)); } const renderElement = this._outputEntries.get(currOutput)!; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index b1cace76689..116569e0ae6 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -150,6 +150,7 @@ export abstract class DiffElementViewModelBase extends Disposable { abstract getOutputOffsetInCell(diffSide: DiffSide, index: number): number; abstract getOutputOffsetInContainer(diffSide: DiffSide, index: number): number; abstract updateOutputHeight(diffSide: DiffSide, index: number, height: number): void; + abstract getNestedCellViewModel(diffSide: DiffSide): DiffNestedCellViewModel; getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) { if (fullWidth) { @@ -251,6 +252,10 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); } + getNestedCellViewModel(diffSide: DiffSide): DiffNestedCellViewModel { + throw new Error('Method not implemented.'); + } + getCellByUri(cellUri: URI): IGenericCellViewModel { if (cellUri.toString() === this.original.uri.toString()) { return this.original; @@ -262,7 +267,7 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { get cellViewModel() { - return this.type === 'insert' ? this.modified : this.original; + return this.type === 'insert' ? this.modified! : this.original!; } constructor( @@ -278,6 +283,10 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { })); } + getNestedCellViewModel(diffSide: DiffSide): DiffNestedCellViewModel { + return this.type === 'insert' ? this.modified! : this.original!; + } + layoutChange() { let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); this._layoutInfo = { @@ -307,7 +316,7 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { this.cellViewModel?.updateOutputHeight(index, height); } - getOutputOffsetInContainer(index: number) { + getOutputOffsetInContainer(diffSide: DiffSide, index: number) { return this.cellViewModel!.getOutputOffset(index); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 09556fb7302..06d9e9844f9 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -104,7 +104,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._register(this._modifiedResourceDisposableStore); // TODO - this._outputRenderer = new OutputRenderer(this as unknown as INotebookEditor, this.instantiationService); + this._outputRenderer = new OutputRenderer(this, this.instantiationService); } focusNotebookCell(cell: IGenericCellViewModel, focus: 'output' | 'editor' | 'container'): void { @@ -535,12 +535,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const scrollTop = this._list.scrollTop; const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); let outputOffset = 0; - if (cellDiffViewModel instanceof SideBySideDiffElementViewModel) { - outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); - } else { - outputOffset = cellTop + (cellDiffViewModel as SingleSideDiffElementViewModel).getOutputOffsetInCell(diffSide, outputIndex); - } - + outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } } else { From 8d5b2904fa2031788bb06d8db86785fd055386eb Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 14:59:04 -0800 Subject: [PATCH 1198/1837] :lipstick: --- .../contrib/notebook/browser/diff/diffElementOutputs.ts | 2 +- .../contrib/notebook/browser/diff/notebookTextDiffEditor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index 55c9d7b4fda..b93b348e5c4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -6,7 +6,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; +import { DiffElementViewModelBase, SideBySideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { DiffSide, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { ICellOutputViewModel, IRenderOutput, outputHasDynamicHeight, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 06d9e9844f9..dfdc8b8d6ba 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; -import { IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffSide, DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; From 3337693651f0f3d38bc5ea5c26a7d3c2594bee6c Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 15:08:25 -0800 Subject: [PATCH 1199/1837] dedup. --- .../browser/diff/notebookTextDiffEditor.ts | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index dfdc8b8d6ba..e586bde9000 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -526,29 +526,20 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId + (diffSide === DiffSide.Modified ? '-right' : 'left'), async () => { - if (diffSide === DiffSide.Modified) { - if (!this._modifiedWebview!.insetMapping.has(output.source)) { - const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._modifiedWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); - } else { - const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - const scrollTop = this._list.scrollTop; - const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); - let outputOffset = 0; - outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); - this._modifiedWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); - } + const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview; + if (!activeWebview) { + return; + } + + if (!activeWebview.insetMapping.has(output.source)) { + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + await activeWebview.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); } else { - if (!this._originalWebview!.insetMapping.has(output.source)) { - const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - await this._originalWebview?.createInset({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset()); - } else { - const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); - const scrollTop = this._list.scrollTop; - const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); - const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); - this._originalWebview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); - } + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + const scrollTop = this._list.scrollTop; + const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); + const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); + activeWebview.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } }); } From 71d63c7f741aa637e15d6e2189c54726e2e8236f Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 16:39:30 -0800 Subject: [PATCH 1200/1837] no transform for ITransformOutput --- .../browser/diff/notebookTextDiffEditor.ts | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index e586bde9000..a55bb3a7954 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -29,7 +29,7 @@ import { Emitter } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { NotebookDiffEditorEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { CellUri, INotebookDiffEditorModel, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellUri, INotebookDiffEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; @@ -118,7 +118,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD updateOutputHeight(cellInfo: IDiffCellInfo, output: IDisplayOutputViewModel, outputHeight: number, isInit: boolean): void { const diffElement = cellInfo.diffElement; const cell = this.getCellByInfo(cellInfo); - const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.model as ITransformedDisplayOutputDto).outputId); + const outputIndex = cell.outputsViewModels.findIndex(viewModel => viewModel.model === output.model); if (diffElement instanceof SideBySideDiffElementViewModel) { const info = CellUri.parse(cellInfo.cellUri); @@ -260,23 +260,24 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD return; } - if (cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId) < 0) { + if (cell.outputsViewModels.findIndex(viewModel => viewModel.model === key.model) < 0) { // output is already gone removedItems.push(key); + } else { + const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); + if (activeWebview.shouldUpdateInset(cell, key, cellTop)) { + // TODO: why? does it mean, we create new output view model every time? + const outputIndex = cell.outputsViewModels.findIndex(viewModel => viewModel.model === key.model); + const outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex); + + updateItems.push({ + output: key, + cellTop: cellTop, + outputOffset: outputOffset + }); + } } - const cellTop = this._list.getAbsoluteTopOfElement(value.cellInfo.diffElement); - if (activeWebview.shouldUpdateInset(cell, key, cellTop)) { - // TODO: why? does it mean, we create new output view model every time? - const outputIndex = cell.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (key.model as ITransformedDisplayOutputDto).outputId); - const outputOffset = cellTop + value.cellInfo.diffElement.getOutputOffsetInCell(diffSide, outputIndex); - - updateItems.push({ - output: key, - cellTop: cellTop, - outputOffset: outputOffset - }); - } }); removedItems.forEach(output => activeWebview.removeInset(output)); @@ -537,7 +538,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } else { const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); const scrollTop = this._list.scrollTop; - const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => (viewModel.model as ITransformedDisplayOutputDto).outputId === (output.source.model as ITransformedDisplayOutputDto).outputId); + const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => viewModel.model === output.source.model); const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); activeWebview.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]); } From d46abd43537dcc0835408316cb8704416bbbd986 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 17:41:35 -0800 Subject: [PATCH 1201/1837] avoid plain/text being rendered multiple times --- .../notebook/browser/diff/diffComponents.ts | 249 +++++++++++------- .../browser/diff/diffElementOutputs.ts | 11 + .../browser/diff/diffElementViewModel.ts | 6 +- .../browser/diff/notebookDiffEditorBrowser.ts | 1 + .../browser/diff/notebookTextDiffEditor.ts | 21 +- 5 files changed, 188 insertions(+), 100 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 30dfeb6d1ac..9bf86b83dc4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -284,63 +284,50 @@ abstract class AbstractElementRenderer extends Disposable { updateOutputRendering(renderRichOutput: boolean = true) { if (this.cell.outputFoldingState === PropertyFoldingState.Expanded) { + this._outputInfoContainer.style.display = 'block'; if (renderRichOutput) { - if (this._outputEditorContainer) { - this._hideOutputs(); - this._outputEditorContainer.style.display = 'none'; - this._outputEditorDisposeStore.clear(); - } - - this._outputInfoContainer.style.display = 'block'; - - if (!this._outputViewContainer) { - this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); - this._buildOutputContainer(); - } else { - // todo, show insets - this._showOutputs(); - // this.cell.layoutChange(); - } - - this.cell.layoutChange(); + this._hideOutputsRaw(); + this._buildOutputRendererContainer(); + this._showOutputsRenderer(); } else { - if (this._outputInfoContainer) { - this._hideOutputs(); - this._outputInfoContainer.style.display = 'none'; - this._outputEditorDisposeStore.clear(); - } - - this._outputInfoContainer.style.display = 'block'; - - if (!this._outputEditorContainer || !this._outputEditor) { - // create editor - this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); - this._buildOutputEditor(); - } else { - this._outputEditorContainer.style.display = 'block'; - this.cell.outputHeight = this._outputEditor.getContentHeight(); - } - - this.cell.layoutChange(); + this._hideOutputsRenderer(); + this._buildOutputRawContainer(); + this._showOutputsRaw(); } } else { - if (renderRichOutput) { - this._hideOutputs(); - this._outputInfoContainer.style.display = 'none'; - this._outputEditorDisposeStore.clear(); - this.cell.layoutChange(); - } else { - this._outputInfoContainer.style.display = 'none'; - this._outputEditorDisposeStore.clear(); - this.cell.layoutChange(); - } + this._outputInfoContainer.style.display = 'none'; + + this._hideOutputsRaw(); + this._hideOutputsRenderer(); + } + + this.cell.layoutChange(); + } + + private _buildOutputRawContainer() { + if (!this._outputEditorContainer) { + this._outputEditorContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-editor-container')); + this._buildOutputEditor(); } } - abstract _buildOutputContainer(): void; - abstract _hideOutputs(): void; - abstract _showOutputs(): void; + private _showOutputsRaw() { + if (this._outputEditorContainer) { + this._outputEditorContainer.style.display = 'block'; + this.cell.outputHeight = this._outputEditor!.getContentHeight(); + } + } + + private _hideOutputsRaw() { + if (this._outputEditorContainer) { + this._outputEditorContainer.style.display = 'none'; + } + } + + abstract _buildOutputRendererContainer(): void; + abstract _hideOutputsRenderer(): void; + abstract _showOutputsRenderer(): void; private _applySanitizedMetadataChanges(currentMetadata: NotebookCellMetadata, newMetadata: any) { let result: { [key: string]: any } = {}; @@ -838,19 +825,46 @@ export class DeletedElement extends SingleSideDiffElement { }); } - _buildOutputContainer() { - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputViewContainer!); - this._outputLeftView.render(); - this.cell.layoutChange(); + _buildOutputRendererContainer() { + if (!this._outputViewContainer) { + this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); + + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputViewContainer!); + this._register(this._outputLeftView); + this._outputLeftView.render(); + + const removedOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.original!.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original!.id, ['nb-cellDeleted'], []); + removedOutputRenderListener.dispose(); + } + }); + + this._register(removedOutputRenderListener); + } + + this._outputViewContainer.style.display = 'block'; } - _showOutputs() { - this._outputLeftView?.render(); - this.cell.layoutChange(); + _decorate() { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original!.id, ['nb-cellDeleted'], []); } - _hideOutputs() { - this._outputLeftView?.hideOutputs(); + _showOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'block'; + + this._outputLeftView?.showOutputs(); + this._decorate(); + } + } + + _hideOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'none'; + + this._outputLeftView?.hideOutputs(); + } } } @@ -911,19 +925,42 @@ export class InsertElement extends SingleSideDiffElement { }); } - _buildOutputContainer() { - this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputViewContainer!); - this._outputRightView.render(); - this.cell.layoutChange(); + _buildOutputRendererContainer() { + if (!this._outputViewContainer) { + this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputViewContainer!); + this._register(this._outputRightView); + this._outputRightView.render(); + + const insertOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.modified!.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified!.id, ['nb-cellAdded'], []); + insertOutputRenderListener.dispose(); + } + }); + this._register(insertOutputRenderListener); + } + + this._outputViewContainer.style.display = 'block'; } - _showOutputs() { - this._outputRightView?.render(); - this.cell.layoutChange(); + _decorate() { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified!.id, ['nb-cellAdded'], []); } - _hideOutputs() { - this._outputRightView?.hideOutputs(); + _showOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'block'; + this._outputRightView?.showOutputs(); + this._decorate(); + } + } + + _hideOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'none'; + this._outputRightView?.hideOutputs(); + } } layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { @@ -1081,38 +1118,40 @@ export class ModifiedElement extends AbstractElementRenderer { this._outputHeader.buildHeader(); } - _buildOutputContainer() { - this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left')); - this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right')); - // We should use the original text model here - this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputLeftContainer!); - this._outputLeftView.render(); - this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputRightContainer!); - this._outputRightView.render(); + _buildOutputRendererContainer() { + if (!this._outputViewContainer) { + this._outputViewContainer = DOM.append(this._outputInfoContainer, DOM.$('.output-view-container')); + this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left')); + this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right')); + // We should use the original text model here + this._outputLeftView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.original!, DiffSide.Original, this._outputLeftContainer!); + this._outputLeftView.render(); + this._register(this._outputLeftView); + this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputRightContainer!); + this._outputRightView.render(); + this._register(this._outputRightView); - const originalOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { - if (e.cell.uri.toString() === this.cell.original.uri.toString()) { - this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original.id, ['nb-cellDeleted'], []); - originalOutputRenderListener.dispose(); - } - }); + const originalOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.original.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original.id, ['nb-cellDeleted'], []); + originalOutputRenderListener.dispose(); + } + }); - const modifiedOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { - if (e.cell.uri.toString() === this.cell.modified.uri.toString()) { - this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified.id, ['nb-cellAdded'], []); - modifiedOutputRenderListener.dispose(); - } - }); + const modifiedOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => { + if (e.cell.uri.toString() === this.cell.modified.uri.toString()) { + this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified.id, ['nb-cellAdded'], []); + modifiedOutputRenderListener.dispose(); + } + }); - this._decorate(); - this.cell.layoutChange(); - } + this._register(originalOutputRenderListener); + this._register(modifiedOutputRenderListener); - _showOutputs() { - this._outputLeftView?.render(); - this._outputRightView?.render(); - this._decorate(); - this.cell.layoutChange(); + this._decorate(); + } + + this._outputViewContainer.style.display = 'block'; } _decorate() { @@ -1120,9 +1159,23 @@ export class ModifiedElement extends AbstractElementRenderer { this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Modified, this.cell.modified.id, ['nb-cellAdded'], []); } - _hideOutputs() { - this._outputLeftView?.hideOutputs(); - this._outputRightView?.hideOutputs(); + _showOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'block'; + + this._outputLeftView?.showOutputs(); + this._outputRightView?.showOutputs(); + this._decorate(); + } + } + + _hideOutputsRenderer() { + if (this._outputViewContainer) { + this._outputViewContainer.style.display = 'none'; + + this._outputLeftView?.hideOutputs(); + this._outputRightView?.hideOutputs(); + } } updateSourceEditor(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index b93b348e5c4..1d76d0473c9 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -193,6 +193,17 @@ export class OutputContainer extends Disposable { } } + showOutputs() { + for (let index = 0; index < this._outputViewModels.length; index++) { + const currOutput = this._outputViewModels[index]; + + if (currOutput.isDisplayOutput()) { + // always add to the end + this._editor.showInset(this._diffElementViewModel, currOutput.cellViewModel, currOutput, this._diffSide); + } + } + } + hideOutputs() { this._outputEntries.forEach((outputElement, cellOutputViewModel) => { if (cellOutputViewModel.isDisplayOutput()) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 116569e0ae6..7ff9fcf54f6 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -249,7 +249,11 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { } getOutputTotalHeight() { - return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); + if (this.renderOutput) { + return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); + } else { + return this._layoutInfo.outputHeight; + } } getNestedCellViewModel(diffSide: DiffSide): DiffNestedCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index 50e07189d1b..62a398904f3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -33,6 +33,7 @@ export interface INotebookTextDiffEditor extends ICommonNotebookEditor { layoutNotebookCell(cell: DiffElementViewModelBase, height: number): void; getOutputRenderer(): OutputRenderer; createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void; + showInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, displayOutput: IDisplayOutputViewModel, diffSide: DiffSide): void; hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IDisplayOutputViewModel): void; /** * Trigger the editor to scroll from scroll event programmatically diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index a55bb3a7954..28513cb0135 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -349,7 +349,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); await this._modifiedWebview.createWebview(); - this._modifiedWebview.element.style.width = `calc(50%)`; + this._modifiedWebview.element.style.width = `calc(50% - 16px)`; this._modifiedWebview.element.style.left = `calc(50%)`; } @@ -553,6 +553,25 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } + showInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, displayOutput: IDisplayOutputViewModel, diffSide: DiffSide) { + this._insetModifyQueueByOutputId.queue(displayOutput.model.outputId + (diffSide === DiffSide.Modified ? '-right' : 'left'), async () => { + const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview; + if (!activeWebview) { + return; + } + + if (!activeWebview.insetMapping.has(displayOutput)) { + return; + } + + const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel); + const scrollTop = this._list.scrollTop; + const outputIndex = cellViewModel.outputsViewModels.findIndex(viewModel => viewModel.model === displayOutput.model); + const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex); + activeWebview.updateViewScrollTop(-scrollTop, true, [{ output: displayOutput, cellTop, outputOffset }]); + }); + } + hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IDisplayOutputViewModel) { this._modifiedWebview?.hideInset(output); this._originalWebview?.hideInset(output); From 141572a2b21da35a08a7595f8ba8d1bb341ccd80 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 17:53:19 -0800 Subject: [PATCH 1202/1837] render outputs in text by default. --- .../contrib/notebook/browser/diff/diffComponents.ts | 12 ++++++------ .../notebook/browser/diff/diffElementViewModel.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 9bf86b83dc4..70a3a290eb5 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -83,7 +83,7 @@ class PropertyHeader extends Disposable { readonly propertyHeaderContainer: HTMLElement, readonly notebookEditor: INotebookTextDiffEditor, readonly accessor: { - updateInfoRendering: () => void; + updateInfoRendering: (renderOutput: boolean) => void; checkIfModified: (cell: DiffElementViewModelBase) => boolean; getFoldingState: (cell: DiffElementViewModelBase) => PropertyFoldingState; updateFoldingState: (cell: DiffElementViewModelBase, newState: PropertyFoldingState) => void; @@ -172,7 +172,7 @@ class PropertyHeader extends Disposable { const oldFoldingState = this.accessor.getFoldingState(this.cell); this.accessor.updateFoldingState(this.cell, oldFoldingState === PropertyFoldingState.Expanded ? PropertyFoldingState.Collapsed : PropertyFoldingState.Expanded); this._updateFoldingIcon(); - this.accessor.updateInfoRendering(); + this.accessor.updateInfoRendering(this.cell.renderOutput); } } @@ -180,7 +180,7 @@ class PropertyHeader extends Disposable { })); this._updateFoldingIcon(); - this.accessor.updateInfoRendering(); + this.accessor.updateInfoRendering(this.cell.renderOutput); } refresh() { @@ -282,7 +282,7 @@ abstract class AbstractElementRenderer extends Disposable { } } - updateOutputRendering(renderRichOutput: boolean = true) { + updateOutputRendering(renderRichOutput: boolean) { if (this.cell.outputFoldingState === PropertyFoldingState.Expanded) { this._outputInfoContainer.style.display = 'block'; if (renderRichOutput) { @@ -566,7 +566,7 @@ abstract class AbstractElementRenderer extends Disposable { this._outputEditor = this.instantiationService.createInstance(CodeEditorWidget, this._outputEditorContainer!, { ...fixedEditorOptions, dimension: { - width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), + width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, this.cell.type === 'unchanged' || this.cell.type === 'modified'), height: 0 }, overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode() @@ -981,7 +981,7 @@ export class InsertElement extends SingleSideDiffElement { if (state.outputEditor || state.outerWidth) { this._outputEditor?.layout({ - width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), + width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), height: this.cell.outputHeight }); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 7ff9fcf54f6..1b1fe014d41 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -91,7 +91,7 @@ export abstract class DiffElementViewModelBase extends Disposable { return this._layoutInfo.metadataHeight; } - private _renderOutput = true; + private _renderOutput = false; set renderOutput(value: boolean) { this._renderOutput = value; @@ -337,7 +337,11 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { } getOutputTotalHeight() { - return this.cellViewModel?.getOutputTotalHeight() ?? 0; + if (this.renderOutput) { + return this.cellViewModel?.getOutputTotalHeight() ?? 0; + } else { + return this._layoutInfo.outputHeight; + } } getCellByUri(cellUri: URI): IGenericCellViewModel { From 5e865477065e9cc361f14784722ef2419dcd5b90 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 17 Dec 2020 19:56:06 -0800 Subject: [PATCH 1203/1837] only show render style switcher when the property is expanded --- .../notebook/browser/diff/diffComponents.ts | 34 ++++++++++++++----- .../browser/diff/notebookDiffActions.ts | 27 ++++++++++----- .../browser/diff/notebookDiffEditorBrowser.ts | 3 ++ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 70a3a290eb5..022b28ded62 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -8,7 +8,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DiffElementViewModelBase, getFormatedMetadataJSON, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; -import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -24,7 +24,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Delayer } from 'vs/base/common/async'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -77,6 +77,7 @@ class PropertyHeader extends Disposable { protected _statusSpan!: HTMLElement; protected _toolbar!: ToolBar; protected _menu!: IMenu; + protected _propertyExpanded?: IContextKey; constructor( readonly cell: DiffElementViewModelBase, @@ -133,14 +134,23 @@ class PropertyHeader extends Disposable { cell: this.cell }; - this._menu = this.menuService.createMenu(this.accessor.menuId, this.contextKeyService); + const scopedContextKeyService = this.contextKeyService.createScoped(cellToolbarContainer); + const propertyChanged = NOTEBOOK_DIFF_CELL_PROPERTY.bindTo(scopedContextKeyService); + propertyChanged.set(metadataChanged); + this._propertyExpanded = NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED.bindTo(scopedContextKeyService); + + this._menu = this.menuService.createMenu(this.accessor.menuId, scopedContextKeyService); this._register(this._menu); - if (metadataChanged) { + const actions: IAction[] = []; + createAndFillInActionBarActions(this._menu, { shouldForwardArgs: true }, actions); + this._toolbar.setActions(actions); + + this._register(this._menu.onDidChange(() => { const actions: IAction[] = []; createAndFillInActionBarActions(this._menu, { shouldForwardArgs: true }, actions); this._toolbar.setActions(actions); - } + })); this._register(this.notebookEditor.onMouseUp(e => { if (!e.event.target) { @@ -202,9 +212,12 @@ class PropertyHeader extends Disposable { private _updateFoldingIcon() { if (this.accessor.getFoldingState(this.cell) === PropertyFoldingState.Collapsed) { DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(collapsedIcon))); + this._propertyExpanded?.set(false); } else { DOM.reset(this._foldingIndicator, ...renderCodicons(ThemeIcon.asCodiconLabel(expandedIcon))); + this._propertyExpanded?.set(true); } + } } @@ -258,6 +271,10 @@ abstract class AbstractElementRenderer extends Disposable { this._register(cell.onDidLayoutChange(e => this.layout(e))); this._register(cell.onDidLayoutChange(e => this.updateBorders())); this.buildBody(); + + this._register(cell.onDidStateChange(() => { + this.updateOutputRendering(this.cell.renderOutput); + })); } abstract buildBody(): void; @@ -758,6 +775,7 @@ export class DeletedElement extends SingleSideDiffElement { } styleContainer(container: HTMLElement) { + container.classList.remove('inserted'); container.classList.add('removed'); } @@ -887,6 +905,7 @@ export class InsertElement extends SingleSideDiffElement { } styleContainer(container: HTMLElement): void { + container.classList.remove('removed'); container.classList.add('inserted'); } @@ -1016,13 +1035,10 @@ export class ModifiedElement extends AbstractElementRenderer { @IContextKeyService protected readonly contextKeyService: IContextKeyService ) { super(notebookEditor, cell, templateData, 'full', instantiationService, modeService, modelService, contextMenuService, keybindingService, notificationService, menuService, contextKeyService); - - this._register(cell.onDidStateChange(() => { - this.updateOutputRendering(this.cell.renderOutput); - })); } styleContainer(container: HTMLElement): void { + container.classList.remove('inserted', 'removed'); } buildBody() { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index 5b3d84c23b8..0bd867fa6aa 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -9,6 +9,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ActiveEditorContext, viewColumnToEditorGroup } from 'vs/workbench/common/editor'; import { DiffElementViewModelBase } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; +import { NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; import { openAsTextIcon, revertIcon, showOutputRawIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; @@ -60,8 +61,10 @@ registerAction2(class extends Action2 { icon: revertIcon, f1: false, menu: { - id: MenuId.NotebookDiffCellMetadataTitle - } + id: MenuId.NotebookDiffCellMetadataTitle, + when: NOTEBOOK_DIFF_CELL_PROPERTY + }, + precondition: NOTEBOOK_DIFF_CELL_PROPERTY } ); } @@ -110,12 +113,13 @@ registerAction2(class extends Action2 { super( { id: 'notebook.diff.cell.switchOutputRenderingStyleToText', - title: localize('notebook.diff.cell.switchOutputRenderingStyleToText', "View outputs raw data"), + title: localize('notebook.diff.cell.switchOutputRenderingStyleToText', "Switch Output Rendering"), icon: showOutputRawIcon, f1: false, menu: { - id: MenuId.NotebookDiffCellOutputsTitle - }, + id: MenuId.NotebookDiffCellOutputsTitle, + when: NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED + } } ); } @@ -137,8 +141,10 @@ registerAction2(class extends Action2 { icon: revertIcon, f1: false, menu: { - id: MenuId.NotebookDiffCellOutputsTitle - } + id: MenuId.NotebookDiffCellOutputsTitle, + when: NOTEBOOK_DIFF_CELL_PROPERTY + }, + precondition: NOTEBOOK_DIFF_CELL_PROPERTY } ); } @@ -168,8 +174,11 @@ registerAction2(class extends Action2 { icon: revertIcon, f1: false, menu: { - id: MenuId.NotebookDiffCellInputTitle - } + id: MenuId.NotebookDiffCellInputTitle, + when: NOTEBOOK_DIFF_CELL_PROPERTY + }, + precondition: NOTEBOOK_DIFF_CELL_PROPERTY + } ); } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index 62a398904f3..f5b2de9e665 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -14,6 +14,7 @@ import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; +import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export enum DiffSide { Original = 0, @@ -97,3 +98,5 @@ export interface CellDiffViewModelLayoutChangeEvent { } export const DIFF_CELL_MARGIN = 16; +export const NOTEBOOK_DIFF_CELL_PROPERTY = new RawContextKey('notebookDiffCellPropertyChanged', false); +export const NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED = new RawContextKey('notebookDiffCellPropertyExpanded', false); From 7f1af9efb1f39143f56a8ce85f1ee330f14b2d2c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 17 Dec 2020 18:00:54 +0100 Subject: [PATCH 1204/1837] remove more unused code --- .../browser/parts/editor/breadcrumbsPicker.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts index a1aaf248f4b..3c91f49ba07 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts @@ -186,8 +186,6 @@ class FileIdentityProvider implements IIdentityProvider { - private readonly _parents = new WeakMap(); - constructor( @IFileService private readonly _fileService: IFileService, ) { } @@ -200,13 +198,8 @@ class FileDataSource implements IAsyncDataSource { - if (IWorkspace.isIWorkspace(element)) { - const folders = element.folders; - for (let child of folders) { - this._parents.set(element, child); - } - return folders; + return element.folders; } let uri: URI; if (IWorkspaceFolder.isIWorkspaceFolder(element)) { @@ -217,10 +210,7 @@ class FileDataSource implements IAsyncDataSource Date: Fri, 18 Dec 2020 08:56:17 +0100 Subject: [PATCH 1205/1837] Fixes #112391: (Re)layout the hover widget after adding async content --- src/vs/editor/contrib/hover/modesContentHover.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 57f95fe179f..23d5256dcbc 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -616,6 +616,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { actions.dispose(); quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available"); + this._editor.layoutContentWidget(this); return; } quickfixPlaceholderElement.style.display = 'none'; @@ -643,6 +644,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { }); } })); + this._editor.layoutContentWidget(this); }); } From 98166ea0b190351aa7902b2d3dd9f35b7aadaeb6 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 18 Dec 2020 00:10:42 -0800 Subject: [PATCH 1206/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd32e3eb5f3..aea8429065e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "d60e5fce8e04f63a47a67e1cd197af8c8ea326e8", + "distro": "c89ced323fffc6ffd5caa6e9bb6662b8e26b5fb4", "author": { "name": "Microsoft Corporation" }, From 2c83509a15464bc41dcd20bbf4def3e90efaeea2 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 09:25:35 +0100 Subject: [PATCH 1207/1837] Fixes #112666: Recompute minimap options (which hold the background color) when the tokens color change --- src/vs/editor/browser/viewParts/minimap/minimap.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 7ca33211a3c..348315fa9a8 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -862,6 +862,7 @@ export class Minimap extends ViewPart implements IMinimapModel { } } public onTokensColorsChanged(e: viewEvents.ViewTokensColorsChangedEvent): boolean { + this._onOptionsMaybeChanged(); return this._actual.onTokensColorsChanged(); } public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean { From 2dd359c71535aec34d1b4ba23f1b0e3bec844e8e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 09:39:10 +0100 Subject: [PATCH 1208/1837] Use the root typings for keytar since we are loading the root node module (#112718) --- extensions/github-authentication/package.json | 1 - extensions/github-authentication/yarn.lock | 448 +----------------- .../microsoft-authentication/package.json | 1 - extensions/microsoft-authentication/yarn.lock | 422 +---------------- 4 files changed, 4 insertions(+), 868 deletions(-) diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index b7626df85f8..d8a20545c43 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -58,7 +58,6 @@ "vscode-nls": "^4.1.2" }, "devDependencies": { - "@types/keytar": "^4.4.2", "@types/node": "^10.12.21", "@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 e808558aeb3..5f2c8bd9e8f 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -2,13 +2,6 @@ # yarn lockfile v1 -"@types/keytar@^4.4.2": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@types/keytar/-/keytar-4.4.2.tgz#49ef917d6cbb4f19241c0ab50cd35097b5729b32" - integrity sha512-xtQcDj9ruGnMwvSu1E2BH4SFa5Dv2PvSPd0CKEBLN5hEj/v5YpXJY+B6hAfuKIbvEomD7vJTc/P1s1xPNh2kRw== - dependencies: - keytar "*" - "@types/node-fetch@2.5.7": version "2.5.7" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" @@ -32,16 +25,6 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0" integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw== -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -51,56 +34,11 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -bl@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" - integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -buffer@^5.5.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" - integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -108,43 +46,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -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== - dependencies: - mimic-response "^2.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "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= - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -157,18 +63,6 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - form-data@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" @@ -178,75 +72,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -keytar@*: - version "6.0.1" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-6.0.1.tgz#996961abdebf300b2d34bb2eab6e42a8096b1ed8" - integrity sha512-1Ihpf2tdM3sLwGMkYHXYhVC/hx5BDR7CWFL4IrBA3IDZo0xHhS2nM+tU9Y+u/U7okNfbVkwmKsieLkcWRMh93g== - dependencies: - node-addon-api "^3.0.0" - prebuild-install "5.3.4" - mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -259,270 +84,16 @@ mime-types@^2.1.12: dependencies: mime-db "1.44.0" -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== - -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - -mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -napi-build-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" - integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== - -node-abi@^2.7.0: - version "2.19.1" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.1.tgz#6aa32561d0a5e2fdb6810d8c25641b657a8cea85" - integrity sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A== - dependencies: - semver "^5.4.1" - -node-addon-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247" - integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg== - node-fetch@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -prebuild-install@5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.4.tgz#6982d10084269d364c1856550b7d090ea31fa293" - integrity sha512-AkKN+pf4fSEihjapLEEj8n85YIw/tN6BQqkhzbDc0RvEZGdkpJBGMUYx66AAMcPG2KzmPQS7Cm16an4HVBRRMA== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp "^0.5.1" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -safe-buffer@^5.0.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -semver@^5.3.0, semver@^5.4.1: +semver@^5.3.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -simple-concat@^1.0.0: - version "1.0.1" - 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.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -tar-fs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5" - integrity sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^2.0.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa" - integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - uuid@8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" @@ -540,23 +111,6 @@ vscode-nls@^4.1.2: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 061a222fd3e..f3eafae72e9 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -38,7 +38,6 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "devDependencies": { - "@types/keytar": "^4.0.1", "@types/node": "^10.12.21", "@types/node-fetch": "^2.5.7", "@types/randombytes": "^2.0.0", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index 75893ec149b..48477e958b1 100644 --- a/extensions/microsoft-authentication/yarn.lock +++ b/extensions/microsoft-authentication/yarn.lock @@ -2,13 +2,6 @@ # yarn lockfile v1 -"@types/keytar@^4.0.1": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@types/keytar/-/keytar-4.4.2.tgz#49ef917d6cbb4f19241c0ab50cd35097b5729b32" - integrity sha512-xtQcDj9ruGnMwvSu1E2BH4SFa5Dv2PvSPd0CKEBLN5hEj/v5YpXJY+B6hAfuKIbvEomD7vJTc/P1s1xPNh2kRw== - dependencies: - keytar "*" - "@types/node-fetch@^2.5.7": version "2.5.7" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" @@ -46,16 +39,6 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0" integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw== -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -65,19 +48,6 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -88,13 +58,6 @@ base64-js@^1.0.2: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== -bl@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88" - integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A== - dependencies: - readable-stream "^3.0.1" - buffer@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -103,16 +66,6 @@ buffer@^5.6.0: base64-js "^1.0.2" ieee754 "^1.1.4" -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -120,43 +73,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -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== - dependencies: - mimic-response "^2.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "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= - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -174,18 +95,6 @@ emitter-component@^1.1.1: resolved "https://registry.yarnpkg.com/emitter-component/-/emitter-component-1.1.1.tgz#065e2dbed6959bf470679edabeaf7981d1003ab6" integrity sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY= -end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - form-data@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" @@ -195,75 +104,16 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -keytar@*: - version "5.0.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.0.0.tgz#c89b6b7a4608fd7af633d9f8474b1a7eb97cbe6f" - integrity sha512-a5UheK59YOlJf9i+2Osaj/kkH6mK0RCHVMtJ84u6ZfbfRIbOJ/H4b5VlOF/LgNHF6s78dRSBzZnvIuPiBKv6wg== - dependencies: - nan "2.14.0" - prebuild-install "5.3.3" - mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -276,155 +126,18 @@ mime-types@^2.1.12: dependencies: mime-db "1.44.0" -mimic-response@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" - integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -nan@2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -napi-build-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" - integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== - -node-abi@^2.7.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63" - integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA== - dependencies: - semver "^5.4.1" - node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -prebuild-install@5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" - integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.0" - mkdirp "^0.5.1" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - "randombytes@github:rmacfarlane/randombytes#b28d4ecee46262801ea09f15fa1f1513a05c5971": version "2.1.0" resolved "https://codeload.github.com/rmacfarlane/randombytes/tar.gz/b28d4ecee46262801ea09f15fa1f1513a05c5971" dependencies: safe-buffer "^5.1.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.1, readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -434,21 +147,11 @@ safe-buffer@^5.1.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -semver@^5.3.0, semver@^5.4.1: +semver@^5.3.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - sha.js@2.4.11: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -457,25 +160,6 @@ sha.js@2.4.11: inherits "^2.0.1" safe-buffer "^5.0.1" -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= - -simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - stream@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stream/-/stream-0.0.2.tgz#7f5363f057f6592c5595f00bc80a27f5cec1f0ef" @@ -483,89 +167,6 @@ stream@0.0.2: dependencies: emitter-component "^1.1.1" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -tar-fs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" - integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== - dependencies: - chownr "^1.1.1" - mkdirp "^0.5.1" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" - integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== - dependencies: - bl "^3.0.0" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - uuid@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e" @@ -583,23 +184,6 @@ vscode-nls@^4.1.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" From 63d49f6a135fcc1c8cc909f80402e61087ce8509 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 18 Dec 2020 10:03:18 +0100 Subject: [PATCH 1209/1837] don't disable the current remote resolve when bisect'ing extensions, fixes https://github.com/microsoft/vscode/issues/112473 --- .../browser/extensionBisect.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts index a344e1a5678..b60cd526762 100644 --- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts @@ -21,6 +21,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; // --- bisect service @@ -73,6 +74,7 @@ class ExtensionBisectService implements IExtensionBisectService { constructor( @ILogService logService: ILogService, @IStorageService private readonly _storageService: IStorageService, + @IWorkbenchEnvironmentService private readonly _envService: IWorkbenchEnvironmentService ) { const raw = _storageService.get(ExtensionBisectService._storageKey, StorageScope.GLOBAL); this._state = BisectState.fromJSON(raw); @@ -97,12 +99,26 @@ class ExtensionBisectService implements IExtensionBisectService { isDisabledByBisect(extension: IExtension): boolean { if (!this._state) { + // bisect isn't active + return false; + } + if (this._isRemoteResolver(extension)) { + // the current remote resolver extension cannot be disabled return false; } const disabled = this._disabled.get(extension.identifier.id); return disabled ?? false; } + private _isRemoteResolver(extension: IExtension): boolean { + if (extension.manifest.enableProposedApi !== true) { + return false; + } + const idx = this._envService.remoteAuthority?.indexOf('+'); + const activationEvent = `onResolveRemoteAuthority:${this._envService.remoteAuthority?.substr(0, idx)}`; + return Boolean(extension.manifest.activationEvents?.find(e => e === activationEvent)); + } + async start(extensions: ILocalExtension[]): Promise { if (this._state) { throw new Error('invalid state'); From 1324dcf085c7dcda82657ac5cfefbae40791be7e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Dec 2020 10:20:29 +0100 Subject: [PATCH 1210/1837] fix #110982 --- .../electron-browser/desktop.main.ts | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index 19678d72168..93dcb0f386e 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -6,7 +6,7 @@ import * as fs from 'fs'; import * as gracefulFs from 'graceful-fs'; import { createHash } from 'crypto'; -import { stat } from 'vs/base/node/pfs'; +import { exists, stat } from 'vs/base/node/pfs'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows'; import { mark } from 'vs/base/common/performance'; @@ -21,7 +21,7 @@ import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INativeWorkbenchConfiguration, INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { ISingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { ISingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, reviveWorkspaceIdentifier, IWorkspaceIdentifier, IMultiFolderWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces'; import { ILogService } from 'vs/platform/log/common/log'; import { NativeStorageService } from 'vs/platform/storage/node/storageService'; import { Schemas } from 'vs/base/common/network'; @@ -280,7 +280,7 @@ class DesktopMain extends Disposable { return service; }), - this.createKeyboardLayoutService(logService, mainProcessService).then(service => { + this.createKeyboardLayoutService(mainProcessService).then(service => { // KeyboardLayout serviceCollection.set(IKeyboardLayoutService, service); @@ -307,15 +307,15 @@ class DesktopMain extends Disposable { } private async resolveWorkspaceInitializationPayload(): Promise { + let workspaceInitializationPayload: IWorkspaceInitializationPayload | undefined; // Multi-root workspace if (this.configuration.workspace) { - return this.configuration.workspace; + workspaceInitializationPayload = await this.resolveMultiFolderWorkspaceInitializationPayload(this.configuration.workspace); } // Single-folder workspace - let workspaceInitializationPayload: IWorkspaceInitializationPayload | undefined; - if (this.configuration.folderUri) { + else if (this.configuration.folderUri) { workspaceInitializationPayload = await this.resolveSingleFolderWorkspaceInitializationPayload(this.configuration.folderUri); } @@ -336,6 +336,18 @@ class DesktopMain extends Disposable { return workspaceInitializationPayload; } + private async resolveMultiFolderWorkspaceInitializationPayload(workspace: IWorkspaceIdentifier): Promise { + + // It is possible that the workspace file does not exist + // on disk anymore, so we return `undefined` in that case + // (https://github.com/microsoft/vscode/issues/110982) + if (workspace.configPath.scheme === Schemas.file && !await exists(workspace.configPath.fsPath)) { + return undefined; + } + + return workspace; + } + private async resolveSingleFolderWorkspaceInitializationPayload(folderUri: ISingleFolderWorkspaceIdentifier): Promise { try { const folder = folderUri.scheme === Schemas.file @@ -388,7 +400,6 @@ class DesktopMain extends Disposable { return workspaceService; } catch (error) { onUnexpectedError(error); - logService.error(error); return workspaceService; } @@ -404,13 +415,12 @@ class DesktopMain extends Disposable { return storageService; } catch (error) { onUnexpectedError(error); - logService.error(error); return storageService; } } - private async createKeyboardLayoutService(logService: ILogService, mainProcessService: IMainProcessService): Promise { + private async createKeyboardLayoutService(mainProcessService: IMainProcessService): Promise { const keyboardLayoutService = new KeyboardLayoutService(mainProcessService); try { @@ -419,7 +429,6 @@ class DesktopMain extends Disposable { return keyboardLayoutService; } catch (error) { onUnexpectedError(error); - logService.error(error); return keyboardLayoutService; } From 13ea3e08a1e1d216618100d6b13fa2f1bb69887c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 18 Dec 2020 19:22:10 +1000 Subject: [PATCH 1211/1837] Fix hover widget. --- src/vs/editor/contrib/hover/modesContentHover.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 57f95fe179f..1e443d58de1 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Color, RGBA } from 'vs/base/common/color'; import { IMarkdownString, MarkdownString, isEmptyMarkdownString, markedStringsEquals } from 'vs/base/common/htmlContent'; -import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; @@ -31,7 +31,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener'; import { MarkerController, NextMarkerAction } from 'vs/editor/contrib/gotoError/gotoError'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { CancelablePromise, createCancelablePromise, disposableTimeout } from 'vs/base/common/async'; +import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction'; import { QuickFixAction, QuickFixController } from 'vs/editor/contrib/codeAction/codeActionCommands'; import { CodeActionKind, CodeActionTrigger } from 'vs/editor/contrib/codeAction/types'; @@ -606,11 +606,12 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this.recentMarkerCodeActionsInfo = undefined; } } - const updatePlaceholderDisposable = this.recentMarkerCodeActionsInfo && !this.recentMarkerCodeActionsInfo.hasCodeActions ? Disposable.None : disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 200)); + if (!quickfixPlaceholderElement.textContent) { + quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."); + } const codeActionsPromise = this.getCodeActions(markerHover.marker); disposables.add(toDisposable(() => codeActionsPromise.cancel())); codeActionsPromise.then(actions => { - updatePlaceholderDisposable.dispose(); this.recentMarkerCodeActionsInfo = { marker: markerHover.marker, hasCodeActions: actions.validActions.length > 0 }; if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { From 1141224b80fed13b1b42614dbe72e71fc5d1b941 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 10:13:38 +0100 Subject: [PATCH 1212/1837] Remove debug console log --- build/npm/postinstall.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 88d10e2f2ff..8ec98a72693 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -39,8 +39,6 @@ if (!(process.platform === 'win32' && (process.arch === 'arm64' || process.env[' if (process.env['VSCODE_REMOTE_CXX']) { env['CXX'] = process.env['VSCODE_REMOTE_CXX']; } if (process.env['VSCODE_REMOTE_NODE_GYP']) { env['npm_config_node_gyp'] = process.env['VSCODE_REMOTE_NODE_GYP']; } - console.log('remote yarn install env', JSON.stringify(env, undefined, ' ')); - yarnInstall('remote', { env }); // node modules used by vscode server yarnInstall('remote/web'); // node modules used by vscode web } From 90f9a7de88536309ae179d41612879f44493b60d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 10:14:08 +0100 Subject: [PATCH 1213/1837] Execute `yarn --ignore-engines` for extensions --- build/npm/postinstall.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 8ec98a72693..6a4d7a9f717 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -21,6 +21,10 @@ function yarnInstall(location, opts) { const argv = JSON.parse(raw); const original = argv.original || []; const args = original.filter(arg => arg === '--ignore-optional' || arg === '--frozen-lockfile'); + if (opts.ignoreEngines) { + args.push('--ignore-engines'); + delete opts.ignoreEngines; + } console.log(`Installing dependencies in ${location}...`); console.log(`$ yarn ${args.join(' ')}`); @@ -53,7 +57,7 @@ const extensions = allExtensionFolders.filter(e => { } }); -extensions.forEach(extension => yarnInstall(`extensions/${extension}`)); +extensions.forEach(extension => yarnInstall(`extensions/${extension}`, { ignoreEngines: true })); function yarnInstallBuildDependencies() { // make sure we install the deps of build/lib/watch for the system installed From aa2864d53f7fd0a68ce6787fd2d3c1d3ecb329da Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 10:25:58 +0100 Subject: [PATCH 1214/1837] Remove most of the `yarn` license warnings --- extensions/debug-server-ready/package.json | 1 + extensions/git-ui/package.json | 1 + extensions/github-authentication/package.json | 1 + extensions/github/package.json | 1 + extensions/microsoft-authentication/package.json | 1 + extensions/package.json | 1 + extensions/vscode-test-resolver/package.json | 1 + test/integration/browser/package.json | 1 + test/smoke/package.json | 1 + 9 files changed, 9 insertions(+) diff --git a/extensions/debug-server-ready/package.json b/extensions/debug-server-ready/package.json index 1116990646f..fc485044807 100644 --- a/extensions/debug-server-ready/package.json +++ b/extensions/debug-server-ready/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "^1.32.0" }, diff --git a/extensions/git-ui/package.json b/extensions/git-ui/package.json index b08942888ea..2aa9add1c75 100644 --- a/extensions/git-ui/package.json +++ b/extensions/git-ui/package.json @@ -3,6 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "vscode", + "license": "MIT", "version": "1.0.0", "engines": { "vscode": "^1.5.0" diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index b7626df85f8..bc520a1d551 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -3,6 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "vscode", + "license": "MIT", "version": "0.0.1", "engines": { "vscode": "^1.41.0" diff --git a/extensions/github/package.json b/extensions/github/package.json index 464453d3992..74030783f4e 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -3,6 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "vscode", + "license": "MIT", "version": "0.0.1", "engines": { "vscode": "^1.41.0" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 061a222fd3e..4127bd269ad 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -1,6 +1,7 @@ { "name": "microsoft-authentication", "publisher": "vscode", + "license": "MIT", "displayName": "%displayName%", "description": "%description%", "version": "0.0.1", diff --git a/extensions/package.json b/extensions/package.json index 7abc2e1e6b8..7a3c2e9a2db 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -1,6 +1,7 @@ { "name": "vscode-extensions", "version": "0.0.1", + "license": "MIT", "description": "Dependencies shared by all extensions", "dependencies": { "typescript": "4.1.2" diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index 47f4eb56156..0a112f12a91 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -3,6 +3,7 @@ "description": "Test resolver for VS Code", "version": "0.0.1", "publisher": "vscode", + "license": "MIT", "enableProposedApi": true, "private": true, "engines": { diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json index f71102e23d5..39c4603f80b 100644 --- a/test/integration/browser/package.json +++ b/test/integration/browser/package.json @@ -1,6 +1,7 @@ { "name": "code-oss-dev-integration-test", "version": "0.1.0", + "license": "MIT", "main": "./index.js", "scripts": { "postinstall": "tsc", diff --git a/test/smoke/package.json b/test/smoke/package.json index 5c85b5f15d2..2d1ebf915de 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -1,6 +1,7 @@ { "name": "code-oss-dev-smoke-test", "version": "0.1.0", + "license": "MIT", "main": "./src/main.js", "scripts": { "postinstall": "npm run compile", From d6a6b44a13056b65caa392c33336f97d3b567d89 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 10:30:15 +0100 Subject: [PATCH 1215/1837] Remove all `yarn` warnings --- remote/package.json | 1 + remote/web/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/remote/package.json b/remote/package.json index 57710a189ba..39263d21528 100644 --- a/remote/package.json +++ b/remote/package.json @@ -1,6 +1,7 @@ { "name": "vscode-reh", "version": "0.0.0", + "private": true, "dependencies": { "applicationinsights": "1.0.8", "chokidar": "3.4.3", diff --git a/remote/web/package.json b/remote/web/package.json index 09ecb81a3da..35b2bd96500 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -1,6 +1,7 @@ { "name": "vscode-web", "version": "0.0.0", + "private": true, "dependencies": { "iconv-lite-umd": "0.6.8", "jschardet": "2.2.1", From daad75c2c6b003bfcd4304044b5551c7c9bf641e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 18 Dec 2020 10:31:24 +0100 Subject: [PATCH 1216/1837] [css] update to vscode-uri@3.0 --- .../client/src/customData.ts | 6 +- .../client/src/node/nodeFs.ts | 4 +- .../client/src/requests.ts | 58 -------------- extensions/css-language-features/package.json | 3 +- .../css-language-features/server/package.json | 4 +- .../server/src/node/nodeFs.ts | 4 +- .../server/src/requests.ts | 76 +------------------ .../server/src/test/requests.test.ts | 62 --------------- .../server/src/utils/documentContext.ts | 4 +- .../server/test/index.js | 2 +- .../css-language-features/server/yarn.lock | 18 ++--- extensions/css-language-features/yarn.lock | 5 ++ 12 files changed, 29 insertions(+), 217 deletions(-) delete mode 100644 extensions/css-language-features/server/src/test/requests.test.ts diff --git a/extensions/css-language-features/client/src/customData.ts b/extensions/css-language-features/client/src/customData.ts index 24b56f12b06..bab5cc407e9 100644 --- a/extensions/css-language-features/client/src/customData.ts +++ b/extensions/css-language-features/client/src/customData.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { workspace, extensions, Uri, EventEmitter, Disposable } from 'vscode'; -import { resolvePath, joinPath } from './requests'; +import { Utils } from 'vscode-uri'; export function getCustomDataSource(toDispose: Disposable[]) { let pathsInWorkspace = getCustomDataPathsInAllWorkspaces(); @@ -50,7 +50,7 @@ function getCustomDataPathsInAllWorkspaces(): string[] { if (Array.isArray(paths)) { for (const path of paths) { if (typeof path === 'string') { - dataPaths.push(resolvePath(rootFolder, path).toString()); + dataPaths.push(Utils.resolvePath(rootFolder, path).toString()); } } } @@ -80,7 +80,7 @@ function getCustomDataPathsFromAllExtensions(): string[] { const customData = extension.packageJSON?.contributes?.css?.customData; if (Array.isArray(customData)) { for (const rp of customData) { - dataPaths.push(joinPath(extension.extensionUri, rp).toString()); + dataPaths.push(Utils.joinPath(extension.extensionUri, rp).toString()); } } } diff --git a/extensions/css-language-features/client/src/node/nodeFs.ts b/extensions/css-language-features/client/src/node/nodeFs.ts index c13ef2e1c08..0b572018884 100644 --- a/extensions/css-language-features/client/src/node/nodeFs.ts +++ b/extensions/css-language-features/client/src/node/nodeFs.ts @@ -5,11 +5,11 @@ import * as fs from 'fs'; import { Uri } from 'vscode'; -import { getScheme, RequestService, FileType } from '../requests'; +import { RequestService, FileType } from '../requests'; export function getNodeFSRequestService(): RequestService { function ensureFileUri(location: string) { - if (getScheme(location) !== 'file') { + if (!location.startsWith('file://')) { throw new Error('fileRequestService can only handle file URLs'); } } diff --git a/extensions/css-language-features/client/src/requests.ts b/extensions/css-language-features/client/src/requests.ts index 47378dc43db..f06ce978c64 100644 --- a/extensions/css-language-features/client/src/requests.ts +++ b/extensions/css-language-features/client/src/requests.ts @@ -88,61 +88,3 @@ export interface RequestService { stat(uri: string): Promise; readDirectory(uri: string): Promise<[string, FileType][]>; } - -export function getScheme(uri: string) { - return uri.substr(0, uri.indexOf(':')); -} - -export function dirname(uri: string) { - const lastIndexOfSlash = uri.lastIndexOf('/'); - return lastIndexOfSlash !== -1 ? uri.substr(0, lastIndexOfSlash) : ''; -} - -export function basename(uri: string) { - const lastIndexOfSlash = uri.lastIndexOf('/'); - return uri.substr(lastIndexOfSlash + 1); -} - -const Slash = '/'.charCodeAt(0); -const Dot = '.'.charCodeAt(0); - -export function isAbsolutePath(path: string) { - return path.charCodeAt(0) === Slash; -} - -export function resolvePath(uri: Uri, path: string): Uri { - if (isAbsolutePath(path)) { - return uri.with({ path: normalizePath(path.split('/')) }); - } - return joinPath(uri, path); -} - -export function normalizePath(parts: string[]): string { - const newParts: string[] = []; - for (const part of parts) { - if (part.length === 0 || part.length === 1 && part.charCodeAt(0) === Dot) { - // ignore - } else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) { - newParts.pop(); - } else { - newParts.push(part); - } - } - if (parts.length > 1 && parts[parts.length - 1].length === 0) { - newParts.push(''); - } - let res = newParts.join('/'); - if (parts[0].length === 0) { - res = '/' + res; - } - return res; -} - - -export function joinPath(uri: Uri, ...paths: string[]): Uri { - const parts = uri.path.split('/'); - for (let path of paths) { - parts.push(...path.split('/')); - } - return uri.with({ path: normalizePath(parts) }); -} diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index ed612c632ab..66adf1fb259 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -808,7 +808,8 @@ }, "dependencies": { "vscode-languageclient": "^7.0.0", - "vscode-nls": "^4.1.2" + "vscode-nls": "^4.1.2", + "vscode-uri": "^3.0.0" }, "devDependencies": { "@types/node": "^12.11.7" diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 0bf2e76903c..f32400be34c 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -10,9 +10,9 @@ "main": "./out/node/cssServerMain", "browser": "./dist/browser/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^5.0.0", + "vscode-css-languageservice": "^5.0.1", "vscode-languageserver": "^7.0.0", - "vscode-uri": "^2.1.2" + "vscode-uri": "^3.0.0" }, "devDependencies": { "@types/mocha": "7.0.2", diff --git a/extensions/css-language-features/server/src/node/nodeFs.ts b/extensions/css-language-features/server/src/node/nodeFs.ts index c7b1301296d..c72617e3af1 100644 --- a/extensions/css-language-features/server/src/node/nodeFs.ts +++ b/extensions/css-language-features/server/src/node/nodeFs.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RequestService, getScheme } from '../requests'; +import { RequestService } from '../requests'; import { URI as Uri } from 'vscode-uri'; import * as fs from 'fs'; @@ -11,7 +11,7 @@ import { FileType } from 'vscode-css-languageservice'; export function getNodeFSRequestService(): RequestService { function ensureFileUri(location: string) { - if (getScheme(location) !== 'file') { + if (!location.startsWith('file://')) { throw new Error('fileRequestService can only handle file URLs'); } } diff --git a/extensions/css-language-features/server/src/requests.ts b/extensions/css-language-features/server/src/requests.ts index 4b91fbd2a41..8ace0b0c899 100644 --- a/extensions/css-language-features/server/src/requests.ts +++ b/extensions/css-language-features/server/src/requests.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { URI } from 'vscode-uri'; import { RequestType, Connection } from 'vscode-languageserver'; import { RuntimeEnvironment } from './cssServer'; @@ -99,79 +98,6 @@ export function getRequestService(handledSchemas: string[], connection: Connecti }; } -export function getScheme(uri: string) { +function getScheme(uri: string) { return uri.substr(0, uri.indexOf(':')); } - -export function dirname(uri: string) { - const lastIndexOfSlash = uri.lastIndexOf('/'); - return lastIndexOfSlash !== -1 ? uri.substr(0, lastIndexOfSlash) : ''; -} - -export function basename(uri: string) { - const lastIndexOfSlash = uri.lastIndexOf('/'); - return uri.substr(lastIndexOfSlash + 1); -} - - -const Slash = '/'.charCodeAt(0); -const Dot = '.'.charCodeAt(0); - -export function extname(uri: string) { - for (let i = uri.length - 1; i >= 0; i--) { - const ch = uri.charCodeAt(i); - if (ch === Dot) { - if (i > 0 && uri.charCodeAt(i - 1) !== Slash) { - return uri.substr(i); - } else { - break; - } - } else if (ch === Slash) { - break; - } - } - return ''; -} - -export function isAbsolutePath(path: string) { - return path.charCodeAt(0) === Slash; -} - -export function resolvePath(uriString: string, path: string): string { - if (isAbsolutePath(path)) { - const uri = URI.parse(uriString); - const parts = path.split('/'); - return uri.with({ path: normalizePath(parts) }).toString(); - } - return joinPath(uriString, path); -} - -export function normalizePath(parts: string[]): string { - const newParts: string[] = []; - for (const part of parts) { - if (part.length === 0 || part.length === 1 && part.charCodeAt(0) === Dot) { - // ignore - } else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) { - newParts.pop(); - } else { - newParts.push(part); - } - } - if (parts.length > 1 && parts[parts.length - 1].length === 0) { - newParts.push(''); - } - let res = newParts.join('/'); - if (parts[0].length === 0) { - res = '/' + res; - } - return res; -} - -export function joinPath(uriString: string, ...paths: string[]): string { - const uri = URI.parse(uriString); - const parts = uri.path.split('/'); - for (let path of paths) { - parts.push(...path.split('/')); - } - return uri.with({ path: normalizePath(parts) }).toString(); -} diff --git a/extensions/css-language-features/server/src/test/requests.test.ts b/extensions/css-language-features/server/src/test/requests.test.ts deleted file mode 100644 index 3f287fefed0..00000000000 --- a/extensions/css-language-features/server/src/test/requests.test.ts +++ /dev/null @@ -1,62 +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 'mocha'; -import * as assert from 'assert'; -import { joinPath, normalizePath, resolvePath, extname } from '../requests'; - -suite('requests', () => { - test('join', async function () { - assert.equal(joinPath('foo://a/foo/bar', 'x'), 'foo://a/foo/bar/x'); - assert.equal(joinPath('foo://a/foo/bar/', 'x'), 'foo://a/foo/bar/x'); - assert.equal(joinPath('foo://a/foo/bar/', '/x'), 'foo://a/foo/bar/x'); - assert.equal(joinPath('foo://a/foo/bar/', 'x/'), 'foo://a/foo/bar/x/'); - assert.equal(joinPath('foo://a/foo/bar/', 'x', 'y'), 'foo://a/foo/bar/x/y'); - assert.equal(joinPath('foo://a/foo/bar/', 'x/', '/y'), 'foo://a/foo/bar/x/y'); - assert.equal(joinPath('foo://a/foo/bar/', '.', '/y'), 'foo://a/foo/bar/y'); - assert.equal(joinPath('foo://a/foo/bar/', 'x/y/z', '..'), 'foo://a/foo/bar/x/y'); - }); - - test('resolve', async function () { - assert.equal(resolvePath('foo://a/foo/bar', 'x'), 'foo://a/foo/bar/x'); - assert.equal(resolvePath('foo://a/foo/bar/', 'x'), 'foo://a/foo/bar/x'); - assert.equal(resolvePath('foo://a/foo/bar/', '/x'), 'foo://a/x'); - assert.equal(resolvePath('foo://a/foo/bar/', 'x/'), 'foo://a/foo/bar/x/'); - }); - - test('normalize', async function () { - function assertNormalize(path: string, expected: string) { - assert.equal(normalizePath(path.split('/')), expected, path); - } - assertNormalize('a', 'a'); - assertNormalize('/a', '/a'); - assertNormalize('a/', 'a/'); - assertNormalize('a/b', 'a/b'); - assertNormalize('/a/foo/bar/x', '/a/foo/bar/x'); - assertNormalize('/a/foo/bar//x', '/a/foo/bar/x'); - assertNormalize('/a/foo/bar///x', '/a/foo/bar/x'); - assertNormalize('/a/foo/bar/x/', '/a/foo/bar/x/'); - assertNormalize('a/foo/bar/x/', 'a/foo/bar/x/'); - assertNormalize('a/foo/bar/x//', 'a/foo/bar/x/'); - assertNormalize('//a/foo/bar/x//', '/a/foo/bar/x/'); - assertNormalize('a/.', 'a'); - assertNormalize('a/./b', 'a/b'); - assertNormalize('a/././b', 'a/b'); - assertNormalize('a/n/../b', 'a/b'); - assertNormalize('a/n/../', 'a/'); - assertNormalize('a/n/../', 'a/'); - assertNormalize('/a/n/../..', '/'); - assertNormalize('..', ''); - assertNormalize('/..', '/'); - }); - - test('extname', async function () { - function assertExtName(input: string, expected: string) { - assert.equal(extname(input), expected, input); - } - assertExtName('foo://a/foo/bar', ''); - assertExtName('foo://a/foo/bar.foo', '.foo'); - assertExtName('foo://a/foo/.foo', ''); - }); -}); diff --git a/extensions/css-language-features/server/src/utils/documentContext.ts b/extensions/css-language-features/server/src/utils/documentContext.ts index f8bc67f8b10..a7beffd0310 100644 --- a/extensions/css-language-features/server/src/utils/documentContext.ts +++ b/extensions/css-language-features/server/src/utils/documentContext.ts @@ -6,7 +6,7 @@ import { DocumentContext } from 'vscode-css-languageservice'; import { endsWith, startsWith } from '../utils/strings'; import { WorkspaceFolder } from 'vscode-languageserver'; -import { resolvePath } from '../requests'; +import { Utils, URI } from 'vscode-uri'; export function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext { function getRootFolder(): string | undefined { @@ -31,7 +31,7 @@ export function getDocumentContext(documentUri: string, workspaceFolders: Worksp } } base = base.substr(0, base.lastIndexOf('/') + 1); - return resolvePath(base, ref); + return Utils.resolvePath(URI.parse(base), ref).toString(); }, }; } diff --git a/extensions/css-language-features/server/test/index.js b/extensions/css-language-features/server/test/index.js index 4ab853bd503..faf8bc503fa 100644 --- a/extensions/css-language-features/server/test/index.js +++ b/extensions/css-language-features/server/test/index.js @@ -28,7 +28,7 @@ if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { const mocha = new Mocha(options); -glob.sync(__dirname + '/../out/test/**/*.test.js') +glob.sync(path.join(__dirname, '../out/test/**/*.test.js')) .forEach(file => mocha.addFile(file)); mocha.run(failures => process.exit(failures ? -1 : 0)); diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 12054ecb136..c8704bc01f5 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -12,15 +12,15 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== -vscode-css-languageservice@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.0.tgz#04fd899e25407a2fccd8f59a5896e2f020269bda" - integrity sha512-DTMa8QbVmujFPvD3NxoC5jjIXCyCG+cvn3hNzwQRhvhsk8LblNymBZBwzfcDdgEtqsi4O/2AB5HnMIRzxhzEzg== +vscode-css-languageservice@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.1.tgz#0061e0af23e7c49feba3abfda90799a4877738ee" + integrity sha512-9Lzf7XQD82ykwuyuma2r5g2NkrFth96k7PC4YCwtMoLIKxHXGDqHm7NIzjvY2qi43WgUROpw9XXTKKr8NmNuhA== dependencies: vscode-languageserver-textdocument "^1.0.1" vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" - vscode-uri "^2.1.2" + vscode-uri "^3.0.0" vscode-jsonrpc@6.0.0: version "6.0.0" @@ -57,7 +57,7 @@ vscode-nls@^5.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== -vscode-uri@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" - integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== +vscode-uri@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.0.tgz#a881b16614999d97e71d5d29ea453d4f8c19499d" + integrity sha512-boWPjBN8UPv8/9OnEGumoXgIVreVjs3RyqULtfHC3GRT1aCnaotYRKOhZERmaMsCVVt6nPmmI/ec7i1FH2kctw== diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 109e1ad3cb5..5498c095c95 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -78,6 +78,11 @@ vscode-nls@^4.1.2: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== +vscode-uri@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.0.tgz#a881b16614999d97e71d5d29ea453d4f8c19499d" + integrity sha512-boWPjBN8UPv8/9OnEGumoXgIVreVjs3RyqULtfHC3GRT1aCnaotYRKOhZERmaMsCVVt6nPmmI/ec7i1FH2kctw== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" From 3d9d6b34204083442ed286ed389a7e3e9d3bf75e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 18 Dec 2020 10:41:16 +0100 Subject: [PATCH 1217/1837] trigger layout when resource labels have rendered, fixes https://github.com/microsoft/vscode/issues/112799 --- src/vs/workbench/browser/parts/editor/tabsTitleControl.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index ead79b7a776..58bebbd4e48 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -611,6 +611,7 @@ export class TabsTitleControl extends TitleControl { // Tab Editor Label const editorLabel = this.tabResourceLabels.create(tabContainer); + const editorLabelRenderDisposable = editorLabel.onDidRender(() => this.layout(this.dimensions)); // Tab Actions const tabActionsContainer = document.createElement('div'); @@ -636,7 +637,7 @@ export class TabsTitleControl extends TitleControl { // Eventing const eventsDisposable = this.registerTabListeners(tabContainer, index, tabsContainer, tabsScrollbar); - this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel)); + this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel, editorLabelRenderDisposable)); return tabContainer; } From abf082cf74a572866c1cc5c7a94f87719ec22b54 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 11:02:23 +0100 Subject: [PATCH 1218/1837] Log more details when exiting --- .../services/extensions/node/extensionHostProcessSetup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index dc41f93c46c..ccd4e8259c0 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -268,7 +268,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise Date: Fri, 18 Dec 2020 11:13:32 +0100 Subject: [PATCH 1219/1837] Use IFileOperationUndoRedoInfo --- .../mainThreadFileSystemEventService.ts | 10 +-- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 13 +--- .../workingCopyFileOperationParticipant.ts | 6 +- .../common/workingCopyFileService.ts | 74 ++++++++----------- .../browser/workingCopyFileService.test.ts | 12 +-- .../test/common/workbenchTestServices.ts | 8 +- 6 files changed, 52 insertions(+), 71 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index b7706f0dc96..7bf3cb81904 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -10,7 +10,7 @@ import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/ext import { localize } from 'vs/nls'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, SourceTargetPairWithOptions } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, SourceTargetPair, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { reviveWorkspaceEditDto2 } from 'vs/workbench/api/browser/mainThreadEditors'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; @@ -74,8 +74,8 @@ export class MainThreadFileSystemEventService { const fileOperationParticipant = new class implements IWorkingCopyFileOperationParticipant { - async participate(files: SourceTargetPairWithOptions[], operation: FileOperation, timeout: number, token: CancellationToken) { - if (files.some(f => f.options?.isUndoing)) { + async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo, timeout: number, token: CancellationToken) { + if (undoInfo.isUndoing) { return; } @@ -169,11 +169,9 @@ export class MainThreadFileSystemEventService { logService.info('[onWill-handler] applying additional workspace edit from extensions', data.extensionNames); - // TODO@isidor undo redo group is per resource, this is false generalization - const undoRedoGroupId = files.length > 0 ? files[0].options?.undoRedoGroupId : undefined; await bulkEditService.apply( reviveWorkspaceEditDto2(data.edit), - { undoRedoGroupId, showPreview } + { undoRedoGroupId: undoInfo.undoRedoGroupId, showPreview } ); } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index fc9abffd80b..04ea382ea8a 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -8,7 +8,7 @@ import { WorkspaceFileEditOptions } from 'vs/editor/common/modes'; import { IFileService, FileSystemProviderCapabilities, IFileContent } from 'vs/platform/files/common/files'; import { IProgress } from 'vs/platform/progress/common/progress'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileService, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { IWorkspaceUndoRedoElement, UndoRedoElementType, IUndoRedoService, UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -18,11 +18,6 @@ import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import * as resources from 'vs/base/common/resources'; import { CancellationToken } from 'vs/base/common/cancellation'; -interface IFileOperationUndoRedoInfo { - undoRedoGroupId?: number; - isUndoing?: boolean; -} - interface IFileOperation { uris: URI[]; perform(token: CancellationToken): Promise; @@ -57,7 +52,7 @@ class RenameOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } - await this._workingCopyFileService.move([{ file: { source: this.oldUri, target: this.newUri }, options: { overwrite: this.options.overwrite, ...this.undoRedoInfo } }], token); + await this._workingCopyFileService.move([{ file: { source: this.oldUri, target: this.newUri }, overwrite: this.options.overwrite }], this.undoRedoInfo, token); return new RenameOperation(this.oldUri, this.newUri, this.options, { isUndoing: true }, this._workingCopyFileService, this._fileService); } @@ -93,7 +88,7 @@ class CopyOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } - const stat = await this._workingCopyFileService.copy([{ file: { source: this.oldUri, target: this.newUri }, options: { overwrite: this.options.overwrite, ...this.undoRedoInfo } }], token); + const stat = await this._workingCopyFileService.copy([{ file: { source: this.oldUri, target: this.newUri }, overwrite: this.options.overwrite }], this.undoRedoInfo, token); const folder = this.options.folder || (stat.length === 1 && stat[0].isDirectory); return this._instaService.createInstance(DeleteOperation, this.newUri, { recursive: true, folder, ...this.options }, { isUndoing: true }, false); } @@ -175,7 +170,7 @@ class DeleteOperation implements IFileOperation { } const useTrash = !this.options.skipTrashBin && this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue('files.enableTrash'); - await this._workingCopyFileService.delete([{ resource: this.oldUri, options: { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo } }], token); + await this._workingCopyFileService.delete([{ resource: this.oldUri, useTrash, recursive: this.options.recursive }], this.undoRedoInfo, token); if (typeof this.options.maxSize === 'number' && fileContent && (fileContent?.size > this.options.maxSize)) { return new Noop(); diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index d2a912b8352..87d5005df8a 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -6,7 +6,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkingCopyFileOperationParticipant, SourceTargetPairWithOptions } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileOperationParticipant, SourceTargetPair, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { FileOperation } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { LinkedList } from 'vs/base/common/linkedList'; @@ -27,7 +27,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { return toDisposable(() => remove()); } - async participate(files: SourceTargetPairWithOptions[], operation: FileOperation, token: CancellationToken | undefined): Promise { + async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, token: CancellationToken | undefined): Promise { const timeout = this.configurationService.getValue('files.participants.timeout'); if (timeout <= 0) { return; // disabled @@ -36,7 +36,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { // For each participant for (const participant of this.participants) { try { - await participant.participate(files, operation, timeout, token ?? CancellationToken.None); + await participant.participate(files, operation, undoInfo, timeout, token ?? CancellationToken.None); } catch (err) { this.logService.warn(err); } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 54a91d5d2f6..c5fb0ee11c8 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -31,11 +31,9 @@ export interface SourceTargetPair { readonly target: URI } -export interface SourceTargetPairWithOptions extends SourceTargetPair { - options?: { - undoRedoGroupId?: number; - isUndoing?: boolean - } +export interface IFileOperationUndoRedoInfo { + undoRedoGroupId?: number; + isUndoing?: boolean } export interface WorkingCopyFileEvent extends IWaitUntil { @@ -64,8 +62,9 @@ export interface IWorkingCopyFileOperationParticipant { * change the working copies before they are being saved to disk. */ participate( - files: SourceTargetPairWithOptions[], + files: SourceTargetPair[], operation: FileOperation, + undoInfo: IFileOperationUndoRedoInfo | undefined, timeout: number, token: CancellationToken ): Promise; @@ -73,21 +72,13 @@ export interface IWorkingCopyFileOperationParticipant { export interface IDeleteOperation { resource: URI; - options?: { - useTrash?: boolean; - recursive?: boolean; - undoRedoGroupId?: number; - isUndoing?: boolean - }; + useTrash?: boolean; + recursive?: boolean; } export interface IMoveOperation { file: Required; - options?: { - overwrite?: boolean; - undoRedoGroupId?: number; - isUndoing?: boolean - } + overwrite?: boolean; } export interface ICopyOperation extends IMoveOperation { } @@ -167,7 +158,7 @@ export interface IWorkingCopyFileService { * Note: events will only be emitted for the provided resource, but not any * parent folders that are being created as part of the operation. */ - createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; + createFolder(resource: URI, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will move working copies matching the provided resources and corresponding children @@ -176,7 +167,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - move(operations: IMoveOperation[], token?: CancellationToken): Promise; + move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will copy working copies matching the provided resources and corresponding children @@ -185,7 +176,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - copy(operations: ICopyOperation[], token?: CancellationToken): Promise; + copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will delete working copies matching the provided resources and children @@ -194,7 +185,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - delete(operations: IDeleteOperation[], token?: CancellationToken): Promise; + delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; //#endregion @@ -282,7 +273,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi } // file operation participant - await this.runFileOperationParticipants([{ target: resource, options: { isUndoing: options?.isUndoing, undoRedoGroupId: options?.undoRedoGroupId } }], FileOperation.CREATE, token); + await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options, token); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] }; @@ -310,21 +301,20 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stat; } - async move(operations: IMoveOperation[], token?: CancellationToken): Promise { - return this.doMoveOrCopy(operations, true, token); + async move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return this.doMoveOrCopy(operations, true, undoInfo, token); } - async copy(operations: ICopyOperation[], token?: CancellationToken): Promise { - return this.doMoveOrCopy(operations, false, token); + async copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return this.doMoveOrCopy(operations, false, undoInfo, token); } - private async doMoveOrCopy(operations: IMoveOperation[] | ICopyOperation[], move: boolean, token?: CancellationToken): Promise { + private async doMoveOrCopy(operations: IMoveOperation[] | ICopyOperation[], move: boolean, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { const stats: IFileStatWithMetadata[] = []; // validate move/copy operation before starting - for (const operation of operations) { - const { source, target } = operation.file; - const validateMoveOrCopy = await (move ? this.fileService.canMove(source, target, operation.options?.overwrite) : this.fileService.canCopy(source, target, operation.options?.overwrite)); + for (const { file: { source, target }, overwrite } of operations) { + const validateMoveOrCopy = await (move ? this.fileService.canMove(source, target, overwrite) : this.fileService.canCopy(source, target, overwrite)); if (validateMoveOrCopy instanceof Error) { throw validateMoveOrCopy; } @@ -332,16 +322,14 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi // file operation participant const files = operations.map(o => o.file); - // TODO@isidor should the options be passed here - await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, token); + await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, undoInfo, token); // before event const event = { correlationId: this.correlationIds++, operation: move ? FileOperation.MOVE : FileOperation.COPY, files }; await this._onWillRunWorkingCopyFileOperation.fireAsync(event, CancellationToken.None); try { - for (const operation of operations) { - const { source, target } = operation.file; + for (const { file: { source, target }, overwrite } of operations) { // if source and target are not equal, handle dirty working copies // depending on the operation: // - move: revert both source and target (if any) @@ -353,9 +341,9 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi // now we can rename the source to target via file operation if (move) { - stats.push(await this.fileService.move(source, target, operation.options?.overwrite)); + stats.push(await this.fileService.move(source, target, overwrite)); } else { - stats.push(await this.fileService.copy(source, target, operation.options?.overwrite)); + stats.push(await this.fileService.copy(source, target, overwrite)); } } } catch (error) { @@ -372,19 +360,19 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return stats; } - async delete(operations: IDeleteOperation[], token?: CancellationToken): Promise { + async delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { // validate delete operation before starting for (const operation of operations) { - const validateDelete = await this.fileService.canDelete(operation.resource, operation.options); + const validateDelete = await this.fileService.canDelete(operation.resource, { recursive: operation.recursive, useTrash: operation.useTrash }); if (validateDelete instanceof Error) { throw validateDelete; } } // file operation participant - const files = operations.map(operation => ({ target: operation.resource, options: operation.options })); - await this.runFileOperationParticipants(files, FileOperation.DELETE, token); + const files = operations.map(operation => ({ target: operation.resource })); + await this.runFileOperationParticipants(files, FileOperation.DELETE, undoInfo, token); // before events const event = { correlationId: this.correlationIds++, operation: FileOperation.DELETE, files }; @@ -401,7 +389,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi // now actually delete from disk try { for (const operation of operations) { - await this.fileService.del(operation.resource, operation.options); + await this.fileService.del(operation.resource, { recursive: operation.recursive, useTrash: operation.useTrash }); } } catch (error) { @@ -426,8 +414,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return this.fileOperationParticipants.addFileOperationParticipant(participant); } - private runFileOperationParticipants(files: SourceTargetPairWithOptions[], operation: FileOperation, token: CancellationToken | undefined): Promise { - return this.fileOperationParticipants.participate(files, operation, token); + private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, token: CancellationToken | undefined): Promise { + return this.fileOperationParticipants.participate(files, operation, undoInfo, token); } //#endregion diff --git a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts index 238b49c2c5a..78eecbaa6f3 100644 --- a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts +++ b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts @@ -53,7 +53,7 @@ suite('WorkingCopyFileService', () => { let sourceModel: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8', undefined); (accessor.textFileService.files).add(sourceModel.resource, sourceModel); - const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, options: { overwrite: true } }], true); + const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, overwrite: true }], true); sourceModel.dispose(); assert.equal(eventCounter, 3); @@ -68,8 +68,8 @@ suite('WorkingCopyFileService', () => { (accessor.textFileService.files).add(targetModel2.resource, targetModel2); const eventCounter = await testEventsMoveOrCopy([ - { file: { source: sourceModel1.resource, target: sourceModel1.resource }, options: { overwrite: true } }, - { file: { source: sourceModel2.resource, target: targetModel2.resource }, options: { overwrite: true } } + { file: { source: sourceModel1.resource, target: sourceModel1.resource }, overwrite: true }, + { file: { source: sourceModel2.resource, target: targetModel2.resource }, overwrite: true } ], true); sourceModel1.dispose(); @@ -97,7 +97,7 @@ suite('WorkingCopyFileService', () => { let sourceModel: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8', undefined); (accessor.textFileService.files).add(sourceModel.resource, sourceModel); - const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, options: { overwrite: true } }]); + const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, overwrite: true }]); sourceModel.dispose(); assert.equal(eventCounter, 3); @@ -112,8 +112,8 @@ suite('WorkingCopyFileService', () => { (accessor.textFileService.files).add(targetModel2.resource, targetModel2); const eventCounter = await testEventsMoveOrCopy([ - { file: { source: sourceModel1.resource, target: sourceModel1.resource }, options: { overwrite: true } }, - { file: { source: sourceModel2.resource, target: targetModel2.resource }, options: { overwrite: true } } + { file: { source: sourceModel1.resource, target: sourceModel1.resource }, overwrite: true }, + { file: { source: sourceModel2.resource, target: targetModel2.resource }, overwrite: true } ]); sourceModel1.dispose(); diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index 63502cf7697..79c02bedf6b 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -16,7 +16,7 @@ import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { InMemoryStorageService, WillSaveStateReason } from 'vs/platform/storage/common/storage'; import { WorkingCopyService, IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; @@ -196,7 +196,7 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService { addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; } - async delete(operations: IDeleteOperation[], token?: CancellationToken): Promise { } + async delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { } registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; } @@ -205,9 +205,9 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService { create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean | undefined; } | undefined): Promise { throw new Error('Method not implemented.'); } createFolder(resource: URI): Promise { throw new Error('Method not implemented.'); } - move(operations: IMoveOperation[]): Promise { throw new Error('Method not implemented.'); } + move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo): Promise { throw new Error('Method not implemented.'); } - copy(operations: ICopyOperation[], token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } + copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } } export function mock(): Ctor { From d4e98289a349086db78f1c60e18573e59c466dce Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 18 Dec 2020 11:17:52 +0100 Subject: [PATCH 1220/1837] [css] revert changes to test runner --- extensions/css-language-features/server/test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/css-language-features/server/test/index.js b/extensions/css-language-features/server/test/index.js index faf8bc503fa..4ab853bd503 100644 --- a/extensions/css-language-features/server/test/index.js +++ b/extensions/css-language-features/server/test/index.js @@ -28,7 +28,7 @@ if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { const mocha = new Mocha(options); -glob.sync(path.join(__dirname, '../out/test/**/*.test.js')) +glob.sync(__dirname + '/../out/test/**/*.test.js') .forEach(file => mocha.addFile(file)); mocha.run(failures => process.exit(failures ? -1 : 0)); From eb3cfcda015cdcb1f2904a06a4a1fc02aabb4c0a Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Fri, 18 Dec 2020 02:17:55 -0800 Subject: [PATCH 1221/1837] chore: bump electron@11.1.0 --- .yarnrc | 2 +- cgmanifest.json | 4 ++-- package.json | 4 ++-- yarn.lock | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.yarnrc b/.yarnrc index e93e4570cfb..914682b9e33 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://electronjs.org/headers" -target "11.0.5" +target "11.1.0" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index fffd667ab0a..3e5c192873f 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "296cba563ea41277fd2b8b5a3b246acb9888befa" + "commitHash": "101a2282ab3ae030ace05e70043739386c24b3cb" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "11.0.5" + "version": "11.1.0" }, { "component": { diff --git a/package.json b/package.json index aea8429065e..92be75cbad4 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "compile-web": "gulp compile-web --max_old_space_size=4095", "watch-web": "gulp watch-web --max_old_space_size=4095", "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", - "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.0.5", + "electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.1.0", "playwright-install": "node node_modules/playwright/install.js" }, "dependencies": { @@ -112,7 +112,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "11.0.5", + "electron": "11.1.0", "electron-rebuild": "2.0.3", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", diff --git a/yarn.lock b/yarn.lock index 23a791261f6..1bf3b732fd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2936,10 +2936,10 @@ electron-to-chromium@^1.2.7: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@11.0.5: - version "11.0.5" - resolved "https://registry.yarnpkg.com/electron/-/electron-11.0.5.tgz#ca83cc294fecef08755a528e4a18f8a5534d220f" - integrity sha512-gGMnlDk2nrI/r9gtxDMtOmGPhI9OOTWxABI0K/zQ3QyiAIdtYM4/AkPAcZ6ZZ1cJ4LShaCrFTHqia8ZL3i9zCg== +electron@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.1.0.tgz#8dfdf579d1eb79feef3e3d2937fc022e72129c90" + integrity sha512-RFAhR/852VMaRd9NSe7jprwSoG9dLc6u1GwnqRWg+/3cy/8Zrwt1Betw1lXiZH7hGuB9K2cqju83Xv5Pq5ZSGA== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" From 4db298aab63d37610663dd541248fe058a522410 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 11:20:55 +0100 Subject: [PATCH 1222/1837] Avoid text flickering, just render   to have a height --- src/vs/editor/contrib/hover/modesContentHover.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 1e443d58de1..d7095b418b9 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Color, RGBA } from 'vs/base/common/color'; import { IMarkdownString, MarkdownString, isEmptyMarkdownString, markedStringsEquals } from 'vs/base/common/htmlContent'; -import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore, combinedDisposable, MutableDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; @@ -31,7 +31,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener'; import { MarkerController, NextMarkerAction } from 'vs/editor/contrib/gotoError/gotoError'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; +import { CancelablePromise, createCancelablePromise, disposableTimeout } from 'vs/base/common/async'; import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction'; import { QuickFixAction, QuickFixController } from 'vs/editor/contrib/codeAction/codeActionCommands'; import { CodeActionKind, CodeActionTrigger } from 'vs/editor/contrib/codeAction/types'; @@ -606,12 +606,15 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this.recentMarkerCodeActionsInfo = undefined; } } + const updatePlaceholderDisposable = this.recentMarkerCodeActionsInfo && !this.recentMarkerCodeActionsInfo.hasCodeActions ? Disposable.None : disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 200)); if (!quickfixPlaceholderElement.textContent) { - quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."); + // Have some content in here to avoid flickering + quickfixPlaceholderElement.textContent = String.fromCharCode(0xA0); //   } const codeActionsPromise = this.getCodeActions(markerHover.marker); disposables.add(toDisposable(() => codeActionsPromise.cancel())); codeActionsPromise.then(actions => { + updatePlaceholderDisposable.dispose(); this.recentMarkerCodeActionsInfo = { marker: markerHover.marker, hasCodeActions: actions.validActions.length > 0 }; if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { From 34f1e7ae2079466f2a5696bd111a5bf84c67783a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 11:22:42 +0100 Subject: [PATCH 1223/1837] Revert 0d14d3e38a8aba6e2bcd6d5dd729c4d47b3d4f97 --- src/vs/editor/contrib/hover/modesContentHover.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 0098c96a074..d7095b418b9 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -620,7 +620,6 @@ export class ModesContentHoverWidget extends ContentHoverWidget { if (!this.recentMarkerCodeActionsInfo.hasCodeActions) { actions.dispose(); quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available"); - this._editor.layoutContentWidget(this); return; } quickfixPlaceholderElement.style.display = 'none'; @@ -648,7 +647,6 @@ export class ModesContentHoverWidget extends ContentHoverWidget { }); } })); - this._editor.layoutContentWidget(this); }); } From 780ae7676088104fcc9f9dc795b03e243c0e05ba Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 18 Dec 2020 11:39:26 +0100 Subject: [PATCH 1224/1837] workingCopyService: create and createFolder also use IOperation interfaces --- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 4 +- .../textfile/browser/textFileService.ts | 3 +- .../common/workingCopyFileService.ts | 41 +++++++++++++------ .../browser/workingCopyFileService.test.ts | 4 +- .../browser/api/mainThreadEditors.test.ts | 8 ++-- .../test/common/workbenchTestServices.ts | 7 ++-- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 04ea382ea8a..73a7234fd28 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -120,9 +120,9 @@ class CreateOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } if (this.options.folder) { - await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo }, token); + await this._workingCopyFileService.createFolder([{ resource: this.newUri }], this.undoRedoInfo, token); } else { - await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token); + await this._workingCopyFileService.create([{ resource: this.newUri, contents: this.contents, overwrite: this.options.overwrite }], this.undoRedoInfo, token); } return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder && !this.contents); } diff --git a/src/vs/workbench/services/textfile/browser/textFileService.ts b/src/vs/workbench/services/textfile/browser/textFileService.ts index 13ddf1513c7..208a0cda90b 100644 --- a/src/vs/workbench/services/textfile/browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/browser/textFileService.ts @@ -151,7 +151,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex async create(resource: URI, value?: string | ITextSnapshot, options?: ICreateFileOptions): Promise { const readable = await this.getEncodedReadable(resource, value); - return this.workingCopyFileService.create(resource, readable, options); + const result = await this.workingCopyFileService.create([{ resource, contents: readable, overwrite: options?.overwrite }]); + return result[0]; } async write(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise { diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index c5fb0ee11c8..1c3d2055b1a 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -32,7 +32,15 @@ export interface SourceTargetPair { } export interface IFileOperationUndoRedoInfo { + + /** + * Id of the undo group that the file operation belongs to. + */ undoRedoGroupId?: number; + + /** + * Flag indicates if the operation is an undo. + */ isUndoing?: boolean } @@ -70,6 +78,15 @@ export interface IWorkingCopyFileOperationParticipant { ): Promise; } +export interface ICreateOperation { + resource: URI; + overwrite?: boolean; +} + +export interface ICreateFileOperation extends ICreateOperation { + contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, +} + export interface IDeleteOperation { resource: URI; useTrash?: boolean; @@ -147,7 +164,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise; + create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will create a folder and any parent folder that needs to be created. @@ -158,7 +175,7 @@ export interface IWorkingCopyFileService { * Note: events will only be emitted for the provided resource, but not any * parent folders that are being created as part of the operation. */ - createFolder(resource: URI, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; + createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will move working copies matching the provided resources and corresponding children @@ -254,38 +271,38 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi //#region File operations - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { - return this.doCreateFileOrFolder(resource, true, contents, options, token); + create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return Promise.all(operations.map(o => this.doCreateFileOrFolder(o, true, undoInfo, token))); } - createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { - return this.doCreateFileOrFolder(resource, false, undefined, options, token); + createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return Promise.all(operations.map(o => this.doCreateFileOrFolder(o, false, undoInfo, token))); } - async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise { + async doCreateFileOrFolder(operation: ICreateFileOperation | ICreateOperation, isFile: boolean, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { // validate create operation before starting if (isFile) { - const validateCreate = await this.fileService.canCreateFile(resource, options); + const validateCreate = await this.fileService.canCreateFile(operation.resource, { overwrite: operation.overwrite }); if (validateCreate instanceof Error) { throw validateCreate; } } // file operation participant - await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options, token); + await this.runFileOperationParticipants([{ target: operation.resource }], FileOperation.CREATE, undoInfo, token); // before events - const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] }; + const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: operation.resource }] }; await this._onWillRunWorkingCopyFileOperation.fireAsync(event, CancellationToken.None); // now actually create on disk let stat: IFileStatWithMetadata; try { if (isFile) { - stat = await this.fileService.createFile(resource, contents, { overwrite: options?.overwrite }); + stat = await this.fileService.createFile(operation.resource, (operation as ICreateFileOperation).contents, { overwrite: operation.overwrite }); } else { - stat = await this.fileService.createFolder(resource); + stat = await this.fileService.createFolder(operation.resource); } } catch (error) { diff --git a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts index 78eecbaa6f3..3ea04364e32 100644 --- a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts +++ b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts @@ -224,7 +224,7 @@ suite('WorkingCopyFileService', () => { eventCounter++; }); - await accessor.workingCopyFileService.createFolder(resource); + await accessor.workingCopyFileService.createFolder([{ resource }]); assert.equal(eventCounter, 3); @@ -459,7 +459,7 @@ suite('WorkingCopyFileService', () => { eventCounter++; }); - await accessor.workingCopyFileService.create(resource, contents); + await accessor.workingCopyFileService.create([{ resource, contents }]); assert.ok(!accessor.workingCopyService.isDirty(model.resource)); model.dispose(); diff --git a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts index 8ce5268be39..cf370439d42 100644 --- a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts @@ -40,7 +40,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ILabelService } from 'vs/platform/label/common/label'; -import { IWorkingCopyFileService, IMoveOperation, IDeleteOperation, ICopyOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileService, IMoveOperation, IDeleteOperation, ICopyOperation, ICreateFileOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService'; import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -103,8 +103,10 @@ suite('MainThreadEditors', () => { }); services.set(IWorkingCopyFileService, new class extends mock() { onDidRunWorkingCopyFileOperation = Event.None; - create(resource: URI) { - createdResources.add(resource); + create(operations: ICreateFileOperation[]) { + for (const operation of operations) { + createdResources.add(operation.resource); + } return Promise.resolve(Object.create(null)); } move(operations: IMoveOperation[]) { diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index 79c02bedf6b..6a00cd3ef4d 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -16,10 +16,9 @@ import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { InMemoryStorageService, WillSaveStateReason } from 'vs/platform/storage/common/storage'; import { WorkingCopyService, IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo, ICreateFileOperation, ICreateOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; -import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -202,8 +201,8 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService { getDirty(resource: URI): IWorkingCopy[] { return []; } - create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean | undefined; } | undefined): Promise { throw new Error('Method not implemented.'); } - createFolder(resource: URI): Promise { throw new Error('Method not implemented.'); } + create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } + createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo): Promise { throw new Error('Method not implemented.'); } From 9c30a0e98cc3c3fc337e04a63e2165514573ed8f Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 18 Dec 2020 11:41:14 +0100 Subject: [PATCH 1225/1837] null guard --- .../api/browser/mainThreadFileSystemEventService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index 7bf3cb81904..c03943332e4 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -74,8 +74,8 @@ export class MainThreadFileSystemEventService { const fileOperationParticipant = new class implements IWorkingCopyFileOperationParticipant { - async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo, timeout: number, token: CancellationToken) { - if (undoInfo.isUndoing) { + async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, timeout: number, token: CancellationToken) { + if (undoInfo?.isUndoing) { return; } @@ -171,7 +171,7 @@ export class MainThreadFileSystemEventService { await bulkEditService.apply( reviveWorkspaceEditDto2(data.edit), - { undoRedoGroupId: undoInfo.undoRedoGroupId, showPreview } + { undoRedoGroupId: undoInfo?.undoRedoGroupId, showPreview } ); } From b069dbe0aeb72786f81a449e6a53de4926aef952 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Dec 2020 12:05:57 +0100 Subject: [PATCH 1226/1837] Tab decorations need to update scrollbar (fix #112799) --- src/vs/workbench/browser/labels.ts | 35 ++++++++++++++----- .../browser/parts/editor/tabsTitleControl.ts | 15 ++++++-- .../browser/parts/editor/titleControl.ts | 2 +- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 5984484d21e..a4729a6bf6c 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -100,6 +100,10 @@ export const DEFAULT_LABELS_CONTAINER: IResourceLabelsContainer = { }; export class ResourceLabels extends Disposable { + + private _onDidChangeDecorations = this._register(new Emitter()); + readonly onDidChangeDecorations = this._onDidChangeDecorations.event; + private widgets: ResourceLabelWidget[] = []; private labels: IResourceLabel[] = []; @@ -148,7 +152,18 @@ export class ResourceLabels extends Disposable { })); // notify when file decoration changes - this._register(this.decorationsService.onDidChangeDecorations(e => this.widgets.forEach(widget => widget.notifyFileDecorationsChanges(e)))); + this._register(this.decorationsService.onDidChangeDecorations(e => { + let notifyDidChangeDecorations = false; + this.widgets.forEach(widget => { + if (widget.notifyFileDecorationsChanges(e)) { + notifyDidChangeDecorations = true; + } + }); + + if (notifyDidChangeDecorations) { + this._onDidChangeDecorations.fire(); + } + })); // notify when theme changes this._register(this.themeService.onDidColorThemeChange(() => this.widgets.forEach(widget => widget.notifyThemeChange()))); @@ -311,19 +326,21 @@ class ResourceLabelWidget extends IconLabel { } } - notifyFileDecorationsChanges(e: IResourceDecorationChangeEvent): void { + notifyFileDecorationsChanges(e: IResourceDecorationChangeEvent): boolean { if (!this.options) { - return; + return false; } const resource = toResource(this.label); if (!resource) { - return; + return false; } if (this.options.fileDecorations && e.affectsResource(resource)) { - this.render(false); + return this.render(false); } + + return false; } notifyExtensionsRegistered(): void { @@ -465,7 +482,7 @@ class ResourceLabelWidget extends IconLabel { this.setLabel(''); } - private render(clearIconCache: boolean): void { + private render(clearIconCache: boolean): boolean { if (this.isHidden) { if (!this.needsRedraw) { this.needsRedraw = clearIconCache ? Redraw.Full : Redraw.Basic; @@ -475,7 +492,7 @@ class ResourceLabelWidget extends IconLabel { this.needsRedraw = Redraw.Full; } - return; + return false; } if (this.label) { @@ -492,7 +509,7 @@ class ResourceLabelWidget extends IconLabel { } if (!this.label) { - return; + return false; } this.renderDisposables.clear(); @@ -558,6 +575,8 @@ class ResourceLabelWidget extends IconLabel { this.setLabel(label || '', this.label.description, iconLabelOptions); this._onDidRender.fire(); + + return true; } dispose(): void { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 58bebbd4e48..74056984c52 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -129,6 +129,9 @@ export class TabsTitleControl extends TitleControl { // If we are connected to remote, this accounts for the // remote OS. (async () => this.path = await this.pathService.path)(); + + // React to decorations changing for our resource labels + this._register(this.tabResourceLabels.onDidChangeDecorations(() => this.doHandleDecorationsChange())); } protected create(parent: HTMLElement): void { @@ -161,7 +164,7 @@ export class TabsTitleControl extends TitleControl { // Editor Actions Toolbar this.createEditorActionsToolBar(this.editorToolbarContainer); - // Breadcrumbs (are on a separate row below tabs and actions) + // Breadcrumbs const breadcrumbsContainer = document.createElement('div'); breadcrumbsContainer.classList.add('tabs-breadcrumbs'); this.titleContainer.appendChild(breadcrumbsContainer); @@ -380,6 +383,13 @@ export class TabsTitleControl extends TitleControl { })); } + private doHandleDecorationsChange(): void { + + // A change to decorations potentially has an impact on the size of tabs + // so we need to trigger a layout in that case to adjust things + this.layout(this.dimensions); + } + protected updateEditorActionsToolbar(): void { super.updateEditorActionsToolbar(); @@ -611,7 +621,6 @@ export class TabsTitleControl extends TitleControl { // Tab Editor Label const editorLabel = this.tabResourceLabels.create(tabContainer); - const editorLabelRenderDisposable = editorLabel.onDidRender(() => this.layout(this.dimensions)); // Tab Actions const tabActionsContainer = document.createElement('div'); @@ -637,7 +646,7 @@ export class TabsTitleControl extends TitleControl { // Eventing const eventsDisposable = this.registerTabListeners(tabContainer, index, tabsContainer, tabsScrollbar); - this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel, editorLabelRenderDisposable)); + this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel)); return tabContainer; } diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 0eaa213ab76..d38fb6d9951 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -109,7 +109,7 @@ export abstract class TitleControl extends Themable { this.registerListeners(); } - protected registerListeners(): void { + private registerListeners(): void { // Update actions toolbar when extension register that may contribute them this._register(this.extensionService.onDidRegisterExtensions(() => this.updateEditorActionsToolbar())); From 0adc15c4bb876a9537a5b25a8fb64786e6396e36 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Dec 2020 12:08:43 +0100 Subject: [PATCH 1227/1837] configureCrashReporter should check whether we are on Electron --- src/bootstrap-fork.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index f32627f531f..430a69c505c 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -213,7 +213,7 @@ function configureCrashReporter() { if (typeof crashReporterOptionsRaw === 'string') { try { const crashReporterOptions = JSON.parse(crashReporterOptionsRaw); - if (crashReporterOptions) { + if (crashReporterOptions && process['crashReporter'] /* Electron only */) { process['crashReporter'].start(crashReporterOptions); } } catch (error) { From 9034b769fa8bb55869f64e89e2898e9227c5e5ec Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Dec 2020 13:24:17 +0100 Subject: [PATCH 1228/1837] fix #112805 --- src/vs/base/parts/storage/test/node/storage.test.ts | 6 ++---- src/vs/base/test/node/pfs/pfs.test.ts | 6 ++---- .../files/test/electron-browser/diskFileService.test.ts | 9 +++------ src/vs/platform/state/test/node/state.test.ts | 3 +-- src/vs/platform/storage/test/node/storageService.test.ts | 3 +-- .../test/electron-main/workspacesMainService.test.ts | 2 -- .../backup/test/electron-browser/backupTracker.test.ts | 7 ++----- .../electron-browser/nativeTextFileService.io.test.ts | 9 +++------ 8 files changed, 14 insertions(+), 31 deletions(-) diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index e735634c2ec..4eb61ffcbc7 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -16,8 +16,7 @@ import { isWindows } from 'vs/base/common/platform'; suite('Storage Library', function () { - // Given issues such as https://github.com/microsoft/vscode/issues/108113 - // we see random test failures when accessing the native file system. + // https://github.com/microsoft/vscode/issues/108113 this.retries(3); this.timeout(1000 * 20); @@ -299,8 +298,7 @@ suite('Storage Library', function () { suite('SQLite Storage Library', function () { - // Given issues such as https://github.com/microsoft/vscode/issues/108113 - // we see random test failures when accessing the native file system. + // https://github.com/microsoft/vscode/issues/108113 this.retries(3); this.timeout(1000 * 20); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index fd324076b26..9bfc330a393 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -17,11 +17,9 @@ import { VSBuffer } from 'vs/base/common/buffer'; suite('PFS', function () { - // Given issues such as https://github.com/microsoft/vscode/issues/84066 - // we see random test failures when accessing the native file system. To - // diagnose further, we retry node.js file access tests up to 3 times to - // rule out any random disk issue. + // https://github.com/microsoft/vscode/issues/84066 this.retries(3); + this.timeout(1000 * 20); test('writeFile', async () => { const id = uuid.generateUuid(); diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index 34197b7d9ee..773c6c9bc16 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -130,13 +130,10 @@ suite('Disk File Service', function () { const disposables = new DisposableStore(); - // Given issues such as https://github.com/microsoft/vscode/issues/78602 - // and https://github.com/microsoft/vscode/issues/92334 we see random test - // failures when accessing the native file system. To diagnose further, we - // retry node.js file access tests up to 3 times to rule out any random disk - // issue and increase the timeout. + // https://github.com/microsoft/vscode/issues/78602 + // https://github.com/microsoft/vscode/issues/92334 this.retries(3); - this.timeout(1000 * 10); + this.timeout(1000 * 20); setup(async () => { const logService = new NullLogService(); diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index 362b9de2882..c9c8eaf9989 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -16,8 +16,7 @@ suite('StateService', () => { test('Basics', async function () { - // Given issues such as https://github.com/microsoft/vscode/issues/112447 - // we see random test failures when accessing the native file system. + // https://github.com/microsoft/vscode/issues/112447 this.retries(3); this.timeout(1000 * 20); diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index 5ee00224650..1546b2384ca 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -26,8 +26,7 @@ suite('NativeStorageService', function () { test('Migrate Data', async function () { - // Given issues such as https://github.com/microsoft/vscode/issues/108113 - // we see random test failures when accessing the native file system. + // https://github.com/microsoft/vscode/issues/108113 this.retries(3); this.timeout(1000 * 20); diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 303be42b5a6..9a3868ab637 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -422,8 +422,6 @@ suite('WorkspacesMainService', () => { }); test('getUntitledWorkspaceSync', async function () { - this.retries(3); - let untitled = service.getUntitledWorkspacesSync(); assert.equal(untitled.length, 0); diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts index 0be5a78b4ad..7182610f3fd 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts @@ -96,12 +96,9 @@ suite('BackupTracker', function () { let accessor: TestServiceAccessor; let disposables: IDisposable[] = []; - // Given issues such as https://github.com/microsoft/vscode/issues/112146 - // we see random test failures when accessing the native file system. To - // diagnose further, we retry node.js file access tests up to 3 times to rule - // out any random disk issue and increase the timeout. + // https://github.com/microsoft/vscode/issues/112146 this.retries(3); - this.timeout(1000 * 10); + this.timeout(1000 * 20); setup(async () => { const instantiationService = workbenchInstantiationService(); diff --git a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts index 722fb0cc3bf..fff6619519c 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts @@ -33,13 +33,10 @@ suite('Files - NativeTextFileService i/o', function () { let service: ITextFileService; let testDir: string; - // Given issues such as https://github.com/microsoft/vscode/issues/78602 - // and https://github.com/microsoft/vscode/issues/92334 we see random test - // failures when accessing the native file system. To diagnose further, we - // retry node.js file access tests up to 3 times to rule out any random disk - // issue and increase the timeout. + // https://github.com/microsoft/vscode/issues/78602 + // https://github.com/microsoft/vscode/issues/92334 this.retries(3); - this.timeout(1000 * 10); + this.timeout(1000 * 20); createSuite({ setup: async () => { From f74ad9692f688a0fdd34d39d075e82be91dea4ef Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 13:28:39 +0100 Subject: [PATCH 1229/1837] Align `@types/*` dev dependencies (#112718) --- build/package.json | 8 +++--- build/yarn.lock | 26 +++++++++---------- extensions/configuration-editing/package.json | 2 +- extensions/configuration-editing/yarn.lock | 8 +++--- extensions/css-language-features/package.json | 2 +- .../css-language-features/server/package.json | 4 +-- .../css-language-features/server/yarn.lock | 16 ++++++------ 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-ui/package.json | 2 +- extensions/git-ui/yarn.lock | 8 +++--- extensions/git/package.json | 4 +-- extensions/git/yarn.lock | 16 ++++++------ extensions/github-authentication/package.json | 4 +-- extensions/github-authentication/yarn.lock | 10 +++---- 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 | 4 +-- .../html-language-features/server/yarn.lock | 16 ++++++------ 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 | 4 +-- .../json-language-features/server/yarn.lock | 16 ++++++------ extensions/json-language-features/yarn.lock | 8 +++--- .../markdown-language-features/package.json | 2 +- .../markdown-language-features/yarn.lock | 8 +++--- extensions/merge-conflict/package.json | 2 +- extensions/merge-conflict/yarn.lock | 8 +++--- .../microsoft-authentication/package.json | 4 +-- extensions/microsoft-authentication/yarn.lock | 10 +++---- 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 | 4 +-- .../typescript-language-features/yarn.lock | 16 ++++++------ extensions/vscode-api-tests/package.json | 4 +-- extensions/vscode-api-tests/yarn.lock | 16 ++++++------ 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 +- .../src/notebook.test.ts | 2 +- extensions/vscode-notebook-tests/yarn.lock | 8 +++--- extensions/vscode-test-resolver/package.json | 2 +- extensions/vscode-test-resolver/yarn.lock | 8 +++--- package.json | 8 +++--- test/automation/package.json | 4 +-- test/automation/yarn.lock | 8 +++--- test/integration/browser/package.json | 6 ++--- test/integration/browser/yarn.lock | 18 ++++++------- test/smoke/package.json | 6 ++--- test/smoke/src/areas/workbench/launch.test.ts | 4 +-- test/smoke/src/main.ts | 10 +++---- test/smoke/src/utils.ts | 6 ++--- test/smoke/yarn.lock | 24 ++++++++--------- yarn.lock | 26 +++++++++---------- 72 files changed, 257 insertions(+), 257 deletions(-) diff --git a/build/package.json b/build/package.json index 3ec73fd8382..27dc694bc31 100644 --- a/build/package.json +++ b/build/package.json @@ -20,12 +20,12 @@ "@types/gulp-uglify": "^3.0.5", "@types/mime": "0.0.29", "@types/minimatch": "^3.0.3", - "@types/minimist": "^1.2.0", - "@types/mocha": "2.2.39", - "@types/node": "^12.11.7", + "@types/minimist": "^1.2.1", + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9", "@types/pump": "^1.0.1", "@types/request": "^2.47.0", - "@types/rimraf": "^2.0.2", + "@types/rimraf": "^2.0.4", "@types/terser": "^3.12.0", "@types/through": "^0.0.29", "@types/through2": "^2.0.34", diff --git a/build/yarn.lock b/build/yarn.lock index 3f865daf638..4a94ffd6754 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -225,22 +225,22 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/minimist@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" - integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= +"@types/minimist@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" + integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== -"@types/mocha@2.2.39": - version "2.2.39" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.39.tgz#f68d63db8b69c38e9558b4073525cf96c4f7a829" - integrity sha1-9o1j24tpw46VWLQHNSXPlsT3qCk= +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== "@types/node@*": version "8.0.51" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@^12.11.7": +"@types/node@^12.19.9": version "12.19.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== @@ -262,10 +262,10 @@ "@types/node" "*" "@types/tough-cookie" "*" -"@types/rimraf@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== +"@types/rimraf@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" + integrity sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q== dependencies: "@types/glob" "*" "@types/node" "*" diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 42340041320..26348576288 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -128,6 +128,6 @@ ] }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock index 36aab5fd224..ebfaa046da4 100644 --- a/extensions/configuration-editing/yarn.lock +++ b/extensions/configuration-editing/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== jsonc-parser@^2.2.1: version "2.2.1" diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 66adf1fb259..32861b82500 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -812,6 +812,6 @@ "vscode-uri": "^3.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index f32400be34c..c818cc01a5d 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -15,8 +15,8 @@ "vscode-uri": "^3.0.0" }, "devDependencies": { - "@types/mocha": "7.0.2", - "@types/node": "^12.11.7" + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9" }, "scripts": { "compile": "gulp compile-extension:css-language-features-server", diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index c8704bc01f5..387d4456256 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -2,15 +2,15 @@ # yarn lockfile v1 -"@types/mocha@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce" - integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w== +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-css-languageservice@^5.0.1: version "5.0.1" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 5498c095c95..c75543eac48 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== 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 f0dc778263e..0f349851c7e 100644 --- a/extensions/debug-auto-launch/package.json +++ b/extensions/debug-auto-launch/package.json @@ -29,7 +29,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "prettier": { "printWidth": 100, diff --git a/extensions/debug-auto-launch/yarn.lock b/extensions/debug-auto-launch/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/debug-auto-launch/yarn.lock +++ b/extensions/debug-auto-launch/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== 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 fc485044807..ac199f0593a 100644 --- a/extensions/debug-server-ready/package.json +++ b/extensions/debug-server-ready/package.json @@ -138,6 +138,6 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/debug-server-ready/yarn.lock b/extensions/debug-server-ready/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/debug-server-ready/yarn.lock +++ b/extensions/debug-server-ready/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 82b4e1fea69..968a7fd1bfa 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -430,7 +430,7 @@ "deps": "yarn add vscode-emmet-helper" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "dependencies": { "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 3bb7f3316d5..3a097ca54d6 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -53,10 +53,10 @@ resolved "https://registry.yarnpkg.com/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz#46cffea119a0a003312a21c2d9b5628cb5fcd442" integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= -"@types/node@^12.11.7": - version "12.19.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46" - integrity sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== emmet@^2.1.5: version "2.1.6" diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index bdd02d870a9..14c98dc5c90 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -59,6 +59,6 @@ }, "devDependencies": { "@types/markdown-it": "0.0.2", - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock index 50adf31c099..0cc52354796 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@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/node@^6.0.46": version "6.0.78" diff --git a/extensions/git-ui/package.json b/extensions/git-ui/package.json index 2aa9add1c75..1b20849b19a 100644 --- a/extensions/git-ui/package.json +++ b/extensions/git-ui/package.json @@ -26,6 +26,6 @@ "watch": "gulp watch-extension:git-ui" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/git-ui/yarn.lock b/extensions/git-ui/yarn.lock index 40784952b89..e03bdd573ea 100644 --- a/extensions/git-ui/yarn.lock +++ b/extensions/git-ui/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== diff --git a/extensions/git/package.json b/extensions/git/package.json index 8cc1a070377..45d4d333abe 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2319,8 +2319,8 @@ "devDependencies": { "@types/byline": "4.2.31", "@types/file-type": "^5.2.1", - "@types/mocha": "2.2.43", - "@types/node": "^12.12.31", + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9", "@types/which": "^1.0.28" } } diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 4029d537352..971cc6e091c 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -16,20 +16,20 @@ dependencies: "@types/node" "*" -"@types/mocha@2.2.43": - version "2.2.43" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27" - integrity sha512-xNlAmH+lRJdUMXClMTI9Y0pRqIojdxfm7DHsIxoB2iTzu3fnPmSMEN8SsSx0cdwV36d02PWCWaDUoZPDSln+xw== +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== "@types/node@*": version "8.0.51" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@^12.12.31": - version "12.12.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.31.tgz#d6b4f9645fee17f11319b508fb1001797425da51" - integrity sha512-T+wnJno8uh27G9c+1T+a1/WYCHzLeDqtsGJkoEdSp2X8RTh3oOCZQcUnjAx90CS8cmmADX51O0FI/tu9s0yssg== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/which@^1.0.28": version "1.0.28" diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index 0645048512f..70adf885634 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -59,8 +59,8 @@ "vscode-nls": "^4.1.2" }, "devDependencies": { - "@types/node": "^10.12.21", - "@types/node-fetch": "2.5.7", + "@types/node": "^12.19.9", + "@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 5f2c8bd9e8f..1da6beed526 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node-fetch@2.5.7": +"@types/node-fetch@^2.5.7": version "2.5.7" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== @@ -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@^10.12.21": - version "10.17.24" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.24.tgz#c57511e3a19c4b5e9692bb2995c40a3a52167944" - integrity sha512-5SCfvCxV74kzR3uWgTYiGxrd69TbT1I6+cMx1A5kEly/IVveJBimtAMlXiEyVFn5DvUFewQWxOOiJhlxeQwxgA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/uuid@8.0.0": version "8.0.0" diff --git a/extensions/github/package.json b/extensions/github/package.json index 74030783f4e..828ca9659e7 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -63,6 +63,6 @@ "vscode-nls": "^4.1.2" }, "devDependencies": { - "@types/node": "^10.12.21" + "@types/node": "^12.19.9" } } diff --git a/extensions/github/yarn.lock b/extensions/github/yarn.lock index a9e0ba38b6b..5e790ac2903 100644 --- a/extensions/github/yarn.lock +++ b/extensions/github/yarn.lock @@ -104,10 +104,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== -"@types/node@^10.12.21": - version "10.17.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.14.tgz#b6c60ebf2fb5e4229fdd751ff9ddfae0f5f31541" - integrity sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== before-after-hook@^2.1.0: version "2.1.0" diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index 40344a17913..ccf9440b3a8 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/grunt/yarn.lock b/extensions/grunt/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/grunt/yarn.lock +++ b/extensions/grunt/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 3577dd8e37e..b0b25f31afa 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/gulp/yarn.lock b/extensions/gulp/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/gulp/yarn.lock +++ b/extensions/gulp/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== 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 4d39f2a5e8f..ec59830eb1a 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -244,6 +244,6 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index 7a46c654f32..5b187b5ae79 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -16,8 +16,8 @@ "vscode-uri": "^2.1.2" }, "devDependencies": { - "@types/mocha": "^8.0.3", - "@types/node": "^12.11.7" + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9" }, "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 747e89cca4f..c5cda8eef21 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -2,15 +2,15 @@ # yarn lockfile v1 -"@types/mocha@^8.0.3": - version "8.0.3" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.3.tgz#51b21b6acb6d1b923bbdc7725c38f9f455166402" - integrity sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg== +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-css-languageservice@^5.0.0: version "5.0.0" diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index 716146e2034..dea3c0177dd 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== applicationinsights@1.0.8: version "1.0.8" diff --git a/extensions/jake/package.json b/extensions/jake/package.json index e919813a216..03e60fe32b9 100644 --- a/extensions/jake/package.json +++ b/extensions/jake/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/jake/yarn.lock +++ b/extensions/jake/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== 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 ddfad88efe8..61744a22209 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -135,6 +135,6 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 6be6c7c96ba..e7065fef258 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -19,8 +19,8 @@ "vscode-uri": "^2.1.2" }, "devDependencies": { - "@types/mocha": "2.2.33", - "@types/node": "^12.11.7" + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9" }, "scripts": { "prepublishOnly": "npm run clean && npm run compile", diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index d38ac210239..b9b521f0d3d 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -2,15 +2,15 @@ # yarn lockfile v1 -"@types/mocha@2.2.33": - version "2.2.33" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.33.tgz#d79a0061ec270379f4d9e225f4096fb436669def" - integrity sha1-15oAYewnA3n02eIl9AlvtDZmne8= +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== agent-base@4: version "4.1.2" diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index 2f93800d4ea..8946235df55 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== agent-base@4: version "4.2.1" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 864bba056bd..d72f4cd947f 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -334,7 +334,7 @@ "@types/highlight.js": "10.1.0", "@types/lodash.throttle": "^4.1.3", "@types/markdown-it": "0.0.2", - "@types/node": "^12.11.7", + "@types/node": "^12.19.9", "lodash.throttle": "^4.1.1" } } diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 42cef5218ff..b2068e2d480 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -26,10 +26,10 @@ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA= -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== applicationinsights@1.0.8: version "1.0.8" diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index d438b96ca61..708166d4508 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -139,6 +139,6 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index fa30eb64de1..0d1f221cf12 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -39,11 +39,11 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "devDependencies": { - "@types/node": "^10.12.21", + "@types/node": "^12.19.9", "@types/node-fetch": "^2.5.7", "@types/randombytes": "^2.0.0", "@types/sha.js": "^2.4.0", - "@types/uuid": "^8.0.0" + "@types/uuid": "8.0.0" }, "dependencies": { "buffer": "^5.6.0", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index 48477e958b1..58e34ee843a 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@^10.12.21": - version "10.17.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" - integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/randombytes@^2.0.0": version "2.0.0" @@ -34,7 +34,7 @@ dependencies: "@types/node" "*" -"@types/uuid@^8.0.0": +"@types/uuid@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0" integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw== diff --git a/extensions/npm/package.json b/extensions/npm/package.json index 5210c52963f..873107fd70a 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -28,7 +28,7 @@ }, "devDependencies": { "@types/minimatch": "^3.0.3", - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "resolutions": { "which-pm/load-yaml-file/**/argparse": "1.0.9" diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index 0fa2f344a26..c8ca31e3343 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@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== agent-base@4: version "4.2.0" diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json index 2856782f547..63801b228c3 100644 --- a/extensions/php-language-features/package.json +++ b/extensions/php-language-features/package.json @@ -82,6 +82,6 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" } } diff --git a/extensions/php-language-features/yarn.lock b/extensions/php-language-features/yarn.lock index 7af62a72ce7..687f15f481e 100644 --- a/extensions/php-language-features/yarn.lock +++ b/extensions/php-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 6c2c9499d91..783657aece7 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -24,8 +24,8 @@ "vscode-nls": "^4.1.1" }, "devDependencies": { - "@types/node": "^12.11.7", - "@types/rimraf": "2.0.2", + "@types/node": "^12.19.9", + "@types/rimraf": "^2.0.4", "@types/semver": "^5.5.0", "terser": "^4.8.0", "typescript-web": "npm:typescript@^4.2.0-dev.20201209" diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 1fdba2390f1..6907a50fd6f 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -20,15 +20,15 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256" integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA== -"@types/node@^12.11.7": - version "12.12.62" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.62.tgz#733923d73669188d35950253dd18a21570085d2b" - integrity sha512-qAfo81CsD7yQIM9mVyh6B/U47li5g7cfpVQEDMfQeF8pSZVwzbhwU3crc0qG4DmpsebpJPR49AKOExQyJ05Cpg== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== -"@types/rimraf@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== +"@types/rimraf@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" + integrity sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q== dependencies: "@types/glob" "*" "@types/node" "*" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 80f26fd569d..f7facc24b7a 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -113,7 +113,7 @@ "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-api-tests ./tsconfig.json" }, "devDependencies": { - "@types/mocha": "2.2.43", - "@types/node": "^12.11.7" + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9" } } diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index 11bd660666f..0e3ca71c654 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -2,12 +2,12 @@ # yarn lockfile v1 -"@types/mocha@2.2.43": - version "2.2.43" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27" - integrity sha512-xNlAmH+lRJdUMXClMTI9Y0pRqIojdxfm7DHsIxoB2iTzu3fnPmSMEN8SsSx0cdwV36d02PWCWaDUoZPDSln+xw== +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index 454f983a2a7..30c728cfb4e 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": "^12.11.7" + "@types/node": "^12.19.9" }, "contributes": { "semanticTokenTypes": [ diff --git a/extensions/vscode-colorize-tests/yarn.lock b/extensions/vscode-colorize-tests/yarn.lock index f5cad7b6b29..a02d1775928 100644 --- a/extensions/vscode-colorize-tests/yarn.lock +++ b/extensions/vscode-colorize-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== 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 e5a7575eefb..481b8db61ec 100644 --- a/extensions/vscode-custom-editor-tests/package.json +++ b/extensions/vscode-custom-editor-tests/package.json @@ -21,7 +21,7 @@ "p-limit": "^3.0.2" }, "devDependencies": { - "@types/node": "^12.11.7", + "@types/node": "^12.19.9", "@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 99746c8e453..29a81a09a49 100644 --- a/extensions/vscode-custom-editor-tests/yarn.lock +++ b/extensions/vscode-custom-editor-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.12.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.53.tgz#be0d375933c3d15ef2380dafb3b0350ea7021129" - integrity sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@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 a5abb3ec203..85f01c009bc 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -19,7 +19,7 @@ }, "dependencies": {}, "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "contributes": { "commands": [ diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index d1368d1d58f..480fb62d3e4 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -1269,7 +1269,7 @@ suite('regression', () => { await vscode.commands.executeCommand('vscode.open', cell.uri, vscode.ViewColumn.Active); assert.strictEqual(!!vscode.window.activeNotebookEditor, true); - assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.toString(), resource.toString()); + assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), resource.toString()); }); test('Cannot open notebook from cell-uri with vscode.open-command', async function () { diff --git a/extensions/vscode-notebook-tests/yarn.lock b/extensions/vscode-notebook-tests/yarn.lock index 6dd08a8693a..e03bdd573ea 100644 --- a/extensions/vscode-notebook-tests/yarn.lock +++ b/extensions/vscode-notebook-tests/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.12.37" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.37.tgz#cb4782d847f801fa58316da5b4801ca3a59ae790" - integrity sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index 0a112f12a91..be40b29fbd4 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -22,7 +22,7 @@ ], "main": "./out/extension", "devDependencies": { - "@types/node": "^12.11.7" + "@types/node": "^12.19.9" }, "contributes": { "resourceLabelFormatters": [ diff --git a/extensions/vscode-test-resolver/yarn.lock b/extensions/vscode-test-resolver/yarn.lock index 40784952b89..e03bdd573ea 100644 --- a/extensions/vscode-test-resolver/yarn.lock +++ b/extensions/vscode-test-resolver/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== diff --git a/package.json b/package.json index 92be75cbad4..35f1036e69b 100644 --- a/package.json +++ b/package.json @@ -85,13 +85,13 @@ "@types/applicationinsights": "0.20.0", "@types/chokidar": "2.1.3", "@types/cookie": "^0.3.3", - "@types/debug": "^4.1.5", + "@types/debug": "4.1.5", "@types/graceful-fs": "4.1.2", "@types/http-proxy-agent": "^2.0.1", "@types/keytar": "^4.4.0", - "@types/minimist": "^1.2.0", - "@types/mocha": "2.2.39", - "@types/node": "^12.11.7", + "@types/minimist": "^1.2.1", + "@types/mocha": "^8.2.0", + "@types/node": "^12.19.9", "@types/sinon": "^1.16.36", "@types/trusted-types": "^1.0.6", "@types/vscode-windows-registry": "^1.0.0", diff --git a/test/automation/package.json b/test/automation/package.json index fdad32d4e4f..aab98104f71 100644 --- a/test/automation/package.json +++ b/test/automation/package.json @@ -24,7 +24,7 @@ "@types/debug": "4.1.5", "@types/mkdirp": "0.5.1", "@types/ncp": "2.0.1", - "@types/node": "^12.11.7", + "@types/node": "^12.19.9", "@types/tmp": "0.1.0", "cpx": "^1.5.0", "mkdirp": "^0.5.1", @@ -36,4 +36,4 @@ "vscode-uri": "^2.0.3", "watch": "^1.0.2" } -} \ No newline at end of file +} diff --git a/test/automation/yarn.lock b/test/automation/yarn.lock index cf8184cc4c5..4e37fb4cd55 100644 --- a/test/automation/yarn.lock +++ b/test/automation/yarn.lock @@ -26,10 +26,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.1.tgz#3b5c3a26393c19b400844ac422bd0f631a94d69d" integrity sha512-aK9jxMypeSrhiYofWWBf/T7O+KwaiAHzM4sveCdWPn71lzUSMimRnKzhXDKfKwV1kWoBo2P1aGgaIYGLf9/ljw== -"@types/node@^12.11.7": - version "12.12.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.26.tgz#213e153babac0ed169d44a6d919501e68f59dea9" - integrity sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/tmp@0.1.0": version "0.1.0" diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json index 39c4603f80b..5ae027e9bd0 100644 --- a/test/integration/browser/package.json +++ b/test/integration/browser/package.json @@ -9,10 +9,10 @@ }, "devDependencies": { "@types/mkdirp": "0.5.1", - "@types/node": "^12.11.7", + "@types/node": "^12.19.9", "@types/optimist": "0.0.29", - "@types/rimraf": "2.0.2", - "@types/tmp": "^0.1.0", + "@types/rimraf": "^2.0.4", + "@types/tmp": "0.1.0", "rimraf": "^2.6.1", "tmp": "0.0.33", "tree-kill": "1.2.2", diff --git a/test/integration/browser/yarn.lock b/test/integration/browser/yarn.lock index 126da8138c5..d66658e6b5a 100644 --- a/test/integration/browser/yarn.lock +++ b/test/integration/browser/yarn.lock @@ -33,25 +33,25 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.0.tgz#b417deda18cf8400f278733499ad5547ed1abec4" integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ== -"@types/node@^12.11.7": - version "12.12.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.26.tgz#213e153babac0ed169d44a6d919501e68f59dea9" - integrity sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/optimist@0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/optimist/-/optimist-0.0.29.tgz#a8873580b3a84b69ac1e687323b15fbbeb90479a" integrity sha1-qIc1gLOoS2msHmhzI7Ffu+uQR5o= -"@types/rimraf@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== +"@types/rimraf@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" + integrity sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q== dependencies: "@types/glob" "*" "@types/node" "*" -"@types/tmp@^0.1.0": +"@types/tmp@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd" integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA== diff --git a/test/smoke/package.json b/test/smoke/package.json index 2d1ebf915de..debabba2919 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -14,10 +14,10 @@ "devDependencies": { "@types/htmlparser2": "3.7.29", "@types/mkdirp": "0.5.1", - "@types/mocha": "2.2.41", + "@types/mocha": "^8.2.0", "@types/ncp": "2.0.1", - "@types/node": "^12.11.7", - "@types/rimraf": "2.0.2", + "@types/node": "^12.19.9", + "@types/rimraf": "^2.0.4", "cpx": "^1.5.0", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", diff --git a/test/smoke/src/areas/workbench/launch.test.ts b/test/smoke/src/areas/workbench/launch.test.ts index 3d1e4c42fd0..0365098ff24 100644 --- a/test/smoke/src/areas/workbench/launch.test.ts +++ b/test/smoke/src/areas/workbench/launch.test.ts @@ -20,8 +20,8 @@ export function setup() { afterEach(async function () { if (app) { - if (this.currentTest.state === 'failed') { - const name = this.currentTest.fullTitle().replace(/[^a-z0-9\-]/ig, '_'); + if (this.currentTest!.state === 'failed') { + const name = this.currentTest!.fullTitle().replace(/[^a-z0-9\-]/ig, '_'); await app.captureScreenshot(name); } } diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 6bd6204c6e5..7864474af2b 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -268,20 +268,20 @@ after(async function () { if (opts.log) { const logsDir = path.join(userDataDir, 'logs'); const destLogsDir = path.join(path.dirname(opts.log), 'logs'); - await new Promise((c, e) => ncp(logsDir, destLogsDir, err => err ? e(err) : c())); + await new Promise((c, e) => ncp(logsDir, destLogsDir, err => err ? e(err) : c(undefined))); } - await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c())); + await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c(undefined))); }); describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { if (screenshotsPath) { afterEach(async function () { - if (this.currentTest.state !== 'failed') { + if (this.currentTest!.state !== 'failed') { return; } const app = this.app as Application; - const name = this.currentTest.fullTitle().replace(/[^a-z0-9\-]/ig, '_'); + const name = this.currentTest!.fullTitle().replace(/[^a-z0-9\-]/ig, '_'); await app.captureScreenshot(name); }); @@ -290,7 +290,7 @@ describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { if (opts.log) { beforeEach(async function () { const app = this.app as Application; - const title = this.currentTest.fullTitle(); + const title = this.currentTest!.fullTitle(); app.logger.log('*** Test start:', title); }); diff --git a/test/smoke/src/utils.ts b/test/smoke/src/utils.ts index 35d9ef41ad9..c987c19992c 100644 --- a/test/smoke/src/utils.ts +++ b/test/smoke/src/utils.ts @@ -3,15 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ISuiteCallbackContext, ITestCallbackContext } from 'mocha'; +import { Suite, Context } from 'mocha'; -export function describeRepeat(n: number, description: string, callback: (this: ISuiteCallbackContext) => void): void { +export function describeRepeat(n: number, description: string, callback: (this: Suite) => void): void { for (let i = 0; i < n; i++) { describe(`${description} (iteration ${i})`, callback); } } -export function itRepeat(n: number, description: string, callback: (this: ITestCallbackContext, done: MochaDone) => any): void { +export function itRepeat(n: number, description: string, callback: (this: Context) => any): void { for (let i = 0; i < n; i++) { it(`${description} (iteration ${i})`, callback); } diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index a91bba0d682..a5050d6aa41 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -33,10 +33,10 @@ dependencies: "@types/node" "*" -"@types/mocha@2.2.41": - version "2.2.41" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608" - integrity sha1-4nzwgXFT658nE7LT9saPHhw8pgg= +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== "@types/ncp@2.0.1": version "2.0.1" @@ -50,15 +50,15 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== -"@types/node@^12.11.7": - version "12.12.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.34.tgz#0a5d6ae5d22612f0cf5f10320e1fc5d2a745dcb8" - integrity sha512-BneGN0J9ke24lBRn44hVHNeDlrXRYF+VRp0HbSUNnEZahXGAysHZIqnf/hER6aabdBgzM4YOV4jrR8gj4Zfi0g== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== -"@types/rimraf@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== +"@types/rimraf@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" + integrity sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q== dependencies: "@types/glob" "*" "@types/node" "*" diff --git a/yarn.lock b/yarn.lock index 1bf3b732fd7..ab660b1300f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -238,7 +238,7 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== -"@types/debug@^4.1.5": +"@types/debug@4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== @@ -290,15 +290,15 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/minimist@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" - integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= +"@types/minimist@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" + integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== -"@types/mocha@2.2.39": - version "2.2.39" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.39.tgz#f68d63db8b69c38e9558b4073525cf96c4f7a829" - integrity sha1-9o1j24tpw46VWLQHNSXPlsT3qCk= +"@types/mocha@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" + integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== "@types/node@*": version "4.2.22" @@ -315,10 +315,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.24.tgz#d4606afd8cf6c609036b854360367d1b2c78931f" integrity sha512-1Ciqv9pqwVtW6FsIUKSZNB82E5Cu1I2bBTj1xuIHXLe/1zYLl3956Nbhg2MzSYHVfl9/rmanjbQIb7LibfCnug== -"@types/node@^12.11.7": - version "12.12.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" - integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== +"@types/node@^12.19.9": + version "12.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" + integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== "@types/node@^13.13.5": version "13.13.34" From db82bc13aa6c85233ae67ad8d265a9a3d6837d3d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 13:39:23 +0100 Subject: [PATCH 1230/1837] Move /build/ dev dependencies to root (#112718) --- build/package.json | 22 +- build/yarn.lock | 3142 +------------------------------------------- package.json | 31 +- yarn.lock | 688 +++++++++- 4 files changed, 650 insertions(+), 3233 deletions(-) diff --git a/build/package.json b/build/package.json index 3ec73fd8382..e0673d4189e 100644 --- a/build/package.json +++ b/build/package.json @@ -32,27 +32,7 @@ "@types/underscore": "^1.8.9", "@types/xml2js": "0.0.33", "@typescript-eslint/experimental-utils": "~2.13.0", - "@typescript-eslint/parser": "^3.3.0", - "applicationinsights": "1.0.8", - "azure-storage": "^2.1.0", - "electron-osx-sign": "^0.4.16", - "github-releases": "^0.4.1", - "gulp-azure-storage": "^0.11.1", - "gulp-bom": "^1.0.0", - "gulp-gzip": "^1.4.2", - "gulp-sourcemaps": "^1.11.0", - "gulp-uglify": "^3.0.0", - "iconv-lite-umd": "0.6.8", - "jsonc-parser": "^2.3.0", - "mime": "^1.4.1", - "minimatch": "^3.0.4", - "minimist": "^1.2.3", - "request": "^2.85.0", - "terser": "4.3.8", - "typescript": "4.2.0-dev.20201207", - "vsce": "1.48.0", - "vscode-telemetry-extractor": "^1.6.0", - "xml2js": "^0.4.17" + "typescript": "4.2.0-dev.20201207" }, "scripts": { "compile": "tsc -p tsconfig.build.json", diff --git a/build/yarn.lock b/build/yarn.lock index 3f865daf638..08b653e434a 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -19,43 +19,6 @@ universal-user-agent "^6.0.0" uuid "^8.3.0" -"@dsherret/to-absolute-glob@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1f6475dc8bd974cea07a2daf3864b317b1dd332c" - integrity sha1-H2R13IvZdM6gei2vOGSzF7HdMyw= - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -"@gulp-sourcemaps/map-sources@1.X": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" - integrity sha1-iQrnxdjId/bThIYCFazp1+yUW9o= - dependencies: - normalize-path "^2.0.1" - through2 "^2.0.3" - -"@nodelib/fs.scandir@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" - integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== - dependencies: - "@nodelib/fs.stat" "2.0.1" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" - integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== - -"@nodelib/fs.walk@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" - integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== - dependencies: - "@nodelib/fs.scandir" "2.1.1" - fastq "^1.6.0" - "@types/ansi-colors@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@types/ansi-colors/-/ansi-colors-3.2.0.tgz#3e4fe85d9131ce1c6994f3040bd0b25306c16a6e" @@ -91,11 +54,6 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/eslint@4.16.1": version "4.16.1" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.1.tgz#19730c9fcb66b6e44742d12b27a603fabfeb2f49" @@ -343,17 +301,6 @@ resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de" integrity sha1-IMXdZGAkUoTWSlVpABW5XkCft94= -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/experimental-utils@~2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.13.0.tgz#958614faa6f77599ee2b241740e0ea402482533d" @@ -363,22 +310,6 @@ "@typescript-eslint/typescript-estree" "2.13.0" eslint-scope "^5.0.0" -"@typescript-eslint/parser@^3.3.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - "@typescript-eslint/typescript-estree@2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.13.0.tgz#a2e746867da772c857c13853219fced10d2566bc" @@ -392,321 +323,11 @@ semver "^6.3.0" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== - dependencies: - eslint-visitor-keys "^1.1.0" - -acorn@4.X: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= - -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== - -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ajv@^6.12.3: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-colors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" - integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== - dependencies: - ansi-wrap "^0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-wrap@0.1.0, ansi-wrap@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -any-promise@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= - -append-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= - dependencies: - buffer-equal "^1.0.0" - -applicationinsights@1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" - integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== - dependencies: - diagnostic-channel "0.2.0" - diagnostic-channel-publishers "0.2.1" - zone.js "0.7.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-back@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-differ@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" - integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== - -array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.2.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= - -aws4@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" - integrity sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w== - -aws4@^1.8.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" - integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== - -azure-storage@^2.1.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.6.0.tgz#84747ee54a4bd194bb960f89f3eff89d67acf1cf" - integrity sha1-hHR+5UpL0ZS7lg+J8+/4nWes8c8= - dependencies: - browserify-mime "~1.2.9" - extend "~1.2.1" - json-edm-parser "0.1.2" - md5.js "1.3.4" - readable-stream "~2.0.0" - request "~2.81.0" - underscore "~1.8.3" - uuid "^3.0.0" - validator "~3.35.0" - xml2js "0.2.7" - xmlbuilder "0.4.3" - -azure-storage@^2.10.2: - version "2.10.3" - resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.3.tgz#c5966bf929d87587d78f6847040ea9a4b1d4a50a" - integrity sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ== - dependencies: - browserify-mime "~1.2.9" - extend "^3.0.2" - json-edm-parser "0.1.2" - md5.js "1.3.4" - readable-stream "~2.0.0" - request "^2.86.0" - underscore "~1.8.3" - uuid "^3.0.0" - validator "~9.4.1" - xml2js "0.2.8" - xmlbuilder "^9.0.7" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.2.3: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== - dependencies: - hoek "4.x.x" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -715,308 +336,21 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserify-mime@~1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/browserify-mime/-/browserify-mime-1.2.9.tgz#aeb1af28de6c0d7a6a2ce40adb68ff18422af31f" - integrity sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8= - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -bytes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -cheerio@^1.0.0-rc.1: - version "1.0.0-rc.2" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" - integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -cloneable-readable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" - integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-block-writer@9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-9.4.1.tgz#1448fca79dfc7a3649000f4c85be6bc770604c4c" - integrity sha512-LHAB+DL4YZDcwK8y/kAxZ0Lf/ncwLh/Ux4cTVWbPwIdrf1gPxXiPcwpz8r8/KqXu1aD+Raz46EOxDjFlbyO6bA== - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -colors@^1.1.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.1.tgz#f4a3d302976aaf042356ba1ade3b1a2c62d9d794" - integrity sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg== - -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= - dependencies: - delayed-stream "~1.0.0" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= - dependencies: - delayed-stream "~1.0.0" - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -command-line-args@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a" - integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg== - dependencies: - array-back "^3.0.1" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -commander@^2.20.0, commander@~2.20.0: +commander@^2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== -commander@^2.8.1: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - -compare-version@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" - integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -convert-source-map@1.X: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -convert-source-map@^1.5.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4= - dependencies: - boom "5.x.x" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-what@2.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" - integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== - -css@2.X: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug-fabulous@0.0.X: - version "0.0.4" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763" - integrity sha1-+gccXYdIRoVCSAdCHKSxawsaB2M= - dependencies: - debug "2.X" - lazy-debug-legacy "0.0.X" - object-assign "4.1.0" - -debug@2.X, debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" @@ -1024,198 +358,6 @@ debug@^4.1.1: dependencies: ms "2.1.2" -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -delayed-stream@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.6.tgz#a2646cb7ec3d5d7774614670a7a65de0c173edbc" - integrity sha1-omRst+w9XXd0YUZwp6Zd4MFz7bw= - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -denodeify@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= - -detect-newline@2.X: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= - -diagnostic-channel-publishers@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" - integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM= - -diagnostic-channel@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" - integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc= - dependencies: - semver "^5.3.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domelementtype@1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.2.1.tgz#578558ef23befac043a1abb0db07635509393479" - integrity sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA== - -domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - -electron-osx-sign@^0.4.16: - version "0.4.16" - resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.16.tgz#0be8e579b2d9fa4c12d2a21f063898294b3434aa" - integrity sha512-ziMWfc3NmQlwnWLW6EaZq8nH2BWVng/atX5GWsGwhexJYpdW6hsg//MkAfRTRx1kR3Veiqkeiog1ibkbA4x0rg== - dependencies: - bluebird "^3.5.0" - compare-version "^0.1.2" - debug "^2.6.8" - isbinaryfile "^3.0.2" - minimist "^1.2.0" - plist "^3.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: - version "1.18.0-next.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" - integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - eslint-scope@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" @@ -1224,13 +366,6 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" @@ -1248,267 +383,17 @@ estraverse@^4.1.0, estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -event-stream@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extend@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-1.2.1.tgz#a0f5fd6cfc83a5fe49ef698d60ec8a624dd4576c" - integrity sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w= - -extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= - -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -fancy-log@^1.1.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - -fancy-log@^1.3.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" - integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== - dependencies: - "@nodelib/fs.stat" "^2.0.1" - "@nodelib/fs.walk" "^1.2.1" - glob-parent "^5.0.0" - is-glob "^4.0.1" - merge2 "^1.2.3" - micromatch "^4.0.2" - fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fastq@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" - integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== - dependencies: - reusify "^1.0.0" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -flush-write-stream@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-mkdirp-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= - dependencies: - graceful-fs "^4.1.11" - through2 "^2.0.3" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -github-releases@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.4.1.tgz#4a13bdf85c4161344271db3d81db08e7379102ff" - integrity sha1-ShO9+FxBYTRCcds9gdsI5zeRAv8= - dependencies: - minimatch "3.0.4" - optimist "0.6.1" - prettyjson "1.2.1" - request "2.81.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" - integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== - dependencies: - is-glob "^4.0.1" - -glob-stream@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= - dependencies: - extend "^3.0.0" - glob "^7.1.1" - glob-parent "^3.1.0" - is-negated-glob "^1.0.0" - ordered-read-streams "^1.0.0" - pumpify "^1.3.5" - readable-stream "^2.1.5" - remove-trailing-separator "^1.0.1" - to-absolute-glob "^2.0.0" - unique-stream "^2.0.2" - -glob@^7.0.6: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.6: +glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1520,300 +405,6 @@ glob@^7.1.1, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globby@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - -glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - integrity sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw== - dependencies: - sparkles "^1.0.0" - -graceful-fs@4.X: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= - -graceful-fs@^4.0.0, graceful-fs@^4.1.11: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== - -gulp-azure-storage@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/gulp-azure-storage/-/gulp-azure-storage-0.11.1.tgz#0e5f5d0f789da11206f1e5a9311a6cf7107877d7" - integrity sha512-csOwItwZV1P9GLsORVQy+CFwjYDdHNrBol89JlHdlhGx0fTgJBc1COTRZbjGRyRjgdUuVguo3YLl4ToJ10/SIQ== - dependencies: - azure-storage "^2.10.2" - delayed-stream "0.0.6" - event-stream "3.3.4" - mime "^1.3.4" - progress "^1.1.8" - queue "^3.0.10" - streamifier "^0.1.1" - vinyl "^2.2.0" - vinyl-fs "^3.0.3" - yargs "^15.3.0" - -gulp-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-bom/-/gulp-bom-1.0.0.tgz#38a183a07187bd57a7922d37977441f379df2abf" - integrity sha1-OKGDoHGHvVenki03l3RB83nfKr8= - dependencies: - gulp-util "^3.0.0" - through2 "^2.0.0" - -gulp-gzip@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/gulp-gzip/-/gulp-gzip-1.4.2.tgz#0422a94014248655b5b1a9eea1c2abee1d4f4337" - integrity sha512-ZIxfkUwk2XmZPTT9pPHrHUQlZMyp9nPhg2sfoeN27mBGpi7OaHnOD+WCN41NXjfJQ69lV1nQ9LLm1hYxx4h3UQ== - dependencies: - ansi-colors "^1.0.1" - bytes "^3.0.0" - fancy-log "^1.3.2" - plugin-error "^1.0.0" - stream-to-array "^2.3.0" - through2 "^2.0.3" - -gulp-sourcemaps@^1.11.0: - version "1.12.1" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.12.1.tgz#b437d1f3d980cf26e81184823718ce15ae6597b6" - integrity sha1-tDfR89mAzyboEYSCNxjOFa5ll7Y= - dependencies: - "@gulp-sourcemaps/map-sources" "1.X" - acorn "4.X" - convert-source-map "1.X" - css "2.X" - debug-fabulous "0.0.X" - detect-newline "2.X" - graceful-fs "4.X" - source-map "~0.6.0" - strip-bom "2.X" - through2 "2.X" - vinyl "1.X" - -gulp-uglify@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.2.tgz#5f5b2e8337f879ca9dec971feb1b82a5a87850b0" - integrity sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg== - dependencies: - array-each "^1.0.1" - extend-shallow "^3.0.2" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - isobject "^3.0.1" - make-error-cause "^1.1.1" - safe-buffer "^5.1.2" - through2 "^2.0.0" - uglify-js "^3.0.5" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-util@^3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4= - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio= - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== - -htmlparser2@^3.9.1: - version "3.10.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" - integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.0.6" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.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" - -iconv-lite-umd@0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" - integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== - -ignore@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" - integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1822,63 +413,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@~2.0.0: +inherits@2: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.4, is-callable@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" - integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== - -is-date-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -1886,493 +430,28 @@ is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-negated-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= - -is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" - integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== - dependencies: - has-symbols "^1.0.1" - -is-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== - dependencies: - is-unc-path "^1.0.0" - -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== - dependencies: - has-symbols "^1.0.1" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== - dependencies: - unc-path-regex "^0.1.2" - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= - -is-windows@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isbinaryfile@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" - integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== - dependencies: - buffer-alloc "^1.2.0" - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - jsbi@^3.1.3: version "3.1.4" resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.4.tgz#9654dd02207a66a4911b4e4bb74265bc2cbc9dd0" integrity sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg== -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-edm-parser@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/json-edm-parser/-/json-edm-parser-0.1.2.tgz#1e60b0fef1bc0af67bc0d146dfdde5486cd615b4" - integrity sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ= - dependencies: - jsonparse "~1.2.0" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsonc-parser@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee" - integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonparse@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.2.0.tgz#5c0c5685107160e72fe7489bddea0b44c2bc67bd" - integrity sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -lazy-debug-legacy@0.0.X: - version "0.0.1" - resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" - integrity sha1-U3cWwHduTPeePtG2IfdljCkRsbE= - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= - dependencies: - flush-write-stream "^1.0.2" - -linkify-it@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" - integrity sha1-2UpGSPmxwXnWT6lykSaL22zpQ08= - dependencies: - uc.micro "^1.0.1" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.unescape@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= -lodash@^4.15.0, lodash@^4.17.10: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== - -lodash@^4.17.15: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -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" - -make-error-cause@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" - integrity sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0= - dependencies: - make-error "^1.2.0" - -make-error@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" - integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -markdown-it@^8.3.1: - version "8.4.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" - integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - -md5.js@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" - integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0= - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== - -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= - dependencies: - mime-db "~1.30.0" - -mime-types@~2.1.17: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@~2.1.19: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -mime@^1.3.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - -mime@^1.4.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.3.tgz#3db5c0765545ab8637be71f333a104a965a9ca3f" - integrity sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw== - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2, ms@^2.1.1: +ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multimatch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" - integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== - dependencies: - "@types/minimatch" "^3.0.3" - array-differ "^3.0.0" - array-union "^2.1.0" - arrify "^2.0.1" - minimatch "^3.0.4" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -mute-stream@~0.0.4: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - node-abort-controller@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.1.0.tgz#8a734a631b022af29963be7245c1483cbb9e070d" @@ -2383,610 +462,33 @@ node-fetch@^2.6.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -normalize-path@^2.0.1, normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -now-and-later@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" - integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== - dependencies: - once "^1.3.2" - -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - integrity sha1-ejs9DpgGPUP0wD8uiubNUahog6A= - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-inspect@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.0.4, object.assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" - integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.0" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -optimist@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -ordered-read-streams@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= - dependencies: - readable-stream "^2.0.1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -parse-semver@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parse-semver/-/parse-semver-1.1.1.tgz#9a4afd6df063dc4826f93fba4a99cf223f666cb8" - integrity sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg= - dependencies: - semver "^5.1.0" - -parse5@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== - dependencies: - "@types/node" "*" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== - -plist@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" - integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== - dependencies: - base64-js "^1.2.3" - xmlbuilder "^9.0.7" - xmldom "0.1.x" - -plugin-error@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" - integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== - dependencies: - ansi-colors "^1.0.1" - arr-diff "^4.0.0" - arr-union "^3.1.0" - extend-shallow "^3.0.2" - -prettyjson@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" - integrity sha1-/P+rQdGcq0365eV15kJGYZsS0ok= - dependencies: - colors "^1.1.2" - minimist "^1.2.0" - priorityqueuejs@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz#2ee4f23c2560913e08c07ce5ccdd6de3df2c5af8" integrity sha1-LuTyPCVgkT4IwHzlzN1t498sWvg= -process-nextick-args@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.0.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -queue@^3.0.10: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -read@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= - dependencies: - mute-stream "~0.0.4" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^2.1.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.0.6.tgz#351302e4c68b5abd6a2ed55376a7f9a25be3057a" - integrity sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@~2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - -remove-bom-buffer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" - integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== - dependencies: - is-buffer "^1.1.5" - is-utf8 "^0.2.1" - -remove-bom-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= - dependencies: - remove-bom-buffer "^3.0.0" - safe-buffer "^5.1.0" - through2 "^2.0.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" - integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== - -request@2.81.0, request@~2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -request@^2.85.0: - version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" - integrity sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@^2.86.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-options@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= - dependencies: - value-or-function "^3.0.0" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -reusify@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - -safe-buffer@^5.0.1, safe-buffer@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -sax@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.2.tgz#735ffaa39a1cff8ffb9598f0223abdb03a9fb2ea" - integrity sha1-c1/6o5oc/4/7lZjwIjq9sDqfsuo= - -sax@0.5.x: - version "0.5.8" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" - integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE= - -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - semaphore@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -semver@^5.1.0, semver@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== - 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" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== - dependencies: - hoek "4.x.x" - -source-map-resolve@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-support@~0.5.12: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -2995,145 +497,11 @@ source-map-support@~0.5.12: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.1: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -stream-to-array@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" - integrity sha1-u/azn19D7DC8cbq8s3VXrOzzQ1M= - dependencies: - any-promise "^1.1.0" - -streamifier@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimend@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" - integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - -string.prototype.trimstart@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" - integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - -string_decoder@^1.1.1, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-bom@2.X: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - terser@*: version "4.2.1" resolved "https://registry.yarnpkg.com/terser/-/terser-4.2.1.tgz#1052cfe17576c66e7bc70fcc7119f22b155bdac1" @@ -3143,114 +511,6 @@ terser@*: source-map "~0.6.1" source-map-support "~0.5.12" -terser@4.3.8: - version "4.3.8" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.8.tgz#707f05f3f4c1c70c840e626addfdb1c158a17136" - integrity sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@2.X, through2@^2.0.0, through2@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@~2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -tmp@0.0.29: - version "0.0.29" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" - integrity sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA= - dependencies: - os-tmpdir "~1.0.1" - -to-absolute-glob@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-through@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= - dependencies: - through2 "^2.0.3" - -tough-cookie@~2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= - dependencies: - punycode "^1.4.1" - -tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -ts-morph@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-3.1.3.tgz#bbfa1d14481ee23bdd1c030340ccf4a243cfc844" - integrity sha512-CwjgyJTtd3f8vBi7Vr0IOgdOY6Wi/Tq0MhieXOE2B5ns5WWRD7BwMNHtv+ZufKI/S2U/lMrh+Q3bOauE4tsv2g== - dependencies: - "@dsherret/to-absolute-glob" "^2.0.2" - code-block-writer "9.4.1" - fs-extra "^8.1.0" - glob-parent "^5.0.0" - globby "^10.0.1" - is-negated-glob "^1.0.0" - multimatch "^4.0.0" - typescript "^3.0.1" - tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -3268,408 +528,22 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tunnel@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.4.tgz#2d3785a158c174c9a16dc2c046ec5fc5f1742213" - integrity sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -typed-rest-client@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-0.9.0.tgz#f768cc0dc3f4e950f06e04825c36b3e7834aa1f2" - integrity sha1-92jMDcP06VDwbgSCXDaz54NKofI= - dependencies: - tunnel "0.0.4" - underscore "1.8.3" - typescript@4.2.0-dev.20201207: version "4.2.0-dev.20201207" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20201207.tgz#19a34bc7d2d42a7467c512c63f135587ac848807" integrity sha512-fPHBDi/fgdX4WiRC7cFVv/aL069PgUaDWuLYUSHatWZujz/Lkc9bkf/zL3rKdNSCxlNKAMs3fhJv/yompOphZA== -typescript@^3.0.1: - version "3.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" - integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" - integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg== - -uglify-js@^3.0.5: - version "3.6.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" - integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== - dependencies: - commander "~2.20.0" - source-map "~0.6.1" - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= - -underscore@1.8.3, underscore@~1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= - -underscore@^1.8.3: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-join@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78" - integrity sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg= - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== - -uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - uuid@^8.3.0: version "8.3.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== -validator@~3.35.0: - version "3.35.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-3.35.0.tgz#3f07249402c1fc8fc093c32c6e43d72a79cca1dc" - integrity sha1-PwcklALB/I/Ak8MsbkPXKnnModw= - -validator@~9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663" - integrity sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA== - -value-or-function@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" - integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== - dependencies: - fs-mkdirp-stream "^1.0.0" - glob-stream "^6.1.0" - graceful-fs "^4.0.0" - is-valid-glob "^1.0.0" - lazystream "^1.0.0" - lead "^1.0.0" - object.assign "^4.0.4" - pumpify "^1.3.5" - readable-stream "^2.3.3" - remove-bom-buffer "^3.0.0" - remove-bom-stream "^1.2.0" - resolve-options "^1.1.0" - through2 "^2.0.0" - to-through "^2.0.0" - value-or-function "^3.0.0" - vinyl "^2.0.0" - vinyl-sourcemap "^1.1.0" - -vinyl-sourcemap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= - dependencies: - append-buffer "^1.0.2" - convert-source-map "^1.5.0" - graceful-fs "^4.1.6" - normalize-path "^2.1.1" - now-and-later "^2.0.0" - remove-bom-buffer "^3.0.0" - vinyl "^2.0.0" - -vinyl-sourcemaps-apply@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" - integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= - dependencies: - source-map "^0.5.1" - -vinyl@1.X: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.0, vinyl@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" - integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vsce@1.48.0: - version "1.48.0" - resolved "https://registry.yarnpkg.com/vsce/-/vsce-1.48.0.tgz#31c1a4c6909c3b8bdc48b3d32cc8c8e94c7113a2" - integrity sha512-1qJn6QLRTu26FIvvMbK/gzHLLdxJVTg9CUTSnCjJHObCCF5CQ0F3FUv7t+5cT7i0J5v5YljrsRY09u7dPBcEnA== - dependencies: - cheerio "^1.0.0-rc.1" - commander "^2.8.1" - denodeify "^1.2.1" - glob "^7.0.6" - lodash "^4.17.10" - markdown-it "^8.3.1" - mime "^1.3.4" - minimatch "^3.0.3" - osenv "^0.1.3" - parse-semver "^1.1.1" - read "^1.0.7" - semver "^5.1.0" - tmp "0.0.29" - url-join "^1.1.0" - vso-node-api "6.1.2-preview" - yauzl "^2.3.1" - yazl "^2.2.2" - -vscode-ripgrep@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.6.2.tgz#fb912c7465699f10ce0218a6676cc632c77369b4" - integrity sha512-jkZEWnQFcE+QuQFfxQXWcWtDafTmgkp3DjMKawDkajZwgnDlGKpFp15ybKrZNVTi1SLEF/12BzxYSZVVZ2XrkA== - dependencies: - https-proxy-agent "^4.0.0" - proxy-from-env "^1.1.0" - -vscode-telemetry-extractor@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.6.0.tgz#e9d9c1d24863cce8d3d715f0287de3b31eb90c56" - integrity sha512-zSxvkbyAMa1lTRGIHfGg7gW2e9Sey+2zGYD19uNWCsVEfoXAr2NB6uzb0sNHtbZ2SSqxSePmFXzBAavsudT5fw== - dependencies: - command-line-args "^5.1.1" - ts-morph "^3.1.3" - vscode-ripgrep "^1.6.2" - -vso-node-api@6.1.2-preview: - version "6.1.2-preview" - resolved "https://registry.yarnpkg.com/vso-node-api/-/vso-node-api-6.1.2-preview.tgz#aab3546df2451ecd894e071bb99b5df19c5fa78f" - integrity sha1-qrNUbfJFHs2JTgcbuZtd8Zxfp48= - dependencies: - q "^1.0.1" - tunnel "0.0.4" - typed-rest-client "^0.9.0" - underscore "^1.8.3" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -xml2js@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.7.tgz#1838518bb01741cae0878bab4915e494c32306af" - integrity sha1-GDhRi7AXQcrgh4urSRXklMMjBq8= - dependencies: - sax "0.5.2" - -xml2js@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2" - integrity sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I= - dependencies: - sax "0.5.x" - -xml2js@^0.4.17: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xmlbuilder@0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-0.4.3.tgz#c4614ba74e0ad196e609c9272cd9e1ddb28a8a58" - integrity sha1-xGFLp04K0ZbmCcknLNnh3bKKilg= - -xmlbuilder@^9.0.7: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xmlbuilder@~9.0.1: - version "9.0.4" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f" - integrity sha1-UZy0ymhtAFqEINNJbz8MruzKWA8= - -xmldom@0.1.x: - version "0.1.31" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff" - integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ== - -xtend@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -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== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^15.3.0: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yauzl@^2.3.1: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yazl@^2.2.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" - integrity sha1-7CblzIfVYBud+EMtvdPNLlFzoHE= - dependencies: - buffer-crc32 "~0.2.3" - -zone.js@0.7.6: - version "0.7.6" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" - integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk= diff --git a/package.json b/package.json index 92be75cbad4..96be9e62255 100644 --- a/package.json +++ b/package.json @@ -105,26 +105,30 @@ "@typescript-eslint/eslint-plugin": "3.2.0", "@typescript-eslint/parser": "^3.3.0", "ansi-colors": "^3.2.3", + "applicationinsights": "1.0.8", "asar": "^3.0.3", + "azure-storage": "^2.1.0", "chromium-pickle-js": "^0.2.0", "copy-webpack-plugin": "^6.0.3", "cson-parser": "^1.3.3", "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "11.1.0", + "electron-osx-sign": "^0.4.16", "electron-rebuild": "2.0.3", - "eslint": "6.8.0", + "electron": "11.1.0", "eslint-plugin-jsdoc": "^19.1.0", "eslint-plugin-mocha": "8.0.0", + "eslint": "6.8.0", "event-stream": "3.3.4", "fancy-log": "^1.3.3", "fast-plist": "0.1.2", "file-loader": "^4.2.0", + "github-releases": "^0.4.1", "glob": "^5.0.13", - "gulp": "^4.0.0", "gulp-atom-electron": "^1.22.0", "gulp-azure-storage": "^0.11.1", + "gulp-bom": "^1.0.0", "gulp-buffer": "0.0.2", "gulp-concat": "^2.6.1", "gulp-cssnano": "^2.1.3", @@ -132,16 +136,21 @@ "gulp-filter": "^5.1.0", "gulp-flatmap": "^1.0.2", "gulp-gunzip": "^1.0.0", + "gulp-gzip": "^1.4.2", "gulp-json-editor": "^2.5.0", "gulp-plumber": "^1.2.0", "gulp-remote-retry-src": "^0.6.0", "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.4", "gulp-shell": "^0.6.5", + "gulp-sourcemaps": "^1.11.0", "gulp-tsb": "4.0.5", + "gulp-uglify": "^3.0.0", "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", + "gulp": "^4.0.0", "husky": "^0.13.1", + "iconv-lite-umd": "0.6.8", "innosetup": "6.0.5", "is": "^3.1.0", "istanbul-lib-coverage": "^3.0.0", @@ -150,14 +159,16 @@ "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.0", "jsdom-no-contextify": "^3.1.0", + "jsonc-parser": "^2.3.0", "lazy.js": "^0.4.2", "merge-options": "^1.0.1", "mime": "^1.4.1", "minimatch": "^3.0.4", + "minimist": "^1.2.5", "mkdirp": "^0.5.0", - "mocha": "^8.2.1", "mocha-junit-reporter": "^2.0.0", "mocha-multi-reporters": "^1.5.1", + "mocha": "^8.2.1", "npm-run-all": "^4.1.5", "opn": "^6.0.0", "optimist": "0.3.5", @@ -166,24 +177,28 @@ "pump": "^1.0.1", "queue": "3.0.6", "rcedit": "^1.1.0", + "request": "^2.85.0", "rimraf": "^2.2.8", "sinon": "^1.17.2", - "source-map": "^0.4.4", "source-map-support": "^0.3.2", + "source-map": "^0.4.4", "style-loader": "^1.0.0", + "terser": "4.3.8", "ts-loader": "^6.2.1", "tsec": "googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1", - "typescript": "4.2.0-dev.20201207", "typescript-formatter": "7.1.0", + "typescript": "4.2.0-dev.20201207", "underscore": "^1.8.2", - "vinyl": "^2.0.0", "vinyl-fs": "^3.0.0", + "vinyl": "^2.0.0", "vsce": "1.48.0", "vscode-debugprotocol": "1.43.0", "vscode-nls-dev": "^3.3.1", - "webpack": "^4.43.0", + "vscode-telemetry-extractor": "^1.6.0", "webpack-cli": "^3.3.12", "webpack-stream": "^5.2.1", + "webpack": "^4.43.0", + "xml2js": "^0.4.17", "yaserver": "^0.2.0" }, "repository": { diff --git a/yarn.lock b/yarn.lock index 1bf3b732fd7..24328f37763 100644 --- a/yarn.lock +++ b/yarn.lock @@ -140,6 +140,14 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@dsherret/to-absolute-glob@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1f6475dc8bd974cea07a2daf3864b317b1dd332c" + integrity sha1-H2R13IvZdM6gei2vOGSzF7HdMyw= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + "@electron/get@^1.0.1": version "1.7.2" resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.7.2.tgz#286436a9fb56ff1a1fcdf0e80131fd65f4d1e0fd" @@ -155,6 +163,14 @@ global-agent "^2.0.2" global-tunnel-ng "^2.7.1" +"@gulp-sourcemaps/map-sources@1.X": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" + integrity sha1-iQrnxdjId/bThIYCFazp1+yUW9o= + dependencies: + normalize-path "^2.0.1" + through2 "^2.0.3" + "@istanbuljs/schema@^0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" @@ -285,7 +301,7 @@ resolved "https://registry.yarnpkg.com/@types/keytar/-/keytar-4.4.0.tgz#ca24e6ee6d0df10c003aafe26e93113b8faf0d8e" integrity sha512-cq/NkUUy6rpWD8n7PweNQQBpw2o0cf5v6fbkUVEpOB9VzzIvyPvSEId1/goIj+MciW2v1Lw5mRimKO01XgE9EA== -"@types/minimatch@*": +"@types/minimatch@*", "@types/minimatch@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== @@ -643,6 +659,11 @@ acorn-jsx@^5.1.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn@4.X: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + acorn@^6.0.2: version "6.0.7" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.7.tgz#490180ce18337270232d9488a44be83d9afb7fd3" @@ -906,6 +927,11 @@ ansi-wrap@0.1.0, ansi-wrap@^0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= +any-promise@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1027,11 +1053,21 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-back@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= +array-differ@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" + integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== + array-each@^1.0.0, array-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" @@ -1083,7 +1119,7 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-uniq@^1.0.1: +array-uniq@^1.0.1, array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= @@ -1103,6 +1139,11 @@ arrify@^1.0.0: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asar@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/asar/-/asar-3.0.3.tgz#1fef03c2d6d2de0cbad138788e4f7ae03b129c7b" @@ -1215,6 +1256,11 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio= +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + autoprefixer@^6.3.1: version "6.7.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" @@ -1242,6 +1288,23 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +azure-storage@^2.1.0: + version "2.10.3" + resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.3.tgz#c5966bf929d87587d78f6847040ea9a4b1d4a50a" + integrity sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ== + dependencies: + browserify-mime "~1.2.9" + extend "^3.0.2" + json-edm-parser "0.1.2" + md5.js "1.3.4" + readable-stream "~2.0.0" + request "^2.86.0" + underscore "~1.8.3" + uuid "^3.0.0" + validator "~9.4.1" + xml2js "0.2.8" + xmlbuilder "^9.0.7" + azure-storage@^2.10.2: version "2.10.2" resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.2.tgz#3bcabdbf10e72fd0990db81116e49023c4a675b6" @@ -1309,6 +1372,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -1362,7 +1430,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.5.5: +bluebird@^3.5.0, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -1523,6 +1591,19 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -1533,6 +1614,11 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1570,6 +1656,11 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +bytes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + cacache@^12.0.2: version "12.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" @@ -1690,7 +1781,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -2038,6 +2129,11 @@ coa@~1.0.1: dependencies: q "^1.1.2" +code-block-writer@9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-9.4.1.tgz#1448fca79dfc7a3649000f4c85be6bc770604c4c" + integrity sha512-LHAB+DL4YZDcwK8y/kAxZ0Lf/ncwLh/Ux4cTVWbPwIdrf1gPxXiPcwpz8r8/KqXu1aD+Raz46EOxDjFlbyO6bA== + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -2155,6 +2251,16 @@ combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-line-args@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a" + integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg== + dependencies: + array-back "^3.0.1" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + commander@*, commander@^2.11.0: version "2.15.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322" @@ -2195,6 +2301,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +compare-version@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" + integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= + component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -2255,6 +2366,13 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" +convert-source-map@1.X, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + convert-source-map@^1.1.1: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" @@ -2267,13 +2385,6 @@ convert-source-map@^1.5.0: dependencies: safe-buffer "~5.1.1" -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -2451,6 +2562,16 @@ css-what@2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= +css@2.X: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -2538,12 +2659,26 @@ date-now@^0.1.4: resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= + debounce@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.1.0.tgz#6a1a4ee2a9dc4b7c24bb012558dbcdb05b37f408" integrity sha512-ZQVKfRVlwRfD150ndzEK8M90ABT+Y/JQKs4Y7U4MXdpuoUkkrr4DwKbVux3YjylA5bUMUj0Nc3pMxPJX6N2QQQ== -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: +debug-fabulous@0.0.X: + version "0.0.4" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763" + integrity sha1-+gccXYdIRoVCSAdCHKSxawsaB2M= + dependencies: + debug "2.X" + lazy-debug-legacy "0.0.X" + object-assign "4.1.0" + +debug@2.6.9, debug@2.X, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2744,6 +2879,11 @@ detect-libc@^1.0.2, detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-newline@2.X: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= + detect-node@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" @@ -2847,6 +2987,13 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= + dependencies: + readable-stream "~1.1.9" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -2916,6 +3063,18 @@ editorconfig@^0.15.2: semver "^5.6.0" sigmund "^1.0.1" +electron-osx-sign@^0.4.16: + version "0.4.17" + resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.17.tgz#2727ca0c79e1e4e5ccd3861fb3da9c3c913b006c" + integrity sha512-wUJPmZJQCs1zgdlQgeIpRcvrf7M5/COQaOV68Va1J/SgmWx5KL2otgg+fAae7luw6qz9R8Gvu/Qpe9tAOu/3xQ== + dependencies: + bluebird "^3.5.0" + compare-version "^0.1.2" + debug "^2.6.8" + isbinaryfile "^3.0.2" + minimist "^1.2.0" + plist "^3.0.1" + electron-rebuild@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/electron-rebuild/-/electron-rebuild-2.0.3.tgz#fbcf34d35bf6795a0ded39bfe2aee24526a152c8" @@ -3551,16 +3710,7 @@ extsprintf@1.3.0, extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= -fancy-log@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - -fancy-log@^1.3.3: +fancy-log@^1.1.0, fancy-log@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== @@ -3570,6 +3720,15 @@ fancy-log@^1.3.3: parse-node-version "^1.0.0" time-stamp "^1.0.0" +fancy-log@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + time-stamp "^1.0.0" + fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" @@ -3585,7 +3744,7 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.4: +fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== @@ -3736,6 +3895,13 @@ find-parent-dir@^0.3.0: resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -4111,6 +4277,16 @@ github-releases-ms@^0.5.0: prettyjson "^1.2.1" request "^2.88.0" +github-releases@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.4.2.tgz#3dfa80b809a86418531a53f378845c6e6d580c4c" + integrity sha512-SewGhcOQSl2ZwXMv+MVsZQ/UFirWTQgmL2YrXWDQLIsat2pwurwRzuCOzOFIRYOGZxm0VThyq/cjLD20KOaIMg== + dependencies: + minimatch "3.0.4" + optimist "0.6.1" + prettyjson "1.2.1" + request "^2.88.0" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -4320,6 +4496,20 @@ globalthis@^1.0.0: dependencies: define-properties "^1.1.3" +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" @@ -4373,16 +4563,16 @@ graceful-fs@4.2.3, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@4.X, graceful-fs@^4.1.15, graceful-fs@^4.2.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= -graceful-fs@^4.1.15, graceful-fs@^4.2.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -4426,6 +4616,14 @@ gulp-azure-storage@^0.11.1: vinyl-fs "^3.0.3" yargs "^15.3.0" +gulp-bom@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulp-bom/-/gulp-bom-1.0.0.tgz#38a183a07187bd57a7922d37977441f379df2abf" + integrity sha1-OKGDoHGHvVenki03l3RB83nfKr8= + dependencies: + gulp-util "^3.0.0" + through2 "^2.0.0" + gulp-buffer@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/gulp-buffer/-/gulp-buffer-0.0.2.tgz#af81b4346101736b49942ec6c9fa867ffe737036" @@ -4511,6 +4709,18 @@ gulp-gunzip@^1.0.0: through2 "~2.0.3" vinyl "~2.0.1" +gulp-gzip@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/gulp-gzip/-/gulp-gzip-1.4.2.tgz#0422a94014248655b5b1a9eea1c2abee1d4f4337" + integrity sha512-ZIxfkUwk2XmZPTT9pPHrHUQlZMyp9nPhg2sfoeN27mBGpi7OaHnOD+WCN41NXjfJQ69lV1nQ9LLm1hYxx4h3UQ== + dependencies: + ansi-colors "^1.0.1" + bytes "^3.0.0" + fancy-log "^1.3.2" + plugin-error "^1.0.0" + stream-to-array "^2.3.0" + through2 "^2.0.3" + gulp-json-editor@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.5.0.tgz#23aaa7d30f8425cf60cf1aefae098c257da11ada" @@ -4582,6 +4792,23 @@ gulp-sourcemaps@1.6.0: through2 "^2.0.0" vinyl "^1.0.0" +gulp-sourcemaps@^1.11.0: + version "1.12.1" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.12.1.tgz#b437d1f3d980cf26e81184823718ce15ae6597b6" + integrity sha1-tDfR89mAzyboEYSCNxjOFa5ll7Y= + dependencies: + "@gulp-sourcemaps/map-sources" "1.X" + acorn "4.X" + convert-source-map "1.X" + css "2.X" + debug-fabulous "0.0.X" + detect-newline "2.X" + graceful-fs "4.X" + source-map "~0.6.0" + strip-bom "2.X" + through2 "2.X" + vinyl "1.X" + gulp-symdest@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.1.tgz#b0a6df3d43a0537165946ab8e38c1b7080a66fac" @@ -4602,6 +4829,22 @@ gulp-tsb@4.0.5: through "^2.3.6" vinyl "^2.1.0" +gulp-uglify@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.2.tgz#5f5b2e8337f879ca9dec971feb1b82a5a87850b0" + integrity sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg== + dependencies: + array-each "^1.0.1" + extend-shallow "^3.0.2" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + isobject "^3.0.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + gulp-untar@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4" @@ -4613,6 +4856,30 @@ gulp-untar@^0.0.7: through2 "~2.0.3" vinyl "^1.2.0" +gulp-util@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + gulp-vinyl-zip@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.2.tgz#b79cc1a0e2c3b158ffee294590ade1e9caaf5e7b" @@ -4699,6 +4966,13 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= + dependencies: + sparkles "^1.0.0" + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" @@ -4952,7 +5226,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: +ignore@^5.1.1, ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -5482,6 +5756,13 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isbinaryfile@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" + integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== + dependencies: + buffer-alloc "^1.2.0" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5724,6 +6005,11 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonc-parser@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342" + integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -5824,6 +6110,11 @@ last-run@^1.1.0: default-resolution "^2.0.0" es6-weak-map "^2.0.1" +lazy-debug-legacy@0.0.X: + version "0.0.1" + resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" + integrity sha1-U3cWwHduTPeePtG2IfdljCkRsbE= + lazy.js@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/lazy.js/-/lazy.js-0.4.3.tgz#87f67a07ad36555121e4fff1520df31be66786d8" @@ -5970,16 +6261,78 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash._reinterpolate@~3.0.0: +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= + +lodash._reinterpolate@^3.0.0, lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.clone@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= + dependencies: + lodash._root "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + lodash.isequal@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5995,16 +6348,45 @@ lodash.isundefined@^3.0.1: resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48" integrity sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g= +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= + lodash.some@^4.2.2: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + lodash.template@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" @@ -6013,6 +6395,14 @@ lodash.template@^4.4.0: lodash._reinterpolate "~3.0.0" lodash.templatesettings "^4.0.0" +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.templatesettings@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" @@ -6109,6 +6499,18 @@ make-dir@^3.0.2: dependencies: semver "^6.0.0" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + integrity sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0= + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -6244,7 +6646,7 @@ merge-stream@^1.0.0: dependencies: readable-stream "^2.0.1" -merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -6389,16 +6791,16 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= +minimist@^1.1.0, minimist@^1.2.3, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -6590,6 +6992,24 @@ multimatch@^2.0.0: arrify "^1.0.0" minimatch "^3.0.0" +multimatch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" + integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== + dependencies: + "@types/minimatch" "^3.0.3" + array-differ "^3.0.0" + array-union "^2.1.0" + arrify "^2.0.1" + minimatch "^3.0.4" + +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= + dependencies: + duplexer2 "0.0.2" + mute-stdout@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" @@ -6944,6 +7364,16 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + integrity sha1-ejs9DpgGPUP0wD8uiubNUahog6A= + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= + object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -7086,7 +7516,7 @@ optimist@0.3.5: dependencies: wordwrap "~0.0.2" -optimist@^0.6.1: +optimist@0.6.1, optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= @@ -7591,7 +8021,7 @@ plugin-error@0.1.2, plugin-error@^0.1.2: arr-union "^2.0.1" extend-shallow "^1.1.2" -plugin-error@^1.0.1: +plugin-error@^1.0.0, plugin-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== @@ -7953,7 +8383,7 @@ pretty-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= -prettyjson@^1.2.1: +prettyjson@1.2.1, prettyjson@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" integrity sha1-/P+rQdGcq0365eV15kJGYZsS0ok= @@ -8285,6 +8715,16 @@ readable-stream@^3.1.1, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@~2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -8297,6 +8737,19 @@ readable-stream@~2.0.0: string_decoder "~0.10.x" util-deprecate "~1.0.1" +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -8474,6 +8927,32 @@ replacestream@^4.0.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +request@^2.85.0, request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + request@^2.86.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" @@ -8500,32 +8979,6 @@ request@^2.86.0, request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - requestretry@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/requestretry/-/requestretry-4.0.0.tgz#4e9e7280a7d8561bf33e9925264cf026e2be3e89" @@ -9083,6 +9536,17 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-resolve@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.3.2: version "0.3.3" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f" @@ -9122,7 +9586,7 @@ source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -9306,6 +9770,13 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= +stream-to-array@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" + integrity sha1-u/azn19D7DC8cbq8s3VXrOzzQ1M= + dependencies: + any-promise "^1.1.0" + streamfilter@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.5.tgz#87507111beb8e298451717b511cfed8f002abf53" @@ -9457,7 +9928,7 @@ strip-bom-stream@^1.0.0: first-chunk-stream "^1.0.0" strip-bom "^2.0.0" -strip-bom@^2.0.0: +strip-bom@2.X, strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= @@ -9697,6 +10168,15 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" +terser@4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.8.tgz#707f05f3f4c1c70c840e626addfdb1c158a17136" + integrity sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + terser@^4.1.2: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" @@ -9732,6 +10212,14 @@ through2@2.0.3, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0 readable-stream "^2.1.5" xtend "~4.0.1" +through2@2.X: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + through2@^0.6.0: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" @@ -9902,6 +10390,20 @@ ts-loader@^6.2.1: micromatch "^4.0.0" semver "^6.0.0" +ts-morph@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-3.1.3.tgz#bbfa1d14481ee23bdd1c030340ccf4a243cfc844" + integrity sha512-CwjgyJTtd3f8vBi7Vr0IOgdOY6Wi/Tq0MhieXOE2B5ns5WWRD7BwMNHtv+ZufKI/S2U/lMrh+Q3bOauE4tsv2g== + dependencies: + "@dsherret/to-absolute-glob" "^2.0.2" + code-block-writer "9.4.1" + fs-extra "^8.1.0" + glob-parent "^5.0.0" + globby "^10.0.1" + is-negated-glob "^1.0.0" + multimatch "^4.0.0" + typescript "^3.0.1" + tsec@googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1: version "0.0.1" resolved "https://codeload.github.com/googleinterns/tsec/tar.gz/7bf4ab23686500522341b977b3e2cc04b1f720b1" @@ -9990,11 +10492,26 @@ typescript@^2.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q= +typescript@^3.0.1: + version "3.9.7" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" + integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" integrity sha1-ftUNXg+an7ClczeSWfKndFjVAZI= +uglify-js@^3.0.5: + version "3.12.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.2.tgz#c7ae89da0ed1bb58999c7fce07190b347fdbdaba" + integrity sha512-rWYleAvfJPjduYCt+ELvzybNah/zIkRteGXIBO8X0lteRZPGladF61hFi8tU7qKTsF7u6DUQCtT9k00VlFOgkg== + ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -10298,14 +10815,14 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" -vinyl-sourcemaps-apply@^0.2.1: +vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= dependencies: source-map "^0.5.1" -vinyl@^1.0.0, vinyl@^1.2.0: +vinyl@1.X, vinyl@^1.0.0, vinyl@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= @@ -10314,6 +10831,15 @@ vinyl@^1.0.0, vinyl@^1.2.0: clone-stats "^0.0.1" replace-ext "0.0.1" +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + vinyl@^2.0.0, vinyl@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" @@ -10432,7 +10958,7 @@ vscode-regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/vscode-regexpp/-/vscode-regexpp-3.1.0.tgz#42d059b6fffe99bd42939c0d013f632f0cad823f" integrity sha512-pqtN65VC1jRLawfluX4Y80MMG0DHJydWhe5ZwMHewZD6sys4LbU6lHwFAHxeuaVE6Y6+xZOtAw+9hvq7/0ejkg== -vscode-ripgrep@^1.11.1: +vscode-ripgrep@^1.11.1, vscode-ripgrep@^1.6.2: version "1.11.1" resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.11.1.tgz#9fa3c0a96c2939d5a2389f71218bd1bb6eaa8679" integrity sha512-oHJfpqeXuTQhOO+szqIObYOddwQ9o+lzd4PQLlTQN+sQ7ex8D1qqFip207O2iJyFc5oWE8Bekf4YHTibdbW66w== @@ -10447,6 +10973,15 @@ vscode-sqlite3@4.0.10: dependencies: nan "^2.14.0" +vscode-telemetry-extractor@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.6.0.tgz#e9d9c1d24863cce8d3d715f0287de3b31eb90c56" + integrity sha512-zSxvkbyAMa1lTRGIHfGg7gW2e9Sey+2zGYD19uNWCsVEfoXAr2NB6uzb0sNHtbZ2SSqxSePmFXzBAavsudT5fw== + dependencies: + command-line-args "^5.1.1" + ts-morph "^3.1.3" + vscode-ripgrep "^1.6.2" + vscode-textmate@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" @@ -10748,6 +11283,14 @@ xml2js@0.2.8: dependencies: sax "0.5.x" +xml2js@^0.4.17: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xml2js@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -10766,6 +11309,11 @@ xmlbuilder@^9.0.7: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xmlbuilder@~9.0.1: version "9.0.4" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f" From 7971d627ce87532f5b117fd907f3f54c878cdb68 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 18 Dec 2020 13:52:56 +0100 Subject: [PATCH 1231/1837] first version of outline service, outline creators, and implementations for document symbols and notebooks --- .../browser/outline/documentSymbolsOutline.ts | 271 ++++++++++++++++++ .../contrib/outline/notebooksOutline.ts | 131 +++++++++ .../notebook/browser/notebook.contribution.ts | 1 + .../notebook/browser/notebookEditor.ts | 10 +- .../services/outline/common/outline.ts | 40 +++ .../services/outline/common/outlineService.ts | 35 +++ src/vs/workbench/workbench.common.main.ts | 2 + 7 files changed, 482 insertions(+), 8 deletions(-) create mode 100644 src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts create mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts create mode 100644 src/vs/workbench/services/outline/common/outline.ts create mode 100644 src/vs/workbench/services/outline/common/outlineService.ts diff --git a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts new file mode 100644 index 00000000000..ae74a2c54e4 --- /dev/null +++ b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts @@ -0,0 +1,271 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IEditorPane } from 'vs/workbench/common/editor'; +import { OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; +import { OutlineGroup, OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; +import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { TimeoutTimer } from 'vs/base/common/async'; +import { equals } from 'vs/base/common/arrays'; +import { onUnexpectedError } from 'vs/base/common/errors'; +import { URI } from 'vs/base/common/uri'; +import { ITextModel } from 'vs/editor/common/model'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IPosition } from 'vs/editor/common/core/position'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ScrollType } from 'vs/editor/common/editorCommon'; +import { Range } from 'vs/editor/common/core/range'; + +type DocumentSymbolItem = TreeElement; + +class DocumentSymbolsOutline implements IOutline { + + private readonly _disposables = new DisposableStore(); + + private readonly _onDidChange = new Emitter(); + readonly onDidChange: Event = this._onDidChange.event; + + private readonly _onDidChangeActiveEntry = new Emitter(); + readonly onDidChangeActiveEntry: Event = this._onDidChangeActiveEntry.event; + + private _outlineElements: Array = []; + private _outlineDisposables = new DisposableStore(); + + constructor( + private readonly _editor: ICodeEditor, + @IConfigurationService private readonly _configurationService: IConfigurationService, + @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, + ) { + // update as language, model, providers changes + this._disposables.add(DocumentSymbolProviderRegistry.onDidChange(_ => this._updateOutline())); + this._disposables.add(this._editor.onDidChangeModel(_ => this._updateOutline())); + this._disposables.add(this._editor.onDidChangeModelLanguage(_ => this._updateOutline())); + + // update when config changes (re-render) + this._disposables.add(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('breadcrumbs')) { + this._updateOutline(true); + return; + } + if (this._editor && this._editor.getModel()) { + const editorModel = this._editor.getModel() as ITextModel; + const languageName = editorModel.getLanguageIdentifier().language; + + // Checking for changes in the current language override config. + // We can't be more specific than this because the ConfigurationChangeEvent(e) only includes the first part of the root path + if (e.affectsConfiguration(`[${languageName}]`)) { + this._updateOutline(true); + } + } + })); + + // update soon'ish as model content change + const updateSoon = new TimeoutTimer(); + this._disposables.add(updateSoon); + this._disposables.add(this._editor.onDidChangeModelContent(_ => { + const timeout = OutlineModel.getRequestDelay(this._editor!.getModel()); + updateSoon.cancelAndSet(() => this._updateOutline(true), timeout); + })); + this._updateOutline(); + + // stop when editor dies + this._disposables.add(this._editor.onDidDispose(() => this._outlineDisposables.clear())); + } + + dispose(): void { + this._disposables.dispose(); + this._outlineDisposables.dispose(); + } + + get activeEntry(): DocumentSymbolItem | undefined { + return this._outlineElements[this._outlineElements.length - 1]; + } + + revealInEditor(entry: DocumentSymbolItem): void | Promise { + if (entry instanceof OutlineElement) { + const position = Range.getStartPosition(entry.symbol.selectionRange); + this._editor.revealPositionInCenterIfOutsideViewport(position, ScrollType.Immediate); + this._editor.setPosition(position); + } + this._editor.focus(); + } + + getParent(entry: DocumentSymbolItem): DocumentSymbolItem | undefined { + if (entry instanceof OutlineModel) { + return undefined; + } else { + return entry.parent; + } + } + + private _updateOutline(didChangeContent?: boolean): void { + + this._outlineDisposables.clear(); + if (!didChangeContent) { + this._updateOutlineElements([]); + } + + const editor = this._editor!; + + const buffer = editor.getModel(); + if (!buffer || !DocumentSymbolProviderRegistry.has(buffer)) { + return; + } + + const source = new CancellationTokenSource(); + const versionIdThen = buffer.getVersionId(); + const timeout = new TimeoutTimer(); + + this._outlineDisposables.add({ + dispose: () => { + source.dispose(true); + timeout.dispose(); + } + }); + + OutlineModel.create(buffer, source.token).then(model => { + if (source.token.isCancellationRequested) { + // cancelled -> do nothing + return; + } + if (TreeElement.empty(model)) { + // empty -> no outline elements + this._updateOutlineElements([]); + + } else { + // copy the model + model = model.adopt(); + + this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); + this._outlineDisposables.add(editor.onDidChangeCursorPosition(_ => { + timeout.cancelAndSet(() => { + if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && editor.getModel()) { + this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); + } + }, 150); + })); + } + }).catch(err => { + this._updateOutlineElements([]); + onUnexpectedError(err); + }); + } + + private _getOutlineElements(model: OutlineModel, position: IPosition | null): Array { + if (!model || !position) { + return []; + } + let item: OutlineGroup | OutlineElement | undefined = model.getItemEnclosingPosition(position); + if (!item) { + return this._getOutlineElementsRoot(model); + } + let chain: Array = []; + while (item) { + chain.push(item); + let parent: any = item.parent; + if (parent instanceof OutlineModel) { + break; + } + if (parent instanceof OutlineGroup && parent.parent && parent.parent.children.size === 1) { + break; + } + item = parent; + } + let result: Array = []; + for (let i = chain.length - 1; i >= 0; i--) { + let element = chain[i]; + if (this._isFiltered(element)) { + break; + } + result.push(element); + } + if (result.length === 0) { + return this._getOutlineElementsRoot(model); + } + return result; + } + + private _getOutlineElementsRoot(model: OutlineModel): (OutlineModel | OutlineGroup | OutlineElement)[] { + for (const child of model.children.values()) { + if (!this._isFiltered(child)) { + return [model]; + } + } + return []; + } + + private _isFiltered(element: TreeElement): boolean { + if (element instanceof OutlineElement) { + const key = `breadcrumbs.${OutlineFilter.kindToConfigName[element.symbol.kind]}`; + let uri: URI | undefined; + if (this._editor && this._editor.getModel()) { + const model = this._editor.getModel() as ITextModel; + uri = model.uri; + } + return !this._textResourceConfigurationService.getValue(uri, key); + } + return false; + } + + private _updateOutlineElements(elements: Array): void { + if (!equals(elements, this._outlineElements, DocumentSymbolsOutline._outlineElementEquals)) { + this._outlineElements = elements; + this._onDidChange.fire(this); + } + } + + private static _outlineElementEquals(a: OutlineModel | OutlineGroup | OutlineElement, b: OutlineModel | OutlineGroup | OutlineElement): boolean { + if (a === b) { + return true; + } else if (!a || !b) { + return false; + } else { + return a.id === b.id; + } + } +} + +class DocumentSymbolsOutlineCreator implements IOutlineCreator { + + readonly dispose: () => void; + + constructor( + @IOutlineService outlineService: IOutlineService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + ) { + const reg = outlineService.registerOutlineCreator(this); + this.dispose = () => reg.dispose(); + } + + matches(candidate: IEditorPane): candidate is IEditorPane { + const ctrl = candidate.getControl(); + return isCodeEditor(ctrl) || isDiffEditor(ctrl); + } + + async createOutline(pane: IEditorPane): Promise | undefined> { + const control = pane.getControl(); + let editor: ICodeEditor | undefined; + if (isCodeEditor(control)) { + editor = control as ICodeEditor; + } else if (isDiffEditor(control)) { + editor = control.getModifiedEditor(); + } + if (!editor) { + return undefined; + } + return this._instantiationService.createInstance(DocumentSymbolsOutline, editor); + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DocumentSymbolsOutlineCreator, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts new file mode 100644 index 00000000000..392f67fe8eb --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon } from 'vs/base/common/codicons'; +import { Emitter, Event } from 'vs/base/common/event'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; +import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IEditorPane } from 'vs/workbench/common/editor'; + +class OutlineEntry { + constructor( + readonly cell: ICellViewModel, + readonly label: string, + readonly icon: ThemeIcon + ) { } +} + +class NotebookOutline implements IOutline { + + private readonly _dispoables = new DisposableStore(); + + private readonly _onDidChange = new Emitter(); + readonly onDidChange: Event = this._onDidChange.event; + + private readonly _onDidChangeActiveEntry = new Emitter(); + readonly onDidChangeActiveEntry: Event = this._onDidChangeActiveEntry.event; + + private _activeEntry?: OutlineEntry; + private _entries: OutlineEntry[] = []; + + constructor( + private readonly _editor: NotebookEditor + ) { + this._dispoables.add(_editor.onDidChangeModel(() => { + this._computeEntries(); + this._computeActive(); + })); + this._computeEntries(); + this._computeActive(); + } + + dispose(): void { + this._dispoables.dispose(); + } + + private _computeEntries(): void { + this._entries.length = 0; + + const { viewModel } = this._editor; + if (!viewModel) { + return; + } + for (const cell of viewModel.viewCells) { + const content = cell.getText(); + const regexp = cell.cellKind === CellKind.Markdown + ? /^[ \t]*(\#+)(.+)$/gm // md: header + : /^.*\w+.*\w*$/m; // code: none empty line + + const matches = content.match(regexp); + if (matches && matches.length) { + for (let j = 0; j < matches.length; j++) { + this._entries.push(new OutlineEntry( + cell, + matches[j].replace(/^[ \t]*(\#+)/, ''), + cell.cellKind === CellKind.Markdown ? Codicon.markdown : Codicon.code + )); + } + } + } + this._onDidChange.fire(this); + } + + private _computeActive(): void { + let newActive: OutlineEntry | undefined; + if (this._editor.viewModel) { + const [first] = this._editor.viewModel.selectionHandles; + newActive = typeof first === 'number' + ? this._entries.find(candidate => candidate.cell.handle === first) + : undefined; + } + if (this._activeEntry !== newActive) { + this._activeEntry = newActive; + this._onDidChangeActiveEntry.fire(this); + } + } + + get activeEntry(): OutlineEntry | undefined { + return this._activeEntry; + } + + revealInEditor(entry: OutlineEntry): void | Promise { + const widget = this._editor.getControl(); + if (widget) { + widget.revealInCenterIfOutsideViewport(entry.cell); + widget.selectElement(entry.cell); + } + } + + getParent(_entry: OutlineEntry): OutlineEntry | undefined { + return undefined; + } +} + +class NotebookOutlineCreator implements IOutlineCreator { + + readonly dispose: () => void; + + constructor(@IOutlineService outlineService: IOutlineService) { + const reg = outlineService.registerOutlineCreator(this); + this.dispose = () => reg.dispose(); + } + + matches(candidate: IEditorPane): candidate is NotebookEditor { + return candidate.getId() === NotebookEditor.ID; + } + + async createOutline(editor: NotebookEditor): Promise | undefined> { + return new NotebookOutline(editor); + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NotebookOutlineCreator, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index b3e9c30f768..89debf9bf8f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -60,6 +60,7 @@ import 'vs/workbench/contrib/notebook/browser/contrib/find/findController'; import 'vs/workbench/contrib/notebook/browser/contrib/fold/folding'; import 'vs/workbench/contrib/notebook/browser/contrib/format/formatting'; import 'vs/workbench/contrib/notebook/browser/contrib/toc/tocProvider'; +import 'vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline'; import 'vs/workbench/contrib/notebook/browser/contrib/marker/markerProvider'; import 'vs/workbench/contrib/notebook/browser/contrib/status/editorStatus'; // import 'vs/workbench/contrib/notebook/browser/contrib/scm/scm'; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index d0e14035885..8fbb90be9c1 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -64,14 +64,7 @@ export class NotebookEditor extends EditorPane { this._editorMemento = this.getEditorMemento(_editorGroupService, NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY); } - set viewModel(newModel: NotebookViewModel | undefined) { - if (this._widget.value) { - this._widget.value.viewModel = newModel; - this._onDidChangeModel.fire(); - } - } - - get viewModel() { + get viewModel(): NotebookViewModel | undefined { return this._widget.value?.viewModel; } @@ -155,6 +148,7 @@ export class NotebookEditor extends EditorPane { } this._widget = this.instantiationService.invokeFunction(this._notebookWidgetService.retrieveWidget, group, input); + this._widgetDisposableStore.add(this._widget.value!.onDidChangeModel(() => this._onDidChangeModel.fire())); if (this._dimension) { this._widget.value!.layout(this._dimension, this._rootElement); diff --git a/src/vs/workbench/services/outline/common/outline.ts b/src/vs/workbench/services/outline/common/outline.ts new file mode 100644 index 00000000000..6a11705c4bc --- /dev/null +++ b/src/vs/workbench/services/outline/common/outline.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IEditorPane } from 'vs/workbench/common/editor'; + +export const IOutlineService = createDecorator('IOutlineService'); + +export interface IOutlineService { + _serviceBrand: undefined; + + createOutline(editor: IEditorPane): Promise | undefined>; + + registerOutlineCreator(creator: IOutlineCreator): IDisposable; +} + +export interface IOutlineCreator

{ + matches(candidate: IEditorPane): candidate is P; + createOutline(editor: P): Promise | undefined>; +} + + +export interface IOutline { + + dispose(): void; + + readonly onDidChange: Event; + + readonly activeEntry: E | undefined; + readonly onDidChangeActiveEntry: Event + + revealInEditor(entry: E): Promise | void; + + getParent(entry: E): E | undefined; + // getChildren(parent: E): Iterable +} diff --git a/src/vs/workbench/services/outline/common/outlineService.ts b/src/vs/workbench/services/outline/common/outlineService.ts new file mode 100644 index 00000000000..3c976dcd902 --- /dev/null +++ b/src/vs/workbench/services/outline/common/outlineService.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { LinkedList } from 'vs/base/common/linkedList'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IEditorPane } from 'vs/workbench/common/editor'; +import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; + + +class OutlineService implements IOutlineService { + + declare _serviceBrand: undefined; + + private readonly _factories = new LinkedList>(); + + async createOutline(pane: IEditorPane): Promise | undefined> { + for (let factory of this._factories) { + if (factory.matches(pane)) { + return await factory.createOutline(pane); + } + } + return undefined; + } + + registerOutlineCreator(creator: IOutlineCreator): IDisposable { + const rm = this._factories.push(creator); + return toDisposable(rm); + } +} + + +registerSingleton(IOutlineService, OutlineService, true); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index ba666391193..2b1b4d69388 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -89,6 +89,7 @@ import 'vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService' import 'vs/workbench/services/authentication/browser/authenticationService'; import 'vs/workbench/services/hover/browser/hoverService'; import 'vs/workbench/services/experiment/common/experimentService'; +import 'vs/workbench/services/outline/common/outlineService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; @@ -283,6 +284,7 @@ import 'vs/workbench/contrib/welcome/walkThrough/browser/walkThrough.contributio import 'vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution'; // Outline +import 'vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline'; import 'vs/workbench/contrib/outline/browser/outline.contribution'; // Experiments From edd37076b4b45f44c92fd19618cc0695eca68ff9 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 14:19:51 +0100 Subject: [PATCH 1232/1837] Adopt new mocha types --- .../vscode-notebook-tests/src/notebook.test.ts | 3 +-- src/vs/base/test/common/async.test.ts | 6 +++--- src/vs/base/test/common/filters.perf.test.ts | 2 +- src/vs/base/test/common/paging.test.ts | 1 - src/vs/base/test/common/skipList.test.ts | 3 +-- src/vs/base/test/common/types.test.ts | 4 ++-- src/vs/base/test/common/uri.test.ts | 6 ++---- src/vs/base/test/common/utils.ts | 2 +- src/vs/base/test/node/keytar.test.ts | 1 - .../test/common/services/editorSimpleWorker.test.ts | 1 - .../common/viewModel/splitLinesCollection.test.ts | 1 - .../files/test/browser/textFileEditor.test.ts | 2 +- .../services/extensions/node/proxyResolver.ts | 2 +- .../test/browser/textFileEditorModel.test.ts | 10 +++++----- .../test/browser/api/extHostApiCommands.test.ts | 12 ++++++------ .../test/browser/parts/editor/editorPane.test.ts | 2 +- 16 files changed, 25 insertions(+), 33 deletions(-) diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index 480fb62d3e4..c4b603b42be 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -1272,8 +1272,7 @@ suite('regression', () => { assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), resource.toString()); }); - test('Cannot open notebook from cell-uri with vscode.open-command', async function () { - this.skip(); + test.skip('Cannot open notebook from cell-uri with vscode.open-command', async function () { assertInitalState(); const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index d1baf9b5b7b..ac12abf371b 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -576,12 +576,12 @@ suite('Async', () => { sequentializer.setPending(2, async.timeout(1)); assert.ok(sequentializer.hasPending()); assert.ok(sequentializer.hasPending(2)); - assert.ok(!sequentializer.hasPending(1)); + assert.strictEqual(sequentializer.hasPending(1), false); assert.ok(sequentializer.pending); await async.timeout(2); - assert.ok(!sequentializer.hasPending()); - assert.ok(!sequentializer.hasPending(2)); + assert.strictEqual(sequentializer.hasPending(), false); + assert.strictEqual(sequentializer.hasPending(2), false); assert.ok(!sequentializer.pending); }); diff --git a/src/vs/base/test/common/filters.perf.test.ts b/src/vs/base/test/common/filters.perf.test.ts index 3c20621a578..c189feaa47b 100644 --- a/src/vs/base/test/common/filters.perf.test.ts +++ b/src/vs/base/test/common/filters.perf.test.ts @@ -9,7 +9,7 @@ const patterns = ['cci', 'ida', 'pos', 'CCI', 'enbled', 'callback', 'gGame', 'co const _enablePerf = false; -function perfSuite(name: string, callback: (this: Mocha.ISuiteCallbackContext) => void) { +function perfSuite(name: string, callback: (this: Mocha.Suite) => void) { if (_enablePerf) { suite(name, callback); } diff --git a/src/vs/base/test/common/paging.test.ts b/src/vs/base/test/common/paging.test.ts index 3ce69663384..da7ef18fa3c 100644 --- a/src/vs/base/test/common/paging.test.ts +++ b/src/vs/base/test/common/paging.test.ts @@ -101,7 +101,6 @@ suite('PagedModel', () => { test('preemptive cancellation works', async function () { const pager = new TestPager(() => { assert(false); - return Promise.resolve([]); }); const model = new PagedModel(pager); diff --git a/src/vs/base/test/common/skipList.test.ts b/src/vs/base/test/common/skipList.test.ts index f6a083e3cb2..bd72c015d24 100644 --- a/src/vs/base/test/common/skipList.test.ts +++ b/src/vs/base/test/common/skipList.test.ts @@ -141,8 +141,7 @@ suite('SkipList', function () { } - test('perf', function () { - this.skip(); + test.skip('perf', function () { // data const max = 2 ** 16; diff --git a/src/vs/base/test/common/types.test.ts b/src/vs/base/test/common/types.test.ts index 0bec27fcd84..32e276c1dd5 100644 --- a/src/vs/base/test/common/types.test.ts +++ b/src/vs/base/test/common/types.test.ts @@ -57,7 +57,7 @@ suite('Types', () => { assert(!types.isObject(/test/)); assert(!types.isObject(new RegExp(''))); assert(!types.isFunction(new Date())); - assert(!types.isObject(assert)); + assert.strictEqual(types.isObject(assert), false); assert(!types.isObject(function foo() { })); assert(types.isObject({})); @@ -75,7 +75,7 @@ suite('Types', () => { assert(!types.isEmptyObject(/test/)); assert(!types.isEmptyObject(new RegExp(''))); assert(!types.isEmptyObject(new Date())); - assert(!types.isEmptyObject(assert)); + assert.strictEqual(types.isEmptyObject(assert), false); assert(!types.isEmptyObject(function foo() { /**/ })); assert(!types.isEmptyObject({ foo: 'bar' })); diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index bc4e409c02d..92dde983e73 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -444,8 +444,7 @@ suite('URI', () => { assert.equal(URI.parse('file://some/%A0.txt'), 'file://some/%25A0.txt'); }); - test('Links in markdown are broken if url contains encoded parameters #79474', function () { - this.skip(); + test.skip('Links in markdown are broken if url contains encoded parameters #79474', function () { let strIn = 'https://myhost.com/Redirect?url=http%3A%2F%2Fwww.bing.com%3Fsearch%3Dtom'; let uri1 = URI.parse(strIn); let strOut = uri1.toString(); @@ -459,8 +458,7 @@ suite('URI', () => { assert.equal(strIn, strOut); // fails here!! }); - test('Uri#parse can break path-component #45515', function () { - this.skip(); + test.skip('Uri#parse can break path-component #45515', function () { let strIn = 'https://firebasestorage.googleapis.com/v0/b/brewlangerie.appspot.com/o/products%2FzVNZkudXJyq8bPGTXUxx%2FBetterave-Sesame.jpg?alt=media&token=0b2310c4-3ea6-4207-bbde-9c3710ba0437'; let uri1 = URI.parse(strIn); let strOut = uri1.toString(); diff --git a/src/vs/base/test/common/utils.ts b/src/vs/base/test/common/utils.ts index a5ebd13e53e..c09ff722421 100644 --- a/src/vs/base/test/common/utils.ts +++ b/src/vs/base/test/common/utils.ts @@ -60,7 +60,7 @@ export function suiteRepeat(n: number, description: string, callback: (this: any } } -export function testRepeat(n: number, description: string, callback: (this: any, done: MochaDone) => any): void { +export function testRepeat(n: number, description: string, callback: (this: any) => any): void { for (let i = 0; i < n; i++) { test(`${description} (iteration ${i})`, callback); } diff --git a/src/vs/base/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts index b2f7bab5042..1cc193ce967 100644 --- a/src/vs/base/test/node/keytar.test.ts +++ b/src/vs/base/test/node/keytar.test.ts @@ -10,7 +10,6 @@ suite('Keytar', () => { test('loads and is functional', function (done) { if (platform.isLinux) { // Skip test due to set up issue with Travis. - this.skip(); return; } (async () => { diff --git a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts index 54f73ed0ec2..6a7656347ab 100644 --- a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts +++ b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts @@ -165,7 +165,6 @@ suite('EditorSimpleWorker', () => { return worker.textualSuggest([model.uri.toString()], 'f', '[a-z]+', 'img').then((result) => { if (!result) { assert.ok(false); - return; } assert.equal(result.words.length, 1); assert.equal(typeof result.duration, 'number'); diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index 3156be0e1e8..1e0f886a667 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -391,7 +391,6 @@ suite('SplitLinesCollection', () => { } if (expected === null) { assert.ok(false); - return; } assert.equal(actual.content, expected.content); assert.equal(actual.minColumn, expected.minColumn); diff --git a/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts b/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts index 5577b01eb9b..33342c8fab9 100644 --- a/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts +++ b/src/vs/workbench/contrib/files/test/browser/textFileEditor.test.ts @@ -87,7 +87,7 @@ suite('Files - TextFileEditor', () => { return viewStateTest(this, false); }); - async function viewStateTest(context: Mocha.ITestCallbackContext, restoreViewState: boolean): Promise { + async function viewStateTest(context: Mocha.Context, restoreViewState: boolean): Promise { const [part, accessor] = await createPart(restoreViewState); let editor = await accessor.editorService.openEditor(accessor.editorService.createEditorInput({ resource: toResource.call(context, '/path/index.txt'), forceFile: true })); diff --git a/src/vs/workbench/services/extensions/node/proxyResolver.ts b/src/vs/workbench/services/extensions/node/proxyResolver.ts index 80177b1fad9..d520ce8bd05 100644 --- a/src/vs/workbench/services/extensions/node/proxyResolver.ts +++ b/src/vs/workbench/services/extensions/node/proxyResolver.ts @@ -397,7 +397,7 @@ function tlsPatches(originals: typeof tls) { }; function patch(original: typeof tls.createSecureContext): typeof tls.createSecureContext { - return function (details: tls.SecureContextOptions): ReturnType { + return function (details?: tls.SecureContextOptions): ReturnType { const context = original.apply(null, arguments as any); const certs = (details as any)._vscodeAdditionalCaCerts; if (certs) { diff --git a/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts index 0020a94b7a1..801a1f06262 100644 --- a/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts @@ -182,7 +182,7 @@ suite('Files - TextFileEditorModel', () => { await model.save({ force: true }); assert.ok(savedEvent); - assert.ok(!model.isDirty()); + assert.strictEqual(model.isDirty(), false); model.dispose(); assert.ok(!accessor.modelService.getModel(model.resource)); @@ -373,7 +373,7 @@ suite('Files - TextFileEditorModel', () => { assert.equal(accessor.workingCopyService.isDirty(model.resource), true); await model.revert(); - assert.ok(!model.isDirty()); + assert.strictEqual(model.isDirty(), false); assert.equal(model.textEditorModel!.getValue(), 'Hello Html'); assert.equal(eventCounter, 1); @@ -406,7 +406,7 @@ suite('Files - TextFileEditorModel', () => { assert.equal(accessor.workingCopyService.isDirty(model.resource), true); await model.revert({ soft: true }); - assert.ok(!model.isDirty()); + assert.strictEqual(model.isDirty(), false); assert.equal(model.textEditorModel!.getValue(), 'foo'); assert.equal(eventCounter, 1); @@ -453,7 +453,7 @@ suite('Files - TextFileEditorModel', () => { assert.ok(model.isDirty()); await model.revert({ soft: true }); - assert.ok(!model.isDirty()); + assert.strictEqual(model.isDirty(), false); model.onDidChangeDirty(() => eventCounter++); @@ -470,7 +470,7 @@ suite('Files - TextFileEditorModel', () => { assert.ok(workingCopyEvent); model.setDirty(false); - assert.ok(!model.isDirty()); + assert.strictEqual(model.isDirty(), false); assert.equal(eventCounter, 2); model.dispose(); diff --git a/src/vs/workbench/test/browser/api/extHostApiCommands.test.ts b/src/vs/workbench/test/browser/api/extHostApiCommands.test.ts index c33328c2ce6..aabc4f518eb 100644 --- a/src/vs/workbench/test/browser/api/extHostApiCommands.test.ts +++ b/src/vs/workbench/test/browser/api/extHostApiCommands.test.ts @@ -200,7 +200,7 @@ suite('ExtHostLanguageFeatureCommands', function () { return commands.executeCommand('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => { for (let info of value) { - assert.ok(info instanceof types.SymbolInformation); + assert.strictEqual(info instanceof types.SymbolInformation, true); assert.equal(info.name, 'testing'); assert.equal(info.kind, types.SymbolKind.Array); } @@ -566,8 +566,8 @@ suite('ExtHostLanguageFeatureCommands', function () { return commands.executeCommand('vscode.executeDocumentSymbolProvider', model.uri).then(values => { assert.equal(values.length, 2); let [first, second] = values; - assert.ok(first instanceof types.SymbolInformation); - assert.ok(second instanceof types.SymbolInformation); + assert.strictEqual(first instanceof types.SymbolInformation, true); + assert.strictEqual(second instanceof types.SymbolInformation, true); assert.equal(first.name, 'testing2'); assert.equal(second.name, 'testing1'); }); @@ -594,9 +594,9 @@ suite('ExtHostLanguageFeatureCommands', function () { return commands.executeCommand<(vscode.SymbolInformation & vscode.DocumentSymbol)[]>('vscode.executeDocumentSymbolProvider', model.uri).then(values => { assert.equal(values.length, 2); let [first, second] = values; - assert.ok(first instanceof types.SymbolInformation); - assert.ok(!(first instanceof types.DocumentSymbol)); - assert.ok(second instanceof types.SymbolInformation); + assert.strictEqual(first instanceof types.SymbolInformation, true); + assert.strictEqual(first instanceof types.DocumentSymbol, false); + assert.strictEqual(second instanceof types.SymbolInformation, true); assert.equal(first.name, 'DocumentSymbol'); assert.equal(first.children.length, 1); assert.equal(second.name, 'SymbolInformation'); diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index 2fd3867b693..b9debd51c92 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -107,7 +107,7 @@ suite('Workbench EditorPane', () => { assert(!e.input); await e.setInput(input, options, Object.create(null), CancellationToken.None); - assert.strictEqual(input, e.input); + assert.strictEqual(input, e.input); const group = new TestEditorGroupView(1); e.setVisible(true, group); assert(e.isVisible()); From 4efb4a2e8dbfe8a6a7dbd8269bfc4034e1c21907 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Dec 2020 14:25:40 +0100 Subject: [PATCH 1233/1837] decorations - show them next to the editor label when tabs and breadcrumbs disabled //cc @jrieken --- .../browser/parts/editor/media/notabstitlecontrol.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css index 77a7fa03e7a..321a55b9a63 100644 --- a/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css @@ -22,8 +22,8 @@ padding-left: 20px; } -.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label { - flex: none; +.monaco-workbench .part.editor > .content .editor-group-container > .title > .label-container > .title-label > .monaco-icon-label-container { + flex: none; /* helps to show decorations right next to the label and not at the end */ } .monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before { @@ -32,6 +32,10 @@ /* Breadcrumbs */ +.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label { + flex: none; +} + .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control { flex: 1 50%; overflow: hidden; From 8dc8025cd48e13f2aad52a936cc3ae58578b68fb Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 18 Dec 2020 14:30:14 +0100 Subject: [PATCH 1234/1837] comment out css tests on windows --- scripts/test-integration.bat | 4 ++-- src/vs/workbench/api/common/apiCommands.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index a1cd80e2950..d0be01c45ce 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -73,8 +73,8 @@ call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPat if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in commonJS (CSS, HTML) -call %~dp0\node-electron.bat %~dp0\..\extensions\css-language-features/server/test/index.js -if %errorlevel% neq 0 exit /b %errorlevel% +REM call %~dp0\node-electron.bat %~dp0\..\extensions\css-language-features/server/test/index.js +REM if %errorlevel% neq 0 exit /b %errorlevel% call %~dp0\node-electron.bat %~dp0\..\extensions\html-language-features/server/test/index.js if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/src/vs/workbench/api/common/apiCommands.ts b/src/vs/workbench/api/common/apiCommands.ts index 7670549c68f..063e8566414 100644 --- a/src/vs/workbench/api/common/apiCommands.ts +++ b/src/vs/workbench/api/common/apiCommands.ts @@ -131,7 +131,7 @@ CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (access CommandsRegistry.registerCommand('_workbench.openExternal', function (accessor: ServicesAccessor, uri: UriComponents, options: { allowTunneling?: boolean }) { // TODO: discuss martin, ben where to put this const openerService = accessor.get(IOpenerService); - openerService.open(URI.revive(uri), options); + openerService.open(URI.revive(uri), { openExternal: true, allowTunneling: options?.allowTunneling === true }); }); From c78bd5bd78337a33b596d1166bbff3aa52bebe22 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 18 Dec 2020 14:40:57 +0100 Subject: [PATCH 1235/1837] createFile and createFolder only allow single operation until there are more use cases --- .../contrib/bulkEdit/browser/bulkFileEdits.ts | 4 ++-- .../services/textfile/browser/textFileService.ts | 3 +-- .../workingCopy/common/workingCopyFileService.ts | 12 ++++++------ .../test/browser/workingCopyFileService.test.ts | 4 ++-- .../test/browser/api/mainThreadEditors.test.ts | 6 ++---- .../workbench/test/common/workbenchTestServices.ts | 4 ++-- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts index 73a7234fd28..077f9f8d5c0 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkFileEdits.ts @@ -120,9 +120,9 @@ class CreateOperation implements IFileOperation { return new Noop(); // not overwriting, but ignoring, and the target file exists } if (this.options.folder) { - await this._workingCopyFileService.createFolder([{ resource: this.newUri }], this.undoRedoInfo, token); + await this._workingCopyFileService.createFolder({ resource: this.newUri }, this.undoRedoInfo, token); } else { - await this._workingCopyFileService.create([{ resource: this.newUri, contents: this.contents, overwrite: this.options.overwrite }], this.undoRedoInfo, token); + await this._workingCopyFileService.create({ resource: this.newUri, contents: this.contents, overwrite: this.options.overwrite }, this.undoRedoInfo, token); } return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder && !this.contents); } diff --git a/src/vs/workbench/services/textfile/browser/textFileService.ts b/src/vs/workbench/services/textfile/browser/textFileService.ts index 208a0cda90b..615fa0ca4bb 100644 --- a/src/vs/workbench/services/textfile/browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/browser/textFileService.ts @@ -151,8 +151,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex async create(resource: URI, value?: string | ITextSnapshot, options?: ICreateFileOptions): Promise { const readable = await this.getEncodedReadable(resource, value); - const result = await this.workingCopyFileService.create([{ resource, contents: readable, overwrite: options?.overwrite }]); - return result[0]; + return await this.workingCopyFileService.create({ resource, contents: readable, overwrite: options?.overwrite }); } async write(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise { diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 1c3d2055b1a..c54bc352be7 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -164,7 +164,7 @@ export interface IWorkingCopyFileService { * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and * `onDidRunWorkingCopyFileOperation` events to participate. */ - create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; + create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will create a folder and any parent folder that needs to be created. @@ -175,7 +175,7 @@ export interface IWorkingCopyFileService { * Note: events will only be emitted for the provided resource, but not any * parent folders that are being created as part of the operation. */ - createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; + createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise; /** * Will move working copies matching the provided resources and corresponding children @@ -271,12 +271,12 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi //#region File operations - create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { - return Promise.all(operations.map(o => this.doCreateFileOrFolder(o, true, undoInfo, token))); + create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return this.doCreateFileOrFolder(operation, true, undoInfo, token); } - createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { - return Promise.all(operations.map(o => this.doCreateFileOrFolder(o, false, undoInfo, token))); + createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { + return this.doCreateFileOrFolder(operation, false, undoInfo, token); } async doCreateFileOrFolder(operation: ICreateFileOperation | ICreateOperation, isFile: boolean, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { diff --git a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts index 3ea04364e32..cb1562c837d 100644 --- a/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts +++ b/src/vs/workbench/services/workingCopy/test/browser/workingCopyFileService.test.ts @@ -224,7 +224,7 @@ suite('WorkingCopyFileService', () => { eventCounter++; }); - await accessor.workingCopyFileService.createFolder([{ resource }]); + await accessor.workingCopyFileService.createFolder({ resource }); assert.equal(eventCounter, 3); @@ -459,7 +459,7 @@ suite('WorkingCopyFileService', () => { eventCounter++; }); - await accessor.workingCopyFileService.create([{ resource, contents }]); + await accessor.workingCopyFileService.create({ resource, contents }); assert.ok(!accessor.workingCopyService.isDirty(model.resource)); model.dispose(); diff --git a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts index cf370439d42..ffb4e0e6f61 100644 --- a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts @@ -103,10 +103,8 @@ suite('MainThreadEditors', () => { }); services.set(IWorkingCopyFileService, new class extends mock() { onDidRunWorkingCopyFileOperation = Event.None; - create(operations: ICreateFileOperation[]) { - for (const operation of operations) { - createdResources.add(operation.resource); - } + create(operation: ICreateFileOperation) { + createdResources.add(operation.resource); return Promise.resolve(Object.create(null)); } move(operations: IMoveOperation[]) { diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index 6a00cd3ef4d..1cd6d63130f 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -201,8 +201,8 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService { getDirty(resource: URI): IWorkingCopy[] { return []; } - create(operations: ICreateFileOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } - createFolder(operations: ICreateOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } + create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } + createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise { throw new Error('Method not implemented.'); } move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo): Promise { throw new Error('Method not implemented.'); } From 3bff49d246801371822ed2d735a24a2ff8082f52 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 14:43:07 +0100 Subject: [PATCH 1236/1837] More tweaks to Windows cache exclusions --- .github/workflows/ci.yml | 59 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c0ec3964a5..f62e84d5e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules4- + key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules5- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -71,8 +71,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -125,8 +125,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -184,8 +184,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -246,8 +246,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -291,8 +291,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -329,8 +329,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -381,8 +381,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -427,8 +427,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules4- + # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules5- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -484,8 +484,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules4- + key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules5- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -542,11 +542,12 @@ jobs: with: path: | **/node_modules - !**/Release/*.pdb - !**/Release/*.ilk - !**/Release/obj/** - key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules4- + !**/Release/**/*.pdb + !**/Release/**/*.ilk + !**/Release/**/*.obj + !**/Release/**/*.tlog + key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules5- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -594,8 +595,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules4- + key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules5- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -643,8 +644,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules4- + key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules5- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From 4fc14314b69d4b29cbd3666dbf2ebca159c7ba90 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 14:58:02 +0100 Subject: [PATCH 1237/1837] Fix compilation problem --- extensions/vscode-notebook-tests/src/notebook.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index c4b603b42be..ee80c59278b 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -1287,7 +1287,7 @@ suite('regression', () => { // removes the fragment if it matches something numeric. For notebooks that's not wanted... await vscode.commands.executeCommand('vscode.open', cell.uri); - assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.toString(), resource.toString()); + assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), resource.toString()); }); test('#97830, #97764. Support switch to other editor types', async function () { From 295912f7d5067497a009633a604e84e786b02d4c Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 14:59:34 +0100 Subject: [PATCH 1238/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96be9e62255..c7cb3e1342a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "c89ced323fffc6ffd5caa6e9bb6662b8e26b5fb4", + "distro": "1bfe29babf83d443e20877b37e703152965df6ea", "author": { "name": "Microsoft Corporation" }, From 2c4988b76396998de55e1810fe92c8988c068aed Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 15:10:40 +0100 Subject: [PATCH 1239/1837] Fixes #112301: Wrapped lines contain the wrapping whitespace in the line content --- .../editor/browser/controller/mouseTarget.ts | 5 ++- .../common/controller/cursorMoveOperations.ts | 11 +++---- .../test/browser/controller/cursor.test.ts | 31 +++++++++++++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 88815bb8eb0..d880c1a322f 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -1014,12 +1014,11 @@ export class MouseTargetFactory { } private static _snapToSoftTabBoundary(position: Position, viewModel: IViewModel): Position { - const minColumn = viewModel.getLineMinColumn(position.lineNumber); const lineContent = viewModel.getLineContent(position.lineNumber); const { tabSize } = viewModel.getTextModelOptions(); - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - 1, tabSize, Direction.Nearest); if (newPosition !== -1) { - return new Position(position.lineNumber, newPosition + minColumn); + return new Position(position.lineNumber, newPosition + 1); } return position; } diff --git a/src/vs/editor/common/controller/cursorMoveOperations.ts b/src/vs/editor/common/controller/cursorMoveOperations.ts index 9229c2e3584..ac505bdcdb5 100644 --- a/src/vs/editor/common/controller/cursorMoveOperations.ts +++ b/src/vs/editor/common/controller/cursorMoveOperations.ts @@ -39,11 +39,11 @@ export class MoveOperations { public static leftPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position { const minColumn = model.getLineMinColumn(lineNumber); const lineContent = model.getLineContent(lineNumber); - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left); - if (newPosition === -1) { + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, Direction.Left); + if (newPosition === -1 || newPosition + 1 < minColumn) { return this.leftPosition(model, lineNumber, column); } - return new Position(lineNumber, minColumn + newPosition); + return new Position(lineNumber, newPosition + 1); } public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { @@ -81,13 +81,12 @@ export class MoveOperations { } public static rightPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position { - const minColumn = model.getLineMinColumn(lineNumber); const lineContent = model.getLineContent(lineNumber); - const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right); + const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, Direction.Right); if (newPosition === -1) { return this.rightPosition(model, lineNumber, column); } - return new Position(lineNumber, minColumn + newPosition); + return new Position(lineNumber, newPosition + 1); } public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 9dc368f6998..4fc05dacf97 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -2349,6 +2349,37 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #112301: new stickyTabStops feature interferes with word wrap', () => { + withTestCodeEditor([ + [ + 'function hello() {', + ' console.log(`this is a long console message`)', + '}', + ].join('\n') + ], { wordWrap: 'wordWrapColumn', wordWrapColumn: 32, stickyTabStops: true }, (editor, viewModel) => { + viewModel.setSelections('test', [ + new Selection(2, 31, 2, 31) + ]); + moveRight(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 32)); + + moveRight(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 33)); + + moveRight(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 34)); + + moveLeft(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 33)); + + moveLeft(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 32)); + + moveLeft(editor, viewModel, false); + assertCursor(viewModel, new Position(2, 31)); + }); + }); + test('issue #44805: Should not be able to undo in readonly editor', () => { let model = createTextModel( [ From 14cb2089dc2ec1f3be6eed21a66b2e1023c6d472 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 15:51:24 +0100 Subject: [PATCH 1240/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 92be75cbad4..bae7cf63202 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "c89ced323fffc6ffd5caa6e9bb6662b8e26b5fb4", + "distro": "252d98105e15a5ba22421ff5aef8d1aa7c3b69fa", "author": { "name": "Microsoft Corporation" }, From 75fc5cf5258a0b2e39b2239e63ca335ebdd5514e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 15:53:09 +0100 Subject: [PATCH 1241/1837] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7cb3e1342a..1c1574a9e43 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "1bfe29babf83d443e20877b37e703152965df6ea", + "distro": "467342da4d16e7dab17de5f1e78d70bb5f0b523a", "author": { "name": "Microsoft Corporation" }, From 711ec31c7ea1396d104bb6c7f1baabc55f2e89a4 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 15:58:51 +0100 Subject: [PATCH 1242/1837] Make sure to call done() from unit test --- src/vs/base/test/node/keytar.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts index 1cc193ce967..c27a3286bb1 100644 --- a/src/vs/base/test/node/keytar.test.ts +++ b/src/vs/base/test/node/keytar.test.ts @@ -10,6 +10,7 @@ suite('Keytar', () => { test('loads and is functional', function (done) { if (platform.isLinux) { // Skip test due to set up issue with Travis. + done(); return; } (async () => { From 02443d02f5a1fc84e2a7a443e21e3be541c15ddd Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 16:19:17 +0100 Subject: [PATCH 1243/1837] Fixes #112412: update comments to match placeholders --- .../abstractRuntimeExtensionsEditor.ts | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index 8e0a3cea178..feae800049d 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -297,21 +297,28 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { const activationId = activationTimes.activationReason.extensionId.value; const activationEvent = activationTimes.activationReason.activationEvent; if (activationEvent === '*') { - title = nls.localize('starActivation', "Activated by {0} on start-up", activationId); + title = nls.localize({ + key: 'starActivation', + comment: [ + '{0} will be an extension identifier' + ] + }, "Activated by {0} on start-up", activationId); } else if (/^workspaceContains:/.test(activationEvent)) { let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length); if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) { title = nls.localize({ key: 'workspaceContainsGlobActivation', comment: [ - '{0} will be a glob pattern' + '{0} will be a glob pattern', + '{1} will be an extension identifier' ] - }, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId); + }, "Activated by {1} because a file matching {0} exists in your workspace", fileNameOrGlob, activationId); } else { title = nls.localize({ key: 'workspaceContainsFileActivation', comment: [ - '{0} will be a file name' + '{0} will be a file name', + '{1} will be an extension identifier' ] }, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId); } @@ -320,7 +327,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { title = nls.localize({ key: 'workspaceContainsTimeout', comment: [ - '{0} will be a glob pattern' + '{0} will be a glob pattern', + '{1} will be an extension identifier' ] }, "Activated by {1} because searching for {0} took too long", glob, activationId); } else if (activationEvent === 'onStartupFinished') { @@ -337,7 +345,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { title = nls.localize({ key: 'workspaceGenericActivation', comment: [ - 'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.' + '{0} will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.', + '{1} will be an extension identifier' ] }, "Activated by {1} on {0}", activationEvent, activationId); } From ec9ba0edb68cdbd0d61ceb2e117e3b56eb7a67b4 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 18 Dec 2020 16:22:14 +0100 Subject: [PATCH 1244/1837] debug: Focus child session instead if it is stopped fixes #112595 --- src/vs/workbench/contrib/debug/browser/repl.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 5f286e5fabf..6c179ed3f21 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -837,6 +837,13 @@ registerAction2(class extends ViewAction { const debugService = accessor.get(IDebugService); // If session is already the focused session we need to manualy update the tree since view model will not send a focused change event if (session && session.state !== State.Inactive && session !== debugService.getViewModel().focusedSession) { + if (session.state !== State.Stopped) { + // Focus child session instead if it is stopped #112595 + const stopppedChildSession = debugService.getModel().getSessions().find(s => s.parentSession === session); + if (stopppedChildSession) { + session = stopppedChildSession; + } + } await debugService.focusStackFrame(undefined, undefined, session, true); } else { await view.selectSession(session); From 7cd137263a8821e9320d6e38fc89f4796e056a3d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 16:28:46 +0100 Subject: [PATCH 1245/1837] Fixes #112382: Assume that control characters are wide --- .../editor/common/viewModel/monospaceLineBreaksComputer.ts | 4 ++++ .../common/viewModel/monospaceLineBreaksComputer.test.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts index 5f1a9b94896..9640d007634 100644 --- a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts +++ b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts @@ -448,6 +448,10 @@ function computeCharWidth(charCode: number, visibleColumn: number, tabSize: numb if (strings.isFullWidthCharacter(charCode)) { return columnsForFullWidthChar; } + if (charCode < 32) { + // when using `editor.renderControlCharacters`, the substitutions are often wide + return columnsForFullWidthChar; + } return 1; } diff --git a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts index f5572fcd61b..3ba4653f7be 100644 --- a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts @@ -293,4 +293,9 @@ suite('Editor ViewModel - MonospaceLineBreaksComputer', () => { const factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue); assertLineBreaks(factory, 4, 23, 'this is a line of |text, text that sits |on a line', WrappingIndent.Same); }); + + test('issue #112382: Word wrap doesn\'t work well with control characters', () => { + const factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue); + assertLineBreaks(factory, 4, 6, '\x06\x06\x06|\x06\x06\x06', WrappingIndent.Same); + }); }); From ff744b4fa8a99463d0ad0052fce2cae8042bb2bc Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 18 Dec 2020 16:37:49 +0100 Subject: [PATCH 1246/1837] fixes #112281 --- 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 6c179ed3f21..d279a95605a 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -232,6 +232,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { this.replInput.setModel(this.model); this.updateInputDecoration(); this.refreshReplElements(true); + this.layoutBody(this.dimension.height, this.dimension.width); } })); this._register(this.configurationService.onDidChangeConfiguration(e => { From 6d552620316b3dab299b1501ac41125df4324a79 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 18 Dec 2020 17:31:22 +0100 Subject: [PATCH 1247/1837] update vscode-uri --- extensions/css-language-features/package.json | 2 +- .../css-language-features/server/package.json | 4 ++-- .../css-language-features/server/yarn.lock | 18 +++++++++--------- extensions/css-language-features/yarn.lock | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 32861b82500..3a7c2a49058 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -809,7 +809,7 @@ "dependencies": { "vscode-languageclient": "^7.0.0", "vscode-nls": "^4.1.2", - "vscode-uri": "^3.0.0" + "vscode-uri": "^3.0.1" }, "devDependencies": { "@types/node": "^12.19.9" diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index c818cc01a5d..340971eca31 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -10,9 +10,9 @@ "main": "./out/node/cssServerMain", "browser": "./dist/browser/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^5.0.1", + "vscode-css-languageservice": "^5.0.2", "vscode-languageserver": "^7.0.0", - "vscode-uri": "^3.0.0" + "vscode-uri": "^3.0.1" }, "devDependencies": { "@types/mocha": "^8.2.0", diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 387d4456256..55ad7b259d2 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -12,15 +12,15 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== -vscode-css-languageservice@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.1.tgz#0061e0af23e7c49feba3abfda90799a4877738ee" - integrity sha512-9Lzf7XQD82ykwuyuma2r5g2NkrFth96k7PC4YCwtMoLIKxHXGDqHm7NIzjvY2qi43WgUROpw9XXTKKr8NmNuhA== +vscode-css-languageservice@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.0.2.tgz#92ec069c797dfcf5a67313a18f0211c27b0c6bf6" + integrity sha512-iGOukMyK4EVDIArBMuDmKpBDvg+zoXPyJZi2mGPICKkKTiK8mDAlTr4uxhldg/dwpABEaMlNb+5xeCFDaUyRlQ== dependencies: vscode-languageserver-textdocument "^1.0.1" vscode-languageserver-types "^3.16.0" vscode-nls "^5.0.0" - vscode-uri "^3.0.0" + vscode-uri "^3.0.1" vscode-jsonrpc@6.0.0: version "6.0.0" @@ -57,7 +57,7 @@ vscode-nls@^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.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.0.tgz#a881b16614999d97e71d5d29ea453d4f8c19499d" - integrity sha512-boWPjBN8UPv8/9OnEGumoXgIVreVjs3RyqULtfHC3GRT1aCnaotYRKOhZERmaMsCVVt6nPmmI/ec7i1FH2kctw== +vscode-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.1.tgz#c36502fcf6fa57e63441d3804b5826018e26062e" + integrity sha512-LnMgm97uZM2JDjX/vKbbCk+phm++Ih31e5Ao3lqokawhDRocp2ZAVMRiIhPZx6fS5Sqnquyhxh8ABn9TWCvHoA== diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index c75543eac48..a7528561287 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -78,10 +78,10 @@ vscode-nls@^4.1.2: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -vscode-uri@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.0.tgz#a881b16614999d97e71d5d29ea453d4f8c19499d" - integrity sha512-boWPjBN8UPv8/9OnEGumoXgIVreVjs3RyqULtfHC3GRT1aCnaotYRKOhZERmaMsCVVt6nPmmI/ec7i1FH2kctw== +vscode-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.1.tgz#c36502fcf6fa57e63441d3804b5826018e26062e" + integrity sha512-LnMgm97uZM2JDjX/vKbbCk+phm++Ih31e5Ao3lqokawhDRocp2ZAVMRiIhPZx6fS5Sqnquyhxh8ABn9TWCvHoA== yallist@^4.0.0: version "4.0.0" From 3e8b2d86d176780c3228d0e053aadde245f069bf Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 18 Dec 2020 17:38:23 +0100 Subject: [PATCH 1248/1837] bring back css integration tests --- scripts/test-integration.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index d0be01c45ce..a1cd80e2950 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -73,8 +73,8 @@ call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPat if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in commonJS (CSS, HTML) -REM call %~dp0\node-electron.bat %~dp0\..\extensions\css-language-features/server/test/index.js -REM if %errorlevel% neq 0 exit /b %errorlevel% +call %~dp0\node-electron.bat %~dp0\..\extensions\css-language-features/server/test/index.js +if %errorlevel% neq 0 exit /b %errorlevel% call %~dp0\node-electron.bat %~dp0\..\extensions\html-language-features/server/test/index.js if %errorlevel% neq 0 exit /b %errorlevel% From da4192d2879fbe2333a1eff1732ea94159f76d00 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 17:40:23 +0100 Subject: [PATCH 1249/1837] Leave sorting deps up to yarn --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 1c1574a9e43..77992de8ff5 100644 --- a/package.json +++ b/package.json @@ -114,18 +114,19 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", + "electron": "11.1.0", "electron-osx-sign": "^0.4.16", "electron-rebuild": "2.0.3", - "electron": "11.1.0", + "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "eslint-plugin-mocha": "8.0.0", - "eslint": "6.8.0", "event-stream": "3.3.4", "fancy-log": "^1.3.3", "fast-plist": "0.1.2", "file-loader": "^4.2.0", "github-releases": "^0.4.1", "glob": "^5.0.13", + "gulp": "^4.0.0", "gulp-atom-electron": "^1.22.0", "gulp-azure-storage": "^0.11.1", "gulp-bom": "^1.0.0", @@ -148,7 +149,6 @@ "gulp-uglify": "^3.0.0", "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", - "gulp": "^4.0.0", "husky": "^0.13.1", "iconv-lite-umd": "0.6.8", "innosetup": "6.0.5", @@ -166,9 +166,9 @@ "minimatch": "^3.0.4", "minimist": "^1.2.5", "mkdirp": "^0.5.0", + "mocha": "^8.2.1", "mocha-junit-reporter": "^2.0.0", "mocha-multi-reporters": "^1.5.1", - "mocha": "^8.2.1", "npm-run-all": "^4.1.5", "opn": "^6.0.0", "optimist": "0.3.5", @@ -180,24 +180,24 @@ "request": "^2.85.0", "rimraf": "^2.2.8", "sinon": "^1.17.2", - "source-map-support": "^0.3.2", "source-map": "^0.4.4", + "source-map-support": "^0.3.2", "style-loader": "^1.0.0", "terser": "4.3.8", "ts-loader": "^6.2.1", "tsec": "googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1", - "typescript-formatter": "7.1.0", "typescript": "4.2.0-dev.20201207", + "typescript-formatter": "7.1.0", "underscore": "^1.8.2", - "vinyl-fs": "^3.0.0", "vinyl": "^2.0.0", + "vinyl-fs": "^3.0.0", "vsce": "1.48.0", "vscode-debugprotocol": "1.43.0", "vscode-nls-dev": "^3.3.1", "vscode-telemetry-extractor": "^1.6.0", + "webpack": "^4.43.0", "webpack-cli": "^3.3.12", "webpack-stream": "^5.2.1", - "webpack": "^4.43.0", "xml2js": "^0.4.17", "yaserver": "^0.2.0" }, From c2044d680f49823f108b44fa99130a62f7f889dd Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 17:54:27 +0100 Subject: [PATCH 1250/1837] bust the node module cache --- .github/workflows/ci.yml | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f62e84d5e84..8a7790fbdf6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules5- + key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules6- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -71,8 +71,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -125,8 +125,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -184,8 +184,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -246,8 +246,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -291,8 +291,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Get yarn cache directory path # id: yarnCacheDirPath # if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -329,8 +329,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -381,8 +381,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -427,8 +427,8 @@ jobs: # uses: actions/cache@v2 # with: # path: '**/node_modules' - # key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - # restore-keys: ${{ runner.os }}-cacheNodeModules5- + # key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + # restore-keys: ${{ runner.os }}-cacheNodeModules6- # - name: Restore compiled core code # id: cacheCompiledCoreCode @@ -484,8 +484,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules5- + key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules6- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -546,8 +546,8 @@ jobs: !**/Release/**/*.ilk !**/Release/**/*.obj !**/Release/**/*.tlog - key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules5- + key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules6- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -595,8 +595,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules5- + key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules6- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -644,8 +644,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} - restore-keys: ${{ runner.os }}-cacheNodeModules5- + key: ${{ runner.os }}-cacheNodeModules6-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }} + restore-keys: ${{ runner.os }}-cacheNodeModules6- - name: Execute yarn if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} env: From db27c55205685574af50bbbf44d57491ed992b1d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 17:55:51 +0100 Subject: [PATCH 1251/1837] Adopt `ICodeEditor.executeEdits` --- .../editor/common/commands/replaceCommand.ts | 50 -------------- .../linesOperations/linesOperations.ts | 69 ++++--------------- 2 files changed, 13 insertions(+), 106 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index 0d4aa010d60..3e628f2db76 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -142,53 +142,3 @@ export class ReplaceCommandThatPreservesSelection implements ICommand { return helper.getTrackedSelection(this._selectionId!); } } - -export class ReplaceCommandThatModifiesSelection implements ICommand { - - private readonly _range: Range; - private readonly _text: string; - private readonly _initialSelection: Selection; - private readonly _initialText: string; - private readonly _forceMoveMarkers: boolean; - - constructor(editRange: Range, text: string, initialSelection: Selection, initialText: string, forceMoveMarkers: boolean = false) { - this._range = editRange; - this._text = text; - this._initialSelection = initialSelection; - this._initialText = initialText; - this._forceMoveMarkers = forceMoveMarkers; - } - - public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { - builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers); - } - - public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { - let startColumn = 0; - let endColumn = 0; - const modifiedLines = this._text.split('\n'); - const initialLines = this._initialText.split('\n'); - const { - selectionStartLineNumber, - positionLineNumber, - selectionStartColumn, - positionColumn - } = this._initialSelection; - - const lastInitialLineLength = initialLines[initialLines.length - 1].length; - const lastModifiedLineLength = modifiedLines[modifiedLines.length - 1].length; - - if (selectionStartLineNumber < positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn < positionColumn)) { - startColumn = selectionStartColumn; - endColumn = positionColumn + (lastModifiedLineLength - lastInitialLineLength); - } else if (selectionStartLineNumber > positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn > positionColumn)) { - endColumn = positionColumn; - startColumn = selectionStartColumn + (lastModifiedLineLength - lastInitialLineLength); - } else { - startColumn = selectionStartColumn; - endColumn = positionColumn; - } - - return new Selection(selectionStartLineNumber, startColumn, positionLineNumber, endColumn); - } -} diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 48f57a6cff8..8d3f3e6f8cc 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -8,7 +8,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, IActionOptions, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions'; -import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText, ReplaceCommandThatModifiesSelection } from 'vs/editor/common/commands/replaceCommand'; +import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText } from 'vs/editor/common/commands/replaceCommand'; import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -939,43 +939,39 @@ export class TransposeAction extends EditorAction { export abstract class AbstractCaseAction extends EditorAction { public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - let selections = editor.getSelections(); + const selections = editor.getSelections(); if (selections === null) { return; } - let model = editor.getModel(); + const model = editor.getModel(); if (model === null) { return; } - let wordSeparators = editor.getOption(EditorOption.wordSeparators); + const wordSeparators = editor.getOption(EditorOption.wordSeparators); + const textEdits: IIdentifiedSingleEditOperation[] = []; - let commands: ICommand[] = []; - - for (let i = 0, len = selections.length; i < len; i++) { - let selection = selections[i]; + for (const selection of selections) { if (selection.isEmpty()) { - let cursor = selection.getStartPosition(); + const cursor = selection.getStartPosition(); const word = editor.getConfiguredWordAtPosition(cursor); if (!word) { continue; } - let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - let text = model.getValueInRange(wordRange); - commands.push(new ReplaceCommandThatPreservesSelection(wordRange, this._modifyText(text, wordSeparators), - new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column))); - + const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + const text = model.getValueInRange(wordRange); + textEdits.push(EditOperation.replace(wordRange, this._modifyText(text, wordSeparators))); } else { - let text = model.getValueInRange(selection); - commands.push(new ReplaceCommandThatPreservesSelection(selection, this._modifyText(text, wordSeparators), selection)); + const text = model.getValueInRange(selection); + textEdits.push(EditOperation.replace(selection, this._modifyText(text, wordSeparators))); } } editor.pushUndoStop(); - editor.executeCommands(this.id, commands); + editor.executeEdits(this.id, textEdits); editor.pushUndoStop(); } @@ -1059,45 +1055,6 @@ export class SnakeCaseAction extends AbstractCaseAction { }); } - public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - const selections = editor.getSelections(); - if (selections === null) { - return; - } - - const model = editor.getModel(); - if (model === null) { - return; - } - - const wordSeparators = editor.getOption(EditorOption.wordSeparators); - const commands: ICommand[] = []; - - for (const selection of selections) { - if (selection.isEmpty()) { - const cursor = selection.getStartPosition(); - const word = editor.getConfiguredWordAtPosition(cursor); - - if (!word) { - continue; - } - - const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - const text = model.getValueInRange(wordRange); - commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), - new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); - - } else { - const text = model.getValueInRange(selection); - commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); - } - } - - editor.pushUndoStop(); - editor.executeCommands(this.id, commands); - editor.pushUndoStop(); - } - protected _modifyText(text: string, wordSeparators: string): string { return text.replace(/(?<=\p{Ll})(\p{Lu})|(? Date: Fri, 18 Dec 2020 16:57:52 +0000 Subject: [PATCH 1252/1837] fixes #112792 --- src/vs/workbench/browser/panecomposite.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts index 1f00c9ec5b3..4a8a1144f38 100644 --- a/src/vs/workbench/browser/panecomposite.ts +++ b/src/vs/workbench/browser/panecomposite.ts @@ -67,11 +67,13 @@ export class PaneComposite extends Composite implements IPaneComposite { const result = []; result.push(...this.viewPaneContainer.getContextMenuActions2()); - if (result.length) { + const otherActions = this.viewPaneContainer.getContextMenuActions(); + + if (otherActions.length) { result.push(new Separator()); + result.push(...otherActions); } - result.push(...this.viewPaneContainer.getContextMenuActions()); return result; } From e064043f7a86eef4edd26ecb7e36b0c5e35cbd4f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 18 Dec 2020 18:19:29 +0100 Subject: [PATCH 1253/1837] wire up outline service with breadcrumbs control, WIP --- .../parts/editor/breadcrumbsControl.ts | 192 +++++++------- .../browser/parts/editor/breadcrumbsModel.ts | 248 ++++-------------- .../browser/parts/editor/breadcrumbsPicker.ts | 91 ++++--- .../browser/outline/documentSymbolsOutline.ts | 87 ++++-- .../contrib/outline/notebooksOutline.ts | 97 ++++++- .../services/outline/browser/outline.ts | 59 +++++ .../{common => browser}/outlineService.ts | 18 +- .../services/outline/common/outline.ts | 40 --- .../parts/editor/breadcrumbModel.test.ts | 11 +- src/vs/workbench/workbench.common.main.ts | 2 +- 10 files changed, 440 insertions(+), 405 deletions(-) create mode 100644 src/vs/workbench/services/outline/browser/outline.ts rename src/vs/workbench/services/outline/{common => browser}/outlineService.ts (67%) delete mode 100644 src/vs/workbench/services/outline/common/outline.ts diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 541ea9b2cb2..9fb385fc8d1 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -6,19 +6,17 @@ import * as dom from 'vs/base/browser/dom'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { BreadcrumbsItem, BreadcrumbsWidget, IBreadcrumbsItemEvent } from 'vs/base/browser/ui/breadcrumbs/breadcrumbsWidget'; -import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { tail } from 'vs/base/common/arrays'; import { timeout } from 'vs/base/common/async'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { combinedDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { extUri } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import 'vs/css!./media/breadcrumbscontrol'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; import { ICodeEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; -import { SymbolKinds } from 'vs/editor/common/modes'; -import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; +import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -33,30 +31,78 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { ColorIdentifier, ColorFunction } from 'vs/platform/theme/common/colorRegistry'; import { attachBreadcrumbsStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs'; -import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; +import { BreadcrumbsModel, FileElement, OutlineElement2 } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker'; import { IEditorPartOptions, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { ACTIVE_GROUP, ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; import { onDidChangeZoomLevel } from 'vs/base/browser/browser'; -import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; +import { withNullAsUndefined } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; -import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; -import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { ITreeNode } from 'vs/base/browser/ui/tree/tree'; -class Item extends BreadcrumbsItem { +class OutlineItem extends BreadcrumbsItem { private readonly _disposables = new DisposableStore(); constructor( - readonly element: BreadcrumbElement, + readonly element: OutlineElement2, + readonly options: IBreadcrumbsControlOptions + ) { + super(); + } + + dispose(): void { + this._disposables.dispose(); + } + + equals(other: BreadcrumbsItem): boolean { + if (!(other instanceof OutlineItem)) { + return false; + } + return this.element === other.element && + this.options.showFileIcons === other.options.showFileIcons && + this.options.showSymbolIcons === other.options.showSymbolIcons; + } + + render(container: HTMLElement): void { + const { element, outline } = this.element; + const templateId = outline.treeConfig.delegate.getTemplateId(element); + const renderer = outline.treeConfig.renderers.find(renderer => renderer.templateId === templateId); + if (!renderer) { + container.innerText = '<>'; + return; + } + + const template = renderer.renderTemplate(container); + renderer.renderElement(>{ + element, + children: [], + depth: 0, + visibleChildrenCount: 0, + visibleChildIndex: 0, + collapsible: false, + collapsed: false, + visible: true, + filterData: undefined + }, 0, template, undefined); + + this._disposables.add(toDisposable(() => { renderer.disposeTemplate(template); })); + } + +} + +class FileItem extends BreadcrumbsItem { + + private readonly _disposables = new DisposableStore(); + + constructor( + readonly element: FileElement, readonly options: IBreadcrumbsControlOptions, @IInstantiationService private readonly _instantiationService: IInstantiationService ) { @@ -68,59 +114,26 @@ class Item extends BreadcrumbsItem { } equals(other: BreadcrumbsItem): boolean { - if (!(other instanceof Item)) { + if (!(other instanceof FileItem)) { return false; } - if (this.element instanceof FileElement && other.element instanceof FileElement) { - return (extUri.isEqual(this.element.uri, other.element.uri) && - this.options.showFileIcons === other.options.showFileIcons && - this.options.showSymbolIcons === other.options.showSymbolIcons); - } - if (this.element instanceof TreeElement && other.element instanceof TreeElement) { - return this.element.id === other.element.id; - } - return false; + return (extUri.isEqual(this.element.uri, other.element.uri) && + this.options.showFileIcons === other.options.showFileIcons && + this.options.showSymbolIcons === other.options.showSymbolIcons); + } render(container: HTMLElement): void { - if (this.element instanceof FileElement) { - // file/folder - let label = this._instantiationService.createInstance(ResourceLabel, container, {}); - label.element.setFile(this.element.uri, { - hidePath: true, - hideIcon: this.element.kind === FileKind.FOLDER || !this.options.showFileIcons, - fileKind: this.element.kind, - fileDecorations: { colors: this.options.showDecorationColors, badges: false }, - }); - container.classList.add(FileKind[this.element.kind].toLowerCase()); - this._disposables.add(label); - - } else if (this.element instanceof OutlineModel) { - // has outline element but not in one - let label = document.createElement('div'); - label.innerText = '\u2026'; - label.className = 'hint-more'; - container.appendChild(label); - - } else if (this.element instanceof OutlineGroup) { - // provider - let label = new IconLabel(container); - label.setLabel(this.element.label); - this._disposables.add(label); - - } else if (this.element instanceof OutlineElement) { - // symbol - if (this.options.showSymbolIcons) { - let icon = document.createElement('div'); - icon.className = SymbolKinds.toCssClassName(this.element.symbol.kind); - container.appendChild(icon); - container.classList.add('shows-symbol-icon'); - } - let label = new IconLabel(container); - let title = this.element.symbol.name.replace(/\r|\n|\r\n/g, '\u23CE'); - label.setLabel(title); - this._disposables.add(label); - } + // file/folder + let label = this._instantiationService.createInstance(ResourceLabel, container, {}); + label.element.setFile(this.element.uri, { + hidePath: true, + hideIcon: this.element.kind === FileKind.FOLDER || !this.options.showFileIcons, + fileKind: this.element.kind, + fileDecorations: { colors: this.options.showDecorationColors, badges: false }, + }); + container.classList.add(FileKind[this.element.kind].toLowerCase()); + this._disposables.add(label); } } @@ -171,25 +184,22 @@ export class BreadcrumbsControl { @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IContextViewService private readonly _contextViewService: IContextViewService, @IEditorService private readonly _editorService: IEditorService, - @ICodeEditorService private readonly _codeEditorService: ICodeEditorService, - @IWorkspaceContextService private readonly _workspaceService: IWorkspaceContextService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IThemeService private readonly _themeService: IThemeService, @IQuickInputService private readonly _quickInputService: IQuickInputService, - @IConfigurationService private readonly _configurationService: IConfigurationService, - @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, @IFileService private readonly _fileService: IFileService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @ILabelService private readonly _labelService: ILabelService, + @IConfigurationService configurationService: IConfigurationService, @IBreadcrumbsService breadcrumbsService: IBreadcrumbsService, ) { this.domNode = document.createElement('div'); this.domNode.classList.add('breadcrumbs-control'); dom.append(container, this.domNode); - this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(_configurationService); - this._cfShowIcons = BreadcrumbsConfig.Icons.bindTo(_configurationService); - this._cfTitleScrollbarSizing = BreadcrumbsConfig.TitleScrollbarSizing.bindTo(_configurationService); + this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(configurationService); + this._cfShowIcons = BreadcrumbsConfig.Icons.bindTo(configurationService); + this._cfTitleScrollbarSizing = BreadcrumbsConfig.TitleScrollbarSizing.bindTo(configurationService); const sizing = this._cfTitleScrollbarSizing.getValue() ?? 'default'; this._widget = new BreadcrumbsWidget(this.domNode, BreadcrumbsControl.SCROLLBAR_SIZES[sizing]); @@ -256,14 +266,11 @@ export class BreadcrumbsControl { this._ckBreadcrumbsVisible.set(true); this._ckBreadcrumbsPossible.set(true); - const editor = this._getActiveCodeEditor(); - const model = new EditorBreadcrumbsModel( + const model = this._instantiationService.createInstance(BreadcrumbsModel, fileInfoUri ?? uri, - uri, editor, - this._configurationService, - this._textResourceConfigurationService, - this._workspaceService + this._editorGroup.activeEditorPane ); + this.domNode.classList.toggle('relative-path', model.isRelative()); this.domNode.classList.toggle('backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\'); @@ -274,7 +281,7 @@ export class BreadcrumbsControl { showFileIcons: this._options.showFileIcons && showIcons, showSymbolIcons: this._options.showSymbolIcons && showIcons }; - const items = model.getElements().map(element => new Item(element, options, this._instantiationService)); + const items = model.getElements().map(element => element instanceof FileElement ? new FileItem(element, options, this._instantiationService) : new OutlineItem(element, options)); this._widget.setItems(items); this._widget.reveal(items[items.length - 1]); }; @@ -339,7 +346,7 @@ export class BreadcrumbsControl { return; } - const { element } = event.item as Item; + const { element } = event.item as FileItem | OutlineItem; this._editorGroup.focus(); type BreadcrumbSelectClassification = { @@ -360,7 +367,7 @@ export class BreadcrumbsControl { // using quick pick this._widget.setFocused(undefined); this._widget.setSelection(undefined); - this._quickInputService.quickAccess.show(element instanceof TreeElement ? '@' : ''); + this._quickInputService.quickAccess.show(element instanceof OutlineElement2 ? '@' : ''); return; } @@ -487,7 +494,7 @@ export class BreadcrumbsControl { this._ckBreadcrumbsActive.set(value); } - private _revealInEditor(event: IBreadcrumbsItemEvent, element: BreadcrumbElement, group: SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE | undefined, pinned: boolean = false): void { + private _revealInEditor(event: IBreadcrumbsItemEvent, element: FileElement | OutlineElement2, group: SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE | undefined, pinned: boolean = false): void { if (element instanceof FileElement) { if (element.kind === FileKind.FILE) { // open file in any editor @@ -500,19 +507,24 @@ export class BreadcrumbsControl { this._widget.setSelection(items[idx + 1], BreadcrumbsControl.Payload_Pick); } - } else if (element instanceof OutlineElement) { - // open symbol in code editor - const model = OutlineModel.get(element); - if (model) { - this._codeEditorService.openCodeEditor({ - resource: model.uri, - options: { - selection: Range.collapseToStart(element.symbol.selectionRange), - selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport, - pinned - } - }, withUndefinedAsNull(this._getActiveCodeEditor()), group === SIDE_GROUP); - } + } else if (element instanceof OutlineElement2) { + + element.outline.revealInEditor(element.element); + + // todo@jrieken + // } else if (element instanceof OutlineElement) { + // // open symbol in code editor + // const model = OutlineModel.get(element); + // if (model) { + // this._codeEditorService.openCodeEditor({ + // resource: model.uri, + // options: { + // selection: Range.collapseToStart(element.symbol.selectionRange), + // selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport, + // pinned + // } + // }, withUndefinedAsNull(this._getActiveCodeEditor()), group === SIDE_GROUP); + // } } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts index 01ff3916e98..151eecdd326 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts @@ -3,27 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { equals } from 'vs/base/common/arrays'; -import { TimeoutTimer } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; -import { DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { isEqual, dirname } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { IPosition } from 'vs/editor/common/core/position'; -import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; -import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Schemas } from 'vs/base/common/network'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { FileKind } from 'vs/platform/files/common/files'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; -import { ITextModel } from 'vs/editor/common/model'; -import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; +import { IOutline, IOutlineService } from 'vs/workbench/services/outline/browser/outline'; +import { IEditorPane } from 'vs/workbench/common/editor'; export class FileElement { constructor( @@ -32,11 +25,16 @@ export class FileElement { ) { } } -export type BreadcrumbElement = FileElement | OutlineModel | OutlineGroup | OutlineElement; - type FileInfo = { path: FileElement[], folder?: IWorkspaceFolder }; -export class EditorBreadcrumbsModel { +export class OutlineElement2 { + constructor( + readonly element: any, + readonly outline: IOutline + ) { } +} + +export class BreadcrumbsModel { private readonly _disposables = new DisposableStore(); private readonly _fileInfo: FileInfo; @@ -45,28 +43,32 @@ export class EditorBreadcrumbsModel { private readonly _cfgFilePath: BreadcrumbsConfig<'on' | 'off' | 'last'>; private readonly _cfgSymbolPath: BreadcrumbsConfig<'on' | 'off' | 'last'>; - private _outlineElements: Array = []; - private _outlineDisposables = new DisposableStore(); + private _currentOutline?: IOutline; + private readonly _outlineDisposables = new DisposableStore(); + private readonly _onDidUpdate = new Emitter(); readonly onDidUpdate: Event = this._onDidUpdate.event; constructor( fileInfoUri: URI, - private readonly _uri: URI, - private readonly _editor: ICodeEditor | undefined, - @IConfigurationService private readonly _configurationService: IConfigurationService, - @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, + editor: IEditorPane | undefined, + @IConfigurationService configurationService: IConfigurationService, @IWorkspaceContextService workspaceService: IWorkspaceContextService, + @IOutlineService private readonly _outlineService: IOutlineService, ) { - this._cfgEnabled = BreadcrumbsConfig.IsEnabled.bindTo(_configurationService); - this._cfgFilePath = BreadcrumbsConfig.FilePath.bindTo(_configurationService); - this._cfgSymbolPath = BreadcrumbsConfig.SymbolPath.bindTo(_configurationService); + this._cfgEnabled = BreadcrumbsConfig.IsEnabled.bindTo(configurationService); + this._cfgFilePath = BreadcrumbsConfig.FilePath.bindTo(configurationService); + this._cfgSymbolPath = BreadcrumbsConfig.SymbolPath.bindTo(configurationService); this._disposables.add(this._cfgFilePath.onDidChange(_ => this._onDidUpdate.fire(this))); this._disposables.add(this._cfgSymbolPath.onDidChange(_ => this._onDidUpdate.fire(this))); - this._fileInfo = EditorBreadcrumbsModel._initFilePathInfo(fileInfoUri, workspaceService); - this._bindToEditor(); + this._fileInfo = BreadcrumbsModel._initFilePathInfo(fileInfoUri, workspaceService); + + if (editor) { + this._bindToEditor(editor); + this._disposables.add(_outlineService.onDidChange(() => this._bindToEditor(editor))); + } this._onDidUpdate.fire(this); } @@ -83,8 +85,8 @@ export class EditorBreadcrumbsModel { return Boolean(this._fileInfo.folder); } - getElements(): ReadonlyArray { - let result: BreadcrumbElement[] = []; + getElements(): ReadonlyArray { + let result: (FileElement | OutlineElement2)[] = []; // file path elements if (this._cfgFilePath.getValue() === 'on') { @@ -93,11 +95,19 @@ export class EditorBreadcrumbsModel { result = result.concat(this._fileInfo.path.slice(-1)); } - // symbol path elements - if (this._cfgSymbolPath.getValue() === 'on') { - result = result.concat(this._outlineElements); - } else if (this._cfgSymbolPath.getValue() === 'last' && this._outlineElements.length > 0) { - result = result.concat(this._outlineElements.slice(-1)); + if (this._cfgSymbolPath.getValue() === 'off') { + return result; + } + + if (!this._currentOutline) { + return result; + } + + const { activeEntry } = this._currentOutline; + if (activeEntry) { + for (let element of this._currentOutline.treeConfig.parentChainProvider.getBreadcrumbElements(activeEntry)) { + result.push(new OutlineElement2(element, this._currentOutline)); + } } return result; @@ -136,175 +146,31 @@ export class EditorBreadcrumbsModel { return info; } - private _bindToEditor(): void { - if (!this._editor) { - return; - } - // update as language, model, providers changes - this._disposables.add(DocumentSymbolProviderRegistry.onDidChange(_ => this._updateOutline())); - this._disposables.add(this._editor.onDidChangeModel(_ => this._updateOutline())); - this._disposables.add(this._editor.onDidChangeModelLanguage(_ => this._updateOutline())); - - // update when config changes (re-render) - this._disposables.add(this._configurationService.onDidChangeConfiguration(e => { - if (!this._cfgEnabled.getValue()) { - // breadcrumbs might be disabled (also via a setting/config) and that is - // something we must check before proceeding. - return; - } - if (e.affectsConfiguration('breadcrumbs')) { - this._updateOutline(true); - return; - } - if (this._editor && this._editor.getModel()) { - const editorModel = this._editor.getModel() as ITextModel; - const languageName = editorModel.getLanguageIdentifier().language; - - // Checking for changes in the current language override config. - // We can't be more specific than this because the ConfigurationChangeEvent(e) only includes the first part of the root path - if (e.affectsConfiguration(`[${languageName}]`)) { - this._updateOutline(true); - } - } - })); - - - // update soon'ish as model content change - const updateSoon = new TimeoutTimer(); - this._disposables.add(updateSoon); - this._disposables.add(this._editor.onDidChangeModelContent(_ => { - const timeout = OutlineModel.getRequestDelay(this._editor!.getModel()); - updateSoon.cancelAndSet(() => this._updateOutline(true), timeout); - })); - this._updateOutline(); - - // stop when editor dies - this._disposables.add(this._editor.onDidDispose(() => this._outlineDisposables.clear())); - } - - private _updateOutline(didChangeContent?: boolean): void { + private _bindToEditor(editor: IEditorPane): void { + const newCts = new CancellationTokenSource(); this._outlineDisposables.clear(); - if (!didChangeContent) { - this._updateOutlineElements([]); - } + this._outlineDisposables.add(toDisposable(() => newCts.dispose(true))); - const editor = this._editor!; - - const buffer = editor.getModel(); - if (!buffer || !DocumentSymbolProviderRegistry.has(buffer) || !isEqual(buffer.uri, this._uri)) { - return; - } - - const source = new CancellationTokenSource(); - const versionIdThen = buffer.getVersionId(); - const timeout = new TimeoutTimer(); - - this._outlineDisposables.add({ - dispose: () => { - source.dispose(true); - timeout.dispose(); + this._outlineService.createOutline(editor, newCts.token).then(outline => { + if (newCts.token.isCancellationRequested) { + // cancelled: dispose new outline and reset + outline?.dispose(); + outline = undefined; } - }); - - OutlineModel.create(buffer, source.token).then(model => { - if (source.token.isCancellationRequested) { - // cancelled -> do nothing - return; + this._currentOutline = outline; + this._onDidUpdate.fire(this); + if (outline) { + this._outlineDisposables.add(outline); + this._outlineDisposables.add(outline.onDidChange(() => this._onDidUpdate.fire(this))); + this._outlineDisposables.add(outline.onDidChangeActiveEntry(() => this._onDidUpdate.fire(this))); } - if (TreeElement.empty(model)) { - // empty -> no outline elements - this._updateOutlineElements([]); - } else { - // copy the model - model = model.adopt(); - - this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); - this._outlineDisposables.add(editor.onDidChangeCursorPosition(_ => { - timeout.cancelAndSet(() => { - if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && editor.getModel()) { - this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); - } - }, 150); - })); - } }).catch(err => { - this._updateOutlineElements([]); + this._currentOutline = undefined; + this._onDidUpdate.fire(this); onUnexpectedError(err); }); } - private _getOutlineElements(model: OutlineModel, position: IPosition | null): Array { - if (!model || !position) { - return []; - } - let item: OutlineGroup | OutlineElement | undefined = model.getItemEnclosingPosition(position); - if (!item) { - return this._getOutlineElementsRoot(model); - } - let chain: Array = []; - while (item) { - chain.push(item); - let parent: any = item.parent; - if (parent instanceof OutlineModel) { - break; - } - if (parent instanceof OutlineGroup && parent.parent && parent.parent.children.size === 1) { - break; - } - item = parent; - } - let result: Array = []; - for (let i = chain.length - 1; i >= 0; i--) { - let element = chain[i]; - if (this._isFiltered(element)) { - break; - } - result.push(element); - } - if (result.length === 0) { - return this._getOutlineElementsRoot(model); - } - return result; - } - - private _getOutlineElementsRoot(model: OutlineModel): (OutlineModel | OutlineGroup | OutlineElement)[] { - for (const child of model.children.values()) { - if (!this._isFiltered(child)) { - return [model]; - } - } - return []; - } - - private _isFiltered(element: TreeElement): boolean { - if (element instanceof OutlineElement) { - const key = `breadcrumbs.${OutlineFilter.kindToConfigName[element.symbol.kind]}`; - let uri: URI | undefined; - if (this._editor && this._editor.getModel()) { - const model = this._editor.getModel() as ITextModel; - uri = model.uri; - } - return !this._textResourceConfigurationService.getValue(uri, key); - } - return false; - } - - private _updateOutlineElements(elements: Array): void { - if (!equals(elements, this._outlineElements, EditorBreadcrumbsModel._outlineElementEquals)) { - this._outlineElements = elements; - this._onDidUpdate.fire(this); - } - } - - private static _outlineElementEquals(a: OutlineModel | OutlineGroup | OutlineElement, b: OutlineModel | OutlineGroup | OutlineElement): boolean { - if (a === b) { - return true; - } else if (!a || !b) { - return false; - } else { - return a.id === b.id; - } - } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts index 3c91f49ba07..ca7d080ec81 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts @@ -13,8 +13,8 @@ import { posix } from 'vs/base/common/path'; import { basename, dirname, isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import 'vs/css!./media/breadcrumbscontrol'; -import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; -import { IConfigurationService, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { FileKind, IFileService, IFileStat } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { WorkbenchDataTree, WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; @@ -22,16 +22,17 @@ import { breadcrumbsPickerBackground, widgetShadow } from 'vs/platform/theme/com import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; -import { BreadcrumbElement, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; +import { OutlineElement2, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter } from 'vs/base/browser/ui/tree/tree'; -import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineFilter, OutlineAccessibilityProvider } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { OutlineItemComparator, OutlineNavigationLabelProvider, OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list'; import { IFileIconTheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { IModeService } from 'vs/editor/common/services/modeService'; +// import { IModeService } from 'vs/editor/common/services/modeService'; import { localize } from 'vs/nls'; +import { IOutline } from 'vs/workbench/services/outline/browser/outline'; -export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker { +export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: FileElement | OutlineElement2): BreadcrumbsPicker { return element instanceof FileElement ? instantiationService.createInstance(BreadcrumbsFilePicker, parent) : instantiationService.createInstance(BreadcrumbsOutlinePicker, parent); @@ -103,7 +104,7 @@ export abstract class BreadcrumbsPicker { this._domNode.appendChild(this._treeContainer); this._layoutInfo = { maxHeight, width, arrowSize, arrowOffset, inputHeight: 0 }; - this._tree = this._createTree(this._treeContainer); + this._tree = this._createTree(this._treeContainer, input); this._disposables.add(this._tree.onDidChangeSelection(e => { if (e.browserEvent !== this._fakeEvent) { @@ -153,8 +154,8 @@ export abstract class BreadcrumbsPicker { return this._tree.useAltAsMultipleSelectionModifier; } - protected abstract _setInput(element: BreadcrumbElement): Promise; - protected abstract _createTree(container: HTMLElement): Tree; + protected abstract _setInput(element: FileElement | OutlineElement2): Promise; + protected abstract _createTree(container: HTMLElement, input: any): Tree; protected abstract _getTargetFromEvent(element: any): any | undefined; } @@ -394,7 +395,7 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker { }); } - async _setInput(element: BreadcrumbElement): Promise { + async _setInput(element: FileElement | OutlineElement2): Promise { const { uri, kind } = (element as FileElement); let input: IWorkspace | URI; if (kind === FileKind.ROOT_FOLDER) { @@ -442,29 +443,32 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, - @IModeService private readonly _modeService: IModeService, + // @IModeService private readonly _modeService: IModeService, ) { super(parent, instantiationService, themeService, configurationService); this._symbolSortOrder = BreadcrumbsConfig.SymbolSortOrder.bindTo(this._configurationService); this._outlineComparator = new OutlineItemComparator(); } - protected _createTree(container: HTMLElement) { - return >this._instantiationService.createInstance( + protected _createTree(container: HTMLElement, input: OutlineElement2) { + + const { treeConfig } = input.outline; + + return , any, FuzzyScore>>this._instantiationService.createInstance( WorkbenchDataTree, 'BreadcrumbsOutlinePicker', container, - new OutlineVirtualDelegate(), - [new OutlineGroupRenderer(), this._instantiationService.createInstance(OutlineElementRenderer)], - new OutlineDataSource(), + treeConfig.delegate, + treeConfig.renderers, + treeConfig.treeDataSource, { collapseByDefault: true, expandOnlyOnTwistieClick: true, multipleSelectionSupport: false, sorter: this._outlineComparator, - identityProvider: new OutlineIdentityProvider(), + identityProvider: treeConfig.identProvider, keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(), - accessibilityProvider: new OutlineAccessibilityProvider(localize('breadcrumbs', "Breadcrumbs")), + accessibilityProvider: treeConfig.options.accessibilityProvider, filter: this._instantiationService.createInstance(OutlineFilter, 'breadcrumbs') } ); @@ -475,22 +479,23 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { super.dispose(); } - protected _setInput(input: BreadcrumbElement): Promise { - const element = input as TreeElement; - const model = OutlineModel.get(element)!; - const tree = this._tree as WorkbenchDataTree; + protected _setInput(input: OutlineElement2): Promise { - const overrideConfiguration = { - resource: model.uri, - overrideIdentifier: this._modeService.getModeIdByFilepathOrFirstLine(model.uri) - }; - this._outlineComparator.type = this._getOutlineItemCompareType(overrideConfiguration); - tree.setInput(model); - if (element !== model) { - tree.reveal(element, 0.5); - tree.setFocus([element], this._fakeEvent); - } + const tree = this._tree as WorkbenchDataTree, any, FuzzyScore>; + + // todo@jrieken + // const overrideConfiguration = { + // resource: model.uri, + // overrideIdentifier: this._modeService.getModeIdByFilepathOrFirstLine(model.uri) + // }; + // this._outlineComparator.type = this._getOutlineItemCompareType(overrideConfiguration); + + tree.setInput(input.outline); + // if (element !== model) { + tree.reveal(input.element, 0.5); + tree.setFocus([input.element], this._fakeEvent); + // } tree.domFocus(); return Promise.resolve(); @@ -502,17 +507,17 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { } } - private _getOutlineItemCompareType(overrideConfiguration?: IConfigurationOverrides): OutlineSortOrder { - switch (this._symbolSortOrder.getValue(overrideConfiguration)) { - case 'name': - return OutlineSortOrder.ByName; - case 'type': - return OutlineSortOrder.ByKind; - case 'position': - default: - return OutlineSortOrder.ByPosition; - } - } + // private _getOutlineItemCompareType(overrideConfiguration?: IConfigurationOverrides): OutlineSortOrder { + // switch (this._symbolSortOrder.getValue(overrideConfiguration)) { + // case 'name': + // return OutlineSortOrder.ByName; + // case 'type': + // return OutlineSortOrder.ByKind; + // case 'position': + // default: + // return OutlineSortOrder.ByPosition; + // } + // } } //#endregion diff --git a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts index ae74a2c54e4..bb7d9501374 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts @@ -5,16 +5,16 @@ import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; +import { IOutline, IOutlineCreator, IOutlineService, OutlineTreeConfiguration } from 'vs/workbench/services/outline/browser/outline'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IEditorPane } from 'vs/workbench/common/editor'; -import { OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { OutlineAccessibilityProvider, OutlineElementRenderer, OutlineFilter, OutlineGroupRenderer, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineVirtualDelegate } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { OutlineGroup, OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { TimeoutTimer } from 'vs/base/common/async'; import { equals } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -27,7 +27,8 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ScrollType } from 'vs/editor/common/editorCommon'; import { Range } from 'vs/editor/common/core/range'; -type DocumentSymbolItem = TreeElement; + +type DocumentSymbolItem = OutlineGroup | OutlineElement; class DocumentSymbolsOutline implements IOutline { @@ -39,14 +40,49 @@ class DocumentSymbolsOutline implements IOutline { private readonly _onDidChangeActiveEntry = new Emitter(); readonly onDidChangeActiveEntry: Event = this._onDidChangeActiveEntry.event; - private _outlineElements: Array = []; + private _outlineModel?: OutlineModel; + private _outlineElementChain: Array = []; private _outlineDisposables = new DisposableStore(); + readonly treeConfig: OutlineTreeConfiguration; + constructor( private readonly _editor: ICodeEditor, @IConfigurationService private readonly _configurationService: IConfigurationService, @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, + @IInstantiationService instantiationService: IInstantiationService, ) { + + this.treeConfig = new OutlineTreeConfiguration( + { + getBreadcrumbElements: () => this._outlineElementChain.filter(element => !(element instanceof OutlineModel)) + }, + { + getChildren: (parent) => { + if (parent instanceof OutlineElement || parent instanceof OutlineGroup) { + return parent.children.values(); + } + if (parent === this && this._outlineModel) { + return this._outlineModel.children.values(); + } + return []; + } + }, + new OutlineVirtualDelegate(), + [new OutlineGroupRenderer(), instantiationService.createInstance(OutlineElementRenderer)], + new OutlineIdentityProvider(), + { + collapseByDefault: true, + expandOnlyOnTwistieClick: true, + multipleSelectionSupport: false, + // sorter: this._outlineComparator, + identityProvider: new OutlineIdentityProvider(), + keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(), + accessibilityProvider: new OutlineAccessibilityProvider(''), + filter: instantiationService.createInstance(OutlineFilter, 'breadcrumbs') + } + ); + // update as language, model, providers changes this._disposables.add(DocumentSymbolProviderRegistry.onDidChange(_ => this._updateOutline())); this._disposables.add(this._editor.onDidChangeModel(_ => this._updateOutline())); @@ -88,8 +124,13 @@ class DocumentSymbolsOutline implements IOutline { this._outlineDisposables.dispose(); } + get isEmpty(): boolean { + return this._outlineElementChain.length === 0; + } + get activeEntry(): DocumentSymbolItem | undefined { - return this._outlineElements[this._outlineElements.length - 1]; + const candidate = this._outlineElementChain[this._outlineElementChain.length - 1]; + return candidate instanceof OutlineModel ? undefined : candidate; } revealInEditor(entry: DocumentSymbolItem): void | Promise { @@ -101,19 +142,11 @@ class DocumentSymbolsOutline implements IOutline { this._editor.focus(); } - getParent(entry: DocumentSymbolItem): DocumentSymbolItem | undefined { - if (entry instanceof OutlineModel) { - return undefined; - } else { - return entry.parent; - } - } - private _updateOutline(didChangeContent?: boolean): void { this._outlineDisposables.clear(); if (!didChangeContent) { - this._updateOutlineElements([]); + this._updateOutlineElements(undefined, []); } const editor = this._editor!; @@ -141,23 +174,23 @@ class DocumentSymbolsOutline implements IOutline { } if (TreeElement.empty(model)) { // empty -> no outline elements - this._updateOutlineElements([]); + this._updateOutlineElements(model, []); } else { // copy the model model = model.adopt(); - this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); + this._updateOutlineElements(model, this._getOutlineElements(model, editor.getPosition())); this._outlineDisposables.add(editor.onDidChangeCursorPosition(_ => { timeout.cancelAndSet(() => { if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && editor.getModel()) { - this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition())); + this._updateOutlineElements(model, this._getOutlineElements(model, editor.getPosition())); } }, 150); })); } }).catch(err => { - this._updateOutlineElements([]); + this._updateOutlineElements(undefined, []); onUnexpectedError(err); }); } @@ -218,9 +251,17 @@ class DocumentSymbolsOutline implements IOutline { return false; } - private _updateOutlineElements(elements: Array): void { - if (!equals(elements, this._outlineElements, DocumentSymbolsOutline._outlineElementEquals)) { - this._outlineElements = elements; + private _updateOutlineElements(model: OutlineModel | undefined, elements: Array): void { + let fire = false; + if (this._outlineModel !== model) { + this._outlineModel = model; + fire = true; + } + if (!equals(elements, this._outlineElementChain, DocumentSymbolsOutline._outlineElementEquals)) { + this._outlineElementChain = elements; + fire = true; + } + if (fire) { this._onDidChange.fire(this); } } @@ -253,7 +294,7 @@ class DocumentSymbolsOutlineCreator implements IOutlineCreator | undefined> { + async createOutline(pane: IEditorPane, token: CancellationToken): Promise | undefined> { const control = pane.getControl(); let editor: ICodeEditor | undefined; if (isCodeEditor(control)) { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts index 392f67fe8eb..1a0230eeea6 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts @@ -3,20 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as dom from 'vs/base/browser/dom'; import { Codicon } from 'vs/base/common/codicons'; import { Emitter, Event } from 'vs/base/common/event'; -import { DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; +import { IOutline, IOutlineCreator, IOutlineService, OutlineTreeConfiguration } from 'vs/workbench/services/outline/browser/outline'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IEditorPane } from 'vs/workbench/common/editor'; +import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; +import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; +import { Iterable } from 'vs/base/common/iterator'; -class OutlineEntry { +export class OutlineEntry { constructor( readonly cell: ICellViewModel, readonly label: string, @@ -24,7 +31,59 @@ class OutlineEntry { ) { } } -class NotebookOutline implements IOutline { +class NotebookOutlineTemplate { + + static readonly templateId = 'NotebookOutlineRenderer'; + + constructor( + readonly iconLabel: IconLabel, + readonly iconClass: HTMLElement, + ) { } +} + +class NotebookOutlineRenderer implements ITreeRenderer { + + templateId: string = NotebookOutlineTemplate.templateId; + + renderTemplate(container: HTMLElement): NotebookOutlineTemplate { + const iconClass = dom.$('span'); + container.append(iconClass); + const iconLabel = new IconLabel(container); + + return new NotebookOutlineTemplate(iconLabel, iconClass); + } + + renderElement(element: ITreeNode, _index: number, templateData: NotebookOutlineTemplate, _height: number | undefined): void { + templateData.iconClass.classList.add(...ThemeIcon.asClassNameArray(element.element.icon)); + templateData.iconLabel.setLabel(element.element.label, undefined, { extraClasses: [] }); + } + + disposeTemplate(templateData: NotebookOutlineTemplate): void { + templateData.iconLabel.dispose(); + } +} + +class NotebookOutlineAccessibility implements IListAccessibilityProvider { + getAriaLabel(element: OutlineEntry): string | null { + return element.label; + } + getWidgetAriaLabel(): string { + return ''; + } +} + +class NotebookOutlineVirtualDelegate implements IListVirtualDelegate { + + getHeight(_element: OutlineEntry): number { + return 22; + } + + getTemplateId(_element: OutlineEntry): string { + return NotebookOutlineTemplate.templateId; + } +} + +class NotebookCellOutline implements IOutline { private readonly _dispoables = new DisposableStore(); @@ -37,15 +96,35 @@ class NotebookOutline implements IOutline { private _activeEntry?: OutlineEntry; private _entries: OutlineEntry[] = []; + readonly treeConfig: OutlineTreeConfiguration; + constructor( private readonly _editor: NotebookEditor ) { + + this._computeEntries(); + this._computeActive(); + + const selectionListener = new MutableDisposable(); + this._dispoables.add(selectionListener); this._dispoables.add(_editor.onDidChangeModel(() => { this._computeEntries(); this._computeActive(); + if (_editor.viewModel) { + selectionListener.value = _editor.viewModel.onDidChangeSelection(() => this._computeActive()); + } else { + selectionListener.value = undefined; + } })); - this._computeEntries(); - this._computeActive(); + + this.treeConfig = new OutlineTreeConfiguration( + { getBreadcrumbElements: (element) => Iterable.single(element) }, + { getChildren: parent => parent === this ? this._entries : [] }, + new NotebookOutlineVirtualDelegate(), + [new NotebookOutlineRenderer()], + { getId: element => element.cell.handle }, + { accessibilityProvider: new NotebookOutlineAccessibility() } + ); } dispose(): void { @@ -93,6 +172,10 @@ class NotebookOutline implements IOutline { } } + get isEmpty(): boolean { + return this._entries.length === 0; + } + get activeEntry(): OutlineEntry | undefined { return this._activeEntry; } @@ -124,7 +207,7 @@ class NotebookOutlineCreator implements IOutlineCreator | undefined> { - return new NotebookOutline(editor); + return new NotebookCellOutline(editor); } } diff --git a/src/vs/workbench/services/outline/browser/outline.ts b/src/vs/workbench/services/outline/browser/outline.ts new file mode 100644 index 00000000000..9ab1d8af01a --- /dev/null +++ b/src/vs/workbench/services/outline/browser/outline.ts @@ -0,0 +1,59 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IDataSource, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Event } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkbenchDataTreeOptions } from 'vs/platform/list/browser/listService'; +import { IEditorPane } from 'vs/workbench/common/editor'; + +export const IOutlineService = createDecorator('IOutlineService'); + +export interface IOutlineService { + _serviceBrand: undefined; + onDidChange: Event; + createOutline(editor: IEditorPane, token: CancellationToken): Promise | undefined>; + registerOutlineCreator(creator: IOutlineCreator): IDisposable; +} + +export interface IOutlineCreator

{ + matches(candidate: IEditorPane): candidate is P; + createOutline(editor: P, token: CancellationToken): Promise | undefined>; +} + +export interface IParentChainProvider { + getBreadcrumbElements(element: E): Iterable; +} + +export class OutlineTreeConfiguration { + constructor( + readonly parentChainProvider: IParentChainProvider, + readonly treeDataSource: IDataSource, E>, + readonly delegate: IListVirtualDelegate, + readonly renderers: ITreeRenderer[], + readonly identProvider: IIdentityProvider, + readonly options: IWorkbenchDataTreeOptions, + ) { } +} + +export interface IOutline { + + dispose(): void; + + readonly treeConfig: OutlineTreeConfiguration + + readonly onDidChange: Event; + + readonly isEmpty: boolean; + readonly activeEntry: E | undefined; + readonly onDidChangeActiveEntry: Event + + revealInEditor(entry: E): Promise | void; + //todo@jrieken preview +} diff --git a/src/vs/workbench/services/outline/common/outlineService.ts b/src/vs/workbench/services/outline/browser/outlineService.ts similarity index 67% rename from src/vs/workbench/services/outline/common/outlineService.ts rename to src/vs/workbench/services/outline/browser/outlineService.ts index 3c976dcd902..a3e57523493 100644 --- a/src/vs/workbench/services/outline/common/outlineService.ts +++ b/src/vs/workbench/services/outline/browser/outlineService.ts @@ -3,12 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { LinkedList } from 'vs/base/common/linkedList'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IEditorPane } from 'vs/workbench/common/editor'; -import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/common/outline'; - +import { IOutline, IOutlineCreator, IOutlineService } from 'vs/workbench/services/outline/browser/outline'; +import { Event, Emitter } from 'vs/base/common/event'; class OutlineService implements IOutlineService { @@ -16,10 +17,13 @@ class OutlineService implements IOutlineService { private readonly _factories = new LinkedList>(); - async createOutline(pane: IEditorPane): Promise | undefined> { + private readonly _onDidChange = new Emitter(); + readonly onDidChange: Event = this._onDidChange.event; + + async createOutline(pane: IEditorPane, token: CancellationToken): Promise | undefined> { for (let factory of this._factories) { if (factory.matches(pane)) { - return await factory.createOutline(pane); + return await factory.createOutline(pane, token); } } return undefined; @@ -27,7 +31,11 @@ class OutlineService implements IOutlineService { registerOutlineCreator(creator: IOutlineCreator): IDisposable { const rm = this._factories.push(creator); - return toDisposable(rm); + this._onDidChange.fire(); + return toDisposable(() => { + rm(); + this._onDidChange.fire(); + }); } } diff --git a/src/vs/workbench/services/outline/common/outline.ts b/src/vs/workbench/services/outline/common/outline.ts deleted file mode 100644 index 6a11705c4bc..00000000000 --- a/src/vs/workbench/services/outline/common/outline.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IEditorPane } from 'vs/workbench/common/editor'; - -export const IOutlineService = createDecorator('IOutlineService'); - -export interface IOutlineService { - _serviceBrand: undefined; - - createOutline(editor: IEditorPane): Promise | undefined>; - - registerOutlineCreator(creator: IOutlineCreator): IDisposable; -} - -export interface IOutlineCreator

{ - matches(candidate: IEditorPane): candidate is P; - createOutline(editor: P): Promise | undefined>; -} - - -export interface IOutline { - - dispose(): void; - - readonly onDidChange: Event; - - readonly activeEntry: E | undefined; - readonly onDidChangeActiveEntry: Event - - revealInEditor(entry: E): Promise | void; - - getParent(entry: E): E | undefined; - // getChildren(parent: E): Iterable -} diff --git a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts index 4d7f774bf60..cd016718616 100644 --- a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts @@ -6,12 +6,13 @@ import * as assert from 'assert'; import { URI } from 'vs/base/common/uri'; import { WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; +import { BreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { FileKind } from 'vs/platform/files/common/files'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; import { Workspace } from 'vs/platform/workspace/test/common/testWorkspace'; - +import { mock } from 'vs/base/test/common/mock'; +import { IOutlineService } from 'vs/workbench/services/outline/browser/outline'; suite('Breadcrumb Model', function () { @@ -33,7 +34,7 @@ suite('Breadcrumb Model', function () { test('only uri, inside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); + let model = new BreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, workspaceService, new class extends mock() { }); let elements = model.getElements(); assert.equal(elements.length, 3); @@ -48,7 +49,7 @@ suite('Breadcrumb Model', function () { test('display uri matters for FileElement', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/PATH/file.ts'), URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); + let model = new BreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/PATH/file.ts'), undefined, configService, workspaceService, new class extends mock() { }); let elements = model.getElements(); assert.equal(elements.length, 3); @@ -63,7 +64,7 @@ suite('Breadcrumb Model', function () { test('only uri, outside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/outside/file.ts'), URI.parse('foo:/outside/file.ts'), undefined, configService, configService, workspaceService); + let model = new BreadcrumbsModel(URI.parse('foo:/outside/file.ts'), undefined, configService, workspaceService, new class extends mock() { }); let elements = model.getElements(); assert.equal(elements.length, 2); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 2b1b4d69388..67982e7ecdf 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -89,7 +89,7 @@ import 'vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService' import 'vs/workbench/services/authentication/browser/authenticationService'; import 'vs/workbench/services/hover/browser/hoverService'; import 'vs/workbench/services/experiment/common/experimentService'; -import 'vs/workbench/services/outline/common/outlineService'; +import 'vs/workbench/services/outline/browser/outlineService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; From 58985749f9acab9f633657b546283145cf2f074c Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 18 Dec 2020 09:24:55 -0800 Subject: [PATCH 1254/1837] memory leak --- src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 022b28ded62..91a1ff50d29 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -135,6 +135,7 @@ class PropertyHeader extends Disposable { }; const scopedContextKeyService = this.contextKeyService.createScoped(cellToolbarContainer); + this._register(scopedContextKeyService); const propertyChanged = NOTEBOOK_DIFF_CELL_PROPERTY.bindTo(scopedContextKeyService); propertyChanged.set(metadataChanged); this._propertyExpanded = NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED.bindTo(scopedContextKeyService); From 94fbbb38ae6af8f25993512d5d9ca09a316670f7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 18 Dec 2020 18:32:42 +0100 Subject: [PATCH 1255/1837] tricky selection listening --- .../browser/contrib/outline/notebooksOutline.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts index 1a0230eeea6..82dc63645ff 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebooksOutline.ts @@ -102,21 +102,23 @@ class NotebookCellOutline implements IOutline { private readonly _editor: NotebookEditor ) { - this._computeEntries(); - this._computeActive(); const selectionListener = new MutableDisposable(); + const installSelectionListener = () => { + selectionListener.value = _editor.viewModel?.onDidChangeSelection(() => this._computeActive()); + }; + this._dispoables.add(selectionListener); this._dispoables.add(_editor.onDidChangeModel(() => { this._computeEntries(); this._computeActive(); - if (_editor.viewModel) { - selectionListener.value = _editor.viewModel.onDidChangeSelection(() => this._computeActive()); - } else { - selectionListener.value = undefined; - } + installSelectionListener(); })); + this._computeEntries(); + this._computeActive(); + installSelectionListener(); + this.treeConfig = new OutlineTreeConfiguration( { getBreadcrumbElements: (element) => Iterable.single(element) }, { getChildren: parent => parent === this ? this._entries : [] }, From ea15eb4e5ab86ce2d7fd3aefd6d787b1fa8a7fb6 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Fri, 18 Dec 2020 17:29:24 +0000 Subject: [PATCH 1256/1837] Strengthen sameNodes check :muscle: fixes #112829 --- .../emmet/src/test/toggleComment.test.ts | 27 ++++++++++++++++++- extensions/emmet/src/util.ts | 11 +++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/extensions/emmet/src/test/toggleComment.test.ts b/extensions/emmet/src/test/toggleComment.test.ts index 4793c3ed819..6e6a5c8252e 100644 --- a/extensions/emmet/src/test/toggleComment.test.ts +++ b/extensions/emmet/src/test/toggleComment.test.ts @@ -726,4 +726,29 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => { }); }); -}); \ No newline at end of file + test('toggle comment doesn\'t fail when start and end nodes differ HTML', () => { + const contents = ` +

+

Hello

+
+ `; + const expectedContents = ` + + `; + return withRandomFileEditor(contents, 'html', (editor, doc) => { + editor.selections = [ + new Selection(1, 2, 2, 9), //
to

inclusive + ]; + + return toggleComment().then(() => { + assert.equal(doc.getText(), expectedContents); + return toggleComment().then(() => { + assert.equal(doc.getText(), contents); + return Promise.resolve(); + }); + }); + }); + }); +}); diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index 259a30292d8..17cac93bd4f 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -589,11 +589,20 @@ export function getNodesInBetween(node1: Node, node2: Node): Node[] { return siblings; } +function samePositions(pos1: vscode.Position | undefined, pos2: vscode.Position | undefined): boolean { + if (!pos1 && !pos2) { + return true; + } else if (pos1 && pos2 && pos1.isEqual(pos2)) { + return true; + } + return false; +} + export function sameNodes(node1: Node, node2: Node): boolean { if (!node1 || !node2) { return false; } - return (node1.start).isEqual(node2.start) && (node1.end).isEqual(node2.end); + return samePositions(node1.start, node2.start) && samePositions(node1.end, node2.end); } export function getEmmetConfiguration(syntax: string) { From 775bf46bad45ca9e7b250ea0fff9c160beb03ed1 Mon Sep 17 00:00:00 2001 From: Elliot Jordan Date: Fri, 18 Dec 2020 09:54:56 -0800 Subject: [PATCH 1257/1837] Adjust references to --list-extensions option --- resources/completions/zsh/_code | 4 ++-- src/vs/platform/environment/node/argv.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/completions/zsh/_code b/resources/completions/zsh/_code index c7abee1bc58..087ea61f56a 100644 --- a/resources/completions/zsh/_code +++ b/resources/completions/zsh/_code @@ -17,8 +17,8 @@ arguments=( '--telemetry[show all telemetry events which VS code collects]' '--extensions-dir[set the root path for extensions]:root path:_directories' '--list-extensions[list the installed extensions]' - '--category[filters installed extension list by category, when using --list-extension]' - '--show-versions[show versions of installed extensions, when using --list-extension]' + '--category[filters installed extension list by category, when using --list-extensions]' + '--show-versions[show versions of installed extensions, when using --list-extensions]' '--install-extension[install an extension]:id or path:_files -g "*.vsix(-.)"' '--uninstall-extension[uninstall an extension]:id or path:_files -g "*.vsix(-.)"' '--enable-proposed-api[enables proposed API features for extensions]::extension id: ' diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 1ec40eea8f0..c1362f8638f 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -53,8 +53,8 @@ export const OPTIONS: OptionDescriptions> = { 'extensions-download-dir': { type: 'string' }, 'builtin-extensions-dir': { type: 'string' }, 'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") }, - 'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") }, - 'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") }, + 'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extensions.") }, + 'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extensions.") }, 'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id[@version] | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. The identifier of an extension is always `${publisher}.${name}`. Use `--force` argument to update to latest version. To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.") }, 'uninstall-extension': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") }, 'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") }, From 6ad2dccc786c64f30b7a4389f07cbb2af3908a47 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Fri, 18 Dec 2020 18:01:15 +0000 Subject: [PATCH 1258/1837] Emmet Toggle Comment HTML :lipstick: --- .../emmet/src/test/toggleComment.test.ts | 56 +++++++++---------- extensions/emmet/src/toggleComment.ts | 4 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/extensions/emmet/src/test/toggleComment.test.ts b/extensions/emmet/src/test/toggleComment.test.ts index 6e6a5c8252e..6e7344b3577 100644 --- a/extensions/emmet/src/test/toggleComment.test.ts +++ b/extensions/emmet/src/test/toggleComment.test.ts @@ -26,7 +26,7 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {

  • Bye
    • - +
    • Another Node
    @@ -47,14 +47,14 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => { const expectedContents = `
      -
    • - - +
    • + +
    - + --> --> + -->
    `; return withRandomFileEditor(contents, 'html', (editor, doc) => { @@ -252,16 +252,16 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => { const templateContents = ` `; const expectedContents = ` `; @@ -733,9 +733,9 @@ suite('Tests for Toggle Comment action from Emmet in nested css (SCSS)', () => {
    `; const expectedContents = ` - +
    --> `; return withRandomFileEditor(contents, 'html', (editor, doc) => { editor.selections = [ diff --git a/extensions/emmet/src/toggleComment.ts b/extensions/emmet/src/toggleComment.ts index 952126fca5e..db040bccdee 100644 --- a/extensions/emmet/src/toggleComment.ts +++ b/extensions/emmet/src/toggleComment.ts @@ -11,8 +11,8 @@ import { DocumentStreamReader } from './bufferStream'; const startCommentStylesheet = '/*'; const endCommentStylesheet = '*/'; -const startCommentHTML = ''; +const startCommentHTML = ''; export function toggleComment(): Thenable | undefined { if (!validate() || !vscode.window.activeTextEditor) { From b4a22eba377442084daf3efa57f0fff1cc8327a6 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 18 Dec 2020 10:35:51 -0800 Subject: [PATCH 1259/1837] recompute output height in diff view model. --- .../notebook/browser/diff/diffComponents.ts | 69 +++--- .../browser/diff/diffElementViewModel.ts | 223 ++++++++++-------- .../browser/diff/notebookDiffEditorBrowser.ts | 18 +- 3 files changed, 178 insertions(+), 132 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 91a1ff50d29..4b2402e0c3e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -319,8 +319,6 @@ abstract class AbstractElementRenderer extends Disposable { this._hideOutputsRaw(); this._hideOutputsRenderer(); } - - this.cell.layoutChange(); } private _buildOutputRawContainer() { @@ -333,13 +331,14 @@ abstract class AbstractElementRenderer extends Disposable { private _showOutputsRaw() { if (this._outputEditorContainer) { this._outputEditorContainer.style.display = 'block'; - this.cell.outputHeight = this._outputEditor!.getContentHeight(); + this.cell.rawOutputHeight = this._outputEditor!.getContentHeight(); } } private _hideOutputsRaw() { if (this._outputEditorContainer) { this._outputEditorContainer.style.display = 'none'; + this.cell.rawOutputHeight = 0; } } @@ -563,11 +562,11 @@ abstract class AbstractElementRenderer extends Disposable { modified: modifiedModel }); - this.cell.outputHeight = this._outputEditor.getContentHeight(); + this.cell.rawOutputHeight = this._outputEditor.getContentHeight(); this._register(this._outputEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - this.cell.outputHeight = e.contentHeight; + this.cell.rawOutputHeight = e.contentHeight; } })); @@ -601,11 +600,11 @@ abstract class AbstractElementRenderer extends Disposable { const outputModel = this.modelService.createModel(originaloutputSource, mode, undefined, true); this._outputEditor.setModel(outputModel); - this.cell.outputHeight = this._outputEditor.getContentHeight(); + this.cell.rawOutputHeight = this._outputEditor.getContentHeight(); this._register(this._outputEditor.onDidContentSizeChange((e) => { if (e.contentHeightChanged && this.cell.outputFoldingState === PropertyFoldingState.Expanded) { - this.cell.outputHeight = e.contentHeight; + this.cell.rawOutputHeight = e.contentHeight; } })); } @@ -613,14 +612,14 @@ abstract class AbstractElementRenderer extends Disposable { protected layoutNotebookCell() { this.notebookEditor.layoutNotebookCell( this.cell, - this.cell.totalHeight + this.cell.layoutInfo.totalHeight ); } updateBorders() { - this.templateData.leftBorder.style.height = `${this.cell.totalHeight - 32}px`; - this.templateData.rightBorder.style.height = `${this.cell.totalHeight - 32}px`; - this.templateData.bottomBorder.style.top = `${this.cell.totalHeight - 32}px`; + this.templateData.leftBorder.style.height = `${this.cell.layoutInfo.totalHeight - 32}px`; + this.templateData.rightBorder.style.height = `${this.cell.layoutInfo.totalHeight - 32}px`; + this.templateData.bottomBorder.style.top = `${this.cell.layoutInfo.totalHeight - 32}px`; } dispose() { @@ -716,7 +715,7 @@ abstract class SingleSideDiffElement extends AbstractElementRenderer { this._metadataHeader.buildHeader(); if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { - this.cell.outputHeight = 0; + this.cell.rawOutputHeight = 0; this.cell.outputStatusHeight = 0; this.templateData.outputHeaderContainer.style.display = 'none'; this.templateData.outputInfoContainer.style.display = 'none'; @@ -795,7 +794,7 @@ export class DeletedElement extends SingleSideDiffElement { this.cell.editorHeight = editorHeight; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + if (e.contentHeightChanged && this.cell.layoutInfo.editorHeight !== e.contentHeight) { this.cell.editorHeight = e.contentHeight; } })); @@ -813,31 +812,31 @@ export class DeletedElement extends SingleSideDiffElement { }); } - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean }) { + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputTotalHeight?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { this._editor.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this.cell.editorHeight + height: this.cell.layoutInfo.editorHeight }); } if (state.metadataEditor || state.outerWidth) { this._metadataEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this.cell.metadataHeight + height: this.cell.layoutInfo.metadataHeight }); } - if (state.outputEditor || state.outerWidth) { + if (state.outputTotalHeight || state.outerWidth) { this._outputEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this.cell.outputHeight + height: this.cell.layoutInfo.outputTotalHeight }); } if (this._diagonalFill) { - this._diagonalFill.style.height = `${this.cell.totalHeight - 32}px`; + this._diagonalFill.style.height = `${this.cell.layoutInfo.totalHeight - 32}px`; } this.layoutNotebookCell(); @@ -927,7 +926,7 @@ export class InsertElement extends SingleSideDiffElement { this.cell.editorHeight = editorHeight; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + if (e.contentHeightChanged && this.cell.layoutInfo.editorHeight !== e.contentHeight) { this.cell.editorHeight = e.contentHeight; } })); @@ -983,33 +982,33 @@ export class InsertElement extends SingleSideDiffElement { } } - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputTotalHeight?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight || state.outerWidth) { this._editor.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this.cell.editorHeight + height: this.cell.layoutInfo.editorHeight }); } if (state.metadataEditor || state.outerWidth) { this._metadataEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true), - height: this.cell.metadataHeight + height: this.cell.layoutInfo.metadataHeight }); } - if (state.outputEditor || state.outerWidth) { + if (state.outputTotalHeight || state.outerWidth) { this._outputEditor?.layout({ width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, false), - height: this.cell.outputHeight + height: this.cell.layoutInfo.outputTotalHeight }); } this.layoutNotebookCell(); if (this._diagonalFill) { - this._diagonalFill.style.height = `${this.cell.editorHeight + this.cell.editorMargin + this.cell.metadataStatusHeight + this.cell.metadataHeight + this.cell.outputHeight + this.cell.outputStatusHeight}px`; + this._diagonalFill.style.height = `${this.cell.layoutInfo.editorHeight + this.cell.layoutInfo.editorMargin + this.cell.layoutInfo.metadataStatusHeight + this.cell.layoutInfo.metadataHeight + this.cell.layoutInfo.outputTotalHeight + this.cell.layoutInfo.outputStatusHeight}px`; } }); } @@ -1093,7 +1092,7 @@ export class ModifiedElement extends AbstractElementRenderer { this._metadataHeader.buildHeader(); if (this.notebookEditor.textModel?.transientOptions.transientOutputs) { - this.cell.outputHeight = 0; + this.cell.rawOutputHeight = 0; this.cell.outputStatusHeight = 0; this.templateData.outputHeaderContainer.style.display = 'none'; this.templateData.outputInfoContainer.style.display = 'none'; @@ -1213,7 +1212,7 @@ export class ModifiedElement extends AbstractElementRenderer { this._editorContainer.style.height = `${editorHeight}px`; this._register(this._editor.onDidContentSizeChange((e) => { - if (e.contentHeightChanged && this.cell.editorHeight !== e.contentHeight) { + if (e.contentHeightChanged && this.cell.layoutInfo.editorHeight !== e.contentHeight) { this.cell.editorHeight = e.contentHeight; } })); @@ -1289,31 +1288,31 @@ export class ModifiedElement extends AbstractElementRenderer { this.cell.editorHeight = contentHeight; } - layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { + layout(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputTotalHeight?: boolean }) { DOM.scheduleAtNextAnimationFrame(() => { if (state.editorHeight) { - this._editorContainer.style.height = `${this.cell.editorHeight}px`; + this._editorContainer.style.height = `${this.cell.layoutInfo.editorHeight}px`; this._editor!.layout({ width: this._editor!.getViewWidth(), - height: this.cell.editorHeight + height: this.cell.layoutInfo.editorHeight }); } if (state.outerWidth) { - this._editorContainer.style.height = `${this.cell.editorHeight}px`; + this._editorContainer.style.height = `${this.cell.layoutInfo.editorHeight}px`; this._editor!.layout(); } if (state.metadataEditor || state.outerWidth) { if (this._metadataEditorContainer) { - this._metadataEditorContainer.style.height = `${this.cell.metadataHeight}px`; + this._metadataEditorContainer.style.height = `${this.cell.layoutInfo.metadataHeight}px`; this._metadataEditor?.layout(); } } - if (state.outputEditor || state.outerWidth) { + if (state.outputTotalHeight || state.outerWidth) { if (this._outputEditorContainer) { - this._outputEditorContainer.style.height = `${this.cell.outputHeight}px`; + this._outputEditorContainer.style.height = `${this.cell.layoutInfo.outputTotalHeight}px`; this._outputEditor?.layout(); } } diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts index 1b1fe014d41..6dddaca31bc 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts @@ -6,7 +6,7 @@ import { NotebookDiffEditorEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { CellDiffViewModelLayoutChangeEvent, DiffSide, DIFF_CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; +import { CellDiffViewModelLayoutChangeEvent, DiffSide, DIFF_CELL_MARGIN, IDiffElementLayoutInfo } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { IGenericCellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -22,6 +22,12 @@ export enum PropertyFoldingState { Collapsed } +type ILayoutInfoDelta0 = { [K in keyof IDiffElementLayoutInfo]?: number; }; +interface ILayoutInfoDelta extends ILayoutInfoDelta0 { + rawOutputHeight?: number; + recomputeOutput?: boolean; +} + export abstract class DiffElementViewModelBase extends Disposable { public metadataFoldingState: PropertyFoldingState; public outputFoldingState: PropertyFoldingState; @@ -29,72 +35,53 @@ export abstract class DiffElementViewModelBase extends Disposable { onDidLayoutChange = this._layoutInfoEmitter.event; protected _stateChangeEmitter = new Emitter<{ renderOutput: boolean; }>(); onDidStateChange = this._stateChangeEmitter.event; + protected _layoutInfo!: IDiffElementLayoutInfo; - - protected _layoutInfo!: { - width: number; - editorHeight: number; - editorMargin: number; - metadataStatusHeight: number; - metadataHeight: number; - outputStatusHeight: number; - outputHeight: number; - bodyMargin: number; - }; - - set outputHeight(height: number) { - this._layoutInfo.outputHeight = height; - this._fireLayoutChangeEvent({ outputEditor: true, outputView: true }); + set rawOutputHeight(height: number) { + this._layout({ rawOutputHeight: height }); } - get outputHeight() { - return this._layoutInfo.outputHeight; + get rawOutputHeight() { + throw new Error('Use Cell.layoutInfo.rawOutputHeight'); } set outputStatusHeight(height: number) { - this._layoutInfo.outputStatusHeight = height; - this._fireLayoutChangeEvent({}); + this._layout({ outputStatusHeight: height }); } get outputStatusHeight() { - return this._layoutInfo.outputStatusHeight; + throw new Error('Use Cell.layoutInfo.outputStatusHeight'); } set editorHeight(height: number) { - this._layoutInfo.editorHeight = height; - this._fireLayoutChangeEvent({ editorHeight: true }); + this._layout({ editorHeight: height }); } get editorHeight() { - return this._layoutInfo.editorHeight; + throw new Error('Use Cell.layoutInfo.editorHeight'); } - set editorMargin(height: number) { - this._layoutInfo.editorMargin = height; - this._fireLayoutChangeEvent({}); + set editorMargin(margin: number) { + this._layout({ editorMargin: margin }); } get editorMargin() { - return this._layoutInfo.editorMargin; - } - - get metadataStatusHeight() { - return this._layoutInfo.metadataStatusHeight; + throw new Error('Use Cell.layoutInfo.editorMargin'); } set metadataHeight(height: number) { - this._layoutInfo.metadataHeight = height; - this._fireLayoutChangeEvent({ metadataEditor: true }); + this._layout({ metadataHeight: height }); } get metadataHeight() { - return this._layoutInfo.metadataHeight; + throw new Error('Use Cell.layoutInfo.metadataHeight'); } private _renderOutput = false; set renderOutput(value: boolean) { this._renderOutput = value; + this._layout({ recomputeOutput: true }); this._stateChangeEmitter.fire({ renderOutput: this._renderOutput }); } @@ -102,14 +89,8 @@ export abstract class DiffElementViewModelBase extends Disposable { return this._renderOutput; } - get totalHeight() { - return this._layoutInfo.editorHeight - + this._layoutInfo.editorMargin - + this._layoutInfo.metadataHeight - + this._layoutInfo.metadataStatusHeight - + this._layoutInfo.outputHeight - + this._layoutInfo.outputStatusHeight - + this._layoutInfo.bodyMargin; + get layoutInfo(): IDiffElementLayoutInfo { + return this._layoutInfo; } constructor( @@ -126,12 +107,13 @@ export abstract class DiffElementViewModelBase extends Disposable { editorMargin: 0, metadataHeight: 0, metadataStatusHeight: 25, - outputHeight: 0, + rawOutputHeight: 0, + outputTotalHeight: 0, outputStatusHeight: 25, - bodyMargin: 32 + bodyMargin: 32, + totalHeight: 82 }; - this.metadataFoldingState = PropertyFoldingState.Collapsed; this.outputFoldingState = PropertyFoldingState.Collapsed; @@ -139,13 +121,104 @@ export abstract class DiffElementViewModelBase extends Disposable { this._layoutInfoEmitter.fire({ outerWidth: true }); })); } - private _fireLayoutChangeEvent(state: { outerWidth?: boolean, editorHeight?: boolean, metadataEditor?: boolean, outputEditor?: boolean, outputView?: boolean }) { + + layoutChange() { + this._layout({ recomputeOutput: true }); + } + + protected _layout(delta: ILayoutInfoDelta) { + const width = delta.width !== undefined ? delta.width : this._layoutInfo.width; + const editorHeight = delta.editorHeight !== undefined ? delta.editorHeight : this._layoutInfo.editorHeight; + const editorMargin = delta.editorMargin !== undefined ? delta.editorMargin : this._layoutInfo.editorMargin; + const metadataHeight = delta.metadataHeight !== undefined ? delta.metadataHeight : this._layoutInfo.metadataHeight; + const metadataStatusHeight = delta.metadataStatusHeight !== undefined ? delta.metadataStatusHeight : this._layoutInfo.metadataStatusHeight; + const rawOutputHeight = delta.rawOutputHeight !== undefined ? delta.rawOutputHeight : this._layoutInfo.rawOutputHeight; + const outputStatusHeight = delta.outputStatusHeight !== undefined ? delta.outputStatusHeight : this._layoutInfo.outputStatusHeight; + const bodyMargin = delta.bodyMargin !== undefined ? delta.bodyMargin : this._layoutInfo.bodyMargin; + const outputHeight = (delta.recomputeOutput || delta.rawOutputHeight !== undefined) ? this._getOutputTotalHeight(rawOutputHeight) : this._layoutInfo.outputTotalHeight; + + const totalHeight = editorHeight + + editorMargin + + metadataHeight + + metadataStatusHeight + + outputHeight + + outputStatusHeight + + bodyMargin; + + const newLayout: IDiffElementLayoutInfo = { + width: width, + editorHeight: editorHeight, + editorMargin: editorMargin, + metadataHeight: metadataHeight, + metadataStatusHeight: metadataStatusHeight, + outputTotalHeight: outputHeight, + outputStatusHeight: outputStatusHeight, + bodyMargin: bodyMargin, + rawOutputHeight: rawOutputHeight, + totalHeight: totalHeight + }; + + const changeEvent: CellDiffViewModelLayoutChangeEvent = {}; + + if (newLayout.width !== this._layoutInfo.width) { + changeEvent.width = true; + } + + if (newLayout.editorHeight !== this._layoutInfo.editorHeight) { + changeEvent.editorHeight = true; + } + + if (newLayout.editorMargin !== this._layoutInfo.editorMargin) { + changeEvent.editorMargin = true; + } + + if (newLayout.metadataHeight !== this._layoutInfo.metadataHeight) { + changeEvent.metadataHeight = true; + } + + if (newLayout.metadataStatusHeight !== this._layoutInfo.metadataStatusHeight) { + changeEvent.metadataStatusHeight = true; + } + + if (newLayout.outputTotalHeight !== this._layoutInfo.outputTotalHeight) { + changeEvent.outputTotalHeight = true; + } + + if (newLayout.outputStatusHeight !== this._layoutInfo.outputStatusHeight) { + changeEvent.outputStatusHeight = true; + } + + if (newLayout.bodyMargin !== this._layoutInfo.bodyMargin) { + changeEvent.bodyMargin = true; + } + + if (newLayout.totalHeight !== this._layoutInfo.totalHeight) { + changeEvent.totalHeight = true; + } + + this._layoutInfo = newLayout; + this._fireLayoutChangeEvent(changeEvent); + } + + private _getOutputTotalHeight(rawOutputHeight: number) { + if (this.outputFoldingState === PropertyFoldingState.Collapsed) { + return 0; + } + + if (this.renderOutput) { + return this.getRichOutputTotalHeight(); + } else { + return rawOutputHeight; + } + } + + private _fireLayoutChangeEvent(state: CellDiffViewModelLayoutChangeEvent) { this._layoutInfoEmitter.fire(state); } abstract checkIfOutputsModified(): boolean; abstract checkMetadataIfModified(): boolean; - abstract layoutChange(): void; + abstract getRichOutputTotalHeight(): number; abstract getCellByUri(cellUri: URI): IGenericCellViewModel; abstract getOutputOffsetInCell(diffSide: DiffSide, index: number): number; abstract getOutputOffsetInContainer(diffSide: DiffSide, index: number): number; @@ -188,30 +261,14 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { } this._register(this.original.onDidChangeOutputLayout(() => { - this.layoutChange(); + this._layout({ recomputeOutput: true }); })); this._register(this.modified.onDidChangeOutputLayout(() => { - this.layoutChange(); + this._layout({ recomputeOutput: true }); })); } - layoutChange() { - let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); - this._layoutInfo = { - width: this._layoutInfo.width, - editorHeight: this._layoutInfo.editorHeight, - editorMargin: this._layoutInfo.editorMargin, - metadataHeight: this._layoutInfo.metadataHeight, - metadataStatusHeight: this._layoutInfo.metadataStatusHeight, - outputHeight: outputHeight, - outputStatusHeight: this._layoutInfo.outputStatusHeight, - bodyMargin: this._layoutInfo.bodyMargin - }; - - this._layoutInfoEmitter.fire({}); - } - checkIfOutputsModified() { return !this.documentTextModel.transientOptions.transientOutputs && hash(this.original?.outputs ?? []) !== hash(this.modified?.outputs ?? []); } @@ -248,12 +305,8 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase { + offsetInOutputsContainer; } - getOutputTotalHeight() { - if (this.renderOutput) { - return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); - } else { - return this._layoutInfo.outputHeight; - } + getRichOutputTotalHeight() { + return Math.max(this.original.getOutputTotalHeight(), this.modified.getOutputTotalHeight()); } getNestedCellViewModel(diffSide: DiffSide): DiffNestedCellViewModel { @@ -283,7 +336,7 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { ) { super(documentTextModel, original, modified, type, editorEventDispatcher); this._register(this.cellViewModel!.onDidChangeOutputLayout(() => { - this.layoutChange(); + this._layout({ recomputeOutput: true }); })); } @@ -291,22 +344,6 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { return this.type === 'insert' ? this.modified! : this.original!; } - layoutChange() { - let outputHeight = this.outputFoldingState === PropertyFoldingState.Collapsed ? 0 : this.getOutputTotalHeight(); - this._layoutInfo = { - width: this._layoutInfo.width, - editorHeight: this._layoutInfo.editorHeight, - editorMargin: this._layoutInfo.editorMargin, - metadataHeight: this._layoutInfo.metadataHeight, - metadataStatusHeight: this._layoutInfo.metadataStatusHeight, - outputHeight: outputHeight, - outputStatusHeight: this._layoutInfo.outputStatusHeight, - bodyMargin: this._layoutInfo.bodyMargin - }; - - this._layoutInfoEmitter.fire({}); - } - checkIfOutputsModified(): boolean { return false; @@ -336,12 +373,8 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase { + offsetInOutputsContainer; } - getOutputTotalHeight() { - if (this.renderOutput) { - return this.cellViewModel?.getOutputTotalHeight() ?? 0; - } else { - return this._layoutInfo.outputHeight; - } + getRichOutputTotalHeight() { + return this.cellViewModel?.getOutputTotalHeight() ?? 0; } getCellByUri(cellUri: URI): IGenericCellViewModel { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index f5b2de9e665..71aa2810077 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -88,10 +88,24 @@ export interface CellDiffSideBySideRenderTemplate extends CellDiffCommonRenderTe readonly outputInfoContainer: HTMLElement; } -export interface CellDiffViewModelLayoutChangeEvent { +export interface IDiffElementLayoutInfo { + totalHeight: number; + width: number; + editorHeight: number; + editorMargin: number; + metadataHeight: number; + metadataStatusHeight: number; + rawOutputHeight: number; + outputTotalHeight: number; + outputStatusHeight: number; + bodyMargin: number +} + +type IDiffElementSelfLayoutChangeEvent = { [K in keyof IDiffElementLayoutInfo]?: boolean }; + +export interface CellDiffViewModelLayoutChangeEvent extends IDiffElementSelfLayoutChangeEvent { font?: BareFontInfo; outerWidth?: boolean; - editorHeight?: boolean; metadataEditor?: boolean; outputEditor?: boolean; outputView?: boolean; From 273a5cdf5aaaae8ad6958d0fd969b5579030058e Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Fri, 18 Dec 2020 18:40:35 +0000 Subject: [PATCH 1260/1837] Emmet comment spacing fixup, fixes #112835 --- .../emmet/src/test/toggleComment.test.ts | 98 +++++++++---------- extensions/emmet/src/toggleComment.ts | 25 ++++- 2 files changed, 69 insertions(+), 54 deletions(-) diff --git a/extensions/emmet/src/test/toggleComment.test.ts b/extensions/emmet/src/test/toggleComment.test.ts index 6e7344b3577..42a867f9c10 100644 --- a/extensions/emmet/src/test/toggleComment.test.ts +++ b/extensions/emmet/src/test/toggleComment.test.ts @@ -58,13 +58,13 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
    `; @@ -100,13 +100,13 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => {
    `; @@ -141,8 +141,8 @@ suite('Tests for Toggle Comment action from Emmet (HTML)', () => { - // - // `; - // const expectedContents = ` - // - // - // - // `; - // return withRandomFileEditor(htmlWithCssContents, 'html', (editor, doc) => { - // editor.selections = [ - // new Selection(6, 50, 6, 50), - // new Selection(9, 50, 9, 50), - // new Selection(13, 50, 13, 50) - // ]; + test('update image size in css in html file with multiple cursors', () => { + const htmlWithCssContents = ` + + + + `; + const expectedContents = ` + + + + `; + return withRandomFileEditor(htmlWithCssContents, 'html', (editor, doc) => { + editor.selections = [ + new Selection(6, 50, 6, 50), + new Selection(9, 50, 9, 50), + new Selection(13, 50, 13, 50) + ]; - // return updateImageSize()!.then(() => { - // assert.equal(doc.getText(), expectedContents); - // return Promise.resolve(); - // }); - // }); - // }); + return updateImageSize()!.then(() => { + assert.equal(doc.getText(), expectedContents); + return Promise.resolve(); + }); + }); + }); - // test('update image size in img tag in html file with multiple cursors', () => { - // const htmlwithimgtag = ` - // - // - // - // - // - // `; - // const expectedContents = ` - // - // - // - // - // - // `; - // return withRandomFileEditor(htmlwithimgtag, 'html', (editor, doc) => { - // editor.selections = [ - // new Selection(2, 50, 2, 50), - // new Selection(3, 50, 3, 50), - // new Selection(4, 50, 4, 50) - // ]; + test('update image size in img tag in html file with multiple cursors', () => { + const htmlwithimgtag = ` + + + + + + `; + const expectedContents = ` + + + + + + `; + return withRandomFileEditor(htmlwithimgtag, 'html', (editor, doc) => { + editor.selections = [ + new Selection(2, 50, 2, 50), + new Selection(3, 50, 3, 50), + new Selection(4, 50, 4, 50) + ]; - // return updateImageSize()!.then(() => { - // assert.equal(doc.getText(), expectedContents); - // return Promise.resolve(); - // }); - // }); - // }); - -// }); + return updateImageSize()!.then(() => { + assert.equal(doc.getText(), expectedContents); + return Promise.resolve(); + }); + }); + }); +}); diff --git a/extensions/emmet/src/typings/EmmetFlatNode.d.ts b/extensions/emmet/src/typings/EmmetFlatNode.d.ts index f571b25d5a1..05f5a5b3c77 100644 --- a/extensions/emmet/src/typings/EmmetFlatNode.d.ts +++ b/extensions/emmet/src/typings/EmmetFlatNode.d.ts @@ -18,7 +18,7 @@ declare module 'EmmetFlatNode' { export interface Token { start: number end: number - stream: string + stream: BufferStream toString(): string } @@ -76,4 +76,14 @@ declare module 'EmmetFlatNode' { export interface Stylesheet extends Node { comments: Token[] } + + export interface BufferStream { + peek(): number + next(): number + backUp(n: number): number + current(): string + substring(from: number, to: number): string + eat(match: any): boolean + eatWhile(match: any): boolean + } } diff --git a/extensions/emmet/src/updateImageSize.ts b/extensions/emmet/src/updateImageSize.ts index 3ac3f15a1be..b590fabb25c 100644 --- a/extensions/emmet/src/updateImageSize.ts +++ b/extensions/emmet/src/updateImageSize.ts @@ -5,26 +5,26 @@ // Based on @sergeche's work on the emmet plugin for atom -import { TextEditor, Range, Position, window, TextEdit } from 'vscode'; +import { TextEditor, Position, window, TextEdit } from 'vscode'; import * as path from 'path'; import { getImageSize } from './imageSizeHelper'; -import { parseDocument, getNode, iterateCSSToken, getCssPropertyFromRule, isStyleSheet, validate } from './util'; -import { HtmlNode, CssToken, HtmlToken, Attribute, Property } from 'EmmetNode'; +import { getFlatNode, iterateCSSToken, getCssPropertyFromRule, isStyleSheet, validate, offsetRangeToVsRange } from './util'; +import { HtmlNode, CssToken, HtmlToken, Attribute, Property } from 'EmmetFlatNode'; import { locateFile } from './locateFile'; import parseStylesheet from '@emmetio/css-parser'; -import { DocumentStreamReader } from './bufferStream'; +import { getRootNode } from './parseDocument'; /** * Updates size of context image in given editor */ -export function updateImageSize() { +export function updateImageSize(): Promise | undefined { if (!validate() || !window.activeTextEditor) { return; } const editor = window.activeTextEditor; - let allUpdatesPromise = editor.selections.reverse().map(selection => { - let position = selection.isReversed ? selection.active : selection.anchor; + const allUpdatesPromise = editor.selections.reverse().map(selection => { + const position = selection.isReversed ? selection.active : selection.anchor; if (!isStyleSheet(editor.document.languageId)) { return updateImageSizeHTML(editor, position); } else { @@ -71,15 +71,19 @@ function updateImageSizeHTML(editor: TextEditor, position: Position): Promise { const getPropertyInsiderStyleTag = (editor: TextEditor): Property | null => { - const rootNode = parseDocument(editor.document); - const currentNode = getNode(rootNode, position, true); + const document = editor.document; + const rootNode = getRootNode(document, true); + const offset = document.offsetAt(position); + const currentNode = getFlatNode(rootNode, offset, true); if (currentNode && currentNode.name === 'style' - && currentNode.open.end.isBefore(position) - && currentNode.close.start.isAfter(position)) { - let buffer = new DocumentStreamReader(editor.document, currentNode.open.end, new Range(currentNode.open.end, currentNode.close.start)); - let rootNode = parseStylesheet(buffer); - const node = getNode(rootNode, position, true); - return (node && node.type === 'property') ? node : null; + && currentNode.open && currentNode.close + && currentNode.open.end < offset + && currentNode.close.start > offset) { + const buffer = ' '.repeat(currentNode.open.end) + + document.getText().substring(currentNode.open.end, currentNode.close.start); + const innerRootNode = parseStylesheet(buffer); + const innerNode = getFlatNode(innerRootNode, offset, true); + return (innerNode && innerNode.type === 'property') ? innerNode : null; } return null; }; @@ -96,7 +100,7 @@ function updateImageSizeCSSFile(editor: TextEditor, position: Position): Promise */ function updateImageSizeCSS(editor: TextEditor, position: Position, fetchNode: (editor: TextEditor, position: Position) => Property | null): Promise { const node = fetchNode(editor, position); - const src = node && getImageSrcCSS(node, position); + const src = node && getImageSrcCSS(editor, node, position); if (!src) { return Promise.reject(new Error('No valid image source')); @@ -108,7 +112,7 @@ function updateImageSizeCSS(editor: TextEditor, position: Position, fetchNode: ( // since this action is asynchronous, we have to ensure that editor wasn’t // changed and user didn’t moved caret outside node const prop = fetchNode(editor, position); - if (prop && getImageSrcCSS(prop, position) === src) { + if (prop && getImageSrcCSS(editor, prop, position) === src) { return updateCSSNode(editor, prop, size.width, size.height); } return []; @@ -121,8 +125,10 @@ function updateImageSizeCSS(editor: TextEditor, position: Position, fetchNode: ( * be found */ function getImageHTMLNode(editor: TextEditor, position: Position): HtmlNode | null { - const rootNode = parseDocument(editor.document); - const node = getNode(rootNode, position, true); + const document = editor.document; + const rootNode = getRootNode(document, true); + const offset = document.offsetAt(position); + const node = getFlatNode(rootNode, offset, true); return node && node.name.toLowerCase() === 'img' ? node : null; } @@ -132,8 +138,10 @@ function getImageHTMLNode(editor: TextEditor, position: Position): HtmlNode | nu * be found */ function getImageCSSNode(editor: TextEditor, position: Position): Property | null { - const rootNode = parseDocument(editor.document); - const node = getNode(rootNode, position, true); + const document = editor.document; + const rootNode = getRootNode(document, true); + const offset = document.offsetAt(position); + const node = getFlatNode(rootNode, offset, true); return node && node.type === 'property' ? node : null; } @@ -152,11 +160,11 @@ function getImageSrcHTML(node: HtmlNode): string | undefined { /** * Returns image source from given `url()` token */ -function getImageSrcCSS(node: Property | undefined, position: Position): string | undefined { +function getImageSrcCSS(editor: TextEditor, node: Property | undefined, position: Position): string | undefined { if (!node) { return; } - const urlToken = findUrlToken(node, position); + const urlToken = findUrlToken(editor, node, position); if (!urlToken) { return; } @@ -174,7 +182,12 @@ function getImageSrcCSS(node: Property | undefined, position: Position): string * Updates size of given HTML node */ function updateHTMLTag(editor: TextEditor, node: HtmlNode, width: number, height: number): TextEdit[] { + const document = editor.document; const srcAttr = getAttribute(node, 'src'); + if (!srcAttr) { + return []; + } + const widthAttr = getAttribute(node, 'width'); const heightAttr = getAttribute(node, 'height'); const quote = getAttributeQuote(editor, srcAttr); @@ -186,15 +199,15 @@ function updateHTMLTag(editor: TextEditor, node: HtmlNode, width: number, height if (!widthAttr) { textToAdd += ` width=${quote}${width}${quote}`; } else { - edits.push(new TextEdit(new Range(widthAttr.value.start, widthAttr.value.end), String(width))); + edits.push(new TextEdit(offsetRangeToVsRange(document, widthAttr.value.start, widthAttr.value.end), String(width))); } if (!heightAttr) { textToAdd += ` height=${quote}${height}${quote}`; } else { - edits.push(new TextEdit(new Range(heightAttr.value.start, heightAttr.value.end), String(height))); + edits.push(new TextEdit(offsetRangeToVsRange(document, heightAttr.value.start, heightAttr.value.end), String(height))); } if (textToAdd) { - edits.push(new TextEdit(new Range(endOfAttributes, endOfAttributes), textToAdd)); + edits.push(new TextEdit(offsetRangeToVsRange(document, endOfAttributes, endOfAttributes), textToAdd)); } return edits; @@ -204,6 +217,7 @@ function updateHTMLTag(editor: TextEditor, node: HtmlNode, width: number, height * Updates size of given CSS rule */ function updateCSSNode(editor: TextEditor, srcProp: Property, width: number, height: number): TextEdit[] { + const document = editor.document; const rule = srcProp.parent; const widthProp = getCssPropertyFromRule(rule, 'width'); const heightProp = getCssPropertyFromRule(rule, 'height'); @@ -214,22 +228,22 @@ function updateCSSNode(editor: TextEditor, srcProp: Property, width: number, hei let edits: TextEdit[] = []; if (!srcProp.terminatorToken) { - edits.push(new TextEdit(new Range(srcProp.end, srcProp.end), ';')); + edits.push(new TextEdit(offsetRangeToVsRange(document, srcProp.end, srcProp.end), ';')); } let textToAdd = ''; if (!widthProp) { textToAdd += `${before}width${separator}${width}px;`; } else { - edits.push(new TextEdit(new Range(widthProp.valueToken.start, widthProp.valueToken.end), `${width}px`)); + edits.push(new TextEdit(offsetRangeToVsRange(document, widthProp.valueToken.start, widthProp.valueToken.end), `${width}px`)); } if (!heightProp) { textToAdd += `${before}height${separator}${height}px;`; } else { - edits.push(new TextEdit(new Range(heightProp.valueToken.start, heightProp.valueToken.end), `${height}px`)); + edits.push(new TextEdit(offsetRangeToVsRange(document, heightProp.valueToken.start, heightProp.valueToken.end), `${height}px`)); } if (textToAdd) { - edits.push(new TextEdit(new Range(srcProp.end, srcProp.end), textToAdd)); + edits.push(new TextEdit(offsetRangeToVsRange(document, srcProp.end, srcProp.end), textToAdd)); } return edits; @@ -238,9 +252,9 @@ function updateCSSNode(editor: TextEditor, srcProp: Property, width: number, hei /** * Returns attribute object with `attrName` name from given HTML node */ -function getAttribute(node: HtmlNode, attrName: string): Attribute { +function getAttribute(node: HtmlNode, attrName: string): Attribute | undefined { attrName = attrName.toLowerCase(); - return node && (node.open as any).attributes.find((attr: any) => attr.name.value.toLowerCase() === attrName); + return node && node.attributes.find(attr => attr.name.toString().toLowerCase() === attrName); } /** @@ -248,18 +262,20 @@ function getAttribute(node: HtmlNode, attrName: string): Attribute { * string if attribute wasn’t quoted */ -function getAttributeQuote(editor: TextEditor, attr: any): string { - const range = new Range(attr.value ? attr.value.end : attr.end, attr.end); - return range.isEmpty ? '' : editor.document.getText(range); +function getAttributeQuote(editor: TextEditor, attr: Attribute): string { + const begin = attr.value ? attr.value.end : attr.end; + const end = attr.end; + return begin === end ? '' : editor.document.getText().substring(begin, end); } /** * Finds 'url' token for given `pos` point in given CSS property `node` */ -function findUrlToken(node: Property, pos: Position): CssToken | undefined { +function findUrlToken(editor: TextEditor, node: Property, pos: Position): CssToken | undefined { + const offset = editor.document.offsetAt(pos); for (let i = 0, il = (node as any).parsedValue.length, url; i < il; i++) { iterateCSSToken((node as any).parsedValue[i], (token: CssToken) => { - if (token.type === 'url' && token.start.isBeforeOrEqual(pos) && token.end.isAfterOrEqual(pos)) { + if (token.type === 'url' && token.start <= offset && token.end >= offset) { url = token; return false; } @@ -279,9 +295,9 @@ function findUrlToken(node: Property, pos: Position): CssToken | undefined { function getPropertyDelimitor(editor: TextEditor, node: Property): string { let anchor; if (anchor = (node.previousSibling || node.parent.contentStartToken)) { - return editor.document.getText(new Range(anchor.end, node.start)); + return editor.document.getText().substring(anchor.end, node.start); } else if (anchor = (node.nextSibling || node.parent.contentEndToken)) { - return editor.document.getText(new Range(node.end, anchor.start)); + return editor.document.getText().substring(node.end, anchor.start); } return ''; diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index d3476dc0d91..e83aad0820e 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -6,11 +6,12 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import parseStylesheet from '@emmetio/css-parser'; -import { Node, HtmlNode, CssToken, Property, Rule, Stylesheet } from 'EmmetNode'; -import { Node as FlatNode, HtmlNode as HtmlFlatNode } from 'EmmetFlatNode'; +import { Node, HtmlNode, Stylesheet } from 'EmmetNode'; +import { Node as FlatNode, HtmlNode as HtmlFlatNode, Property as FlatProperty, Rule as FlatRule, CssToken as FlatCssToken } from 'EmmetFlatNode'; import { DocumentStreamReader } from './bufferStream'; import * as EmmetHelper from 'vscode-emmet-helper'; import { TextDocument as LSTextDocument } from 'vscode-languageserver-textdocument'; +import { getRootNode } from './parseDocument'; let _emmetHelper: typeof EmmetHelper; let _currentExtensionsPath: string | undefined = undefined; @@ -652,7 +653,7 @@ export function getEmmetConfiguration(syntax: string) { * Itereates by each child, as well as nested child's children, in their order * and invokes `fn` for each. If `fn` function returns `false`, iteration stops */ -export function iterateCSSToken(token: CssToken, fn: (x: any) => any): boolean { +export function iterateCSSToken(token: FlatCssToken, fn: (x: any) => any): boolean { for (let i = 0, il = token.size; i < il; i++) { if (fn(token.item(i)) === false || iterateCSSToken(token.item(i), fn) === false) { return false; @@ -664,31 +665,35 @@ export function iterateCSSToken(token: CssToken, fn: (x: any) => any): boolean { /** * Returns `name` CSS property from given `rule` */ -export function getCssPropertyFromRule(rule: Rule, name: string): Property | undefined { - return rule.children.find(node => node.type === 'property' && node.name === name) as Property; +export function getCssPropertyFromRule(rule: FlatRule, name: string): FlatProperty | undefined { + return rule.children.find(node => node.type === 'property' && node.name === name) as FlatProperty; } /** * Returns css property under caret in given editor or `null` if such node cannot * be found */ -export function getCssPropertyFromDocument(editor: vscode.TextEditor, position: vscode.Position): Property | null { - const rootNode = parseDocument(editor.document); - const node = getNode(rootNode, position, true); +export function getCssPropertyFromDocument(editor: vscode.TextEditor, position: vscode.Position): FlatProperty | null { + const document = editor.document; + const rootNode = getRootNode(document, true); + const offset = document.offsetAt(position); + const node = getFlatNode(rootNode, offset, true); if (isStyleSheet(editor.document.languageId)) { - return node && node.type === 'property' ? node : null; + return node && node.type === 'property' ? node : null; } - let htmlNode = node; + const htmlNode = node; if (htmlNode && htmlNode.name === 'style' - && htmlNode.open.end.isBefore(position) - && htmlNode.close.start.isAfter(position)) { - let buffer = new DocumentStreamReader(editor.document, htmlNode.start, new vscode.Range(htmlNode.start, htmlNode.end)); - let rootNode = parseStylesheet(buffer); - const node = getNode(rootNode, position, true); - return (node && node.type === 'property') ? node : null; + && htmlNode.open && htmlNode.close + && htmlNode.open.end < offset + && htmlNode.close.start > offset) { + const buffer = ' '.repeat(htmlNode.start) + + document.getText().substring(htmlNode.start, htmlNode.end); + const innerRootNode = parseStylesheet(buffer); + const innerNode = getFlatNode(innerRootNode, offset, true); + return (innerNode && innerNode.type === 'property') ? innerNode : null; } return null; @@ -705,9 +710,7 @@ export function getEmbeddedCssNodeIfAny(document: vscode.TextDocument, currentNo if (innerRange && innerRange.contains(position)) { if (currentHtmlNode.name === 'style' && currentHtmlNode.open.end.isBefore(position) - && currentHtmlNode.close.start.isAfter(position) - - ) { + && currentHtmlNode.close.start.isAfter(position)) { let buffer = new DocumentStreamReader(document, currentHtmlNode.open.end, new vscode.Range(currentHtmlNode.open.end, currentHtmlNode.close.start)); return parseStylesheet(buffer); } From 67bff68034ce7c5ca6123d5c4703a0d4f6bfae98 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 29 Dec 2020 22:09:33 +0100 Subject: [PATCH 1439/1837] Add `monaco.editor.setColorMap` --- .../standalone/browser/standaloneLanguages.ts | 18 +++++++++++++++++ .../browser/standaloneThemeServiceImpl.ts | 20 +++++++++++++------ .../common/standaloneThemeService.ts | 4 ++++ .../test/browser/standaloneLanguages.test.ts | 3 ++- src/vs/monaco.d.ts | 6 ++++++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index dbf225a6c12..9042465ea55 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { CancellationToken } from 'vs/base/common/cancellation'; +import { Color } from 'vs/base/common/color'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; @@ -310,6 +311,22 @@ function isThenable(obj: any): obj is Thenable { return obj && typeof obj.then === 'function'; } +/** + * Change the color map that is used for token colors. + * Supported formats (hex): #RRGGBB, $RRGGBBAA, #RGB, #RGBA + */ +export function setColorMap(colorMap: string[] | null): void { + if (colorMap) { + const result: Color[] = [null!]; + for (let i = 1, len = colorMap.length; i < len; i++) { + result[i] = Color.fromHex(colorMap[i]); + } + StaticServices.standaloneThemeService.get().setColorMapOverride(result); + } else { + StaticServices.standaloneThemeService.get().setColorMapOverride(null); + } +} + /** * Set the tokens provider for a language (manual implementation). */ @@ -570,6 +587,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { // provider methods setLanguageConfiguration: setLanguageConfiguration, + setColorMap: setColorMap, setTokensProvider: setTokensProvider, setMonarchTokensProvider: setMonarchTokensProvider, registerReferenceProvider: registerReferenceProvider, diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 6ef700e276f..0e41b76817b 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -204,6 +204,7 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon private _globalStyleElement: HTMLStyleElement | null; private _styleElements: HTMLStyleElement[]; private _theme!: IStandaloneTheme; + private _colorMapOverride: Color[] | null; constructor() { super(); @@ -221,6 +222,7 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon this._globalStyleElement = null; this._styleElements = []; this.setTheme(VS_THEME_NAME); + this._colorMapOverride = null; iconRegistry.onDidChange(() => { this._codiconCSS = iconRegistry.getCSS(); @@ -288,6 +290,11 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon return this._theme; } + public setColorMapOverride(colorMapOverride: Color[] | null): void { + this._colorMapOverride = colorMapOverride; + this._updateThemeOrColorMap(); + } + public setTheme(themeName: string): string { let theme: StandaloneTheme; if (this._knownThemes.has(themeName)) { @@ -300,7 +307,11 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon return theme.id; } this._theme = theme; + this._updateThemeOrColorMap(); + return theme.id; + } + private _updateThemeOrColorMap(): void { let cssRules: string[] = []; let hasRule: { [rule: string]: boolean; } = {}; let ruleCollector: ICssStyleCollector = { @@ -311,19 +322,16 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon } } }; - themingRegistry.getThemingParticipants().forEach(p => p(theme, ruleCollector, this._environment)); + themingRegistry.getThemingParticipants().forEach(p => p(this._theme, ruleCollector, this._environment)); - let tokenTheme = theme.tokenTheme; - let colorMap = tokenTheme.getColorMap(); + const colorMap = this._colorMapOverride !== null ? this._colorMapOverride : this._theme.tokenTheme.getColorMap(); ruleCollector.addRule(generateTokensCSSForColorMap(colorMap)); this._themeCSS = cssRules.join('\n'); this._updateCSS(); TokenizationRegistry.setColorMap(colorMap); - this._onColorThemeChange.fire(theme); - - return theme.id; + this._onColorThemeChange.fire(this._theme); } private _updateCSS(): void { diff --git a/src/vs/editor/standalone/common/standaloneThemeService.ts b/src/vs/editor/standalone/common/standaloneThemeService.ts index c70a713dd08..afefd369df7 100644 --- a/src/vs/editor/standalone/common/standaloneThemeService.ts +++ b/src/vs/editor/standalone/common/standaloneThemeService.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Color } from 'vs/base/common/color'; import { ITokenThemeRule, TokenTheme } from 'vs/editor/common/modes/supports/tokenization'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; @@ -33,4 +34,7 @@ export interface IStandaloneThemeService extends IThemeService { defineTheme(themeName: string, themeData: IStandaloneThemeData): void; getColorTheme(): IStandaloneTheme; + + setColorMapOverride(colorMapOverride: Color[] | null): void; + } diff --git a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts index e3c7a31f160..1a8a2025e2d 100644 --- a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts +++ b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts @@ -68,7 +68,8 @@ suite('TokenizationSupport2Adapter', () => { tokenColorMap: [] }; } - + setColorMapOverride(colorMapOverride: Color[] | null): void { + } public getFileIconTheme(): IFileIconTheme { return { hasFileIcons: false, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 253e384a7d3..88b0cda830c 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5089,6 +5089,12 @@ declare namespace monaco.languages { tokenize?(line: string, state: IState): ILineTokens; } + /** + * Change the color map that is used for token colors. + * Supported formats (hex): #RRGGBB, $RRGGBBAA, #RGB, #RGBA + */ + export function setColorMap(colorMap: string[] | null): void; + /** * Set the tokens provider for a language (manual implementation). */ From 5ea96ec9cd70be0d1bd91b0f89ee3c634f1d47d6 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 29 Dec 2020 22:47:15 +0100 Subject: [PATCH 1440/1837] Fix `_colorMapOverride` usage before initialization --- .../editor/standalone/browser/standaloneThemeServiceImpl.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 0e41b76817b..f61c9de8586 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -203,8 +203,8 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon private _allCSS: string; private _globalStyleElement: HTMLStyleElement | null; private _styleElements: HTMLStyleElement[]; - private _theme!: IStandaloneTheme; private _colorMapOverride: Color[] | null; + private _theme!: IStandaloneTheme; constructor() { super(); @@ -221,8 +221,8 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon this._allCSS = `${this._codiconCSS}\n${this._themeCSS}`; this._globalStyleElement = null; this._styleElements = []; - this.setTheme(VS_THEME_NAME); this._colorMapOverride = null; + this.setTheme(VS_THEME_NAME); iconRegistry.onDidChange(() => { this._codiconCSS = iconRegistry.getCSS(); @@ -324,7 +324,7 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon }; themingRegistry.getThemingParticipants().forEach(p => p(this._theme, ruleCollector, this._environment)); - const colorMap = this._colorMapOverride !== null ? this._colorMapOverride : this._theme.tokenTheme.getColorMap(); + const colorMap = this._colorMapOverride || this._theme.tokenTheme.getColorMap(); ruleCollector.addRule(generateTokensCSSForColorMap(colorMap)); this._themeCSS = cssRules.join('\n'); From 58852eaa8544ca6b2033bff651ac3960454abc7b Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 29 Dec 2020 23:13:54 +0100 Subject: [PATCH 1441/1837] Add a timeout to the editor tests step --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb4b9dcfbe1..203e4a13c66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -301,5 +301,6 @@ jobs: run: yarn playwright-install - name: Run Editor Tests + timeout-minutes: 5 working-directory: ./test/monaco run: yarn test From e6daf3408523161e285263f016114a7a1504769a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 29 Dec 2020 23:38:37 +0100 Subject: [PATCH 1442/1837] Better simulate real-life CORS in code-web server --- resources/web/code-web.js | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/resources/web/code-web.js b/resources/web/code-web.js index 11a9f87e730..f460db62a9e 100644 --- a/resources/web/code-web.js +++ b/resources/web/code-web.js @@ -28,6 +28,14 @@ const BUILTIN_MARKETPLACE_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'built const WEB_DEV_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'builtInWebDevExtensions'); const WEB_MAIN = path.join(APP_ROOT, 'src', 'vs', 'code', 'browser', 'workbench', 'workbench-dev.html'); +// This is useful to simulate real world CORS +const ALLOWED_CORS_ORIGINS = [ + 'http://localhost:8081', + 'http://127.0.0.1:8081', + 'http://localhost:8080', + 'http://127.0.0.1:8080', +]; + const WEB_PLAYGROUND_VERSION = '0.0.10'; const args = minimist(process.argv, { @@ -281,6 +289,17 @@ secondaryServer.on('error', err => { console.error(err); }); +/** + * @param {import('http').IncomingMessage} req + */ +function addCORSReplyHeader(req) { + if (typeof req.headers['origin'] !== 'string') { + // not a CORS request + return false; + } + return (ALLOWED_CORS_ORIGINS.indexOf(req.headers['origin']) >= 0); +} + /** * @param {import('http').IncomingMessage} req * @param {import('http').ServerResponse} res @@ -291,9 +310,10 @@ async function handleStatic(req, res, parsedUrl) { if (/^\/static\/extensions\//.test(parsedUrl.pathname)) { const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/static/extensions/'.length)); const filePath = getExtensionFilePath(relativePath, (await builtInExtensionsPromise).locations); - const responseHeaders = { - 'Access-Control-Allow-Origin': '*' - }; + const responseHeaders = {}; + if (addCORSReplyHeader(req)) { + responseHeaders['Access-Control-Allow-Origin'] = '*'; + } if (!filePath) { return serveError(req, res, 400, `Bad request.`, responseHeaders); } @@ -315,9 +335,10 @@ async function handleExtension(req, res, parsedUrl) { // Strip `/extension/` from the path const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/extension/'.length)); const filePath = getExtensionFilePath(relativePath, (await commandlineProvidedExtensionsPromise).locations); - const responseHeaders = { - 'Access-Control-Allow-Origin': '*' - }; + const responseHeaders = {}; + if (addCORSReplyHeader(req)) { + responseHeaders['Access-Control-Allow-Origin'] = '*'; + } if (!filePath) { return serveError(req, res, 400, `Bad request.`, responseHeaders); } From f1ea605a69518d9e20b567c64a96b0566e36e448 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 29 Dec 2020 23:41:31 +0100 Subject: [PATCH 1443/1837] Use blob urls instead of data: to maintain current origin --- .../services/extensions/worker/extensionHostWorker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 1c71288b6fb..998c5b87c13 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -52,14 +52,15 @@ self.addEventListener = () => console.trace(`'addEventListener' has been blocked if ((self).Worker) { const ttPolicy = (self).trustedTypes?.createPolicy('extensionHostWorker', { createScriptURL: (value: string) => value }); - // make sure new Worker(...) always uses data: + // make sure new Worker(...) always uses blob: (to maintain current origin) const _Worker = (self).Worker; Worker = function (stringUrl: string | URL, options?: WorkerOptions) { const js = `importScripts('${stringUrl}');`; options = options || {}; options.name = options.name || path.basename(stringUrl.toString()); - const url = `data:text/javascript;charset=utf-8,${encodeURIComponent(js)}`; - return new _Worker(ttPolicy ? ttPolicy.createScriptURL(url) : url, options); + const blob = new Blob([js], { type: 'application/javascript' }); + const blobUrl = URL.createObjectURL(blob); + return new _Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) : blobUrl, options); }; } else { From b5cd082cd47a85cdf254144b88979743f45b6d6d Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 29 Dec 2020 15:02:55 -0800 Subject: [PATCH 1444/1837] Emmet refactor toggle comment (#113557) --- extensions/emmet/src/toggleComment.ts | 104 +++++++++++++------------- extensions/emmet/src/util.ts | 30 ++++---- 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/extensions/emmet/src/toggleComment.ts b/extensions/emmet/src/toggleComment.ts index 06f11b2d15f..1afb8fe2239 100644 --- a/extensions/emmet/src/toggleComment.ts +++ b/extensions/emmet/src/toggleComment.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { getNodesInBetween, getNode, getHtmlNode, parseDocument, sameNodes, isStyleSheet, validate } from './util'; -import { Node, Stylesheet, Rule } from 'EmmetNode'; +import { getNodesInBetween, getFlatNode, getHtmlFlatNode, sameNodes, isStyleSheet, validate, offsetRangeToVsRange, offsetRangeToSelection } from './util'; +import { Node, Stylesheet, Rule } from 'EmmetFlatNode'; import parseStylesheet from '@emmetio/css-parser'; -import { DocumentStreamReader } from './bufferStream'; +import { getRootNode } from './parseDocument'; let startCommentStylesheet: string; let endCommentStylesheet: string; @@ -21,7 +21,7 @@ export function toggleComment(): Thenable | undefined { setupCommentSpacing(); const editor = vscode.window.activeTextEditor; - let rootNode = parseDocument(editor.document); + const rootNode = getRootNode(editor.document, true); if (!rootNode) { return; } @@ -29,7 +29,7 @@ export function toggleComment(): Thenable | undefined { return editor.edit(editBuilder => { let allEdits: vscode.TextEdit[][] = []; editor.selections.reverse().forEach(selection => { - let edits = isStyleSheet(editor.document.languageId) ? toggleCommentStylesheet(selection, rootNode) : toggleCommentHTML(editor.document, selection, rootNode!); + const edits = isStyleSheet(editor.document.languageId) ? toggleCommentStylesheet(editor.document, selection, rootNode) : toggleCommentHTML(editor.document, selection, rootNode!); if (edits.length > 0) { allEdits.push(edits); } @@ -55,21 +55,25 @@ export function toggleComment(): Thenable | undefined { function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node): vscode.TextEdit[] { const selectionStart = selection.isReversed ? selection.active : selection.anchor; const selectionEnd = selection.isReversed ? selection.anchor : selection.active; + const selectionStartOffset = document.offsetAt(selectionStart); + const selectionEndOffset = document.offsetAt(selectionEnd); + const documentText = document.getText(); - let startNode = getHtmlNode(document, rootNode, selectionStart, true); - let endNode = getHtmlNode(document, rootNode, selectionEnd, true); + const startNode = getHtmlFlatNode(documentText, rootNode, selectionStartOffset, true); + const endNode = getHtmlFlatNode(documentText, rootNode, selectionEndOffset, true); if (!startNode || !endNode) { return []; } if (sameNodes(startNode, endNode) && startNode.name === 'style' - && startNode.open.end.isBefore(selectionStart) - && startNode.close.start.isAfter(selectionEnd)) { - let buffer = new DocumentStreamReader(document, startNode.open.end, new vscode.Range(startNode.open.end, startNode.close.start)); - let cssRootNode = parseStylesheet(buffer); - - return toggleCommentStylesheet(selection, cssRootNode); + && startNode.open && startNode.close + && startNode.open.end < selectionStartOffset + && startNode.close.start > selectionEndOffset) { + const buffer = ' '.repeat(startNode.open.end) + + documentText.substring(startNode.open.end, startNode.close.start); + const cssRootNode = parseStylesheet(buffer); + return toggleCommentStylesheet(document, selection, cssRootNode); } let allNodes: Node[] = getNodesInBetween(startNode, endNode); @@ -84,8 +88,8 @@ function toggleCommentHTML(document: vscode.TextDocument, selection: vscode.Sele } - edits.push(new vscode.TextEdit(new vscode.Range(allNodes[0].start, allNodes[0].start), startCommentHTML)); - edits.push(new vscode.TextEdit(new vscode.Range(allNodes[allNodes.length - 1].end, allNodes[allNodes.length - 1].end), endCommentHTML)); + edits.push(new vscode.TextEdit(offsetRangeToVsRange(document, allNodes[0].start, allNodes[0].start), startCommentHTML)); + edits.push(new vscode.TextEdit(offsetRangeToVsRange(document, allNodes[allNodes.length - 1].end, allNodes[allNodes.length - 1].end), endCommentHTML)); return edits; } @@ -95,10 +99,8 @@ function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vs // If current node is commented, then uncomment and return if (node.type === 'comment') { - - unCommentTextEdits.push(new vscode.TextEdit(new vscode.Range(node.start, node.start.translate(0, startCommentHTML.length)), '')); - unCommentTextEdits.push(new vscode.TextEdit(new vscode.Range(node.end.translate(0, -endCommentHTML.length), node.end), '')); - + unCommentTextEdits.push(new vscode.TextEdit(offsetRangeToVsRange(document, node.start, node.start + startCommentHTML.length), '')); + unCommentTextEdits.push(new vscode.TextEdit(offsetRangeToVsRange(document, node.end - endCommentHTML.length, node.end), '')); return unCommentTextEdits; } @@ -110,32 +112,34 @@ function getRangesToUnCommentHTML(node: Node, document: vscode.TextDocument): vs return unCommentTextEdits; } -function toggleCommentStylesheet(selection: vscode.Selection, rootNode: Stylesheet): vscode.TextEdit[] { - let selectionStart = selection.isReversed ? selection.active : selection.anchor; - let selectionEnd = selection.isReversed ? selection.anchor : selection.active; +function toggleCommentStylesheet(document: vscode.TextDocument, selection: vscode.Selection, rootNode: Stylesheet): vscode.TextEdit[] { + const selectionStart = selection.isReversed ? selection.active : selection.anchor; + const selectionEnd = selection.isReversed ? selection.anchor : selection.active; + let selectionStartOffset = document.offsetAt(selectionStart); + let selectionEndOffset = document.offsetAt(selectionEnd); - let startNode = getNode(rootNode, selectionStart, true); - let endNode = getNode(rootNode, selectionEnd, true); + const startNode = getFlatNode(rootNode, selectionStartOffset, true); + const endNode = getFlatNode(rootNode, selectionEndOffset, true); if (!selection.isEmpty) { - selectionStart = adjustStartNodeCss(startNode, selectionStart, rootNode); - selectionEnd = adjustEndNodeCss(endNode, selectionEnd, rootNode); - selection = new vscode.Selection(selectionStart, selectionEnd); + selectionStartOffset = adjustStartNodeCss(startNode, selectionStartOffset, rootNode); + selectionEndOffset = adjustEndNodeCss(endNode, selectionEndOffset, rootNode); + selection = offsetRangeToSelection(document, selectionStartOffset, selectionEndOffset); } else if (startNode) { - selectionStart = startNode.start; - selectionEnd = startNode.end; - selection = new vscode.Selection(selectionStart, selectionEnd); + selectionStartOffset = startNode.start; + selectionEndOffset = startNode.end; + selection = offsetRangeToSelection(document, selectionStartOffset, selectionEndOffset); } // Uncomment the comments that intersect with the selection. let rangesToUnComment: vscode.Range[] = []; let edits: vscode.TextEdit[] = []; rootNode.comments.forEach(comment => { - let commentRange = new vscode.Range(comment.start, comment.end); + const commentRange = offsetRangeToVsRange(document, comment.start, comment.end); if (selection.intersection(commentRange)) { rangesToUnComment.push(commentRange); - edits.push(new vscode.TextEdit(new vscode.Range(comment.start, comment.start.translate(0, startCommentStylesheet.length)), '')); - edits.push(new vscode.TextEdit(new vscode.Range(comment.end.translate(0, -endCommentStylesheet.length), comment.end), '')); + edits.push(new vscode.TextEdit(offsetRangeToVsRange(document, comment.start, comment.start + startCommentStylesheet.length), '')); + edits.push(new vscode.TextEdit(offsetRangeToVsRange(document, comment.end - endCommentStylesheet.length, comment.end), '')); } }); @@ -164,16 +168,15 @@ function setupCommentSpacing() { } } -function adjustStartNodeCss(node: Node | null, pos: vscode.Position, rootNode: Stylesheet): vscode.Position { +function adjustStartNodeCss(node: Node | undefined, offset: number, rootNode: Stylesheet): number { for (const comment of rootNode.comments) { - let commentRange = new vscode.Range(comment.start, comment.end); - if (commentRange.contains(pos)) { - return pos; + if (comment.start <= offset && offset <= comment.end) { + return offset; } } if (!node) { - return pos; + return offset; } if (node.type === 'property') { @@ -181,32 +184,31 @@ function adjustStartNodeCss(node: Node | null, pos: vscode.Position, rootNode: S } const rule = node; - if (pos.isBefore(rule.contentStartToken.end) || !rule.firstChild) { + if (offset < rule.contentStartToken.end || !rule.firstChild) { return rule.start; } - if (pos.isBefore(rule.firstChild.start)) { - return pos; + if (offset < rule.firstChild.start) { + return offset; } let newStartNode = rule.firstChild; - while (newStartNode.nextSibling && pos.isAfter(newStartNode.end)) { + while (newStartNode.nextSibling && offset > newStartNode.end) { newStartNode = newStartNode.nextSibling; } return newStartNode.start; } -function adjustEndNodeCss(node: Node | null, pos: vscode.Position, rootNode: Stylesheet): vscode.Position { +function adjustEndNodeCss(node: Node | undefined, offset: number, rootNode: Stylesheet): number { for (const comment of rootNode.comments) { - let commentRange = new vscode.Range(comment.start, comment.end); - if (commentRange.contains(pos)) { - return pos; + if (comment.start <= offset && offset <= comment.end) { + return offset; } } if (!node) { - return pos; + return offset; } if (node.type === 'property') { @@ -214,16 +216,16 @@ function adjustEndNodeCss(node: Node | null, pos: vscode.Position, rootNode: Sty } const rule = node; - if (pos.isEqual(rule.contentEndToken.end) || !rule.firstChild) { + if (offset === rule.contentEndToken.end || !rule.firstChild) { return rule.end; } - if (pos.isAfter(rule.children[rule.children.length - 1].end)) { - return pos; + if (offset > rule.children[rule.children.length - 1].end) { + return offset; } let newEndNode = rule.children[rule.children.length - 1]; - while (newEndNode.previousSibling && pos.isBefore(newEndNode.start)) { + while (newEndNode.previousSibling && offset < newEndNode.start) { newEndNode = newEndNode.previousSibling; } diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index e83aad0820e..e5653659e01 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -565,7 +565,7 @@ export function findPrevWord(propertyValue: string, pos: number): [number | unde return [newSelectionStart, newSelectionEnd]; } -export function getNodesInBetween(node1: Node, node2: Node): Node[] { +export function getNodesInBetween(node1: FlatNode, node2: FlatNode): FlatNode[] { // Same node if (sameNodes(node1, node2)) { return [node1]; @@ -574,50 +574,46 @@ export function getNodesInBetween(node1: Node, node2: Node): Node[] { // Not siblings if (!sameNodes(node1.parent, node2.parent)) { // node2 is ancestor of node1 - if (node2.start.isBefore(node1.start)) { + if (node2.start < node1.start) { return [node2]; } // node1 is ancestor of node2 - if (node2.start.isBefore(node1.end)) { + if (node2.start < node1.end) { return [node1]; } // Get the highest ancestor of node1 that should be commented - while (node1.parent && node1.parent.end.isBefore(node2.start)) { + while (node1.parent && node1.parent.end < node2.start) { node1 = node1.parent; } // Get the highest ancestor of node2 that should be commented - while (node2.parent && node2.parent.start.isAfter(node1.start)) { + while (node2.parent && node2.parent.start > node1.start) { node2 = node2.parent; } } - const siblings: Node[] = []; - let currentNode = node1; + const siblings: FlatNode[] = []; + let currentNode: FlatNode | undefined = node1; const position = node2.end; - while (currentNode && position.isAfter(currentNode.start)) { + while (currentNode && position > currentNode.start) { siblings.push(currentNode); currentNode = currentNode.nextSibling; } return siblings; } -function samePositions(pos1: vscode.Position | undefined, pos2: vscode.Position | undefined): boolean { - if (!pos1 && !pos2) { - return true; - } else if (pos1 && pos2 && pos1.isEqual(pos2)) { +export function sameNodes(node1: FlatNode | undefined, node2: FlatNode | undefined): boolean { + // return true if they're both undefined + if (!node1 && !node2) { return true; } - return false; -} - -export function sameNodes(node1: Node, node2: Node): boolean { + // return false if only one of them is undefined if (!node1 || !node2) { return false; } - return samePositions(node1.start, node2.start) && samePositions(node1.end, node2.end); + return node1.start === node2.start && node1.end === node2.end; } export function getEmmetConfiguration(syntax: string) { From 15ba9aee0e973b80a8cca63ffc4879858eab0dad Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 29 Dec 2020 16:15:55 -0800 Subject: [PATCH 1445/1837] Emmet improve Expand Abbreviation perf (#113558) --- extensions/emmet/src/abbreviationActions.ts | 85 +++++++----- .../emmet/src/defaultCompletionProvider.ts | 18 +-- .../src/test/partialParsingStylesheet.test.ts | 9 +- extensions/emmet/src/util.ts | 125 +++--------------- 4 files changed, 82 insertions(+), 155 deletions(-) diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index a37741b8e86..a76a46cef23 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { Node, HtmlNode, Rule, Property, Stylesheet } from 'EmmetNode'; -import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, allowedMimeTypesInScriptTag, toLSTextDocument } from './util'; +import { Node, HtmlNode, Rule, Property, Stylesheet } from 'EmmetFlatNode'; +import { getEmmetHelper, getFlatNode, getMappingForIncludedLanguages, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, allowedMimeTypesInScriptTag, toLSTextDocument } from './util'; +import { getRootNode as parseDocument } from './parseDocument'; const trimRegex = /[\u00a0]*[\d#\-\*\u2022]+\.?/; const hexColorRegex = /^#[\da-fA-F]{0,6}$/; @@ -59,7 +60,7 @@ function doWrapping(individualLines: boolean, args: any) { args['language'] = editor.document.languageId; } const syntax = getSyntaxFromArgs(args) || 'html'; - const rootNode = parseDocument(editor.document, false); + const rootNode = parseDocument(editor.document, true); let inPreview = false; let currentValue = ''; @@ -68,31 +69,40 @@ function doWrapping(individualLines: boolean, args: any) { // Fetch general information for the succesive expansions. i.e. the ranges to replace and its contents const rangesToReplace: PreviewRangesWithContent[] = editor.selections.sort((a: vscode.Selection, b: vscode.Selection) => { return a.start.compareTo(b.start); }).map(selection => { let rangeToReplace: vscode.Range = selection.isReversed ? new vscode.Range(selection.active, selection.anchor) : selection; + const document = editor.document; if (!rangeToReplace.isSingleLine && rangeToReplace.end.character === 0) { const previousLine = rangeToReplace.end.line - 1; - const lastChar = editor.document.lineAt(previousLine).text.length; + const lastChar = document.lineAt(previousLine).text.length; rangeToReplace = new vscode.Range(rangeToReplace.start, new vscode.Position(previousLine, lastChar)); } else if (rangeToReplace.isEmpty) { const { active } = selection; - const currentNode = getNode(rootNode, active, true); - if (currentNode && (currentNode.start.line === active.line || currentNode.end.line === active.line)) { - rangeToReplace = new vscode.Range(currentNode.start, currentNode.end); + const activeOffset = document.offsetAt(active); + const currentNode = getFlatNode(rootNode, activeOffset, true); + if (currentNode) { + const currentNodeStart = document.positionAt(currentNode.start); + const currentNodeEnd = document.positionAt(currentNode.end); + if (currentNodeStart.line === active.line || currentNodeEnd.line === active.line) { + rangeToReplace = new vscode.Range(currentNodeStart, currentNodeEnd); + } + else { + rangeToReplace = new vscode.Range(rangeToReplace.start.line, 0, rangeToReplace.start.line, document.lineAt(rangeToReplace.start.line).text.length); + } } else { - rangeToReplace = new vscode.Range(rangeToReplace.start.line, 0, rangeToReplace.start.line, editor.document.lineAt(rangeToReplace.start.line).text.length); + rangeToReplace = new vscode.Range(rangeToReplace.start.line, 0, rangeToReplace.start.line, document.lineAt(rangeToReplace.start.line).text.length); } } - const firstLineOfSelection = editor.document.lineAt(rangeToReplace.start).text.substr(rangeToReplace.start.character); + const firstLineOfSelection = document.lineAt(rangeToReplace.start).text.substr(rangeToReplace.start.character); const matches = firstLineOfSelection.match(/^(\s*)/); const extraWhitespaceSelected = matches ? matches[1].length : 0; rangeToReplace = new vscode.Range(rangeToReplace.start.line, rangeToReplace.start.character + extraWhitespaceSelected, rangeToReplace.end.line, rangeToReplace.end.character); let textToWrapInPreview: string[]; - const textToReplace = editor.document.getText(rangeToReplace); + const textToReplace = document.getText(rangeToReplace); if (individualLines) { textToWrapInPreview = textToReplace.split('\n').map(x => x.trim()); } else { - const wholeFirstLine = editor.document.lineAt(rangeToReplace.start).text; + const wholeFirstLine = document.lineAt(rangeToReplace.start).text; const otherMatches = wholeFirstLine.match(/^(\s*)/); const precedingWhitespace = otherMatches ? otherMatches[1] : ''; textToWrapInPreview = rangeToReplace.isSingleLine ? [textToReplace] : ['\n\t' + textToReplace.split('\n' + precedingWhitespace).join('\n\t') + '\n']; @@ -327,7 +337,7 @@ export function expandEmmetAbbreviation(args: any): Thenable 1000) { rootNode = parsePartialStylesheet(editor.document, editor.selection.isReversed ? editor.selection.anchor : editor.selection.active); } else { - rootNode = parseDocument(editor.document, false); + rootNode = parseDocument(editor.document, true); } return rootNode; @@ -342,24 +352,25 @@ export function expandEmmetAbbreviation(args: any): Thenable { * @param position position to validate * @param abbreviationRange The range of the abbreviation for which given position is being validated */ -export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocument, rootNode: Node | undefined, currentNode: Node | null, syntax: string, position: vscode.Position, abbreviationRange: vscode.Range): boolean { +export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocument, rootNode: Node | undefined, currentNode: Node | undefined, syntax: string, offset: number, abbreviationRange: vscode.Range): boolean { if (isStyleSheet(syntax)) { const stylesheet = rootNode; - if (stylesheet && (stylesheet.comments || []).some(x => position.isAfterOrEqual(x.start) && position.isBeforeOrEqual(x.end))) { + if (stylesheet && (stylesheet.comments || []).some(x => offset >= x.start && offset <= x.end)) { return false; } // Continue validation only if the file was parse-able and the currentNode has been found @@ -419,14 +430,14 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen const propertyNode = currentNode; if (propertyNode.terminatorToken && propertyNode.separator - && position.isAfterOrEqual(propertyNode.separatorToken.end) - && position.isBeforeOrEqual(propertyNode.terminatorToken.start) + && offset >= propertyNode.separatorToken.end + && offset <= propertyNode.terminatorToken.start && abbreviation.indexOf(':') === -1) { return hexColorRegex.test(abbreviation) || abbreviation === '!'; } if (!propertyNode.terminatorToken && propertyNode.separator - && position.isAfterOrEqual(propertyNode.separatorToken.end) + && offset >= propertyNode.separatorToken.end && abbreviation.indexOf(':') === -1) { return hexColorRegex.test(abbreviation) || abbreviation === '!'; } @@ -444,7 +455,7 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen const currentCssNode = currentNode; // Position is valid if it occurs after the `{` that marks beginning of rule contents - if (position.isAfter(currentCssNode.contentStartToken.end)) { + if (offset > currentCssNode.contentStartToken.end) { return true; } @@ -453,12 +464,16 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen // But we should assume it is a valid location for css properties under the parent rule if (currentCssNode.parent && (currentCssNode.parent.type === 'rule' || currentCssNode.parent.type === 'at-rule') - && currentCssNode.selectorToken - && position.line !== currentCssNode.selectorToken.end.line - && currentCssNode.selectorToken.start.character === abbreviationRange.start.character - && currentCssNode.selectorToken.start.line === abbreviationRange.start.line - ) { - return true; + && currentCssNode.selectorToken) { + const position = document.positionAt(offset); + const tokenStartPos = document.positionAt(currentCssNode.selectorToken.start); + const tokenEndPos = document.positionAt(currentCssNode.selectorToken.end); + if (position.line !== tokenEndPos.line + && tokenStartPos.character === abbreviationRange.start.character + && tokenStartPos.line === abbreviationRange.start.line + ) { + return true; + } } return false; @@ -469,7 +484,7 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen const escape = '\\'; const question = '?'; const currentHtmlNode = currentNode; - let start = new vscode.Position(0, 0); + let start = 0; if (currentHtmlNode) { if (currentHtmlNode.name === 'script') { @@ -487,27 +502,27 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen return false; } - const innerRange = getInnerRange(currentHtmlNode); - // Fix for https://github.com/microsoft/vscode/issues/28829 - if (!innerRange || !innerRange.contains(position)) { + if (!currentHtmlNode.open || !currentHtmlNode.close || + !(currentHtmlNode.open.end <= offset && offset <= currentHtmlNode.close.start)) { return false; } // Fix for https://github.com/microsoft/vscode/issues/35128 // Find the position up till where we will backtrack looking for unescaped < or > // to decide if current position is valid for emmet expansion - start = innerRange.start; + start = currentHtmlNode.open.end; let lastChildBeforePosition = currentHtmlNode.firstChild; while (lastChildBeforePosition) { - if (lastChildBeforePosition.end.isAfter(position)) { + if (lastChildBeforePosition.end > offset) { break; } start = lastChildBeforePosition.end; lastChildBeforePosition = lastChildBeforePosition.nextSibling; } } - let textToBackTrack = document.getText(new vscode.Range(start.line, start.character, abbreviationRange.start.line, abbreviationRange.start.character)); + const startPos = document.positionAt(start); + let textToBackTrack = document.getText(new vscode.Range(startPos.line, startPos.character, abbreviationRange.start.line, abbreviationRange.start.character)); // Worse case scenario is when cursor is inside a big chunk of text which needs to backtracked // Backtrack only 500 offsets to ensure we dont waste time doing this diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index 9ac469af615..a4f31e5f8c4 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -4,10 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { Node, Stylesheet } from 'EmmetNode'; +import { Node, Stylesheet } from 'EmmetFlatNode'; import { isValidLocationForEmmetAbbreviation, getSyntaxFromArgs } from './abbreviationActions'; -import { getEmmetHelper, getMappingForIncludedLanguages, parsePartialStylesheet, getEmmetConfiguration, getEmmetMode, isStyleSheet, parseDocument, getNode, allowedMimeTypesInScriptTag, trimQuotes, toLSTextDocument } from './util'; +import { getEmmetHelper, getMappingForIncludedLanguages, parsePartialStylesheet, getEmmetConfiguration, getEmmetMode, isStyleSheet, getFlatNode, allowedMimeTypesInScriptTag, trimQuotes, toLSTextDocument } from './util'; import { getLanguageService, TokenType, Range as LSRange } from 'vscode-html-languageservice'; +import { getRootNode } from './parseDocument'; export class DefaultCompletionItemProvider implements vscode.CompletionItemProvider { @@ -62,8 +63,8 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi const helper = getEmmetHelper(); let validateLocation = syntax === 'html' || syntax === 'jsx' || syntax === 'xml'; - let rootNode: Node | undefined = undefined; - let currentNode: Node | null = null; + let rootNode: Node | undefined; + let currentNode: Node | undefined; const lsDoc = toLSTextDocument(document); position = document.validatePosition(position); @@ -145,19 +146,18 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi return; } + const offset = document.offsetAt(position); if (isStyleSheet(document.languageId) && context.triggerKind !== vscode.CompletionTriggerKind.TriggerForIncompleteCompletions) { validateLocation = true; let usePartialParsing = vscode.workspace.getConfiguration('emmet')['optimizeStylesheetParsing'] === true; - rootNode = usePartialParsing && document.lineCount > 1000 ? parsePartialStylesheet(document, position) : parseDocument(document, false); + rootNode = usePartialParsing && document.lineCount > 1000 ? parsePartialStylesheet(document, position) : getRootNode(document, true); if (!rootNode) { return; } - currentNode = getNode(rootNode, position, true); + currentNode = getFlatNode(rootNode, offset, true); } - - - if (validateLocation && !isValidLocationForEmmetAbbreviation(document, rootNode, currentNode, syntax, position, toRange(extractAbbreviationResults.abbreviationRange))) { + if (validateLocation && !isValidLocationForEmmetAbbreviation(document, rootNode, currentNode, syntax, offset, toRange(extractAbbreviationResults.abbreviationRange))) { return; } diff --git a/extensions/emmet/src/test/partialParsingStylesheet.test.ts b/extensions/emmet/src/test/partialParsingStylesheet.test.ts index 0c19d06b645..b0928e1a32f 100644 --- a/extensions/emmet/src/test/partialParsingStylesheet.test.ts +++ b/extensions/emmet/src/test/partialParsingStylesheet.test.ts @@ -7,15 +7,16 @@ import 'mocha'; import * as assert from 'assert'; import { withRandomFileEditor } from './testUtils'; import * as vscode from 'vscode'; -import { parsePartialStylesheet, getNode } from '../util'; +import { parsePartialStylesheet, getFlatNode } from '../util'; import { isValidLocationForEmmetAbbreviation } from '../abbreviationActions'; suite('Tests for partial parse of Stylesheets', () => { function isValid(doc: vscode.TextDocument, range: vscode.Range, syntax: string): boolean { const rootNode = parsePartialStylesheet(doc, range.end); - const currentNode = getNode(rootNode, range.end, true); - return isValidLocationForEmmetAbbreviation(doc, rootNode, currentNode, syntax, range.end, range); + const endOffset = doc.offsetAt(range.end); + const currentNode = getFlatNode(rootNode, endOffset, true); + return isValidLocationForEmmetAbbreviation(doc, rootNode, currentNode, syntax, endOffset, range); } test('Ignore block comment inside rule', function (): any { @@ -257,4 +258,4 @@ ment */{ }); -}); \ No newline at end of file +}); diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index e5653659e01..97e829ef259 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -6,8 +6,7 @@ import * as vscode from 'vscode'; import parse from '@emmetio/html-matcher'; import parseStylesheet from '@emmetio/css-parser'; -import { Node, HtmlNode, Stylesheet } from 'EmmetNode'; -import { Node as FlatNode, HtmlNode as HtmlFlatNode, Property as FlatProperty, Rule as FlatRule, CssToken as FlatCssToken } from 'EmmetFlatNode'; +import { Node as FlatNode, HtmlNode as HtmlFlatNode, Property as FlatProperty, Rule as FlatRule, CssToken as FlatCssToken, Stylesheet as FlatStylesheet } from 'EmmetFlatNode'; import { DocumentStreamReader } from './bufferStream'; import * as EmmetHelper from 'vscode-emmet-helper'; import { TextDocument as LSTextDocument } from 'vscode-languageserver-textdocument'; @@ -138,21 +137,6 @@ export function getEmmetMode(language: string, excludedLanguages: string[]): str return; } -/** - * Parses the given document using emmet parsing modules - */ -export function parseDocument(document: vscode.TextDocument, showError: boolean = true): Node | undefined { - let parseContent = isStyleSheet(document.languageId) ? parseStylesheet : parse; - try { - return parseContent(new DocumentStreamReader(document)); - } catch (e) { - if (showError) { - vscode.window.showErrorMessage('Emmet: Failed to parse the file'); - } - } - return undefined; -} - const closeBrace = 125; const openBrace = 123; const slash = 47; @@ -164,7 +148,7 @@ const star = 42; * @param document vscode.TextDocument * @param position vscode.Position */ -export function parsePartialStylesheet(document: vscode.TextDocument, position: vscode.Position): Stylesheet | undefined { +export function parsePartialStylesheet(document: vscode.TextDocument, position: vscode.Position): FlatStylesheet | undefined { const isCSS = document.languageId === 'css'; let startPosition = new vscode.Position(0, 0); let endPosition = new vscode.Position(document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length); @@ -304,7 +288,10 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position: } try { - return parseStylesheet(new DocumentStreamReader(document, startPosition, new vscode.Range(startPosition, endPosition))); + const startOffset = document.offsetAt(startPosition); + const endOffset = document.offsetAt(endPosition); + const buffer = ' '.repeat(startOffset) + document.getText().substring(startOffset, endOffset); + return parseStylesheet(buffer); } catch (e) { return; } @@ -313,31 +300,6 @@ export function parsePartialStylesheet(document: vscode.TextDocument, position: /** * Returns node corresponding to given position in the given root node */ -export function getNode(root: Node | undefined, position: vscode.Position, includeNodeBoundary: boolean): Node | null { - if (!root) { - return null; - } - - let currentNode = root.firstChild; - let foundNode: Node | null = null; - - while (currentNode) { - const nodeStart: vscode.Position = currentNode.start; - const nodeEnd: vscode.Position = currentNode.end; - if ((nodeStart.isBefore(position) && nodeEnd.isAfter(position)) - || (includeNodeBoundary && (nodeStart.isBeforeOrEqual(position) && nodeEnd.isAfterOrEqual(position)))) { - - foundNode = currentNode; - // Dig deeper - currentNode = currentNode.firstChild; - } else { - currentNode = currentNode.nextSibling; - } - } - - return foundNode; -} - export function getFlatNode(root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): FlatNode | undefined { if (!root) { return; @@ -380,35 +342,9 @@ export function getFlatNode(root: FlatNode | undefined, offset: number, includeN export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template']; -/** - * Returns HTML node corresponding to given position in the given root node - * If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well - */ -export function getHtmlNode(document: vscode.TextDocument, root: Node | undefined, position: vscode.Position, includeNodeBoundary: boolean): HtmlNode | undefined { - let currentNode = getNode(root, position, includeNodeBoundary); - if (!currentNode) { return; } - - const isTemplateScript = currentNode.name === 'script' && - (currentNode.attributes && - currentNode.attributes.some(x => x.name.toString() === 'type' - && allowedMimeTypesInScriptTag.indexOf(x.value.toString()) > -1)); - - if (isTemplateScript && currentNode.close && - (position.isAfter(currentNode.open.end) && position.isBefore(currentNode.close.start))) { - - let buffer = new DocumentStreamReader(document, currentNode.open.end, new vscode.Range(currentNode.open.end, currentNode.close.start)); - - try { - let scriptInnerNodes = parse(buffer); - currentNode = getNode(scriptInnerNodes, position, includeNodeBoundary) || currentNode; - } catch (e) { } - } - - return currentNode; -} - /** * Finds the HTML node within an HTML document at a given position + * If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well */ export function getHtmlFlatNode(documentText: string, root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): HtmlFlatNode | undefined { const currentNode: HtmlFlatNode | undefined = getFlatNode(root, offset, includeNodeBoundary); @@ -449,31 +385,6 @@ export function offsetRangeToVsRange(document: vscode.TextDocument, start: numbe return new vscode.Range(startPos, endPos); } -/** - * Returns inner range of an html node. - */ -export function getInnerRange(currentNode: HtmlNode): vscode.Range | undefined { - if (!currentNode.close) { - return undefined; - } - return new vscode.Range(currentNode.open.end, currentNode.close.start); -} - -/** - * Returns the deepest non comment node under given node - */ -export function getDeepestNode(node: Node | undefined): Node | undefined { - if (!node || !node.children || node.children.length === 0 || !node.children.find(x => x.type !== 'comment')) { - return node; - } - for (let i = node.children.length - 1; i >= 0; i--) { - if (node.children[i].type !== 'comment') { - return getDeepestNode(node.children[i]); - } - } - return undefined; -} - /** * Returns the deepest non comment node under given node */ @@ -696,18 +607,18 @@ export function getCssPropertyFromDocument(editor: vscode.TextEditor, position: } -export function getEmbeddedCssNodeIfAny(document: vscode.TextDocument, currentNode: Node | null, position: vscode.Position): Node | undefined { +export function getEmbeddedCssNodeIfAny(document: vscode.TextDocument, currentNode: FlatNode | undefined, position: vscode.Position): FlatNode | undefined { if (!currentNode) { return; } - const currentHtmlNode = currentNode; - if (currentHtmlNode && currentHtmlNode.close) { - const innerRange = getInnerRange(currentHtmlNode); - if (innerRange && innerRange.contains(position)) { + const currentHtmlNode = currentNode; + if (currentHtmlNode && currentHtmlNode.open && currentHtmlNode.close) { + const offset = document.offsetAt(position); + if (currentHtmlNode.open.end <= offset && offset <= currentHtmlNode.close.start) { if (currentHtmlNode.name === 'style' - && currentHtmlNode.open.end.isBefore(position) - && currentHtmlNode.close.start.isAfter(position)) { - let buffer = new DocumentStreamReader(document, currentHtmlNode.open.end, new vscode.Range(currentHtmlNode.open.end, currentHtmlNode.close.start)); + && currentHtmlNode.open.end < offset + && currentHtmlNode.close.start > offset) { + const buffer = ' '.repeat(currentHtmlNode.open.end) + document.getText().substring(currentHtmlNode.open.end, currentHtmlNode.close.start); return parseStylesheet(buffer); } } @@ -715,17 +626,17 @@ export function getEmbeddedCssNodeIfAny(document: vscode.TextDocument, currentNo return; } -export function isStyleAttribute(currentNode: Node | null, position: vscode.Position): boolean { +export function isStyleAttribute(currentNode: FlatNode | undefined, offset: number): boolean { if (!currentNode) { return false; } - const currentHtmlNode = currentNode; + const currentHtmlNode = currentNode; const index = (currentHtmlNode.attributes || []).findIndex(x => x.name.toString() === 'style'); if (index === -1) { return false; } const styleAttribute = currentHtmlNode.attributes[index]; - return position.isAfterOrEqual(styleAttribute.value.start) && position.isBeforeOrEqual(styleAttribute.value.end); + return offset >= styleAttribute.value.start && offset <= styleAttribute.value.end; } From 15561c41399e5da051f8bde8107d29a9dc909b9c Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 29 Dec 2020 16:33:41 -0800 Subject: [PATCH 1446/1837] Emmet polish --- extensions/emmet/src/evaluateMathExpression.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extensions/emmet/src/evaluateMathExpression.ts b/extensions/emmet/src/evaluateMathExpression.ts index 588d4dce9ba..cdbcfda1d3f 100644 --- a/extensions/emmet/src/evaluateMathExpression.ts +++ b/extensions/emmet/src/evaluateMathExpression.ts @@ -7,7 +7,6 @@ import * as vscode from 'vscode'; import evaluate, { extract } from '@emmetio/math-expression'; -import { DocumentStreamReader } from './bufferStream'; export function evaluateMathExpression(): Thenable { if (!vscode.window.activeTextEditor) { @@ -15,13 +14,12 @@ export function evaluateMathExpression(): Thenable { return Promise.resolve(false); } const editor = vscode.window.activeTextEditor; - const stream = new DocumentStreamReader(editor.document); return editor.edit(editBuilder => { editor.selections.forEach(selection => { // startpos always comes before endpos const startpos = selection.isReversed ? selection.active : selection.anchor; const endpos = selection.isReversed ? selection.anchor : selection.active; - const selectionText = stream.substring(startpos, endpos); + const selectionText = editor.document.getText(new vscode.Range(startpos, endpos)); try { if (selectionText) { @@ -30,7 +28,7 @@ export function evaluateMathExpression(): Thenable { editBuilder.replace(new vscode.Range(startpos, endpos), result); } else { // no selection made, extract expression from line - const lineToSelectionEnd = stream.substring(new vscode.Position(selection.end.line, 0), endpos); + const lineToSelectionEnd = editor.document.getText(new vscode.Range(new vscode.Position(selection.end.line, 0), endpos)); const extractedIndices = extract(lineToSelectionEnd); if (!extractedIndices) { throw new Error('Invalid extracted indices'); From afb6a0c56eff005e94b1a05a47ec860903b5a116 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Wed, 30 Dec 2020 10:11:14 +0100 Subject: [PATCH 1447/1837] Fix CSP --- .../extensions/worker/httpsWebWorkerExtensionHostIframe.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/worker/httpsWebWorkerExtensionHostIframe.html b/src/vs/workbench/services/extensions/worker/httpsWebWorkerExtensionHostIframe.html index 017f32be250..3db124e5df2 100644 --- a/src/vs/workbench/services/extensions/worker/httpsWebWorkerExtensionHostIframe.html +++ b/src/vs/workbench/services/extensions/worker/httpsWebWorkerExtensionHostIframe.html @@ -1,7 +1,7 @@ - + + + `; + } + + private extensionResourceUrl(...parts: string[]): vscode.Uri { + return this._webviewPanel.webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, ...parts)); + } +} + +function escapeAttribute(value: string | vscode.Uri): string { + return value.toString().replace(/"/g, '"'); +} diff --git a/extensions/simple-browser/src/typings/ref.d.ts b/extensions/simple-browser/src/typings/ref.d.ts new file mode 100644 index 00000000000..c9849d48e08 --- /dev/null +++ b/extensions/simple-browser/src/typings/ref.d.ts @@ -0,0 +1,7 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// +/// diff --git a/extensions/simple-browser/tsconfig.json b/extensions/simple-browser/tsconfig.json new file mode 100644 index 00000000000..d0797affbad --- /dev/null +++ b/extensions/simple-browser/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out", + "experimentalDecorators": true + }, + "include": [ + "src/**/*" + ] +} diff --git a/extensions/simple-browser/webpack.config.js b/extensions/simple-browser/webpack.config.js new file mode 100644 index 00000000000..4a9990ac056 --- /dev/null +++ b/extensions/simple-browser/webpack.config.js @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * 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 = { + entry: { + index: './preview-src/index.ts', + }, + devtool: 'source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'] + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'media') + } +}; diff --git a/extensions/simple-browser/yarn.lock b/extensions/simple-browser/yarn.lock new file mode 100644 index 00000000000..1daa22f5798 --- /dev/null +++ b/extensions/simple-browser/yarn.lock @@ -0,0 +1,2732 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^12.11.7": + version "12.12.69" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.69.tgz#7cb6a3aa0d16664bf2dcd1450ccb8477464fbd79" + integrity sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg== + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.1.0, ajv@^6.10.2: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== + dependencies: + diagnostic-channel "0.2.0" + diagnostic-channel-publishers "0.2.1" + zone.js "0.7.6" + +aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + +bn.js@^5.1.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" + integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.3.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.1.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +diagnostic-channel-publishers@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" + integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM= + +diagnostic-channel@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" + integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc= + dependencies: + semver "^5.3.0" + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +elliptic@^6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esrecurse@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +events@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" + integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + +file-uri-to-path@1.0.0: + version "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== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +findup-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@^1.0.2, loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@^0.5.3: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +nan@^2.12.1: + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.12: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +terser-webpack-plugin@^1.4.3: + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^4.0.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser@^4.1.2: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +ts-loader@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" + integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^4.0.0" + semver "^6.0.0" + +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^3.7.3: + version "3.9.7" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" + integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +uri-js@^4.2.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +v8-compile-cache@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +vscode-codicons@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/vscode-codicons/-/vscode-codicons-0.0.12.tgz#94b867156f3e3a6a4cf7661e9bf2bd0060042390" + integrity sha512-CyGFDf3OmQhtBql/BFheUAlvEZ1MKAgvyCrGktGXEsqYvK5m9456kckDTNvnEAGG8gYjE2ds5O1cle82sMgmAg== + +vscode-extension-telemetry@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" + integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== + dependencies: + applicationinsights "1.0.8" + +vscode-nls@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" + integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== + +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" + +webpack-cli@^3.3.0: + version "3.3.12" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== + dependencies: + chalk "^2.4.2" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.1" + findup-sync "^3.0.0" + global-modules "^2.0.0" + import-local "^2.0.0" + interpret "^1.4.0" + loader-utils "^1.4.0" + supports-color "^6.1.0" + v8-compile-cache "^2.1.1" + yargs "^13.3.2" + +webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.41.2: + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.3.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +zone.js@0.7.6: + version "0.7.6" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" + integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk= diff --git a/extensions/typescript-language-features/src/languageFeatures/refactor.ts b/extensions/typescript-language-features/src/languageFeatures/refactor.ts index cc8c0a5d3a7..7fdc9b43576 100644 --- a/extensions/typescript-language-features/src/languageFeatures/refactor.ts +++ b/extensions/typescript-language-features/src/languageFeatures/refactor.ts @@ -301,6 +301,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider kind.matches(refactor)); return match ? match.kind : vscode.CodeActionKind.Refactor; } From a48ef56fbf7767f55a193d7d5687addd1fc9239c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Jan 2021 19:25:10 -0800 Subject: [PATCH 1510/1837] Fix compile for current TS version --- .../src/languageFeatures/refactor.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/refactor.ts b/extensions/typescript-language-features/src/languageFeatures/refactor.ts index 7fdc9b43576..b8a4bcfdab0 100644 --- a/extensions/typescript-language-features/src/languageFeatures/refactor.ts +++ b/extensions/typescript-language-features/src/languageFeatures/refactor.ts @@ -298,7 +298,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider kind.matches(refactor)); return match ? match.kind : vscode.CodeActionKind.Refactor; From 7db413d4c105482f9d89988cc89ec50982491e1e Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 4 Jan 2021 22:03:21 -0800 Subject: [PATCH 1511/1837] Move secrets API to extension context --- .../src/common/keychain.ts | 9 ++- .../github-authentication/src/extension.ts | 2 +- .../github-authentication/src/github.ts | 16 +++-- .../microsoft-authentication/src/AADHelper.ts | 19 ++--- .../microsoft-authentication/src/extension.ts | 2 +- .../microsoft-authentication/src/keychain.ts | 11 ++- src/vs/vscode.proposed.d.ts | 56 ++++++++------- .../api/browser/extensionHost.contribution.ts | 1 + .../api/browser/mainThreadAuthentication.ts | 54 +------------- .../api/browser/mainThreadSecretState.ts | 72 +++++++++++++++++++ .../workbench/api/common/exHostSecretState.ts | 38 ++++++++++ .../workbench/api/common/extHost.api.impl.ts | 19 +---- .../api/common/extHost.common.services.ts | 2 + .../workbench/api/common/extHost.protocol.ts | 7 ++ .../api/common/extHostAuthentication.ts | 22 ------ .../api/common/extHostExtensionService.ts | 11 ++- src/vs/workbench/api/common/extHostSecrets.ts | 39 ++++++++++ 17 files changed, 236 insertions(+), 144 deletions(-) create mode 100644 src/vs/workbench/api/browser/mainThreadSecretState.ts create mode 100644 src/vs/workbench/api/common/exHostSecretState.ts create mode 100644 src/vs/workbench/api/common/extHostSecrets.ts diff --git a/extensions/github-authentication/src/common/keychain.ts b/extensions/github-authentication/src/common/keychain.ts index 96afff43b09..59fd14a7374 100644 --- a/extensions/github-authentication/src/common/keychain.ts +++ b/extensions/github-authentication/src/common/keychain.ts @@ -31,9 +31,10 @@ export type Keytar = { const SERVICE_ID = `github.auth`; export class Keychain { + constructor(private context: vscode.ExtensionContext) { } async setToken(token: string): Promise { try { - return await vscode.authentication.setPassword(SERVICE_ID, token); + return await this.context.secretState.set(SERVICE_ID, token); } catch (e) { // Ignore Logger.error(`Setting token failed: ${e}`); @@ -47,7 +48,7 @@ export class Keychain { async getToken(): Promise { try { - return await vscode.authentication.getPassword(SERVICE_ID); + return await this.context.secretState.get(SERVICE_ID); } catch (e) { // Ignore Logger.error(`Getting token failed: ${e}`); @@ -57,7 +58,7 @@ export class Keychain { async deleteToken(): Promise { try { - return await vscode.authentication.deletePassword(SERVICE_ID); + return await this.context.secretState.delete(SERVICE_ID); } catch (e) { // Ignore Logger.error(`Deleting token failed: ${e}`); @@ -85,5 +86,3 @@ export class Keychain { } } } - -export const keychain = new Keychain(); diff --git a/extensions/github-authentication/src/extension.ts b/extensions/github-authentication/src/extension.ts index b49942b527d..d414545f047 100644 --- a/extensions/github-authentication/src/extension.ts +++ b/extensions/github-authentication/src/extension.ts @@ -14,7 +14,7 @@ export async function activate(context: vscode.ExtensionContext) { const telemetryReporter = new TelemetryReporter(name, version, aiKey); context.subscriptions.push(vscode.window.registerUriHandler(uriHandler)); - const loginService = new GitHubAuthenticationProvider(); + const loginService = new GitHubAuthenticationProvider(context); await loginService.initialize(context); diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index d1cf45b7d0d..6b97805b199 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import { v4 as uuid } from 'uuid'; -import { keychain } from './common/keychain'; +import { Keychain } from './common/keychain'; import { GitHubServer, NETWORK_ERROR } from './githubServer'; import Logger from './common/logger'; @@ -26,6 +26,12 @@ export class GitHubAuthenticationProvider { private _sessions: vscode.AuthenticationSession[] = []; private _githubServer = new GitHubServer(); + private _keychain: Keychain; + + constructor(context: vscode.ExtensionContext) { + this._keychain = new Keychain(context); + } + public async initialize(context: vscode.ExtensionContext): Promise { try { this._sessions = await this.readSessions(); @@ -34,7 +40,7 @@ export class GitHubAuthenticationProvider { // Ignore, network request failed } - context.subscriptions.push(vscode.authentication.onDidChangePassword(() => this.checkForUpdates())); + context.subscriptions.push(context.secretState.onDidChangePassword(() => this.checkForUpdates())); } private async verifySessions(): Promise { @@ -101,7 +107,7 @@ export class GitHubAuthenticationProvider { } private async readSessions(): Promise { - const storedSessions = await keychain.getToken() || await keychain.tryMigrate(); + const storedSessions = await this._keychain.getToken() || await this._keychain.tryMigrate(); if (storedSessions) { try { const sessionData: SessionData[] = JSON.parse(storedSessions); @@ -132,7 +138,7 @@ export class GitHubAuthenticationProvider { } Logger.error(`Error reading sessions: ${e}`); - await keychain.deleteToken(); + await this._keychain.deleteToken(); } } @@ -140,7 +146,7 @@ export class GitHubAuthenticationProvider { } private async storeSessions(): Promise { - await keychain.setToken(JSON.stringify(this._sessions)); + await this._keychain.setToken(JSON.stringify(this._sessions)); } get sessions(): vscode.AuthenticationSession[] { diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts index 60455f02a96..62c53de6c28 100644 --- a/extensions/microsoft-authentication/src/AADHelper.ts +++ b/extensions/microsoft-authentication/src/AADHelper.ts @@ -10,7 +10,7 @@ import * as vscode from 'vscode'; import { createServer, startServer } from './authServer'; import { v4 as uuid } from 'uuid'; -import { keychain } from './keychain'; +import { Keychain } from './keychain'; import Logger from './logger'; import { toBase64UrlEncoding } from './utils'; import fetch, { Response } from 'node-fetch'; @@ -100,13 +100,16 @@ export class AzureActiveDirectoryService { private _codeExchangePromises = new Map>(); private _codeVerfifiers = new Map(); - constructor() { + private _keychain: Keychain; + + constructor(private _context: vscode.ExtensionContext) { + this._keychain = new Keychain(_context); this._uriHandler = new UriEventHandler(); this._disposables.push(vscode.window.registerUriHandler(this._uriHandler)); } public async initialize(): Promise { - const storedData = await keychain.getToken() || await keychain.tryMigrate(); + const storedData = await this._keychain.getToken() || await this._keychain.tryMigrate(); if (storedData) { try { const sessions = this.parseStoredData(storedData); @@ -146,7 +149,7 @@ export class AzureActiveDirectoryService { } } - this._disposables.push(vscode.authentication.onDidChangePassword(() => this.checkForUpdates)); + this._disposables.push(this._context.secretState.onDidChangePassword(() => this.checkForUpdates)); } private parseStoredData(data: string): IStoredSession[] { @@ -163,13 +166,13 @@ export class AzureActiveDirectoryService { }; }); - await keychain.setToken(JSON.stringify(serializedData)); + await this._keychain.setToken(JSON.stringify(serializedData)); } private async checkForUpdates(): Promise { const addedIds: string[] = []; let removedIds: string[] = []; - const storedData = await keychain.getToken(); + const storedData = await this._keychain.getToken(); if (storedData) { try { const sessions = this.parseStoredData(storedData); @@ -651,7 +654,7 @@ export class AzureActiveDirectoryService { this.removeInMemorySessionData(sessionId); if (this._tokens.length === 0) { - await keychain.deleteToken(); + await this._keychain.deleteToken(); } else { this.storeTokenData(); } @@ -660,7 +663,7 @@ export class AzureActiveDirectoryService { public async clearSessions() { Logger.info('Logging out of all sessions'); this._tokens = []; - await keychain.deleteToken(); + await this._keychain.deleteToken(); this._refreshTimeouts.forEach(timeout => { clearTimeout(timeout); diff --git a/extensions/microsoft-authentication/src/extension.ts b/extensions/microsoft-authentication/src/extension.ts index f31d72d8467..2c08a789715 100644 --- a/extensions/microsoft-authentication/src/extension.ts +++ b/extensions/microsoft-authentication/src/extension.ts @@ -13,7 +13,7 @@ export async function activate(context: vscode.ExtensionContext) { const { name, version, aiKey } = require('../package.json') as { name: string, version: string, aiKey: string }; const telemetryReporter = new TelemetryReporter(name, version, aiKey); - const loginService = new AzureActiveDirectoryService(); + const loginService = new AzureActiveDirectoryService(context); context.subscriptions.push(loginService); await loginService.initialize(); diff --git a/extensions/microsoft-authentication/src/keychain.ts b/extensions/microsoft-authentication/src/keychain.ts index f0e487760eb..a9c9a674d82 100644 --- a/extensions/microsoft-authentication/src/keychain.ts +++ b/extensions/microsoft-authentication/src/keychain.ts @@ -35,7 +35,7 @@ const ACCOUNT_ID = 'account'; export class Keychain { private keytar: Keytar; - constructor() { + constructor(private context: vscode.ExtensionContext) { const keytar = getKeytar(); if (!keytar) { throw new Error('System keychain unavailable'); @@ -46,8 +46,9 @@ export class Keychain { async setToken(token: string): Promise { + try { - return await vscode.authentication.setPassword(SERVICE_ID, token); + return await this.context.secretState.set(SERVICE_ID, token); } catch (e) { Logger.error(`Setting token failed: ${e}`); @@ -69,7 +70,7 @@ export class Keychain { async getToken(): Promise { try { - return await vscode.authentication.getPassword(SERVICE_ID); + return await this.context.secretState.get(SERVICE_ID); } catch (e) { // Ignore Logger.error(`Getting token failed: ${e}`); @@ -79,7 +80,7 @@ export class Keychain { async deleteToken(): Promise { try { - return await vscode.authentication.deletePassword(SERVICE_ID); + return await this.context.secretState.delete(SERVICE_ID); } catch (e) { // Ignore Logger.error(`Deleting token failed: ${e}`); @@ -102,5 +103,3 @@ export class Keychain { } } } - -export const keychain = new Keychain(); diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 61c6cef4b96..092885bb0d6 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -153,31 +153,6 @@ declare module 'vscode' { * provider */ export function logout(providerId: string, sessionId: string): Thenable; - - /** - * Retrieve a password that was stored with key. Returns undefined if there - * is no password matching that key. - * @param key The key the password was stored under. - */ - export function getPassword(key: string): Thenable; - - /** - * Store a password under a given key. - * @param key The key to store the password under - * @param value The password - */ - export function setPassword(key: string, value: string): Thenable; - - /** - * Remove a password from storage. - * @param key The key the password was stored under. - */ - export function deletePassword(key: string): Thenable; - - /** - * Fires when a password is set or deleted. - */ - export const onDidChangePassword: Event; } //#endregion @@ -2366,4 +2341,35 @@ declare module 'vscode' { } //#endregion + + + export interface SecretState { + /** + * Retrieve a secret that was stored with key. Returns undefined if there + * is no password matching that key. + * @param key The key the password was stored under. + */ + get(key: string): Thenable; + + /** + * Store a secret under a given key. + * @param key The key to store the password under + * @param value The password + */ + set(key: string, value: string): Thenable; + + /** + * Remove a secret from storage. + * @param key The key the password was stored under. + */ + delete(key: string): Thenable; + + /** + * Fires when a secret is set or deleted. + */ + onDidChangePassword: Event; + } + export interface ExtensionContext { + secretState: SecretState; + } } diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index a69945ffec0..e94dfa8a519 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -66,6 +66,7 @@ import './mainThreadTunnelService'; import './mainThreadAuthentication'; import './mainThreadTimeline'; import './mainThreadTesting'; +import './mainThreadSecretState'; import 'vs/workbench/api/common/apiCommands'; export class ExtensionPoints implements IWorkbenchContribution { diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index ffc57d866fa..98bb98d8cee 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -18,9 +18,6 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA import { fromNow } from 'vs/base/common/date'; import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { isWeb } from 'vs/base/common/platform'; -import { IEncryptionService } from 'vs/workbench/services/encryption/common/encryptionService'; -import { IProductService } from 'vs/platform/product/common/productService'; -import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials'; const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline', 'vscode.github-browser', 'ms-vscode.github-browser', 'github.codespaces']; @@ -225,10 +222,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu @INotificationService private readonly notificationService: INotificationService, @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, @IQuickInputService private readonly quickInputService: IQuickInputService, - @IExtensionService private readonly extensionService: IExtensionService, - @ICredentialsService private readonly credentialsService: ICredentialsService, - @IEncryptionService private readonly encryptionService: IEncryptionService, - @IProductService private readonly productService: IProductService + @IExtensionService private readonly extensionService: IExtensionService ) { super(); this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication); @@ -250,10 +244,6 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu this._register(this.authenticationService.onDidChangeDeclaredProviders(e => { this._proxy.$setProviders(e); })); - - this._register(this.credentialsService.onDidChangePassword(_ => { - this._proxy.$onDidChangePassword(); - })); } $getProviderIds(): Promise { @@ -466,46 +456,4 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu this.storageService.store(`${extensionName}-${providerId}`, sessionId, StorageScope.GLOBAL, StorageTarget.MACHINE); addAccountUsage(this.storageService, providerId, accountName, extensionId, extensionName); } - - private getFullKey(extensionId: string): string { - return `${this.productService.urlProtocol}${extensionId}`; - } - - async $getPassword(extensionId: string, key: string): Promise { - const fullKey = this.getFullKey(extensionId); - const password = await this.credentialsService.getPassword(fullKey, key); - const decrypted = password && await this.encryptionService.decrypt(password); - - if (decrypted) { - try { - const value = JSON.parse(decrypted); - if (value.extensionId === extensionId) { - return value.content; - } - } catch (_) { - throw new Error('Cannot get password'); - } - } - - return undefined; - } - - async $setPassword(extensionId: string, key: string, value: string): Promise { - const fullKey = this.getFullKey(extensionId); - const toEncrypt = JSON.stringify({ - extensionId, - content: value - }); - const encrypted = await this.encryptionService.encrypt(toEncrypt); - return this.credentialsService.setPassword(fullKey, key, encrypted); - } - - async $deletePassword(extensionId: string, key: string): Promise { - try { - const fullKey = this.getFullKey(extensionId); - await this.credentialsService.deletePassword(fullKey, key); - } catch (_) { - throw new Error('Cannot delete password'); - } - } } diff --git a/src/vs/workbench/api/browser/mainThreadSecretState.ts b/src/vs/workbench/api/browser/mainThreadSecretState.ts new file mode 100644 index 00000000000..92805a0a12a --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadSecretState.ts @@ -0,0 +1,72 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IProductService } from 'vs/platform/product/common/productService'; +import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; +import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials'; +import { IEncryptionService } from 'vs/workbench/services/encryption/common/encryptionService'; +import { ExtHostContext, ExtHostSecretStateShape, IExtHostContext, MainContext, MainThreadSecretStateShape } from '../common/extHost.protocol'; + +@extHostNamedCustomer(MainContext.MainThreadSecretState) +export class MainThreadSecretState extends Disposable implements MainThreadSecretStateShape { + private readonly _proxy: ExtHostSecretStateShape; + + constructor( + extHostContext: IExtHostContext, + @ICredentialsService private readonly credentialsService: ICredentialsService, + @IEncryptionService private readonly encryptionService: IEncryptionService, + @IProductService private readonly productService: IProductService + ) { + super(); + this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSecretState); + + this._register(this.credentialsService.onDidChangePassword(_ => { + this._proxy.$onDidChangePassword(); + })); + } + + private getFullKey(extensionId: string): string { + return `${this.productService.urlProtocol}${extensionId}`; + } + + async $getPassword(extensionId: string, key: string): Promise { + const fullKey = this.getFullKey(extensionId); + const password = await this.credentialsService.getPassword(fullKey, key); + const decrypted = password && await this.encryptionService.decrypt(password); + + if (decrypted) { + try { + const value = JSON.parse(decrypted); + if (value.extensionId === extensionId) { + return value.content; + } + } catch (_) { + throw new Error('Cannot get password'); + } + } + + return undefined; + } + + async $setPassword(extensionId: string, key: string, value: string): Promise { + const fullKey = this.getFullKey(extensionId); + const toEncrypt = JSON.stringify({ + extensionId, + content: value + }); + const encrypted = await this.encryptionService.encrypt(toEncrypt); + return this.credentialsService.setPassword(fullKey, key, encrypted); + } + + async $deletePassword(extensionId: string, key: string): Promise { + try { + const fullKey = this.getFullKey(extensionId); + await this.credentialsService.deletePassword(fullKey, key); + } catch (_) { + throw new Error('Cannot delete password'); + } + } +} diff --git a/src/vs/workbench/api/common/exHostSecretState.ts b/src/vs/workbench/api/common/exHostSecretState.ts new file mode 100644 index 00000000000..35b5d57a61f --- /dev/null +++ b/src/vs/workbench/api/common/exHostSecretState.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ExtHostSecretStateShape, MainContext, MainThreadSecretStateShape } from 'vs/workbench/api/common/extHost.protocol'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export class ExtHostSecretState implements ExtHostSecretStateShape { + private _proxy: MainThreadSecretStateShape; + private _onDidChangePassword = new Emitter(); + readonly onDidChangePassword: Event = this._onDidChangePassword.event; + + constructor(mainContext: IExtHostRpcService) { + this._proxy = mainContext.getProxy(MainContext.MainThreadSecretState); + } + + async $onDidChangePassword(): Promise { + this._onDidChangePassword.fire(); + } + + get(extensionId: string, key: string): Promise { + return this._proxy.$getPassword(extensionId, key); + } + + set(extensionId: string, key: string, value: string): Promise { + return this._proxy.$setPassword(extensionId, key, value); + } + + delete(extensionId: string, key: string): Promise { + return this._proxy.$deletePassword(extensionId, key); + } +} + +export interface IExtHostSecretState extends ExtHostSecretState { } +export const IExtHostSecretState = createDecorator('IExtHostSecretState'); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 46f8891dc6b..4a98ebbfd57 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -83,6 +83,7 @@ import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits'; import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo'; import { ExtHostTesting } from 'vs/workbench/api/common/extHostTesting'; import { ExtHostUriOpeners } from 'vs/workbench/api/common/extHostUriOpener'; +import { IExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState'; export interface IExtensionApiFactory { (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; @@ -108,6 +109,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostTunnelService = accessor.get(IExtHostTunnelService); const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService); const extHostWindow = accessor.get(IExtHostWindow); + const extHostSecretState = accessor.get(IExtHostSecretState); // register addressable instances rpcProtocol.set(ExtHostContext.ExtHostFileSystemInfo, extHostFileSystemInfo); @@ -118,6 +120,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage); rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService); rpcProtocol.set(ExtHostContext.ExtHostWindow, extHostWindow); + rpcProtocol.set(ExtHostContext.ExtHostSecretState, extHostSecretState); // automatically create and register addressable instances const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations)); @@ -226,22 +229,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I logout(providerId: string, sessionId: string): Thenable { checkProposedApiEnabled(extension); return extHostAuthentication.logout(providerId, sessionId); - }, - getPassword(key: string): Thenable { - checkProposedApiEnabled(extension); - return extHostAuthentication.getPassword(extension, key); - }, - setPassword(key: string, value: string): Thenable { - checkProposedApiEnabled(extension); - return extHostAuthentication.setPassword(extension, key, value); - }, - deletePassword(key: string): Thenable { - checkProposedApiEnabled(extension); - return extHostAuthentication.deletePassword(extension, key); - }, - get onDidChangePassword(): Event { - checkProposedApiEnabled(extension); - return extHostAuthentication.onDidChangePassword; } }; diff --git a/src/vs/workbench/api/common/extHost.common.services.ts b/src/vs/workbench/api/common/extHost.common.services.ts index 6c1a02f447c..b1fe830b257 100644 --- a/src/vs/workbench/api/common/extHost.common.services.ts +++ b/src/vs/workbench/api/common/extHost.common.services.ts @@ -21,6 +21,7 @@ import { IExtHostApiDeprecationService, ExtHostApiDeprecationService, } from 'vs import { IExtHostWindow, ExtHostWindow } from 'vs/workbench/api/common/extHostWindow'; import { IExtHostConsumerFileSystem, ExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer'; import { IExtHostFileSystemInfo, ExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo'; +import { IExtHostSecretState, ExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState'; registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths); registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService); @@ -39,3 +40,4 @@ registerSingleton(IExtHostTerminalService, WorkerExtHostTerminalService); registerSingleton(IExtHostTunnelService, ExtHostTunnelService); registerSingleton(IExtHostWindow, ExtHostWindow); registerSingleton(IExtHostWorkspace, ExtHostWorkspace); +registerSingleton(IExtHostSecretState, ExtHostSecretState); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 23b876d8e03..106324b08ad 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -176,7 +176,9 @@ export interface MainThreadAuthenticationShape extends IDisposable { $getSessions(providerId: string): Promise>; $login(providerId: string, scopes: string[]): Promise; $logout(providerId: string, sessionId: string): Promise; +} +export interface MainThreadSecretStateShape extends IDisposable { $getPassword(extensionId: string, key: string): Promise; $setPassword(extensionId: string, key: string, value: string): Promise; $deletePassword(extensionId: string, key: string): Promise; @@ -1105,6 +1107,9 @@ export interface ExtHostAuthenticationShape { $onDidChangeAuthenticationSessions(id: string, label: string, event: modes.AuthenticationSessionsChangeEvent): Promise; $onDidChangeAuthenticationProviders(added: modes.AuthenticationProviderInformation[], removed: modes.AuthenticationProviderInformation[]): Promise; $setProviders(providers: modes.AuthenticationProviderInformation[]): Promise; +} + +export interface ExtHostSecretStateShape { $onDidChangePassword(): Promise; } @@ -1827,6 +1832,7 @@ export const MainContext = { MainThreadProgress: createMainId('MainThreadProgress'), MainThreadQuickOpen: createMainId('MainThreadQuickOpen'), MainThreadStatusBar: createMainId('MainThreadStatusBar'), + MainThreadSecretState: createMainId('MainThreadSecretState'), MainThreadStorage: createMainId('MainThreadStorage'), MainThreadTelemetry: createMainId('MainThreadTelemetry'), MainThreadTerminalService: createMainId('MainThreadTerminalService'), @@ -1883,6 +1889,7 @@ export const ExtHostContext = { ExtHostEditorInsets: createExtId('ExtHostEditorInsets'), ExtHostProgress: createMainId('ExtHostProgress'), ExtHostComments: createMainId('ExtHostComments'), + ExtHostSecretState: createMainId('ExtHostSecretState'), ExtHostStorage: createMainId('ExtHostStorage'), ExtHostUrls: createExtId('ExtHostUrls'), ExtHostUriOpeners: createExtId('ExtHostUriOpeners'), diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 27988418295..3d23cbcde3f 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -29,9 +29,6 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { private _onDidChangeSessions = new Emitter(); readonly onDidChangeSessions: Event = this._onDidChangeSessions.event; - private _onDidChangePassword = new Emitter(); - readonly onDidChangePassword: Event = this._onDidChangePassword.event; - private _inFlightRequests = new Map(); constructor(mainContext: IMainContext) { @@ -237,23 +234,4 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._onDidChangeAuthenticationProviders.fire({ added, removed }); return Promise.resolve(); } - - async $onDidChangePassword(): Promise { - this._onDidChangePassword.fire(); - } - - getPassword(requestingExtension: IExtensionDescription, key: string): Promise { - const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); - return this._proxy.$getPassword(extensionId, key); - } - - setPassword(requestingExtension: IExtensionDescription, key: string, value: string): Promise { - const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); - return this._proxy.$setPassword(extensionId, key, value); - } - - deletePassword(requestingExtension: IExtensionDescription, key: string): Promise { - const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); - return this._proxy.$deletePassword(extensionId, key); - } } diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 76c554108e0..eca1c541dcb 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -36,6 +36,8 @@ import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelServ import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; import { Emitter, Event } from 'vs/base/common/event'; import { IExtensionActivationHost, checkActivateWorkspaceContainsExtension } from 'vs/workbench/api/common/shared/workspaceContains'; +import { ExtHostSecretState, IExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState'; +import { ExtensionSecrets } from 'vs/workbench/api/common/extHostSecrets'; interface ITestRunner { /** Old test runner API, as exported from `vscode/lib/testrunner` */ @@ -95,6 +97,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme private readonly _readyToRunExtensions: Barrier; protected readonly _registry: ExtensionDescriptionRegistry; private readonly _storage: ExtHostStorage; + private readonly _secretState: ExtHostSecretState; private readonly _storagePath: IExtensionStoragePaths; private readonly _activator: ExtensionsActivator; private _extensionPathIndex: Promise> | null; @@ -116,7 +119,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme @IExtHostInitDataService initData: IExtHostInitDataService, @IExtensionStoragePaths storagePath: IExtensionStoragePaths, @IExtHostTunnelService extHostTunnelService: IExtHostTunnelService, - @IExtHostTerminalService extHostTerminalService: IExtHostTerminalService + @IExtHostTerminalService extHostTerminalService: IExtHostTerminalService, ) { super(); this._hostUtils = hostUtils; @@ -139,10 +142,12 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme this._readyToRunExtensions = new Barrier(); this._registry = new ExtensionDescriptionRegistry(this._initData.extensions); this._storage = new ExtHostStorage(this._extHostContext); + this._secretState = new ExtHostSecretState(this._extHostContext); this._storagePath = storagePath; this._instaService = instaService.createChild(new ServiceCollection( - [IExtHostStorage, this._storage] + [IExtHostStorage, this._storage], + [IExtHostSecretState, this._secretState] )); const hostExtensions = new Set(); @@ -379,6 +384,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme const globalState = new ExtensionGlobalMemento(extensionDescription, this._storage); const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage); + const secretState = new ExtensionSecrets(extensionDescription, this._secretState); const extensionMode = extensionDescription.isUnderDevelopment ? (this._initData.environment.extensionTestsLocationURI ? ExtensionMode.Test : ExtensionMode.Development) : ExtensionMode.Production; @@ -394,6 +400,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme return Object.freeze({ globalState, workspaceState, + secretState, subscriptions: [], get extensionUri() { return extensionDescription.extensionLocation; }, get extensionPath() { return extensionDescription.extensionLocation.fsPath; }, diff --git a/src/vs/workbench/api/common/extHostSecrets.ts b/src/vs/workbench/api/common/extHostSecrets.ts new file mode 100644 index 00000000000..0bac101e4bf --- /dev/null +++ b/src/vs/workbench/api/common/extHostSecrets.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type * as vscode from 'vscode'; + +import { ExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { Emitter, Event } from 'vs/base/common/event'; + +export class ExtensionSecrets implements vscode.SecretState { + + protected readonly _id: string; + protected readonly _secretState: ExtHostSecretState; + + private _onDidChangePassword = new Emitter(); + readonly onDidChangePassword: Event = this._onDidChangePassword.event; + + + constructor(extensionDescription: IExtensionDescription, secretState: ExtHostSecretState) { + this._id = ExtensionIdentifier.toKey(extensionDescription.identifier); + this._secretState = secretState; + + this._secretState.onDidChangePassword(_ => this._onDidChangePassword.fire()); + } + + get(key: string): Promise { + return this._secretState.get(this._id, key); + } + + set(key: string, value: string): Promise { + return this._secretState.set(this._id, key, value); + } + + delete(key: string): Promise { + return this._secretState.delete(this._id, key); + } +} From 1bb2ae0e365ea364fb2be8164b914477de72b5c9 Mon Sep 17 00:00:00 2001 From: joan xie Date: Tue, 5 Jan 2021 14:05:23 +0800 Subject: [PATCH 1512/1837] Allow ResourceCommandResolver.getRightResource() to return undefined (#113364) --- extensions/git/src/repository.ts | 10 +++++----- extensions/git/src/test/smoke.test.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 87f24395d6d..eeb90b6f6e8 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -79,7 +79,7 @@ export class Resource implements SourceControlResourceState { return this.resources[0]; } - get rightUri(): Uri { + get rightUri(): Uri | undefined { return this.resources[1]; } @@ -88,7 +88,7 @@ export class Resource implements SourceControlResourceState { } @memoize - private get resources(): [Uri | undefined, Uri] { + private get resources(): [Uri | undefined, Uri | undefined] { return this._commandResolver.getResources(this); } @@ -613,7 +613,7 @@ class ResourceCommandResolver { } } - getResources(resource: Resource): [Uri | undefined, Uri] { + getResources(resource: Resource): [Uri | undefined, Uri | undefined] { for (const submodule of this.repository.submodules) { if (path.join(this.repository.root, submodule.path) === resource.resourceUri.fsPath) { return [undefined, toGitUri(resource.resourceUri, resource.resourceGroupType === ResourceGroupType.Index ? 'index' : 'wt', { submoduleOf: this.repository.root })]; @@ -641,7 +641,7 @@ class ResourceCommandResolver { return undefined; } - private getRightResource(resource: Resource): Uri { + private getRightResource(resource: Resource): Uri | undefined { switch (resource.type) { case Status.INDEX_MODIFIED: case Status.INDEX_ADDED: @@ -677,7 +677,7 @@ class ResourceCommandResolver { return resource.resourceUri; } - throw new Error('Should never happen'); + return undefined; } private getTitle(resource: Resource): string { diff --git a/extensions/git/src/test/smoke.test.ts b/extensions/git/src/test/smoke.test.ts index 9e0933776a3..c8c761bc79b 100644 --- a/extensions/git/src/test/smoke.test.ts +++ b/extensions/git/src/test/smoke.test.ts @@ -124,4 +124,31 @@ suite('git smoke test', function () { assert.equal(repository.state.workingTreeChanges.length, 0); assert.equal(repository.state.indexChanges.length, 0); }); + + test('rename/delete conflict', async function () { + cp.execSync('git branch test', { cwd }); + cp.execSync('git checkout test', { cwd }); + + fs.unlinkSync(file('app.js')); + cp.execSync('git add .', { cwd }); + + await repository.commit('commit on test'); + cp.execSync('git checkout master', { cwd }); + + fs.renameSync(file('app.js'), file('rename.js')); + cp.execSync('git add .', { cwd }); + await repository.commit('commit on master'); + + try { + cp.execSync('git merge test', { cwd }); + } catch (e) { } + + setTimeout(() => { + commands.executeCommand('workbench.scm.focus'); + }, 2e3); + + await new Promise(resolve => { + setTimeout(resolve, 5e3); + }); + }); }); From 998e5e2ea676c1fb937f72048edea5ec85b433a6 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 4 Jan 2021 22:19:55 -0800 Subject: [PATCH 1513/1837] onDidChangePassword -> onDidChange in secrets API --- extensions/github-authentication/src/github.ts | 2 +- extensions/microsoft-authentication/src/AADHelper.ts | 2 +- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHostSecrets.ts | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index 6b97805b199..f065556bd26 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -40,7 +40,7 @@ export class GitHubAuthenticationProvider { // Ignore, network request failed } - context.subscriptions.push(context.secretState.onDidChangePassword(() => this.checkForUpdates())); + context.subscriptions.push(context.secretState.onDidChange(() => this.checkForUpdates())); } private async verifySessions(): Promise { diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts index 62c53de6c28..3bfe6876cd8 100644 --- a/extensions/microsoft-authentication/src/AADHelper.ts +++ b/extensions/microsoft-authentication/src/AADHelper.ts @@ -149,7 +149,7 @@ export class AzureActiveDirectoryService { } } - this._disposables.push(this._context.secretState.onDidChangePassword(() => this.checkForUpdates)); + this._disposables.push(this._context.secretState.onDidChange(() => this.checkForUpdates)); } private parseStoredData(data: string): IStoredSession[] { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 092885bb0d6..5f0c5c685a7 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2367,7 +2367,7 @@ declare module 'vscode' { /** * Fires when a secret is set or deleted. */ - onDidChangePassword: Event; + onDidChange: Event; } export interface ExtensionContext { secretState: SecretState; diff --git a/src/vs/workbench/api/common/extHostSecrets.ts b/src/vs/workbench/api/common/extHostSecrets.ts index 0bac101e4bf..38f49e07aff 100644 --- a/src/vs/workbench/api/common/extHostSecrets.ts +++ b/src/vs/workbench/api/common/extHostSecrets.ts @@ -14,15 +14,15 @@ export class ExtensionSecrets implements vscode.SecretState { protected readonly _id: string; protected readonly _secretState: ExtHostSecretState; - private _onDidChangePassword = new Emitter(); - readonly onDidChangePassword: Event = this._onDidChangePassword.event; + private _onDidChange = new Emitter(); + readonly onDidChange: Event = this._onDidChange.event; constructor(extensionDescription: IExtensionDescription, secretState: ExtHostSecretState) { this._id = ExtensionIdentifier.toKey(extensionDescription.identifier); this._secretState = secretState; - this._secretState.onDidChangePassword(_ => this._onDidChangePassword.fire()); + this._secretState.onDidChangePassword(_ => this._onDidChange.fire()); } get(key: string): Promise { From bdbd644c27dfc041eebfd2bbb009059258f7a9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 09:40:42 +0100 Subject: [PATCH 1514/1837] parallelize hygiene --- build/azure-pipelines/product-build.yml | 6 -- build/azure-pipelines/product-compile.yml | 12 ++- build/azure-pipelines/product-hygiene.yml | 107 ---------------------- package.json | 1 + 4 files changed, 8 insertions(+), 118 deletions(-) delete mode 100644 build/azure-pipelines/product-hygiene.yml diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index a93b7897e4c..84afbc4b0bf 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -35,12 +35,6 @@ stages: VSCODE_ARCH: x64 steps: - template: product-compile.yml - - job: Hygiene - pool: tryout - variables: - VSCODE_ARCH: x64 - steps: - - template: product-hygiene.yml - stage: Windows dependsOn: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index ba5e76ec5df..2737ea1d1f7 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -87,15 +87,17 @@ steps: - script: | set -e - yarn npm-run-all -lp compile-build compile-extensions-build + yarn npm-run-all -lp hygiene monaco-compile-check valid-layers-check compile-build compile-extensions-build yarn npm-run-all -lp minify-vscode minify-vscode-reh minify-vscode-reh-web - displayName: Compile + displayName: Hygiene & Compile - script: | set -e - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ - node build/azure-pipelines/upload-sourcemaps - displayName: Upload sourcemaps + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" node build/azure-pipelines/upload-sourcemaps & + ./build/azure-pipelines/common/extract-telemetry.sh & + AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" ./build/azure-pipelines/common/publish-webview.sh & + wait + displayName: Publish compilation assets condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml deleted file mode 100644 index 477336cd536..00000000000 --- a/build/azure-pipelines/product-hygiene.yml +++ /dev/null @@ -1,107 +0,0 @@ -steps: - - task: NodeTool@0 - inputs: - versionSpec: "12.x" - - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" - - - task: AzureKeyVault@1 - displayName: "Azure Key Vault: Get Secrets" - inputs: - azureSubscription: "vscode-builds-subscription" - KeyVaultName: vscode - - - script: | - set -e - cat << EOF > ~/.netrc - machine github.com - login vscode - password $(github-distro-mixin-password) - EOF - - git config user.email "vscode@microsoft.com" - git config user.name "VSCode" - displayName: Prepare tooling - - - script: | - set -e - git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") - displayName: Merge distro - - - script: | - npx https://aka.ms/enablesecurefeed standAlone - displayName: Switch to Terrapin packages - timeoutInMinutes: 5 - condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) - - - script: | - mkdir -p .build - node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash - displayName: Prepare yarn cache flags - - # using `genericNodeModules` instead of `nodeModules` here to avoid sharing the cache with builds running inside containers - - task: Cache@2 - inputs: - key: 'genericNodeModules | $(Agent.OS) | .build/yarnlockhash' - path: .build/node_modules_cache - cacheHitVar: NODE_MODULES_RESTORED - displayName: Cache node_modules archive - - - script: | - set -e - tar -xzf .build/node_modules_cache/cache.tgz - condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) - displayName: Extract node_modules archive - - - script: | - set -e - for i in {1..3}; do # try 3 times, for Terrapin - yarn --frozen-lockfile && break - if [ $i -eq 3 ]; then - echo "Yarn failed too many times" >&2 - exit 1 - fi - echo "Yarn failed $i, trying again..." - done - env: - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - displayName: Install dependencies - condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) - - - script: | - set -e - node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt - mkdir -p .build/node_modules_cache - tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt - condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) - displayName: Create node_modules archive - - # Mixin must run before optimize, because the CSS loader will inline small SVGs - - script: | - set -e - node build/azure-pipelines/mixin - displayName: Mix in quality - - - script: | - set -e - yarn gulp hygiene - yarn monaco-compile-check - yarn valid-layers-check - displayName: Run hygiene, monaco compile & valid layers checks - condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - - - script: | - set - - ./build/azure-pipelines/common/extract-telemetry.sh - displayName: Extract Telemetry - condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - - - script: | - set -e - AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ - ./build/azure-pipelines/common/publish-webview.sh - displayName: Publish Webview - condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) diff --git a/package.json b/package.json index 56703cd3dc8..443db8e6122 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "watch-extensionsd": "deemon yarn watch-extensions", "kill-watch-extensionsd": "deemon --kill yarn watch-extensions", "mocha": "mocha test/unit/node/all.js --delay", + "hygiene": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js hygiene", "precommit": "node build/hygiene.js", "gulp": "node --max_old_space_size=8192 ./node_modules/gulp/bin/gulp.js", "electron": "node build/lib/electron", From fe795313d8ebbb83b0ae80a5366f4d834bf0b411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 10:08:46 +0100 Subject: [PATCH 1515/1837] Revert "parallelize hygiene" This reverts commit bdbd644c27dfc041eebfd2bbb009059258f7a9c7. --- build/azure-pipelines/product-build.yml | 6 ++ build/azure-pipelines/product-compile.yml | 12 +-- build/azure-pipelines/product-hygiene.yml | 107 ++++++++++++++++++++++ package.json | 1 - 4 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 build/azure-pipelines/product-hygiene.yml diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 84afbc4b0bf..a93b7897e4c 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -35,6 +35,12 @@ stages: VSCODE_ARCH: x64 steps: - template: product-compile.yml + - job: Hygiene + pool: tryout + variables: + VSCODE_ARCH: x64 + steps: + - template: product-hygiene.yml - stage: Windows dependsOn: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 2737ea1d1f7..ba5e76ec5df 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -87,17 +87,15 @@ steps: - script: | set -e - yarn npm-run-all -lp hygiene monaco-compile-check valid-layers-check compile-build compile-extensions-build + yarn npm-run-all -lp compile-build compile-extensions-build yarn npm-run-all -lp minify-vscode minify-vscode-reh minify-vscode-reh-web - displayName: Hygiene & Compile + displayName: Compile - script: | set -e - AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" node build/azure-pipelines/upload-sourcemaps & - ./build/azure-pipelines/common/extract-telemetry.sh & - AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" ./build/azure-pipelines/common/publish-webview.sh & - wait - displayName: Publish compilation assets + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + node build/azure-pipelines/upload-sourcemaps + displayName: Upload sourcemaps condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) - script: | diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml new file mode 100644 index 00000000000..477336cd536 --- /dev/null +++ b/build/azure-pipelines/product-hygiene.yml @@ -0,0 +1,107 @@ +steps: + - task: NodeTool@0 + inputs: + versionSpec: "12.x" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" + + - task: AzureKeyVault@1 + displayName: "Azure Key Vault: Get Secrets" + inputs: + azureSubscription: "vscode-builds-subscription" + KeyVaultName: vscode + + - script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + + - script: | + set -e + git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") + displayName: Merge distro + + - script: | + npx https://aka.ms/enablesecurefeed standAlone + displayName: Switch to Terrapin packages + timeoutInMinutes: 5 + condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true')) + + - script: | + mkdir -p .build + node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash + displayName: Prepare yarn cache flags + + # using `genericNodeModules` instead of `nodeModules` here to avoid sharing the cache with builds running inside containers + - task: Cache@2 + inputs: + key: 'genericNodeModules | $(Agent.OS) | .build/yarnlockhash' + path: .build/node_modules_cache + cacheHitVar: NODE_MODULES_RESTORED + displayName: Cache node_modules archive + + - script: | + set -e + tar -xzf .build/node_modules_cache/cache.tgz + condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) + displayName: Extract node_modules archive + + - script: | + set -e + for i in {1..3}; do # try 3 times, for Terrapin + yarn --frozen-lockfile && break + if [ $i -eq 3 ]; then + echo "Yarn failed too many times" >&2 + exit 1 + fi + echo "Yarn failed $i, trying again..." + done + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + displayName: Install dependencies + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + + - script: | + set -e + node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt + mkdir -p .build/node_modules_cache + tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + displayName: Create node_modules archive + + # Mixin must run before optimize, because the CSS loader will inline small SVGs + - script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + + - script: | + set -e + yarn gulp hygiene + yarn monaco-compile-check + yarn valid-layers-check + displayName: Run hygiene, monaco compile & valid layers checks + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + + - script: | + set - + ./build/azure-pipelines/common/extract-telemetry.sh + displayName: Extract Telemetry + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) + + - script: | + set -e + AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \ + ./build/azure-pipelines/common/publish-webview.sh + displayName: Publish Webview + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) diff --git a/package.json b/package.json index 443db8e6122..56703cd3dc8 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "watch-extensionsd": "deemon yarn watch-extensions", "kill-watch-extensionsd": "deemon --kill yarn watch-extensions", "mocha": "mocha test/unit/node/all.js --delay", - "hygiene": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js hygiene", "precommit": "node build/hygiene.js", "gulp": "node --max_old_space_size=8192 ./node_modules/gulp/bin/gulp.js", "electron": "node build/lib/electron", From 6659f8dfe584ffaa9a3da3f5ff57f657da8d4967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 10:16:37 +0100 Subject: [PATCH 1516/1837] use compile agent pool --- build/azure-pipelines/product-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index a93b7897e4c..6a7b3dc4ce2 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -30,13 +30,13 @@ stages: - stage: Compile jobs: - job: Compile - pool: tryout + pool: compile variables: VSCODE_ARCH: x64 steps: - template: product-compile.yml - job: Hygiene - pool: tryout + pool: compile variables: VSCODE_ARCH: x64 steps: From c4ea0b55906a3ebdedc39f4e921a109181e016d5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Jan 2021 10:36:10 +0100 Subject: [PATCH 1517/1837] fix some spelling mistakes --- src/vs/base/browser/dom.ts | 2 +- src/vs/base/common/fuzzyScorer.ts | 2 +- src/vs/base/parts/sandbox/electron-sandbox/globals.ts | 4 ++-- src/vs/code/electron-main/app.ts | 2 +- src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts | 2 +- src/vs/workbench/browser/parts/editor/tabsTitleControl.ts | 2 +- src/vs/workbench/browser/workbench.contribution.ts | 2 +- src/vs/workbench/common/editor.ts | 2 +- src/vs/workbench/services/editor/browser/codeEditorService.ts | 2 +- src/vs/workbench/services/editor/common/editorService.ts | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 08822d55fc7..e5afa201a7f 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1301,7 +1301,7 @@ export interface IDetectedFullscreen { mode: DetectedFullscreenMode; /** - * Wether we know for sure that we are in fullscreen mode or + * Whether we know for sure that we are in fullscreen mode or * it is a guess. */ guess: boolean; diff --git a/src/vs/base/common/fuzzyScorer.ts b/src/vs/base/common/fuzzyScorer.ts index 11fc4bc0ed3..71414ea9350 100644 --- a/src/vs/base/common/fuzzyScorer.ts +++ b/src/vs/base/common/fuzzyScorer.ts @@ -389,7 +389,7 @@ export function scoreItemFuzzy(item: T, query: IPreparedQuery, fuzzy: boolean // - description (if provided) // - query (normalized) // - number of query pieces (i.e. 'hello world' and 'helloworld' are different) - // - wether fuzzy matching is enabled or not + // - whether fuzzy matching is enabled or not let cacheHash: string; if (description) { cacheHash = `${label}${description}${query.normalized}${Array.isArray(query.values) ? query.values.length : ''}${fuzzy}`; diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 69f3a2a8637..c548c2045ea 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -48,7 +48,7 @@ export interface ISandboxNodeProcess extends INodeProcess { * The order of overwrites is `process.env` < `shellEnv` < `userEnv`. * * It is critical that every process awaits this method early on startup to get the right - * set of environment in `process.env`. + * set of environment in `process.env`. */ resolveEnv(userEnv: IProcessEnvironment): Promise; @@ -76,7 +76,7 @@ export interface ISandboxNodeProcess extends INodeProcess { export interface ISandboxContext { /** - * Wether the renderer runs with `sandbox` enabled or not. + * Whether the renderer runs with `sandbox` enabled or not. */ sandbox: boolean; } diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index b2b9ce108eb..f3a37f0faff 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -303,7 +303,7 @@ export class CodeApplication extends Disposable { // Prefer to use the args and env from the target window // when resolving the shell env. It is possible that // a first window was opened from the UI but a second - // from the CLI and that has implications for wether to + // from the CLI and that has implications for whether to // resolve the shell environment or not. let args: NativeParsedArgs; let env: NodeJS.ProcessEnv; diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 2760fd20c3a..f04002270b1 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -51,7 +51,7 @@ export class NoTabsTitleControl extends TitleControl { // Breadcrumbs this.createBreadcrumbsControl(labelContainer, { showFileIcons: false, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: () => Color.transparent }); titleContainer.classList.toggle('breadcrumbs', Boolean(this.breadcrumbsControl)); - this._register({ dispose: () => titleContainer.classList.remove('breadcrumbs') }); // import to remove because the container is a shared dom node + this._register({ dispose: () => titleContainer.classList.remove('breadcrumbs') }); // important to remove because the container is a shared dom node // Right Actions Container const actionsContainer = document.createElement('div'); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 776ca5bfd28..3da5d6694d9 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1403,7 +1403,7 @@ export class TabsTitleControl extends TitleControl { } // Figure out if active tab is positioned static which has an - // impact on wether to reveal the tab or not later + // impact on whether to reveal the tab or not later let activeTabPositionStatic = this.accessor.partOptions.pinnedTabSizing !== 'normal' && this.group.isSticky(activeIndex); // Special case: we have sticky tabs but the available space for showing tabs diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index b47ccfbe06a..315c12122fc 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -35,7 +35,7 @@ import { isStandalone } from 'vs/base/browser/browser'; }, 'workbench.editor.wrapTabs': { 'type': 'boolean', - 'description': nls.localize('wrapTabs', "Controls whether tabs should be wrapped over multiple lines when exceeding available space or wether a scrollbar should appear instead."), + 'markdownDescription': nls.localize('wrapTabs', "Controls whether tabs should be wrapped over multiple lines when exceeding available space or whether a scrollbar should appear instead. This value is ignored when `#workbench.editor.showTabs#` is disabled."), 'default': false }, 'workbench.editor.scrollToSwitchTabs': { diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2e567ddf9ce..30c8ccd2454 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1215,7 +1215,7 @@ export interface IEditorOpenContext { * An editor is new for a group if it was not part of the group before and * otherwise was already opened in the group and just became the active editor. * - * This hint can e.g. be used to decide wether to restore view state or not. + * This hint can e.g. be used to decide whether to restore view state or not. */ newInGroup?: boolean; } diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index 770b1b34bf3..dfbc193a4cb 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -73,7 +73,7 @@ export class CodeEditorService extends CodeEditorServiceImpl { private async doOpenCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise { // Special case: we want to detect the request to open an editor that - // is different from the current one to decide wether the current editor + // is different from the current one to decide whether the current editor // should be pinned or not. This ensures that the source of a navigation // is not being replaced by the target. An example is "Goto definition" // that otherwise would replace the editor everytime the user navigates. diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 73542a7a14d..ea2991e3f1b 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -175,7 +175,7 @@ export interface IEditorService { * identifier. * * @param order the order of the editors to use - * @param options wether to exclude sticky editors or not + * @param options whether to exclude sticky editors or not */ getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): ReadonlyArray; From f64cf2922f954d0d393244164afddec77b85819e Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 5 Jan 2021 10:38:32 +0100 Subject: [PATCH 1518/1837] Fix remote explorer views getting changed across windows (#113237) Fixes #112200 --- src/vs/workbench/api/browser/viewsExtensionPoint.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index b785735c5a6..cfcebdf5266 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -501,7 +501,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution { originalContainerId: entry.key, group: item.group, remoteAuthority: item.remoteName || (item).remoteAuthority, // TODO@roblou - delete after remote extensions are updated - hideByDefault: initialVisibility === InitialVisibility.Hidden + hideByDefault: initialVisibility === InitialVisibility.Hidden, + workspace: viewContainer?.id === REMOTE ? true : undefined }; From b5ccd30c95dbe8f6119382a1cd15da05449a76f6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Jan 2021 10:41:07 +0100 Subject: [PATCH 1519/1837] css - less generic rules to prevent leaks --- .../parts/editor/media/notabstitlecontrol.css | 12 +++---- .../parts/editor/media/tabstitlecontrol.css | 36 +++++++++---------- .../parts/editor/media/titlecontrol.css | 8 +++-- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css index 669aa107151..4daa4e56f70 100644 --- a/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/notabstitlecontrol.css @@ -14,7 +14,7 @@ flex: auto; } -.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label { +.monaco-workbench .part.editor > .content .editor-group-container > .title > .label-container > .title-label { line-height: 35px; overflow: hidden; text-overflow: ellipsis; @@ -26,10 +26,6 @@ flex: none; /* helps to show decorations right next to the label and not at the end */ } -.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before { - height: 35px; /* tweak the icon size of the editor labels when icons are enabled */ -} - /* Breadcrumbs */ .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label { @@ -86,9 +82,9 @@ display: none; /* hides chevrons when no tabs visible */ } -/* Title Actions */ +/* Editor Actions Toolbar (via title actions) */ -.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions { +.monaco-workbench .part.editor > .content .editor-group-container > .title > .title-actions { display: flex; flex: initial; opacity: 0.5; @@ -96,6 +92,6 @@ height: 35px; } -.monaco-workbench .part.editor > .content .editor-group-container.active > .title .title-actions { +.monaco-workbench .part.editor > .content .editor-group-container.active > .title > .title-actions { opacity: 1; } diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index 7db09e0fca5..b4eab3a03fd 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -344,7 +344,7 @@ margin-right: 0.5em; } -/* No Tab Actions */ +/* Tab Actions: Off */ .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off { padding-right: 10px; /* give a little bit more room if tab actions is off */ @@ -367,23 +367,6 @@ pointer-events: none; /* don't allow tab actions to be clicked when running without tab actions */ } -/* Editor Actions */ - -.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions { - cursor: default; - flex: initial; - padding: 0 8px 0 4px; - height: 35px; -} - -.monaco-workbench .part.editor > .content .editor-group-container > .title > .tabs-and-actions-container.wrapping .editor-actions { - - /* When tabs are wrapped, position the editor actions at the end of the very last row */ - position: absolute; - bottom: 0; - right: 0; -} - /* Breadcrumbs */ .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control { @@ -426,3 +409,20 @@ .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child .codicon:last-child { display: none; /* hides chevrons when last item */ } + +/* Editor Actions Toolbar */ + +.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions { + cursor: default; + flex: initial; + padding: 0 8px 0 4px; + height: 35px; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .title > .tabs-and-actions-container.wrapping .editor-actions { + + /* When tabs are wrapped, position the editor actions at the end of the very last row */ + position: absolute; + bottom: 0; + right: 0; +} diff --git a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css index cdbc22f72ce..420f4031f34 100644 --- a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css @@ -26,6 +26,10 @@ cursor: pointer; } +.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before { + height: 35px; /* tweak the icon size of the editor labels when icons are enabled */ +} + .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .monaco-icon-label::after, .monaco-workbench .part.editor > .content .editor-group-container > .title.tabs .monaco-icon-label::after { padding-right: 0; /* by default the icon label has a padding right and this isn't wanted when not showing tabs and not showing breadcrumbs */ @@ -64,14 +68,12 @@ opacity: 0.4; } -/* Drag Cursor */ +/* Drag and Drop */ .monaco-workbench .part.editor > .content .editor-group-container > .title { cursor: grab; } -/* Drag and Drop Feedback */ - .monaco-editor-group-drag-image { display: inline-block; padding: 1px 7px; From 008f8dcdeeadfb018a23d956c4cbf72dad1069e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 11:01:52 +0100 Subject: [PATCH 1520/1837] missing compilation --- .../lib/eslint/vscode-dts-provider-naming.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/build/lib/eslint/vscode-dts-provider-naming.js b/build/lib/eslint/vscode-dts-provider-naming.js index 8098aa8df8b..924c26ecbb3 100644 --- a/build/lib/eslint/vscode-dts-provider-naming.js +++ b/build/lib/eslint/vscode-dts-provider-naming.js @@ -3,36 +3,36 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -let _a; +var _a; module.exports = new (_a = class ApiProviderNaming { - constructor() { - this.meta = { - messages: { - naming: 'A provider should only have functions like provideXYZ or resolveXYZ', - } - }; - } - create(context) { - const config = context.options[0]; - const allowed = new Set(config.allowed); - return { - ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node) => { - let _a; - const interfaceName = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent).id.name; - if (allowed.has(interfaceName)) { - // allowed - return; + constructor() { + this.meta = { + messages: { + naming: 'A provider should only have functions like provideXYZ or resolveXYZ', } - const methodName = node.key.name; - if (!ApiProviderNaming._providerFunctionNames.test(methodName)) { - context.report({ - node, - messageId: 'naming' - }); + }; + } + create(context) { + const config = context.options[0]; + const allowed = new Set(config.allowed); + return { + ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node) => { + var _a; + const interfaceName = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent).id.name; + if (allowed.has(interfaceName)) { + // allowed + return; + } + const methodName = node.key.name; + if (!ApiProviderNaming._providerFunctionNames.test(methodName)) { + context.report({ + node, + messageId: 'naming' + }); + } } - } - }; - } -}, + }; + } + }, _a._providerFunctionNames = /^(provide|resolve|prepare).+/, _a); From 174bfe9b528e31f60994a945c6772a069df1b84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 11:02:08 +0100 Subject: [PATCH 1521/1837] simplify gitignore --- .gitignore | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index b7f5b58c8ed..a60c7654906 100644 --- a/.gitignore +++ b/.gitignore @@ -5,26 +5,7 @@ Thumbs.db node_modules/ .build/ extensions/**/dist/ -out/ -out-build/ -out-editor/ -out-editor-src/ -out-editor-build/ -out-editor-esm/ -out-editor-esm-bundle/ -out-editor-min/ -out-monaco-editor-core/ -out-vscode/ -out-vscode-min/ -out-vscode-reh/ -out-vscode-reh-min/ -out-vscode-reh-pkg/ -out-vscode-reh-web/ -out-vscode-reh-web-min/ -out-vscode-reh-web-pkg/ -out-vscode-web/ -out-vscode-web-min/ -out-vscode-web-pkg/ +out*/ src/vs/server resources/server build/node_modules From c4aeb68a68afa467a6b86f4141bb1570cd8140bc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Jan 2021 11:13:13 +0100 Subject: [PATCH 1522/1837] debt - introduce and adopt flakySuite --- .../parts/storage/test/node/storage.test.ts | 15 ++---- src/vs/base/test/node/id.test.ts | 21 ++++----- src/vs/base/test/node/pfs/pfs.test.ts | 7 +-- src/vs/base/test/node/port.test.ts | 5 +- src/vs/base/test/node/testUtils.ts | 16 +++++++ .../electron-main/backupMainService.test.ts | 21 ++++----- .../electron-browser/diskFileService.test.ts | 9 +--- src/vs/platform/state/test/node/state.test.ts | 9 +--- .../storage/test/node/storageService.test.ts | 7 +-- .../electron-browser/backupRestorer.test.ts | 6 +-- .../electron-browser/backupTracker.test.ts | 33 +++++-------- .../electron-browser/rawSearchService.test.ts | 14 +----- .../test/node/fileSearch.integrationTest.ts | 4 +- .../services/search/test/node/search.test.ts | 46 ++----------------- .../test/node/textSearch.integrationTest.ts | 4 +- .../nativeTextFileService.io.test.ts | 9 +--- 16 files changed, 73 insertions(+), 153 deletions(-) diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index 4eb61ffcbc7..36fb0f567e1 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -13,12 +13,9 @@ import { mkdirp, writeFile, exists, unlink, rimraf, RimRafMode } from 'vs/base/n import { timeout } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; import { isWindows } from 'vs/base/common/platform'; +import { flakySuite } from 'vs/base/test/node/testUtils'; -suite('Storage Library', function () { - - // https://github.com/microsoft/vscode/issues/108113 - this.retries(3); - this.timeout(1000 * 20); +flakySuite('Storage Library', function () { function uniqueStorageDir(): string { const id = generateUuid(); @@ -296,11 +293,7 @@ suite('Storage Library', function () { }); }); -suite('SQLite Storage Library', function () { - - // https://github.com/microsoft/vscode/issues/108113 - this.retries(3); - this.timeout(1000 * 20); +flakySuite('SQLite Storage Library', function () { function uniqueStorageDir(): string { const id = generateUuid(); @@ -651,8 +644,6 @@ suite('SQLite Storage Library', function () { }); test('very large item value', async function () { - this.timeout(20000); - const storageDir = uniqueStorageDir(); await mkdirp(storageDir); diff --git a/src/vs/base/test/node/id.test.ts b/src/vs/base/test/node/id.test.ts index 637afa5b550..4d12416329b 100644 --- a/src/vs/base/test/node/id.test.ts +++ b/src/vs/base/test/node/id.test.ts @@ -2,22 +2,21 @@ * 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 { getMachineId } from 'vs/base/node/id'; import { getMac } from 'vs/base/node/macAddress'; +import { flakySuite } from 'vs/base/test/node/testUtils'; -suite('ID', () => { +flakySuite('ID', () => { - test('getMachineId', function () { - this.timeout(20000); - return getMachineId().then(id => { - assert.ok(id); - }); + test('getMachineId', async function () { + const id = await getMachineId(); + assert.ok(id); }); - test('getMac', () => { - return getMac().then(macAddress => { - assert.ok(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(macAddress), `Expected a MAC address, got: ${macAddress}`); - }); + test('getMac', async () => { + const macAddress = await getMac(); + assert.ok(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(macAddress), `Expected a MAC address, got: ${macAddress}`); }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 9bfc330a393..85a5644646d 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -14,12 +14,9 @@ import { getPathFromAmdModule } from 'vs/base/common/amd'; import { isWindows } from 'vs/base/common/platform'; import { canNormalize } from 'vs/base/common/normalization'; import { VSBuffer } from 'vs/base/common/buffer'; +import { flakySuite } from 'vs/base/test/node/testUtils'; -suite('PFS', function () { - - // https://github.com/microsoft/vscode/issues/84066 - this.retries(3); - this.timeout(1000 * 20); +flakySuite('PFS', function () { test('writeFile', async () => { const id = uuid.generateUuid(); diff --git a/src/vs/base/test/node/port.test.ts b/src/vs/base/test/node/port.test.ts index 87d8eca9ebf..3ec46e37102 100644 --- a/src/vs/base/test/node/port.test.ts +++ b/src/vs/base/test/node/port.test.ts @@ -6,11 +6,10 @@ import * as assert from 'assert'; import * as net from 'net'; import * as ports from 'vs/base/node/ports'; +import { flakySuite } from 'vs/base/test/node/testUtils'; -suite('Ports', () => { +flakySuite('Ports', () => { test('Finds a free port (no timeout)', function (done) { - this.timeout(1000 * 10); // higher timeout for this test - if (process.env['VSCODE_PID']) { return done(); // this test fails when run from within VS Code } diff --git a/src/vs/base/test/node/testUtils.ts b/src/vs/base/test/node/testUtils.ts index 452e8ae0768..802d9fd1409 100644 --- a/src/vs/base/test/node/testUtils.ts +++ b/src/vs/base/test/node/testUtils.ts @@ -3,9 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import type { Suite } from 'mocha'; import { join } from 'vs/base/common/path'; import { generateUuid } from 'vs/base/common/uuid'; export function getRandomTestPath(tmpdir: string, ...segments: string[]): string { return join(tmpdir, ...segments, generateUuid()); } + +export function flakySuite(title: string, fn: (this: Suite) => void): Suite { + return suite(title, function () { + + // Flaky suites need retries and timeout to complete + // e.g. because they access the file system which can + // be unreliable depending on the environment. + this.retries(3); + this.timeout(1000 * 20); + + // Invoke suite ensuring that `this` is + // properly wired in. + fn.call(this); + }); +} diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 42e2636d885..a127e68d236 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -20,11 +20,11 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/ import { ConsoleLogMainService } from 'vs/platform/log/common/log'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { createHash } from 'crypto'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { Schemas } from 'vs/base/common/network'; import { isEqual } from 'vs/base/common/resources'; -suite('BackupMainService', () => { +flakySuite('BackupMainService', () => { function assertEqualUris(actual: URI[], expected: URI[]) { assert.deepEqual(actual.map(a => a.toString()), expected.map(a => a.toString())); @@ -133,7 +133,6 @@ suite('BackupMainService', () => { }); test('service validates backup workspaces on startup and cleans up (folder workspaces)', async function () { - this.timeout(1000 * 10); // increase timeout for this test // 1) backup workspace path does not exist service.registerFolderBackupSync(fooFile); @@ -179,7 +178,6 @@ suite('BackupMainService', () => { }); test('service validates backup workspaces on startup and cleans up (root workspaces)', async function () { - this.timeout(1000 * 10); // increase timeout for this test // 1) backup workspace path does not exist service.registerWorkspaceBackupSync(toWorkspaceBackupInfo(fooFile.fsPath)); @@ -262,7 +260,7 @@ suite('BackupMainService', () => { assert.equal(1, fs.readdirSync(path.join(backupHome, emptyBackups[0].backupFolder!)).length); }); - suite('loadSync', () => { + flakySuite('loadSync', () => { test('getFolderBackupPaths() should return [] when workspaces.json doesn\'t exist', () => { assertEqualUris(service.getFolderBackupPaths(), []); }); @@ -411,7 +409,6 @@ suite('BackupMainService', () => { }); test('getEmptyWorkspaceBackupPaths() should return [] when folderWorkspaces in workspaces.json is not a string array', async function () { - this.timeout(5000); fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{}}'); await service.initialize(); assert.deepEqual(service.getEmptyWindowBackupPaths(), []); @@ -433,7 +430,7 @@ suite('BackupMainService', () => { }); }); - suite('dedupeFolderWorkspaces', () => { + flakySuite('dedupeFolderWorkspaces', () => { test('should ignore duplicates (folder workspace)', async () => { await ensureFolderExists(existingTestFolder1); @@ -496,7 +493,7 @@ suite('BackupMainService', () => { }); }); - suite('registerWindowForBackups', () => { + flakySuite('registerWindowForBackups', () => { test('should persist paths to workspaces.json (folder workspace)', async () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(barFile); @@ -544,7 +541,7 @@ suite('BackupMainService', () => { assert.deepEqual(json.rootURIWorkspaces.map(b => b.configURIPath), [URI.file(upperFooPath).toString()]); }); - suite('removeBackupPathSync', () => { + flakySuite('removeBackupPathSync', () => { test('should remove folder workspaces from workspaces.json (folder workspace)', async () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(barFile); @@ -607,7 +604,7 @@ suite('BackupMainService', () => { }); }); - suite('getWorkspaceHash', () => { + flakySuite('getWorkspaceHash', () => { test('should ignore case on Windows and Mac', () => { // Skip test on Linux @@ -625,7 +622,7 @@ suite('BackupMainService', () => { }); }); - suite('mixed path casing', () => { + flakySuite('mixed path casing', () => { test('should handle case insensitive paths properly (registerWindowForBackupsSync) (folder workspace)', () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(URI.file(fooFile.fsPath.toUpperCase())); @@ -667,7 +664,7 @@ suite('BackupMainService', () => { }); }); - suite('getDirtyWorkspaces', () => { + flakySuite('getDirtyWorkspaces', () => { test('should report if a workspace or folder has backups', async () => { const folderBackupPath = service.registerFolderBackupSync(fooFile); diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index 773c6c9bc16..e17d0d1d8cb 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -8,7 +8,7 @@ import { tmpdir } from 'os'; import { FileService } from 'vs/platform/files/common/fileService'; import { Schemas } from 'vs/base/common/network'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { generateUuid } from 'vs/base/common/uuid'; import { join, basename, dirname, posix } from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; @@ -118,7 +118,7 @@ export class TestDiskFileSystemProvider extends DiskFileSystemProvider { } } -suite('Disk File Service', function () { +flakySuite('Disk File Service', function () { const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'diskfileservice'); const testSchema = 'test'; @@ -130,11 +130,6 @@ suite('Disk File Service', function () { const disposables = new DisposableStore(); - // https://github.com/microsoft/vscode/issues/78602 - // https://github.com/microsoft/vscode/issues/92334 - this.retries(3); - this.timeout(1000 * 20); - setup(async () => { const logService = new NullLogService(); diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index c9c8eaf9989..2f5f68fe685 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -6,20 +6,15 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { FileStorage } from 'vs/platform/state/node/stateService'; import { mkdirp, rimraf, RimRafMode, writeFileSync } from 'vs/base/node/pfs'; -suite('StateService', () => { +flakySuite('StateService', () => { const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); const storageFile = path.join(parentDir, 'storage.json'); test('Basics', async function () { - - // https://github.com/microsoft/vscode/issues/112447 - this.retries(3); - this.timeout(1000 * 20); - await mkdirp(parentDir); writeFileSync(storageFile, ''); diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index 1546b2384ca..294eb3add7c 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -15,8 +15,9 @@ import { NativeEnvironmentService } from 'vs/platform/environment/node/environme import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { InMemoryStorageDatabase } from 'vs/base/parts/storage/common/storage'; import { URI } from 'vs/base/common/uri'; +import { flakySuite } from 'vs/base/test/node/testUtils'; -suite('NativeStorageService', function () { +flakySuite('NativeStorageService', function () { function uniqueStorageDir(): string { const id = generateUuid(); @@ -26,10 +27,6 @@ suite('NativeStorageService', function () { test('Migrate Data', async function () { - // https://github.com/microsoft/vscode/issues/108113 - this.retries(3); - this.timeout(1000 * 20); - class StorageTestEnvironmentService extends NativeEnvironmentService { constructor(private workspaceStorageFolderPath: URI, private _extensionsPath: string) { diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index dfe8325aacf..4f87b27e3e5 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -10,7 +10,7 @@ import * as path from 'vs/base/common/path'; import * as pfs from 'vs/base/node/pfs'; import { URI } from 'vs/base/common/uri'; import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { DefaultEndOfLine } from 'vs/editor/common/model'; import { hashPath } from 'vs/workbench/services/backup/electron-browser/backupFileService'; import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker'; @@ -51,7 +51,7 @@ class TestBackupRestorer extends BackupRestorer { } } -suite('BackupRestorer', () => { +flakySuite('BackupRestorer', () => { let accessor: TestServiceAccessor; let disposables: IDisposable[] = []; @@ -83,8 +83,6 @@ suite('BackupRestorer', () => { }); test('Restore backups', async function () { - this.timeout(20000); - const backupFileService = new NodeTestBackupFileService(workspaceBackupPath); const instantiationService = workbenchInstantiationService(); instantiationService.stub(IBackupFileService, backupFileService); diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts index 7182610f3fd..5218fd3fc0f 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts @@ -9,7 +9,7 @@ import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as pfs from 'vs/base/node/pfs'; import { URI } from 'vs/base/common/uri'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { hashPath } from 'vs/workbench/services/backup/electron-browser/backupFileService'; import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; @@ -51,13 +51,6 @@ import { timeout } from 'vs/base/common/async'; import { Workspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { IProgressService } from 'vs/platform/progress/common/progress'; -const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backuprestorer'); -const backupHome = path.join(userdataDir, 'Backups'); -const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); - -const workspaceResource = URI.file(platform.isWindows ? 'c:\\workspace' : '/workspace'); -const workspaceBackupPath = path.join(backupHome, hashPath(workspaceResource)); - class TestBackupTracker extends NativeBackupTracker { constructor( @@ -92,15 +85,21 @@ class BeforeShutdownEventImpl implements BeforeShutdownEvent { } } -suite('BackupTracker', function () { +flakySuite('BackupTracker', function () { + let backupHome: string; + let workspaceBackupPath: string; + let accessor: TestServiceAccessor; let disposables: IDisposable[] = []; - // https://github.com/microsoft/vscode/issues/112146 - this.retries(3); - this.timeout(1000 * 20); - setup(async () => { + const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backuprestorer'); + backupHome = path.join(userdataDir, 'Backups'); + const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); + + const workspaceResource = URI.file(platform.isWindows ? 'c:\\workspace' : '/workspace'); + workspaceBackupPath = path.join(backupHome, hashPath(workspaceResource)); + const instantiationService = workbenchInstantiationService(); accessor = instantiationService.createInstance(TestServiceAccessor); @@ -113,8 +112,6 @@ suite('BackupTracker', function () { [new SyncDescriptor(FileEditorInput)] )); - // Delete any existing backups completely and then re-create it. - await pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); await pfs.mkdirp(backupHome); await pfs.mkdirp(workspaceBackupPath); @@ -190,20 +187,14 @@ suite('BackupTracker', function () { } test('Track backups (untitled)', function () { - this.timeout(20000); - return untitledBackupTest(); }); test('Track backups (untitled with initial contents)', function () { - this.timeout(20000); - return untitledBackupTest({ contents: 'Foo Bar' }); }); test('Track backups (file)', async function () { - this.timeout(20000); - const [accessor, part, tracker] = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); diff --git a/src/vs/workbench/services/search/test/electron-browser/rawSearchService.test.ts b/src/vs/workbench/services/search/test/electron-browser/rawSearchService.test.ts index 1be58f5451d..ddeb47d9551 100644 --- a/src/vs/workbench/services/search/test/electron-browser/rawSearchService.test.ts +++ b/src/vs/workbench/services/search/test/electron-browser/rawSearchService.test.ts @@ -12,6 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { IFileQuery, IFileSearchStats, IFolderQuery, IProgressMessage, IRawFileMatch, ISearchEngine, ISearchEngineStats, ISearchEngineSuccess, ISearchProgressItem, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess, isFileMatch, QueryType } from 'vs/workbench/services/search/common/search'; import { IProgressCallback, SearchService as RawSearchService } from 'vs/workbench/services/search/node/rawSearchService'; import { DiskSearch } from 'vs/workbench/services/search/electron-browser/searchService'; +import { flakySuite } from 'vs/base/test/node/testUtils'; const TEST_FOLDER_QUERIES = [ { folder: URI.file(path.normalize('/some/where')) } @@ -70,9 +71,7 @@ class TestSearchEngine implements ISearchEngine { } } -const testTimeout = 5000; - -suite('RawSearchService', () => { +flakySuite('RawSearchService', () => { const rawSearch: IFileQuery = { type: QueryType.File, @@ -91,7 +90,6 @@ suite('RawSearchService', () => { }; test('Individual results', async function () { - this.timeout(testTimeout); let i = 5; const Engine = TestSearchEngine.bind(null, () => i-- ? rawMatch : null); const service = new RawSearchService(); @@ -111,7 +109,6 @@ suite('RawSearchService', () => { }); test('Batch results', async function () { - this.timeout(testTimeout); let i = 25; const Engine = TestSearchEngine.bind(null, () => i-- ? rawMatch : null); const service = new RawSearchService(); @@ -133,7 +130,6 @@ suite('RawSearchService', () => { }); test('Collect batched results', async function () { - this.timeout(testTimeout); const uriPath = '/some/where'; let i = 25; const Engine = TestSearchEngine.bind(null, () => i-- ? rawMatch : null); @@ -171,7 +167,6 @@ suite('RawSearchService', () => { }); test('Multi-root with include pattern and maxResults', async function () { - this.timeout(testTimeout); const service = new RawSearchService(); const query: IFileQuery = { @@ -189,7 +184,6 @@ suite('RawSearchService', () => { }); test('Handles maxResults=0 correctly', async function () { - this.timeout(testTimeout); const service = new RawSearchService(); const query: IFileQuery = { @@ -208,7 +202,6 @@ suite('RawSearchService', () => { }); test('Multi-root with include pattern and exists', async function () { - this.timeout(testTimeout); const service = new RawSearchService(); const query: IFileQuery = { @@ -227,7 +220,6 @@ suite('RawSearchService', () => { }); test('Sorted results', async function () { - this.timeout(testTimeout); const paths = ['bab', 'bbc', 'abb']; const matches: IRawFileMatch[] = paths.map(relativePath => ({ base: path.normalize('/some/where'), @@ -260,7 +252,6 @@ suite('RawSearchService', () => { }); test('Sorted result batches', async function () { - this.timeout(testTimeout); let i = 25; const Engine = TestSearchEngine.bind(null, () => i-- ? rawMatch : null); const service = new RawSearchService(); @@ -287,7 +278,6 @@ suite('RawSearchService', () => { }); test('Cached results', function () { - this.timeout(testTimeout); const paths = ['bcb', 'bbc', 'aab']; const matches: IRawFileMatch[] = paths.map(relativePath => ({ base: path.normalize('/some/where'), diff --git a/src/vs/workbench/services/search/test/node/fileSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/fileSearch.integrationTest.ts index 427de8a4fd9..11e5dd7885e 100644 --- a/src/vs/workbench/services/search/test/node/fileSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/fileSearch.integrationTest.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import * as path from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; +import { flakySuite } from 'vs/base/test/node/testUtils'; import { IFileQuery, IFolderQuery, ISerializedSearchProgressItem, isProgressMessage, QueryType } from 'vs/workbench/services/search/common/search'; import { SearchService } from 'vs/workbench/services/search/node/rawSearchService'; @@ -41,8 +42,7 @@ async function doSearchTest(query: IFileQuery, expectedResultCount: number | Fun assert.equal(results.length, expectedResultCount, `rg ${results.length} !== ${expectedResultCount}`); } -suite('FileSearch-integration', function () { - this.timeout(1000 * 60); // increase timeout for this suite +flakySuite('FileSearch-integration', function () { test('File - simple', () => { const config: IFileQuery = { diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 34d9c2bad1c..20c8dc47a1f 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -11,6 +11,7 @@ import { joinPath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { IFolderQuery, QueryType, IRawFileMatch } from 'vs/workbench/services/search/common/search'; import { Engine as FileSearchEngine, FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +import { flakySuite } from 'vs/base/test/node/testUtils'; const TEST_FIXTURES = path.normalize(getPathFromAmdModule(require, './fixtures')); const EXAMPLES_FIXTURES = URI.file(path.join(TEST_FIXTURES, 'examples')); @@ -29,12 +30,9 @@ const MULTIROOT_QUERIES: IFolderQuery[] = [ { folder: MORE_FIXTURES } ]; -const testTimeout = 5000; - -suite('FileSearchEngine', () => { +flakySuite('FileSearchEngine', () => { test('Files: *.js', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -54,7 +52,6 @@ suite('FileSearchEngine', () => { }); test('Files: maxResults', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -74,7 +71,6 @@ suite('FileSearchEngine', () => { }); test('Files: maxResults without Ripgrep', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -94,7 +90,6 @@ suite('FileSearchEngine', () => { }); test('Files: exists', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -116,7 +111,6 @@ suite('FileSearchEngine', () => { }); test('Files: not exists', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -138,7 +132,6 @@ suite('FileSearchEngine', () => { }); test('Files: exists without Ripgrep', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -160,7 +153,6 @@ suite('FileSearchEngine', () => { }); test('Files: not exists without Ripgrep', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -182,7 +174,6 @@ suite('FileSearchEngine', () => { }); test('Files: examples/com*', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -202,7 +193,6 @@ suite('FileSearchEngine', () => { }); test('Files: examples (fuzzy)', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -222,7 +212,6 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: MULTIROOT_QUERIES, @@ -242,7 +231,6 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with includePattern and maxResults', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: MULTIROOT_QUERIES, @@ -266,7 +254,6 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with includePattern and exists', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: MULTIROOT_QUERIES, @@ -291,7 +278,6 @@ suite('FileSearchEngine', () => { }); test('Files: NPE (CamelCase)', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -311,7 +297,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.*', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -331,7 +316,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.as', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -351,7 +335,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* without derived', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -375,7 +358,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder without wildcard', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -396,7 +378,6 @@ suite('FileSearchEngine', () => { }); test('Files: exclude folder without wildcard #36438', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY_36438, @@ -416,7 +397,6 @@ suite('FileSearchEngine', () => { }); test('Files: include folder without wildcard #36438', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY_36438, @@ -436,7 +416,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder with leading wildcard', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -457,7 +436,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder with trailing wildcard', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -478,7 +456,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude with unicode', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -499,7 +476,6 @@ suite('FileSearchEngine', () => { }); test('Files: *.* include with unicode', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -520,7 +496,6 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with exclude', function (done: () => void) { - this.timeout(testTimeout); const folderQueries: IFolderQuery[] = [ { folder: EXAMPLES_FIXTURES, @@ -555,7 +530,6 @@ suite('FileSearchEngine', () => { }); test('Files: Unicode and Spaces', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -578,7 +552,6 @@ suite('FileSearchEngine', () => { }); test('Files: no results', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -598,7 +571,6 @@ suite('FileSearchEngine', () => { }); test('Files: relative path matched once', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -621,7 +593,6 @@ suite('FileSearchEngine', () => { }); test('Files: Include pattern, single files', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, @@ -646,7 +617,6 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: [], @@ -674,7 +644,6 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only (with include)', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: [], @@ -703,7 +672,6 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only (with exclude)', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: [], @@ -729,7 +697,6 @@ suite('FileSearchEngine', () => { }); test('Files: no dupes in nested folders', function (done: () => void) { - this.timeout(testTimeout); const engine = new FileSearchEngine({ type: QueryType.File, folderQueries: [ @@ -752,10 +719,9 @@ suite('FileSearchEngine', () => { }); }); -suite('FileWalker', () => { +flakySuite('FileWalker', () => { test('Find: exclude subfolder', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -791,7 +757,6 @@ suite('FileWalker', () => { }); test('Find: folder excludes', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -818,7 +783,6 @@ suite('FileWalker', () => { }); test('Find: exclude multiple folders', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -849,7 +813,6 @@ suite('FileWalker', () => { }); test('Find: exclude folder path suffix', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -877,7 +840,6 @@ suite('FileWalker', () => { }); test('Find: exclude subfolder path suffix', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -905,7 +867,6 @@ suite('FileWalker', () => { }); test('Find: exclude folder path', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -933,7 +894,6 @@ suite('FileWalker', () => { }); test('Find: exclude combination of paths', function (done: () => void) { - this.timeout(testTimeout); if (platform.isWindows) { done(); return; diff --git a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts index f2ad6f9a9e2..6b93dd11bf9 100644 --- a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts @@ -11,6 +11,7 @@ import * as glob from 'vs/base/common/glob'; import { URI } from 'vs/base/common/uri'; import { deserializeSearchError, IFolderQuery, ISearchRange, ITextQuery, ITextSearchContext, ITextSearchMatch, QueryType, SearchErrorCode, ISerializedFileMatch } from 'vs/workbench/services/search/common/search'; import { TextSearchEngineAdapter } from 'vs/workbench/services/search/node/textSearchAdapter'; +import { flakySuite } from 'vs/base/test/node/testUtils'; const TEST_FIXTURES = path.normalize(getPathFromAmdModule(require, './fixtures')); const EXAMPLES_FIXTURES = path.join(TEST_FIXTURES, 'examples'); @@ -46,8 +47,7 @@ function doSearchTest(query: ITextQuery, expectedResultCount: number | Function) }); } -suite('TextSearch-integration', function () { - this.timeout(1000 * 60); // increase timeout for this suite +flakySuite('TextSearch-integration', function () { test('Text: GameOfLife', () => { const config: ITextQuery = { diff --git a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts index fff6619519c..26e22260a42 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts @@ -12,7 +12,7 @@ import { rimraf, RimRafMode, copy, readFile, exists, stat } from 'vs/base/node/p import { DisposableStore } from 'vs/base/common/lifecycle'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { tmpdir } from 'os'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { generateUuid } from 'vs/base/common/uuid'; @@ -25,7 +25,7 @@ import { IWorkingCopyFileService, WorkingCopyFileService } from 'vs/workbench/se import { TestWorkingCopyService } from 'vs/workbench/test/common/workbenchTestServices'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; -suite('Files - NativeTextFileService i/o', function () { +flakySuite('Files - NativeTextFileService i/o', function () { const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'textfileservice'); const disposables = new DisposableStore(); @@ -33,11 +33,6 @@ suite('Files - NativeTextFileService i/o', function () { let service: ITextFileService; let testDir: string; - // https://github.com/microsoft/vscode/issues/78602 - // https://github.com/microsoft/vscode/issues/92334 - this.retries(3); - this.timeout(1000 * 20); - createSuite({ setup: async () => { const instantiationService = workbenchInstantiationService(); From a9ed4e9b0a42559b41e96ca894d1a5b9b47da33b Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 5 Jan 2021 11:15:09 +0100 Subject: [PATCH 1523/1837] Fix quick input button height Fixes #113745 --- src/vs/base/parts/quickinput/browser/media/quickInput.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/parts/quickinput/browser/media/quickInput.css b/src/vs/base/parts/quickinput/browser/media/quickInput.css index 4489a73ac61..016c23a5d74 100644 --- a/src/vs/base/parts/quickinput/browser/media/quickInput.css +++ b/src/vs/base/parts/quickinput/browser/media/quickInput.css @@ -121,7 +121,7 @@ font-size: 11px; padding: 0 6px; display: flex; - height: 100%; + height: 27.5px; align-items: center; } From 82b99b3286fb8c573e88669526431ade4bdad81d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Jan 2021 11:18:12 +0100 Subject: [PATCH 1524/1837] skip flaky test (#113620) --- .../services/editor/test/browser/editorsObserver.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index 5f927c5571c..044d6dd50de 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -17,7 +17,6 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { EditorsObserver } from 'vs/workbench/browser/parts/editor/editorsObserver'; import { timeout } from 'vs/base/common/async'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; -import { isWeb } from 'vs/base/common/platform'; const TEST_EDITOR_ID = 'MyTestEditorForEditorsObserver'; const TEST_EDITOR_INPUT_ID = 'testEditorInputForEditorsObserver'; @@ -205,10 +204,7 @@ suite('EditorsObserver', function () { part.dispose(); }); - test('copy group', async function () { - if (isWeb) { - this.skip(); - } + test.skip('copy group', async function () { // https://github.com/microsoft/vscode/issues/113620 const [part, observer] = await createEditorObserver(); const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); From 699d736d7855d58bef19184603ddd80a39076ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 11:18:53 +0100 Subject: [PATCH 1525/1837] distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 56703cd3dc8..c2f58aa5b5c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "93a9b698a51869b29e7d646dbced553755e10c1e", + "distro": "567f2a59872f569eef25a9de7f012f47c1d72e9d", "author": { "name": "Microsoft Corporation" }, @@ -214,4 +214,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file From 7814ffc41ec4635ba3fadd0f1fd987b242d032b8 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Jan 2021 11:31:07 +0100 Subject: [PATCH 1526/1837] Fix #112663 --- .../browser/parts/views/viewPaneContainer.ts | 2 +- .../browser/parts/views/viewsService.ts | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index c02ca3dfcc3..724f7124117 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -1093,7 +1093,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } } - private isViewMergedWithContainer(): boolean { + isViewMergedWithContainer(): boolean { if (!(this.options.mergeViewWithContainerWhenSingleView && this.paneItems.length === 1)) { return false; } diff --git a/src/vs/workbench/browser/parts/views/viewsService.ts b/src/vs/workbench/browser/parts/views/viewsService.ts index 4db26bdf849..8b2d8658deb 100644 --- a/src/vs/workbench/browser/parts/views/viewsService.ts +++ b/src/vs/workbench/browser/parts/views/viewsService.ts @@ -392,12 +392,29 @@ export class ViewsService extends Disposable implements IViewsService { getViewProgressIndicator(viewId: string): IProgressIndicator | undefined { const viewContainer = this.viewDescriptorService.getViewContainerByViewId(viewId); - if (viewContainer === null) { + if (!viewContainer) { return undefined; } - const view = this.viewPaneContainers.get(viewContainer.id)?.viewPaneContainer?.getView(viewId); - return view?.getProgressIndicator(); + const viewPaneContainer = this.viewPaneContainers.get(viewContainer.id)?.viewPaneContainer; + if (!viewPaneContainer) { + return undefined; + } + + const view = viewPaneContainer.getView(viewId); + if (!view) { + return undefined; + } + + if (viewPaneContainer.isViewMergedWithContainer()) { + return this.getViewContainerProgressIndicator(viewContainer); + } + + return view.getProgressIndicator(); + } + + private getViewContainerProgressIndicator(viewContainer: ViewContainer): IProgressIndicator | undefined { + return this.viewDescriptorService.getViewContainerLocation(viewContainer) === ViewContainerLocation.Sidebar ? this.viewletService.getProgressIndicator(viewContainer.id) : this.panelService.getProgressIndicator(viewContainer.id); } private registerViewletOrPanel(viewContainer: ViewContainer, viewContainerLocation: ViewContainerLocation): void { From ded513b20b2386f9b2450583c76eefc9f2646334 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 5 Jan 2021 11:40:36 +0100 Subject: [PATCH 1527/1837] Make cancellation token in resolveTreeItem required Part of #111614 --- src/vs/vscode.proposed.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5f0c5c685a7..197e0fc6b46 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -908,7 +908,7 @@ declare module 'vscode' { //#region Tree data provider: https://github.com/microsoft/vscode/issues/111614 @alexr00 export interface TreeDataProvider { - resolveTreeItem?(item: TreeItem, element: T, token?: CancellationToken): ProviderResult; + resolveTreeItem?(item: TreeItem, element: T, token: CancellationToken): ProviderResult; } ////#endregion From 7449d86b89c7335a2e99c53cd65a58c24ba89da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 11:54:18 +0100 Subject: [PATCH 1528/1837] use esbuild for minification --- build/lib/optimize.js | 73 ++++++++++++++++++---------------------- build/lib/optimize.ts | 78 +++++++++++++++++++------------------------ build/package.json | 5 +-- build/yarn.lock | 51 +--------------------------- package.json | 5 ++- yarn.lock | 63 ++++++++++++++++------------------ 6 files changed, 101 insertions(+), 174 deletions(-) diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 275fcc45a19..1f3cc8f1be0 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -162,47 +162,46 @@ function optimizeTask(opts) { }; } exports.optimizeTask = optimizeTask; +// declare class FileWithCopyright extends VinylFile { +// public __hasOurCopyright: boolean; +// } /** * Wrap around uglify and allow the preserveComments function * to have a file "context" to include our copyright only once per file. */ function uglifyWithCopyrights() { - const composer = require('gulp-uglify/composer'); - const terser = require('terser'); - const preserveComments = (f) => { - return (_node, comment) => { - const text = comment.value; - const type = comment.type; - if (/@minifier_do_not_preserve/.test(text)) { - return false; - } - const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); - if (isOurCopyright) { - if (f.__hasOurCopyright) { - return false; - } - f.__hasOurCopyright = true; - return true; - } - if ('comment2' === type) { - // check for /*!. Note that text doesn't contain leading /* - return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text); - } - else if ('comment1' === type) { - return /license|copyright/i.test(text); - } - return false; - }; - }; - const minify = composer(terser); + const esbuild = require('gulp-esbuild'); + // const preserveComments = (f: FileWithCopyright) => { + // return (_node: any, comment: { value: string; type: string; }) => { + // const text = comment.value; + // const type = comment.type; + // if (/@minifier_do_not_preserve/.test(text)) { + // return false; + // } + // const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); + // if (isOurCopyright) { + // if (f.__hasOurCopyright) { + // return false; + // } + // f.__hasOurCopyright = true; + // return true; + // } + // if ('comment2' === type) { + // // check for /*!. Note that text doesn't contain leading /* + // return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text); + // } else if ('comment1' === type) { + // return /license|copyright/i.test(text); + // } + // return false; + // }; + // }; const input = es.through(); const output = input .pipe(flatmap((stream, f) => { - return stream.pipe(minify({ - output: { - comments: preserveComments(f), - max_line_len: 1024 - } + return stream.pipe(esbuild({ + outfile: f.relative, + sourcemap: true, + minify: true, })); })); return es.duplex(input, output); @@ -211,7 +210,6 @@ function minifyTask(src, sourceMapBaseUrl) { const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined; return cb => { const minifyCSS = require('gulp-cssnano'); - const uglify = require('gulp-uglify'); const sourcemaps = require('gulp-sourcemaps'); const jsFilter = filter('**/*.js', { restore: true }); const cssFilter = filter('**/*.css', { restore: true }); @@ -225,12 +223,7 @@ function minifyTask(src, sourceMapBaseUrl) { sourceRoot: undefined, includeContent: true, addComment: true - }), gulp.dest(src + '-min'), (err) => { - if (err instanceof uglify.GulpUglifyError) { - console.error(`Uglify error in '${err.cause && err.cause.filename}'`); - } - cb(err); - }); + }), gulp.dest(src + '-min'), (err) => cb(err)); }; } exports.minifyTask = minifyTask; diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 897b4b558eb..8f30e886e98 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -232,55 +232,52 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr }; } -declare class FileWithCopyright extends VinylFile { - public __hasOurCopyright: boolean; -} +// declare class FileWithCopyright extends VinylFile { +// public __hasOurCopyright: boolean; +// } /** * Wrap around uglify and allow the preserveComments function * to have a file "context" to include our copyright only once per file. */ function uglifyWithCopyrights(): NodeJS.ReadWriteStream { - const composer = require('gulp-uglify/composer') as typeof import('gulp-uglify/composer'); - const terser = require('terser') as typeof import('terser'); + const esbuild = require('gulp-esbuild') as typeof import('gulp-esbuild'); - const preserveComments = (f: FileWithCopyright) => { - return (_node: any, comment: { value: string; type: string; }) => { - const text = comment.value; - const type = comment.type; + // const preserveComments = (f: FileWithCopyright) => { + // return (_node: any, comment: { value: string; type: string; }) => { + // const text = comment.value; + // const type = comment.type; - if (/@minifier_do_not_preserve/.test(text)) { - return false; - } + // if (/@minifier_do_not_preserve/.test(text)) { + // return false; + // } - const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); + // const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); - if (isOurCopyright) { - if (f.__hasOurCopyright) { - return false; - } - f.__hasOurCopyright = true; - return true; - } + // if (isOurCopyright) { + // if (f.__hasOurCopyright) { + // return false; + // } + // f.__hasOurCopyright = true; + // return true; + // } - if ('comment2' === type) { - // check for /*!. Note that text doesn't contain leading /* - return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text); - } else if ('comment1' === type) { - return /license|copyright/i.test(text); - } - return false; - }; - }; + // if ('comment2' === type) { + // // check for /*!. Note that text doesn't contain leading /* + // return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text); + // } else if ('comment1' === type) { + // return /license|copyright/i.test(text); + // } + // return false; + // }; + // }; - const minify = (composer as any)(terser); const input = es.through(); const output = input .pipe(flatmap((stream, f) => { - return stream.pipe(minify({ - output: { - comments: preserveComments(f), - max_line_len: 1024 - } + return stream.pipe(esbuild({ + outfile: f.relative, + sourcemap: true, + minify: true, })); })); @@ -292,7 +289,6 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => return cb => { const minifyCSS = require('gulp-cssnano') as typeof import('gulp-cssnano'); - const uglify = require('gulp-uglify') as typeof import('gulp-uglify'); const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps'); const jsFilter = filter('**/*.js', { restore: true }); @@ -320,13 +316,7 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => includeContent: true, addComment: true } as any), - gulp.dest(src + '-min') - , (err: any) => { - if (err instanceof (uglify as any).GulpUglifyError) { - console.error(`Uglify error in '${err.cause && err.cause.filename}'`); - } - - cb(err); - }); + gulp.dest(src + '-min'), + (err: any) => cb(err)); }; } diff --git a/build/package.json b/build/package.json index cbd01eccce1..091f8b77940 100644 --- a/build/package.json +++ b/build/package.json @@ -17,7 +17,6 @@ "@types/gulp-json-editor": "^2.2.31", "@types/gulp-rename": "^0.0.33", "@types/gulp-sourcemaps": "^0.0.32", - "@types/gulp-uglify": "^3.0.5", "@types/mime": "0.0.29", "@types/minimatch": "^3.0.3", "@types/minimist": "^1.2.1", @@ -26,7 +25,6 @@ "@types/pump": "^1.0.1", "@types/request": "^2.47.0", "@types/rimraf": "^2.0.4", - "@types/terser": "^3.12.0", "@types/through": "^0.0.29", "@types/through2": "^2.0.34", "@types/underscore": "^1.8.9", @@ -47,5 +45,8 @@ "watch": "tsc -p tsconfig.build.json --watch", "postinstall": "npm run compile", "npmCheckJs": "tsc --noEmit" + }, + "dependencies": { + "source-map": "0.6.1" } } diff --git a/build/yarn.lock b/build/yarn.lock index 71332dd8449..326c464c412 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -151,14 +151,6 @@ dependencies: "@types/node" "*" -"@types/gulp-uglify@^3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/gulp-uglify/-/gulp-uglify-3.0.5.tgz#ddcbbb6bd15a84b8a6c5e2218c2efba98102d135" - integrity sha512-LD2b6gCPugrKI1W188nIp0gm+cAnGGwaTFpPdeZYVXwPHdoCQloy3du0JR62MeMjAwUwlcOb+SKYT6Qgw7yBiA== - dependencies: - "@types/node" "*" - "@types/uglify-js" "^2" - "@types/gulp@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-4.0.5.tgz#f5f498d5bf9538364792de22490a12c0e6bc5eb4" @@ -233,13 +225,6 @@ "@types/glob" "*" "@types/node" "*" -"@types/terser@^3.12.0": - version "3.12.0" - resolved "https://registry.yarnpkg.com/@types/terser/-/terser-3.12.0.tgz#25e020fe9a7a6ae92ce46261f00ced67de6c12ac" - integrity sha512-J0Wy8A7ULEqVJftkWhrXZbH0iBk4tYuTj0gBiiveKaY9deNi6cCsxl0ApJ27ojqwYv51bvEw85lOb8Wt4ng9zA== - dependencies: - terser "*" - "@types/through2@^2.0.34": version "2.0.34" resolved "https://registry.yarnpkg.com/@types/through2/-/through2-2.0.34.tgz#9c2a259a238dace2a05a2f8e94b786961bc27ac4" @@ -259,13 +244,6 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.2.tgz#e0d481d8bb282ad8a8c9e100ceb72c995fb5e709" integrity sha512-vOVmaruQG5EatOU/jM6yU2uCp3Lz6mK1P5Ztu4iJjfM4SVHU9XYktPUQtKlIXuahqXHdEyUarMrBEwg5Cwu+bA== -"@types/uglify-js@^2": - version "2.6.31" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-2.6.31.tgz#c694755eeb6a1bb9f8f321f3ec37cc22ca4c4f6b" - integrity sha512-LjcyGt6CHsgZ0AoofnMwhyxo9hUqz2mgl6IcF+S8B1zdSTxHAvTO/1RPvBAHG3C1ZeAc+AoWA5mb3lDJKtM9Zg== - dependencies: - source-map "^0.6.1" - "@types/underscore@^1.8.9": version "1.8.9" resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.8.9.tgz#fef41f800cd23db1b4f262ddefe49cd952d82323" @@ -517,11 +495,6 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -551,11 +524,6 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - commander@^2.8.1: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -1305,15 +1273,7 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -source-map-support@~0.5.12: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -1355,15 +1315,6 @@ stringstream@~0.0.4: resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= -terser@*: - version "4.2.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.2.1.tgz#1052cfe17576c66e7bc70fcc7119f22b155bdac1" - integrity sha512-cGbc5utAcX4a9+2GGVX4DsenG6v0x3glnDi5hx8816X1McEAwPlPgRtXPJzSBsbpILxZ8MQMT0KvArLuE0HP5A== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - tmp@0.0.29: version "0.0.29" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" diff --git a/package.json b/package.json index c2f58aa5b5c..883ab90dc2e 100644 --- a/package.json +++ b/package.json @@ -135,6 +135,7 @@ "gulp-buffer": "0.0.2", "gulp-concat": "^2.6.1", "gulp-cssnano": "^2.1.3", + "gulp-esbuild": "^0.3.12", "gulp-eslint": "^5.0.0", "gulp-filter": "^5.1.0", "gulp-flatmap": "^1.0.2", @@ -148,7 +149,6 @@ "gulp-shell": "^0.6.5", "gulp-sourcemaps": "^1.11.0", "gulp-tsb": "4.0.5", - "gulp-uglify": "^3.0.0", "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", "husky": "^0.13.1", @@ -183,7 +183,6 @@ "source-map": "^0.4.4", "source-map-support": "^0.3.2", "style-loader": "^1.0.0", - "terser": "^4.8.0", "ts-loader": "^6.2.1", "tsec": "googleinterns/tsec#7bf4ab23686500522341b977b3e2cc04b1f720b1", "typescript": "4.2.0-dev.20201207", @@ -214,4 +213,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 19a1931a8ff..712616fbcbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3194,6 +3194,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" +esbuild@^0.8.29: + version "0.8.29" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.8.29.tgz#cc20fb752e0905a3546d68ae1be58f9b97044c39" + integrity sha512-UDsEoeXuctVgG2hEts1Hwq2jYDGqV7nksEHEZaiCy2v+lXF5ButX4ErPAJAFi5ZNKKW+6Pom93pArV7hki6HnQ== + escalade@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" @@ -4578,6 +4583,15 @@ gulp-cssnano@^2.1.3: plugin-error "^1.0.1" vinyl-sourcemaps-apply "^0.2.1" +gulp-esbuild@^0.3.12: + version "0.3.12" + resolved "https://registry.yarnpkg.com/gulp-esbuild/-/gulp-esbuild-0.3.12.tgz#3b8b8e8110b445af76b3fb145fc208d86a6d0ef5" + integrity sha512-gUNMGMnfvF7tHvJilpXqH67phe25jVDnstqQQ69mS7DsPtI4LKPnF8y5o0rt56ww8+Pf9MmT+sKJfErqUGt+RA== + dependencies: + esbuild "^0.8.29" + plugin-error "^1.0.1" + vinyl "^2.2.1" + gulp-eslint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-5.0.0.tgz#2a2684095f774b2cf79310262078c56cc7a12b52" @@ -4732,22 +4746,6 @@ gulp-tsb@4.0.5: through "^2.3.6" vinyl "^2.1.0" -gulp-uglify@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.2.tgz#5f5b2e8337f879ca9dec971feb1b82a5a87850b0" - integrity sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg== - dependencies: - array-each "^1.0.1" - extend-shallow "^3.0.2" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - isobject "^3.0.1" - make-error-cause "^1.1.1" - safe-buffer "^5.1.2" - through2 "^2.0.0" - uglify-js "^3.0.5" - vinyl-sourcemaps-apply "^0.2.0" - gulp-untar@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4" @@ -6383,18 +6381,6 @@ make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error-cause@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" - integrity sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0= - dependencies: - make-error "^1.2.0" - -make-error@^1.2.0: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -10000,7 +9986,7 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.1.2, terser@^4.8.0: +terser@^4.1.2: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== @@ -10305,11 +10291,6 @@ typical@^4.0.0: resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== -uglify-js@^3.0.5: - version "3.12.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.2.tgz#c7ae89da0ed1bb58999c7fce07190b347fdbdaba" - integrity sha512-rWYleAvfJPjduYCt+ELvzybNah/zIkRteGXIBO8X0lteRZPGladF61hFi8tU7qKTsF7u6DUQCtT9k00VlFOgkg== - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -10608,7 +10589,7 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" -vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: +vinyl-sourcemaps-apply@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= @@ -10657,6 +10638,18 @@ vinyl@^2.0.2, vinyl@^2.2.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" +vinyl@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + vinyl@~2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" From 09e281c091ac27700bdfe3cab7c04f14c8e39120 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Jan 2021 11:58:04 +0100 Subject: [PATCH 1529/1837] Fix #113732 --- .../platform/keybinding/common/keybindingResolver.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/keybinding/common/keybindingResolver.ts b/src/vs/platform/keybinding/common/keybindingResolver.ts index 3582ce6d6b8..00b98179c85 100644 --- a/src/vs/platform/keybinding/common/keybindingResolver.ts +++ b/src/vs/platform/keybinding/common/keybindingResolver.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isNonEmptyArray } from 'vs/base/common/arrays'; -import { MenuRegistry } from 'vs/platform/actions/common/actions'; +import { isIMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { IContext, ContextKeyExpression, ContextKeyExprType } from 'vs/platform/contextkey/common/contextkey'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; @@ -364,9 +364,14 @@ export class KeybindingResolver { } unboundCommands.push(id); }; - for (const id of MenuRegistry.getCommands().keys()) { - addCommand(id, true); + + // Add all commands from Command Palette + for (const menuItem of MenuRegistry.getMenuItems(MenuId.CommandPalette)) { + if (isIMenuItem(menuItem)) { + addCommand(menuItem.command.id, true); + } } + for (const id of CommandsRegistry.getCommands().keys()) { addCommand(id, false); } From cefe06d375f12c19dc053364ec3c8f9f27bb7ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:01:07 +0100 Subject: [PATCH 1530/1837] build-essential --- build/azure-pipelines/product-compile.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index ba5e76ec5df..295d4545925 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -55,6 +55,13 @@ steps: condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) displayName: Extract node_modules archive + - script: | + set -e + sudo apt update + sudo apt install -y build-essential + displayName: Install build tools + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin From 035e15b7712e1a4f09170a2dc1596f6cf4f785a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:02:14 +0100 Subject: [PATCH 1531/1837] revert pool --- build/azure-pipelines/product-build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 6a7b3dc4ce2..5824fba72f9 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -30,13 +30,15 @@ stages: - stage: Compile jobs: - job: Compile - pool: compile + pool: + vmImage: "Ubuntu-18.04" variables: VSCODE_ARCH: x64 steps: - template: product-compile.yml - job: Hygiene - pool: compile + pool: + vmImage: "Ubuntu-18.04" variables: VSCODE_ARCH: x64 steps: From a96a29b753576dbf7f2865afe9ef8f53f03fadba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:05:34 +0100 Subject: [PATCH 1532/1837] pkg-config --- build/azure-pipelines/product-compile.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 295d4545925..e34c2c9e8c0 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -57,8 +57,9 @@ steps: - script: | set -e - sudo apt update - sudo apt install -y build-essential + sudo apt update -y + sudo apt install -y build-essential pkg-config + displayName: Install build tools condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) From dd9e52a40d99381d03b3f65ac022a699fd6aaa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:09:40 +0100 Subject: [PATCH 1533/1837] libs --- build/azure-pipelines/product-compile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index e34c2c9e8c0..096d9a635a2 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -58,7 +58,7 @@ steps: - script: | set -e sudo apt update -y - sudo apt install -y build-essential pkg-config + sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin displayName: Install build tools condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) From 750948b7b5cad4190ad86e13322591a5018095f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:21:16 +0100 Subject: [PATCH 1534/1837] fix hygiene as well --- build/azure-pipelines/product-hygiene.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 477336cd536..214b3e74def 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -55,6 +55,11 @@ steps: condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) displayName: Extract node_modules archive + - script: | + set -e + sudo apt update -y + sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin + - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin From 0652b9cbec222b262b6ca80ee604c7a3b595009c Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Jan 2021 13:02:30 +0100 Subject: [PATCH 1535/1837] debug toolbar docked actions only appear in debug viewlet --- src/vs/workbench/contrib/debug/browser/debugToolBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index af79b513e47..b833f2b133e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -14,7 +14,7 @@ import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecut import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugConfiguration, IDebugService, State, CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug'; import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; @@ -26,7 +26,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; -import { IContextKeyService, ContextKeyExpression, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, ContextKeyExpression, ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons'; import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib/debug/browser/debugColors'; @@ -280,7 +280,7 @@ const registerDebugToolBarItem = (id: string, title: string, order: number, icon // Register actions in debug viewlet when toolbar is docked MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { group: 'navigation', - when: ContextKeyExpr.and(when, CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')), + when: ContextKeyExpr.and(when, ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')), order, command: { id, From e008e41d27b34b19dd321b18344dedbd3f74db83 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Jan 2021 13:14:56 +0100 Subject: [PATCH 1536/1837] fixes #113242 --- src/vs/workbench/contrib/debug/browser/debugCommands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index f2d4ea46571..ad88803c84c 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -335,7 +335,7 @@ export function registerCommands(): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ id: CONTINUE_ID, - weight: KeybindingWeight.WorkbenchContrib, + weight: KeybindingWeight.WorkbenchContrib + 10, // Use a stronger weight to get priority over start debugging F5 shortcut primary: KeyCode.F5, when: CONTEXT_IN_DEBUG_MODE, handler: (accessor: ServicesAccessor, _: string, context: CallStackContext | unknown) => { From f90c518b03c7f865f8c36c68e7036e5b2f2b8879 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Jan 2021 13:53:18 +0100 Subject: [PATCH 1537/1837] debug: remove enableBreakpointsFor since php-debug now moved to new api --- .../workbench/contrib/debug/browser/debugAdapterManager.ts | 5 ----- src/vs/workbench/contrib/debug/common/debug.ts | 1 - 2 files changed, 6 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts index ea61d8877bd..bf1fc62feef 100644 --- a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts @@ -54,11 +54,6 @@ export class AdapterManager implements IAdapterManager { if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { added.collector.error(nls.localize('debugNoType', "Debugger 'type' can not be omitted and must be of type 'string'.")); } - if (rawAdapter.enableBreakpointsFor && rawAdapter.enableBreakpointsFor.languageIds) { // Support deprecated field since the php-debug extension depends on it - rawAdapter.enableBreakpointsFor.languageIds.forEach(modeId => { - this.breakpointModeIdsSet.add(modeId); - }); - } if (rawAdapter.type !== '*') { const existing = this.getDebugger(rawAdapter.type); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 3a9b36fb18e..44dc592ccfc 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -636,7 +636,6 @@ export interface IDebuggerContribution extends IPlatformSpecificAdapterContribut // supported languages languages?: string[]; - enableBreakpointsFor?: { languageIds?: string[] }; // debug configuration support configurationAttributes?: any; From f06ebe74253a62cf60feb84f1a9cba56a8ea132a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 14:48:59 +0100 Subject: [PATCH 1538/1837] :lipstick: --- build/azure-pipelines/product-compile.yml | 1 - build/azure-pipelines/product-hygiene.yml | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 096d9a635a2..35b4d7cdb09 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -59,7 +59,6 @@ steps: set -e sudo apt update -y sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin - displayName: Install build tools condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 214b3e74def..8405167ab13 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -59,6 +59,8 @@ steps: set -e sudo apt update -y sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin + displayName: Install build tools + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) - script: | set -e From 13e313c2b58c3b16959326044daeee84f937ec1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 12:01:07 +0100 Subject: [PATCH 1539/1837] fix compile and hygiene cache miss --- build/azure-pipelines/product-compile.yml | 7 +++++++ build/azure-pipelines/product-hygiene.yml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index ba5e76ec5df..35b4d7cdb09 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -55,6 +55,13 @@ steps: condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) displayName: Extract node_modules archive + - script: | + set -e + sudo apt update -y + sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin + displayName: Install build tools + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin diff --git a/build/azure-pipelines/product-hygiene.yml b/build/azure-pipelines/product-hygiene.yml index 477336cd536..8405167ab13 100644 --- a/build/azure-pipelines/product-hygiene.yml +++ b/build/azure-pipelines/product-hygiene.yml @@ -55,6 +55,13 @@ steps: condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) displayName: Extract node_modules archive + - script: | + set -e + sudo apt update -y + sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin + displayName: Install build tools + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + - script: | set -e for i in {1..3}; do # try 3 times, for Terrapin From e8ad195f3e037849a311942fa78c67da87b796c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 14:49:59 +0100 Subject: [PATCH 1540/1837] Revert "revert pool" This reverts commit 035e15b7712e1a4f09170a2dc1596f6cf4f785a7. --- build/azure-pipelines/product-build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 5824fba72f9..6a7b3dc4ce2 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -30,15 +30,13 @@ stages: - stage: Compile jobs: - job: Compile - pool: - vmImage: "Ubuntu-18.04" + pool: compile variables: VSCODE_ARCH: x64 steps: - template: product-compile.yml - job: Hygiene - pool: - vmImage: "Ubuntu-18.04" + pool: compile variables: VSCODE_ARCH: x64 steps: From 48dbb328998393097c6dc8b0fea4c5bef62bd437 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Jan 2021 14:56:49 +0100 Subject: [PATCH 1541/1837] fix https://github.com/microsoft/vscode/issues/113819 --- .../extensionManagement/browser/extensionBisect.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts index b60cd526762..cd3b096a9a3 100644 --- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts @@ -11,8 +11,8 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; -import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ContextKeyEqualsExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -216,7 +216,13 @@ registerAction2(class extends Action2 { title: { value: localize('title.start', "Start Extension Bisect"), original: 'Start Extension Bisect' }, category: localize('help', "Help"), f1: true, - precondition: ExtensionBisectUi.ctxIsBisectActive.negate() + precondition: ExtensionBisectUi.ctxIsBisectActive.negate(), + menu: { + id: MenuId.ViewContainerTitle, + when: ContextKeyEqualsExpr.create('viewContainer', 'workbench.view.extensions'), + group: '2_enablement', + order: 3 + } }); } From 2d1b63d6a3ef6a8d51be9f91c9ca80043ab3416b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Jan 2021 15:11:44 +0100 Subject: [PATCH 1542/1837] Fix showing views submenu when view is merged with view container and view has secondary actions. --- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 724f7124117..de6f5ea47b5 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -593,16 +593,16 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { let menuActions = this.menuActions.getSecondaryActions(); const isViewsSubMenuAction = (action: IAction) => action instanceof SubmenuItemAction && action.item.submenu === ViewsSubMenu; const index = menuActions.findIndex(a => isViewsSubMenuAction(a)); + const viewPaneContainerActions = this.isViewMergedWithContainer() ? this.paneItems[0].pane.getSecondaryActions() : []; if (index !== -1) { if (index !== 0) { menuActions = [menuActions[index], ...menuActions.slice(0, index), ...menuActions.slice(index + 1)]; } - if (menuActions.length === 1) { + if (menuActions.length === 1 && viewPaneContainerActions.length === 0) { menuActions = (menuActions[0]).actions; } } - const viewPaneContainerActions = this.isViewMergedWithContainer() ? this.paneItems[0].pane.getSecondaryActions() : []; if (menuActions.length && viewPaneContainerActions.length) { return [ ...menuActions, From 37b0d344c7b31d915645074e51baf24b18abe072 Mon Sep 17 00:00:00 2001 From: Nick Rayburn Date: Tue, 5 Jan 2021 09:17:59 -0600 Subject: [PATCH 1543/1837] add a RANDOM_UUID snippet variable --- src/vs/editor/contrib/snippet/snippetVariables.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index bdfe96e7c65..8a23b709b61 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -17,6 +17,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { normalizeDriveLetter } from 'vs/base/common/labels'; import { URI } from 'vs/base/common/uri'; import { OvertypingCapturer } from 'vs/editor/contrib/suggest/suggestOvertypingCapturer'; +import { generateUuid } from 'vs/base/common/uuid'; export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze({ 'CURRENT_YEAR': true, @@ -49,6 +50,7 @@ export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze( 'WORKSPACE_FOLDER': true, 'RANDOM': true, 'RANDOM_HEX': true, + 'RANDOM_UUID': true }); export class CompositeSnippetVariableResolver implements VariableResolver { @@ -343,6 +345,8 @@ export class RandomBasedVariableResolver implements VariableResolver { } else if (name === 'RANDOM_HEX') { return Math.random().toString(16).slice(-6); + } else if (name === 'RANDOM_UUID') { + return generateUuid(); } return undefined; From 51ea16966b6fc47dec26f34676fca73586e29d8e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Jan 2021 16:43:52 +0100 Subject: [PATCH 1544/1837] :lipstick: remove appendChildren infavor of append, fyi @bpasero --- src/vs/base/browser/dom.ts | 21 +++++++++---------- .../browser/parts/statusbar/statusbarPart.ts | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 24ac47e58e4..bbb81a0b407 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -24,6 +24,9 @@ export function clearNode(node: HTMLElement): void { } } +/** + * @deprecated Use node.isConnected directly + */ export function isInDOM(node: Node | null): boolean { return node?.isConnected ?? false; } @@ -998,9 +1001,13 @@ export function after(sibling: HTMLElement, child: T): T { return child; } -export function append(parent: HTMLElement, ...children: T[]): T { +export function append(parent: HTMLElement, child: T): T; +export function append(parent: HTMLElement, ...children: (T | string)[]): void; +export function append(parent: HTMLElement, ...children: (T | string)[]): T | void { parent.append(...children); - return children[children.length - 1]; + if (children.length === 1 && typeof children[0] !== 'string') { + return children[0]; + } } export function prepend(parent: HTMLElement, child: T): T { @@ -1008,20 +1015,12 @@ export function prepend(parent: HTMLElement, child: T): T { return child; } - /** * Removes all children from `parent` and appends `children` */ export function reset(parent: HTMLElement, ...children: Array): void { parent.innerText = ''; - appendChildren(parent, ...children); -} - -/** - * Appends `children` to `parent` - */ -export function appendChildren(parent: HTMLElement, ...children: Array): void { - parent.append(...children); + append(parent, ...children); } const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/; diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 2e77f75e627..10ac9fa8ece 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -21,7 +21,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { isThemeColor } from 'vs/editor/common/editorCommon'; import { Color } from 'vs/base/common/color'; -import { EventHelper, createStyleSheet, addDisposableListener, EventType, hide, show, isAncestor, appendChildren } from 'vs/base/browser/dom'; +import { EventHelper, createStyleSheet, addDisposableListener, EventType, hide, show, isAncestor, append } from 'vs/base/browser/dom'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -750,7 +750,7 @@ class StatusBarCodiconLabel extends SimpleIconLabel { } // Append new elements - appendChildren(this.container, ...renderLabelWithIcons(textContent)); + append(this.container, ...renderLabelWithIcons(textContent)); } // No Progress: no special handling From b99faeeb3cea47f5ec5c0c4aadff28a7d3f676ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 5 Jan 2021 16:46:54 +0100 Subject: [PATCH 1545/1837] fix minification target --- build/lib/optimize.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 8f30e886e98..81d57745a9f 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -278,6 +278,8 @@ function uglifyWithCopyrights(): NodeJS.ReadWriteStream { outfile: f.relative, sourcemap: true, minify: true, + platform: 'node', + target: ['node12.18'] })); })); From c907b8fff853b9b706f62a23a94c117f64d83dbe Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Jan 2021 16:49:39 +0100 Subject: [PATCH 1546/1837] no vscode-imports --- src/vs/vscode.proposed.d.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 197e0fc6b46..f5d7716f650 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Command } from 'vscode'; - /** * This is the place for API experiments and proposals. * These API are NOT stable and subject to change. They are only available in the Insiders From 6c95b041ea6adc0f45ea2c5c6f6acfc81513b5c5 Mon Sep 17 00:00:00 2001 From: HaoboGu Date: Wed, 6 Jan 2021 00:10:32 +0800 Subject: [PATCH 1547/1837] test: add tests for #113403 --- src/vs/base/test/common/filters.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index 17a3f681c73..22889a15a79 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -534,6 +534,11 @@ suite('Filters', () => { assert.ok(Boolean(match)); }); + test('Wrong highlight after emoji #113403', function () { + assertMatches('di', '⭐div classname="">', '⭐^d^iv classname="">', fuzzyScore); + assertMatches('di', 'adiv classname="">', 'adiv classname="">', fuzzyScore); + }); + test('Suggestion is not highlighted #85826', function () { assertMatches('SemanticTokens', 'SemanticTokensEdits', '^S^e^m^a^n^t^i^c^T^o^k^e^n^sEdits', fuzzyScore); assertMatches('SemanticTokens', 'SemanticTokensEdits', '^S^e^m^a^n^t^i^c^T^o^k^e^n^sEdits', fuzzyScoreGracefulAggressive); From c41302c5ab1cc332ba2a66a55a03968af3e6c207 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 5 Jan 2021 17:18:22 +0100 Subject: [PATCH 1548/1837] Relax worker.onerror after a successful worker start --- .../extensions/worker/httpWebWorkerExtensionHostIframe.html | 3 ++- .../extensions/worker/httpsWebWorkerExtensionHostIframe.html | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html index b1cf47e22cb..d8387db2fe4 100644 --- a/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html +++ b/src/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html @@ -1,7 +1,7 @@ - + From e4dc7b4d7966789b3724a34649a071a87d53f9fa Mon Sep 17 00:00:00 2001 From: 0dinD Date: Fri, 8 Jan 2021 10:15:23 +0100 Subject: [PATCH 1709/1837] Clarify OpenDialogOptions note (#113831) (#113998) This PR fixes #113831, see that issue fore a more detailed description. --- src/vs/vscode.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 3765ae1775d..31276a2f588 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1700,8 +1700,8 @@ declare module 'vscode' { /** * Options to configure the behaviour of a file open dialog. * - * * Note 1: A dialog can select files, folders, or both. This is not true for Windows - * which enforces to open either files or folder, but *not both*. + * * Note 1: On Windows and Linux, a file dialog cannot be both a file selector and a folder selector, so if you + * set both `canSelectFiles` and `canSelectFolders` to `true` on these platforms, a folder selector will be shown. * * Note 2: Explicitly setting `canSelectFiles` and `canSelectFolders` to `false` is futile * and the editor then silently adjusts the options to select files. */ From 35766c616cb051722e8c18ec05f82ea1e18d79f3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 10:16:09 +0100 Subject: [PATCH 1710/1837] #113757 show sidebar actions also on view title context menu --- .../browser/actions/layoutActions.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 6ab923314c5..391d3ae3062 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -176,6 +176,17 @@ MenuRegistry.appendMenuItems([{ when: ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), order: 1 } +}, { + id: MenuId.ViewTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: ToggleSidebarPositionAction.ID, + title: nls.localize('move sidebar right', "Move Side Bar Right") + }, + when: ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), + order: 1 + } }, { id: MenuId.ViewContainerTitleContext, item: { @@ -187,6 +198,17 @@ MenuRegistry.appendMenuItems([{ when: ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), order: 1 } +}, { + id: MenuId.ViewTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: ToggleSidebarPositionAction.ID, + title: nls.localize('move sidebar left', "Move Side Bar Left") + }, + when: ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), + order: 1 + } }]); MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { @@ -277,6 +299,17 @@ MenuRegistry.appendMenuItems([{ when: SideBarVisibleContext, order: 2 } +}, { + id: MenuId.ViewTitleContext, + item: { + group: '3_workbench_layout_move', + command: { + id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + title: nls.localize('compositePart.hideSideBarLabel', "Hide Side Bar"), + }, + when: SideBarVisibleContext, + order: 2 + } }]); MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { From 4c42e6c111b867e871348523fb381fd57367aa5f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 10:56:09 +0100 Subject: [PATCH 1711/1837] Fix #114013 --- .../platform/configuration/common/configurationRegistry.ts | 7 +++++++ src/vs/platform/userDataSync/common/userDataSync.ts | 3 ++- src/vs/workbench/electron-sandbox/desktop.contribution.ts | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 07680c0f29b..7504cb721b3 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -112,6 +112,13 @@ export interface IConfigurationPropertySchema extends IJSONSchema { scope?: ConfigurationScope; included?: boolean; tags?: string[]; + /** + * When enabled this setting is ignored during sync and user can override this. + */ + ignoreSync?: boolean; + /** + * When enabled this setting is ignored during sync and user cannot override this. + */ disallowSyncIgnore?: boolean; enumItemLabels?: string[]; } diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 80871ec7374..310fea185f2 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -31,9 +31,10 @@ export function getDisallowedIgnoredSettings(): string[] { export function getDefaultIgnoredSettings(): string[] { const allSettings = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); + const ignoreSyncSettings = Object.keys(allSettings).filter(setting => !!allSettings[setting].ignoreSync); const machineSettings = Object.keys(allSettings).filter(setting => allSettings[setting].scope === ConfigurationScope.MACHINE || allSettings[setting].scope === ConfigurationScope.MACHINE_OVERRIDABLE); const disallowedSettings = getDisallowedIgnoredSettings(); - return distinct([CONFIGURATION_SYNC_STORE_KEY, ...machineSettings, ...disallowedSettings]); + return distinct([CONFIGURATION_SYNC_STORE_KEY, ...ignoreSyncSettings, ...machineSettings, ...disallowedSettings]); } export function registerConfiguration(): IDisposable { diff --git a/src/vs/workbench/electron-sandbox/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts index 9dd8fb5be0c..7c5efce7623 100644 --- a/src/vs/workbench/electron-sandbox/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -232,7 +232,8 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; 'window.zoomLevel': { 'type': 'number', 'default': 0, - 'description': nls.localize('zoomLevel', "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.") + 'description': nls.localize('zoomLevel', "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."), + ignoreSync: true }, 'window.newWindowDimensions': { 'type': 'string', From 128987f575ee1815521f944f4c73ff153922c894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 8 Jan 2021 10:56:28 +0100 Subject: [PATCH 1712/1837] remove duplicate step --- build/azure-pipelines/product-compile.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 80149cf0b23..08e3f694520 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -49,13 +49,6 @@ steps: condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true')) displayName: Extract node_modules cache - - script: | - set -e - sudo apt update -y - sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libsecret-1-dev libnotify-bin - displayName: Install build tools - condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) - - script: | npx https://aka.ms/enablesecurefeed standAlone timeoutInMinutes: 5 From adc68dc3561d18d63878a60b9c02ef400c3a25dd Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 11:00:50 +0100 Subject: [PATCH 1713/1837] Add `canTunnel` to tunnel service Part of microsoft/vscode-internalbacklog#1709 --- src/vs/platform/remote/common/tunnel.ts | 5 +++++ src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index 0250f7f000c..ee0709aaac4 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -47,6 +47,7 @@ export interface ITunnelService { readonly onTunnelClosed: Event<{ host: string, port: number }>; readonly canElevate: boolean; + canTunnel(uri: URI): boolean; openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean): Promise | undefined; closeTunnel(remoteHost: string, remotePort: number): Promise; setTunnelProvider(provider: ITunnelProvider | undefined, features: TunnelProviderFeatures): IDisposable; @@ -256,6 +257,10 @@ export abstract class AbstractTunnelService implements ITunnelService { return portMap ? portMap.get(remotePort) : undefined; } + canTunnel(uri: URI): boolean { + return !!extractLocalHostUriMetaDataForPortMapping(uri); + } + protected abstract retainOrCreateTunnel(addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean): Promise | undefined; } diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index 6478fa4649c..13dc420cdd8 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -564,6 +564,7 @@ class SimpleTunnelService implements ITunnelService { onTunnelOpened = Event.None; onTunnelClosed = Event.None; + canTunnel(uri: URI): boolean { return false; } openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number): Promise | undefined { return undefined; } async closeTunnel(remoteHost: string, remotePort: number): Promise { } setTunnelProvider(provider: ITunnelProvider | undefined): IDisposable { return Disposable.None; } From eb940d4ed6d86c5f549f13ffad5da15bebfa6abe Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 11:14:35 +0100 Subject: [PATCH 1714/1837] Fix #113988 --- .../common/userDataSyncService.ts | 214 +++++++++++------- 1 file changed, 127 insertions(+), 87 deletions(-) diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index 2cf4ac375dc..ad5494bc422 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -445,131 +445,171 @@ class ManualSyncTask extends Disposable implements IManualSyncTask { } async preview(): Promise<[SyncResource, ISyncResourcePreview][]> { - if (this.isDisposed) { - throw new Error('Disposed'); + try { + if (this.isDisposed) { + throw new Error('Disposed'); + } + if (!this.previewsPromise) { + this.previewsPromise = createCancelablePromise(token => this.getPreviews(token)); + } + if (!this.previews) { + this.previews = await this.previewsPromise; + } + return this.previews; + } catch (error) { + this.logService.error(error); + throw error; } - if (!this.previewsPromise) { - this.previewsPromise = createCancelablePromise(token => this.getPreviews(token)); - } - if (!this.previews) { - this.previews = await this.previewsPromise; - } - return this.previews; } async accept(resource: URI, content?: string | null): Promise<[SyncResource, ISyncResourcePreview][]> { - return this.performAction(resource, sychronizer => sychronizer.accept(resource, content)); + try { + return await this.performAction(resource, sychronizer => sychronizer.accept(resource, content)); + } catch (error) { + this.logService.error(error); + throw error; + } } async merge(resource?: URI): Promise<[SyncResource, ISyncResourcePreview][]> { - if (resource) { - return this.performAction(resource, sychronizer => sychronizer.merge(resource)); - } else { - return this.mergeAll(); + try { + if (resource) { + return await this.performAction(resource, sychronizer => sychronizer.merge(resource)); + } else { + return await this.mergeAll(); + } + } catch (error) { + this.logService.error(error); + throw error; } } async discard(resource: URI): Promise<[SyncResource, ISyncResourcePreview][]> { - return this.performAction(resource, sychronizer => sychronizer.discard(resource)); + try { + return await this.performAction(resource, sychronizer => sychronizer.discard(resource)); + } catch (error) { + this.logService.error(error); + throw error; + } } async discardConflicts(): Promise<[SyncResource, ISyncResourcePreview][]> { - if (!this.previews) { - throw new Error('Missing preview. Create preview and try again.'); - } - if (this.synchronizingResources.length) { - throw new Error('Cannot discard while synchronizing resources'); - } + try { + if (!this.previews) { + throw new Error('Missing preview. Create preview and try again.'); + } + if (this.synchronizingResources.length) { + throw new Error('Cannot discard while synchronizing resources'); + } - const conflictResources: URI[] = []; - for (const [, syncResourcePreview] of this.previews) { - for (const resourcePreview of syncResourcePreview.resourcePreviews) { - if (resourcePreview.mergeState === MergeState.Conflict) { - conflictResources.push(resourcePreview.previewResource); + const conflictResources: URI[] = []; + for (const [, syncResourcePreview] of this.previews) { + for (const resourcePreview of syncResourcePreview.resourcePreviews) { + if (resourcePreview.mergeState === MergeState.Conflict) { + conflictResources.push(resourcePreview.previewResource); + } } } - } - for (const resource of conflictResources) { - await this.discard(resource); + for (const resource of conflictResources) { + await this.discard(resource); + } + return this.previews; + } catch (error) { + this.logService.error(error); + throw error; } - return this.previews; } async apply(): Promise<[SyncResource, ISyncResourcePreview][]> { - if (!this.previews) { - throw new Error('You need to create preview before applying'); - } - if (this.synchronizingResources.length) { - throw new Error('Cannot pull while synchronizing resources'); - } - const previews: [SyncResource, ISyncResourcePreview][] = []; - for (const [syncResource, preview] of this.previews) { - this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); - this._onSynchronizeResources.fire(this.synchronizingResources); + try { + if (!this.previews) { + throw new Error('You need to create preview before applying'); + } + if (this.synchronizingResources.length) { + throw new Error('Cannot pull while synchronizing resources'); + } + const previews: [SyncResource, ISyncResourcePreview][] = []; + for (const [syncResource, preview] of this.previews) { + this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); + this._onSynchronizeResources.fire(this.synchronizingResources); - const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; + const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; - /* merge those which are not yet merged */ - for (const resourcePreview of preview.resourcePreviews) { - if ((resourcePreview.localChange !== Change.None || resourcePreview.remoteChange !== Change.None) && resourcePreview.mergeState === MergeState.Preview) { - await synchroniser.merge(resourcePreview.previewResource); + /* merge those which are not yet merged */ + for (const resourcePreview of preview.resourcePreviews) { + if ((resourcePreview.localChange !== Change.None || resourcePreview.remoteChange !== Change.None) && resourcePreview.mergeState === MergeState.Preview) { + await synchroniser.merge(resourcePreview.previewResource); + } } - } - /* apply */ - const newPreview = await synchroniser.apply(false, this.syncHeaders); - if (newPreview) { - previews.push(this.toSyncResourcePreview(synchroniser.resource, newPreview)); - } + /* apply */ + const newPreview = await synchroniser.apply(false, this.syncHeaders); + if (newPreview) { + previews.push(this.toSyncResourcePreview(synchroniser.resource, newPreview)); + } - this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); - this._onSynchronizeResources.fire(this.synchronizingResources); + this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); + this._onSynchronizeResources.fire(this.synchronizingResources); + } + this.previews = previews; + return this.previews; + } catch (error) { + this.logService.error(error); + throw error; } - this.previews = previews; - return this.previews; } async pull(): Promise { - if (!this.previews) { - throw new Error('You need to create preview before applying'); - } - if (this.synchronizingResources.length) { - throw new Error('Cannot pull while synchronizing resources'); - } - for (const [syncResource, preview] of this.previews) { - this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); - this._onSynchronizeResources.fire(this.synchronizingResources); - const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; - for (const resourcePreview of preview.resourcePreviews) { - await synchroniser.accept(resourcePreview.remoteResource); + try { + if (!this.previews) { + throw new Error('You need to create preview before applying'); } - await synchroniser.apply(true, this.syncHeaders); - this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); - this._onSynchronizeResources.fire(this.synchronizingResources); + if (this.synchronizingResources.length) { + throw new Error('Cannot pull while synchronizing resources'); + } + for (const [syncResource, preview] of this.previews) { + this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); + this._onSynchronizeResources.fire(this.synchronizingResources); + const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; + for (const resourcePreview of preview.resourcePreviews) { + await synchroniser.accept(resourcePreview.remoteResource); + } + await synchroniser.apply(true, this.syncHeaders); + this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); + this._onSynchronizeResources.fire(this.synchronizingResources); + } + this.previews = []; + } catch (error) { + this.logService.error(error); + throw error; } - this.previews = []; } async push(): Promise { - if (!this.previews) { - throw new Error('You need to create preview before applying'); - } - if (this.synchronizingResources.length) { - throw new Error('Cannot pull while synchronizing resources'); - } - for (const [syncResource, preview] of this.previews) { - this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); - this._onSynchronizeResources.fire(this.synchronizingResources); - const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; - for (const resourcePreview of preview.resourcePreviews) { - await synchroniser.accept(resourcePreview.localResource); + try { + if (!this.previews) { + throw new Error('You need to create preview before applying'); } - await synchroniser.apply(true, this.syncHeaders); - this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); - this._onSynchronizeResources.fire(this.synchronizingResources); + if (this.synchronizingResources.length) { + throw new Error('Cannot pull while synchronizing resources'); + } + for (const [syncResource, preview] of this.previews) { + this.synchronizingResources.push([syncResource, preview.resourcePreviews.map(r => r.localResource)]); + this._onSynchronizeResources.fire(this.synchronizingResources); + const synchroniser = this.synchronisers.find(s => s.resource === syncResource)!; + for (const resourcePreview of preview.resourcePreviews) { + await synchroniser.accept(resourcePreview.localResource); + } + await synchroniser.apply(true, this.syncHeaders); + this.synchronizingResources.splice(this.synchronizingResources.findIndex(s => s[0] === syncResource), 1); + this._onSynchronizeResources.fire(this.synchronizingResources); + } + this.previews = []; + } catch (error) { + this.logService.error(error); + throw error; } - this.previews = []; } async stop(): Promise { From 44c9b4bb7f3c207e68bccffc806f93b828560f0d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 11:26:10 +0100 Subject: [PATCH 1715/1837] use TrustedFunction workaround when loading extension sources inside web worker --- .../electron-browser/workbench/workbench.html | 2 +- .../api/worker/extHostExtensionService.ts | 35 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/vs/code/electron-browser/workbench/workbench.html b/src/vs/code/electron-browser/workbench/workbench.html index 25ea4acfa0e..12f380b55d4 100644 --- a/src/vs/code/electron-browser/workbench/workbench.html +++ b/src/vs/code/electron-browser/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index 82a203344cc..5c925cc7366 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -12,6 +12,31 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; import { timeout } from 'vs/base/common/async'; +namespace TrustedFunction { + + // workaround a chrome issue not allowing to create new functions + // see https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor + const ttpTrustedFunction = self.trustedTypes?.createPolicy('TrustedFunctionWorkaround', { + createScript: (_, ...args: string[]) => { + args.forEach((arg) => { + if (!self.trustedTypes?.isScript(arg)) { + throw new Error('TrustedScripts only, please'); + } + }); + // NOTE: This is insecure without parsing the arguments and body, + // Malicious inputs can escape the function body and execute immediately! + const fnArgs = args.slice(0, -1).join(','); + const fnBody = args.pop()!.toString(); + const body = `(function anonymous(${fnArgs}) {\n${fnBody}\n})`; + return body; + } + }); + + export function create(...args: string[]): Function { + return self.eval(ttpTrustedFunction?.createScript('', ...args) as unknown as string); + } +} + class WorkerRequireInterceptor extends RequireInterceptor { _installInterceptor() { } @@ -35,6 +60,8 @@ class WorkerRequireInterceptor extends RequireInterceptor { export class ExtHostExtensionService extends AbstractExtHostExtensionService { readonly extensionRuntime = ExtensionRuntime.Webworker; + private static _ttpExtensionScripts = self.trustedTypes?.createPolicy('ExtensionScripts', { createScript: source => source }); + private _fakeModules?: WorkerRequireInterceptor; protected async _beforeAlmostReadyToRunExtensions(): Promise { @@ -71,9 +98,15 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { // Here we append #vscode-extension to serve as a marker, such that source maps // can be adjusted for the extra wrapping function. const sourceURL = `${module.toString(true)}#vscode-extension`; + const fullSource = `${source}\n//# sourceURL=${sourceURL}`; let initFn: Function; try { - initFn = new Function('module', 'exports', 'require', `${source}\n//# sourceURL=${sourceURL}`); + initFn = TrustedFunction.create( + ExtHostExtensionService._ttpExtensionScripts?.createScript('module') as unknown as string ?? 'module', + ExtHostExtensionService._ttpExtensionScripts?.createScript('exports') as unknown as string ?? 'exports', + ExtHostExtensionService._ttpExtensionScripts?.createScript('require') as unknown as string ?? 'require', + ExtHostExtensionService._ttpExtensionScripts?.createScript(fullSource) as unknown as string ?? fullSource + ); } catch (err) { if (extensionId) { console.error(`Loading code for extension ${extensionId.value} failed: ${err.message}`); From ed6c343edb720d91ee0859e566c84b5687f5a9d5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 11:30:42 +0100 Subject: [PATCH 1716/1837] gracefull fallback for TrustedFunction --- src/vs/workbench/api/worker/extHostExtensionService.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index 5c925cc7366..fb48c617355 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -33,7 +33,10 @@ namespace TrustedFunction { }); export function create(...args: string[]): Function { - return self.eval(ttpTrustedFunction?.createScript('', ...args) as unknown as string); + if (!ttpTrustedFunction) { + return new Function(...args); + } + return self.eval(ttpTrustedFunction.createScript('', ...args) as unknown as string); } } From 5adcd2521e9be045553fa0f02fee7ca5381165e7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 11:58:25 +0100 Subject: [PATCH 1717/1837] Fix #113257 --- .../extensions/browser/extensions.contribution.ts | 2 +- .../contrib/extensions/browser/extensionsActions.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index fab860c4bcb..4cb6024b20f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -526,7 +526,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi try { await this.extensionsWorkbenchService.install(extension); } catch (err) { - runAction(this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, InstallOperation.Update, err)); + runAction(this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, extension.latestVersion, InstallOperation.Update, err)); } })); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index a2bb18373cb..8b630a9249e 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -98,6 +98,7 @@ export class PromptExtensionInstallFailureAction extends Action { constructor( private readonly extension: IExtension, + private readonly version: string, private readonly installOperation: InstallOperation, private readonly error: Error, @IProductService private readonly productService: IProductService, @@ -128,7 +129,7 @@ export class PromptExtensionInstallFailureAction extends Action { if (this.extension.gallery && this.productService.extensionsGallery) { promptChoices.push({ label: localize('download', "Try Downloading Manually..."), - run: () => this.openerService.open(URI.parse(`${this.productService.extensionsGallery!.serviceUrl}/publishers/${this.extension.publisher}/vsextensions/${this.extension.name}/${this.extension.version}/vspackage`)).then(() => { + run: () => this.openerService.open(URI.parse(`${this.productService.extensionsGallery!.serviceUrl}/publishers/${this.extension.publisher}/vsextensions/${this.extension.name}/${this.version}/vspackage`)).then(() => { this.notificationService.prompt( Severity.Info, localize('install vsix', 'Once downloaded, please manually install the downloaded VSIX of \'{0}\'.', this.extension.identifier.id), @@ -277,7 +278,7 @@ export abstract class AbstractInstallAction extends ExtensionAction { try { return await this.extensionsWorkbenchService.install(extension, this.getInstallOptions()); } catch (error) { - await this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, InstallOperation.Install, error).run(); + await this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, extension.latestVersion, InstallOperation.Install, error).run(); return undefined; } } @@ -705,7 +706,7 @@ export class UpdateAction extends ExtensionAction { await this.extensionsWorkbenchService.install(extension); alert(localize('updateExtensionComplete', "Updating extension {0} to version {1} completed.", extension.displayName, extension.latestVersion)); } catch (err) { - this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, InstallOperation.Update, err).run(); + this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, extension.latestVersion, InstallOperation.Update, err).run(); } } @@ -1053,7 +1054,7 @@ export class InstallAnotherVersionAction extends ExtensionAction { await this.extensionsWorkbenchService.installVersion(this.extension!, pick.id); } } catch (error) { - this.instantiationService.createInstance(PromptExtensionInstallFailureAction, this.extension!, InstallOperation.Install, error).run(); + this.instantiationService.createInstance(PromptExtensionInstallFailureAction, this.extension!, pick.latest ? this.extension!.latestVersion : pick.id, InstallOperation.Install, error).run(); } } return null; @@ -1641,7 +1642,7 @@ export class InstallRecommendedExtensionAction extends Action { try { await this.extensionWorkbenchService.install(extension); } catch (err) { - this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, InstallOperation.Install, err).run(); + this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, extension.latestVersion, InstallOperation.Install, err).run(); } } } From ca6a7a699893a7d0a2be4cf2865162e43ca7f70f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 11:44:02 +0100 Subject: [PATCH 1718/1837] :lipstick: --- .../services/extensions/browser/webWorkerExtensionHost.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index a061c8b9454..1f3eb2032eb 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -229,7 +229,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost const emitter = new Emitter(); const url = getWorkerBootstrapUrl(FileAccess.asBrowserUri('../worker/extensionHostWorkerMain.js', require).toString(true), 'WorkerExtensionHost'); - const worker = new Worker(ttPolicy ? ttPolicy.createScriptURL(url) as unknown as string : url, { name: 'WorkerExtensionHost' }); + const worker = new Worker(ttPolicy?.createScriptURL(url) as unknown as string ?? url, { name: 'WorkerExtensionHost' }); const barrier = new Barrier(); let port!: MessagePort; From a5a0c1527d16edc72f42467a5de4039b38c0f91b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 12:00:42 +0100 Subject: [PATCH 1719/1837] add tsec config and exemption file (defunct?) --- package.json | 2 +- src/tsec.exemptions.json | 5 +++++ src/tsec.tsconfig.json | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/tsec.exemptions.json create mode 100644 src/tsec.tsconfig.json diff --git a/package.json b/package.json index 40676799076..edc7afb9bc4 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "smoketest": "cd test/smoke && node test/index.js", "download-builtin-extensions": "node build/lib/builtInExtensions.js", "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", - "tsec-compile-check": "node node_modules/vscode-tsec/bin/tsec -p src/tsconfig.json --noEmit", + "tsec-compile-check": "node node_modules/vscode-tsec/bin/tsec -p src/tsec.tsconfig.json", "valid-layers-check": "node build/lib/layersChecker.js", "strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes", "update-distro": "node build/npm/update-distro.js", diff --git a/src/tsec.exemptions.json b/src/tsec.exemptions.json new file mode 100644 index 00000000000..dc1e805868f --- /dev/null +++ b/src/tsec.exemptions.json @@ -0,0 +1,5 @@ +{ + "ban-trustedtypes-createpolicy": [ + "**/*.ts" + ] +} diff --git a/src/tsec.tsconfig.json b/src/tsec.tsconfig.json new file mode 100644 index 00000000000..c0b7ef95ff9 --- /dev/null +++ b/src/tsec.tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "plugins": [ + { + "name": "tsec", + "exemptionConfig": "./tsec.exemptions.json" + } + ] + } +} From 6d2e0aa21d386fbc4096c6a801b9248b866a0c6d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 12:10:51 +0100 Subject: [PATCH 1720/1837] rename tsc config file for better intellisense --- package.json | 2 +- src/{tsec.tsconfig.json => tsconfig.tsec.json} | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) rename src/{tsec.tsconfig.json => tsconfig.tsec.json} (76%) diff --git a/package.json b/package.json index edc7afb9bc4..ba7cd3439fb 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "smoketest": "cd test/smoke && node test/index.js", "download-builtin-extensions": "node build/lib/builtInExtensions.js", "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", - "tsec-compile-check": "node node_modules/vscode-tsec/bin/tsec -p src/tsec.tsconfig.json", + "tsec-compile-check": "node node_modules/vscode-tsec/bin/tsec -p src/tsconfig.tsec.json", "valid-layers-check": "node build/lib/layersChecker.js", "strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes", "update-distro": "node build/npm/update-distro.js", diff --git a/src/tsec.tsconfig.json b/src/tsconfig.tsec.json similarity index 76% rename from src/tsec.tsconfig.json rename to src/tsconfig.tsec.json index c0b7ef95ff9..d2524df22d4 100644 --- a/src/tsec.tsconfig.json +++ b/src/tsconfig.tsec.json @@ -8,5 +8,9 @@ "exemptionConfig": "./tsec.exemptions.json" } ] - } + }, + "exclude": [ + "*/test/*", + "**/*.test.ts" + ] } From 5ed73f6e850bd1814b237c15127c0dfd447c54d9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 12:27:42 +0100 Subject: [PATCH 1721/1837] don't theme icon for MD elements --- .../browser/contrib/outline/notebookOutline.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts index ce8c79f31d6..47c1e9dd0c3 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts @@ -154,15 +154,17 @@ class NotebookOutlineRenderer implements ITreeRenderer, _index: number, template: NotebookOutlineTemplate, _height: number | undefined): void { - template.iconLabel.setLabel(element.element.label, undefined, { matches: createMatches(element.filterData) }); - if (this._themeService.getFileIconTheme().hasFileIcons) { - template.iconClass.className = 'element-icon ' + getIconClassesForModeId(element.element.cell.language ?? '').join(' '); + renderElement(node: ITreeNode, _index: number, template: NotebookOutlineTemplate, _height: number | undefined): void { + template.iconLabel.setLabel(node.element.label, undefined, { matches: createMatches(node.filterData) }); + + // code cells get to use their file icon (assuming the theme supports that) + if (node.element.cell.cellKind === CellKind.Code && this._themeService.getFileIconTheme().hasFileIcons) { + template.iconClass.className = 'element-icon ' + getIconClassesForModeId(node.element.cell.language ?? '').join(' '); } else { - template.iconClass.className = 'element-icon ' + ThemeIcon.asClassNameArray(element.element.icon).join(' '); + template.iconClass.className = 'element-icon ' + ThemeIcon.asClassNameArray(node.element.icon).join(' '); } - const { markerInfo } = element.element; + const { markerInfo } = node.element; template.container.style.removeProperty('--outline-element-color'); template.decoration.innerText = ''; From 288e8c233a8ac03bec99d8d91a85d718382b5d09 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 13:16:36 +0100 Subject: [PATCH 1722/1837] Fix #110525 --- .../browser/parts/activitybar/activitybarPart.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e81de005a86..ae19d9af659 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -653,7 +653,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } else { const cachedComposite = this.cachedViewContainers.filter(c => c.id === compositeId)[0]; compositeActions = { - activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined)), + activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined, true)), pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar) }; } @@ -720,15 +720,15 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private toActivity({ id, focusCommand }: ViewContainer, { icon, title: name }: IViewContainerModel): IActivity { - return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id); + return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id, false); } - private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined): IActivity { + private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined, placeholder: boolean): IActivity { let cssClass: string | undefined = undefined; let iconUrl: URI | undefined = undefined; if (URI.isUri(icon)) { iconUrl = icon; - cssClass = `activity-${id.replace(/\./g, '-')}`; + cssClass = `${placeholder ? 'placeholder-' : ''}activity-${id.replace(/\./g, '-')}`; const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`; createCSSRule(iconClass, ` mask: ${asCSSUrl(icon)} no-repeat 50% 50%; From 91a0d07f3e7db3c67dce7fdfa30061d559018633 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 13:38:44 +0100 Subject: [PATCH 1723/1837] Improve `canTunnel` Part of microsoft/vscode-internalbacklog#1709 --- src/vs/platform/remote/common/tunnel.ts | 20 --------- .../remote/browser/tunnelServiceImpl.ts | 43 +++++++++++++++++++ .../electron-browser/tunnelServiceImpl.ts | 9 +++- src/vs/workbench/workbench.web.main.ts | 3 +- 4 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 src/vs/workbench/services/remote/browser/tunnelServiceImpl.ts diff --git a/src/vs/platform/remote/common/tunnel.ts b/src/vs/platform/remote/common/tunnel.ts index ee0709aaac4..7a38ca6e9fa 100644 --- a/src/vs/platform/remote/common/tunnel.ts +++ b/src/vs/platform/remote/common/tunnel.ts @@ -264,24 +264,4 @@ export abstract class AbstractTunnelService implements ITunnelService { protected abstract retainOrCreateTunnel(addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean): Promise | undefined; } -export class TunnelService extends AbstractTunnelService { - protected retainOrCreateTunnel(_addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean): Promise | undefined { - const existing = this.getTunnelFromMap(remoteHost, remotePort); - if (existing) { - ++existing.refcount; - return existing.value; - } - if (this._tunnelProvider) { - const preferredLocalPort = localPort === undefined ? remotePort : localPort; - const tunnelOptions = { remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort }; - const creationInfo = { elevationRequired: elevateIfNeeded ? isPortPrivileged(preferredLocalPort) : false }; - const tunnel = this._tunnelProvider.forwardPort(tunnelOptions, creationInfo); - if (tunnel) { - this.addTunnelToMap(remoteHost, remotePort, tunnel); - } - return tunnel; - } - return undefined; - } -} diff --git a/src/vs/workbench/services/remote/browser/tunnelServiceImpl.ts b/src/vs/workbench/services/remote/browser/tunnelServiceImpl.ts new file mode 100644 index 00000000000..7917fbc5a1e --- /dev/null +++ b/src/vs/workbench/services/remote/browser/tunnelServiceImpl.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { URI } from 'vs/base/common/uri'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection'; +import { AbstractTunnelService, isPortPrivileged, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; + +export class TunnelService extends AbstractTunnelService { + constructor( + @ILogService logService: ILogService, + @IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService + ) { + super(logService); + } + + protected retainOrCreateTunnel(_addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean): Promise | undefined { + const existing = this.getTunnelFromMap(remoteHost, remotePort); + if (existing) { + ++existing.refcount; + return existing.value; + } + + if (this._tunnelProvider) { + const preferredLocalPort = localPort === undefined ? remotePort : localPort; + const tunnelOptions = { remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort }; + const creationInfo = { elevationRequired: elevateIfNeeded ? isPortPrivileged(preferredLocalPort) : false }; + const tunnel = this._tunnelProvider.forwardPort(tunnelOptions, creationInfo); + if (tunnel) { + this.addTunnelToMap(remoteHost, remotePort, tunnel); + } + return tunnel; + } + return undefined; + } + + canTunnel(uri: URI): boolean { + return super.canTunnel(uri) && !!this.environmentService.remoteAuthority; + } +} diff --git a/src/vs/workbench/services/remote/electron-browser/tunnelServiceImpl.ts b/src/vs/workbench/services/remote/electron-browser/tunnelServiceImpl.ts index b74b211066f..92f51dc00d7 100644 --- a/src/vs/workbench/services/remote/electron-browser/tunnelServiceImpl.ts +++ b/src/vs/workbench/services/remote/electron-browser/tunnelServiceImpl.ts @@ -9,14 +9,21 @@ import { ISignService } from 'vs/platform/sign/common/sign'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { BaseTunnelService } from 'vs/platform/remote/node/tunnelService'; import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { URI } from 'vs/base/common/uri'; export class TunnelService extends BaseTunnelService { public constructor( @ILogService logService: ILogService, @ISignService signService: ISignService, @IProductService productService: IProductService, - @IRemoteAgentService _remoteAgentService: IRemoteAgentService + @IRemoteAgentService _remoteAgentService: IRemoteAgentService, + @IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService ) { super(nodeSocketFactory, logService, signService, productService); } + + canTunnel(uri: URI): boolean { + return super.canTunnel(uri) && !!this.environmentService.remoteAuthority; + } } diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index bc640014d69..f3a1eb84cd2 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -67,7 +67,8 @@ import { IExtensionTipsService } from 'vs/platform/extensionManagement/common/ex import { ExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionTipsService'; import { IWorkbenchExtensioManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService'; -import { ITunnelService, TunnelService } from 'vs/platform/remote/common/tunnel'; +import { ITunnelService } from 'vs/platform/remote/common/tunnel'; +import { TunnelService } from 'vs/workbench/services/remote/browser/tunnelServiceImpl'; import { ILoggerService } from 'vs/platform/log/common/log'; import { FileLoggerService } from 'vs/platform/log/common/fileLogService'; import { UserDataSyncMachinesService, IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines'; From fe175afdb80bd7a28caae83028e7440b45698007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 8 Jan 2021 13:30:34 +0100 Subject: [PATCH 1724/1837] list widget should not remove rows from DOM when reusing fix #112621 --- src/vs/base/browser/ui/list/listView.ts | 112 ++++++++---- src/vs/base/browser/ui/list/rowCache.ts | 3 +- .../test/browser/ui/tree/objectTree.test.ts | 168 ++++++++---------- .../contrib/scm/browser/scmViewPane.ts | 10 -- 4 files changed, 155 insertions(+), 138 deletions(-) diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 5fd727bb24d..b26c34c9517 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -432,8 +432,24 @@ export class ListView implements ISpliceable, IDisposable { const deleteRange = { start, end: start + deleteCount }; const removeRange = Range.intersect(previousRenderRange, deleteRange); + // try to reuse rows, avoid removing them from DOM + const rowsToDispose = new Map(); for (let i = removeRange.start; i < removeRange.end; i++) { - this.removeItemFromDOM(i); + const item = this.items[i]; + item.dragStartDisposable.dispose(); + + if (item.row) { + let rows = rowsToDispose.get(item.templateId); + + if (!rows) { + rows = []; + rowsToDispose.set(item.templateId, rows); + } + + rows.push([item.row, item.element, i, item.size]); + } + + item.row = null; } const previousRestRange: IRange = { start: start + deleteCount, end: this.items.length }; @@ -491,7 +507,24 @@ export class ListView implements ISpliceable, IDisposable { for (const range of insertRanges) { for (let i = range.start; i < range.end; i++) { - this.insertItemInDOM(i, beforeElement); + const item = this.items[i]; + const rows = rowsToDispose.get(item.templateId); + const rowData = rows?.pop(); + const row = rowData && rowData[0]; // try to reuse a row + + this.insertItemInDOM(i, beforeElement, row); + } + } + + for (const [templateId, rows] of rowsToDispose) { + for (const [row, element, index, size] of rows) { + const renderer = this.renderers.get(templateId); + + if (renderer && renderer.disposeElement) { + renderer.disposeElement(element, index, row.templateData, size); + } + + this.cache.release(row); } } @@ -699,24 +732,26 @@ export class ListView implements ISpliceable, IDisposable { // DOM operations - private insertItemInDOM(index: number, beforeElement: HTMLElement | null): void { + private insertItemInDOM(index: number, beforeElement: HTMLElement | null, row?: IRow): void { const item = this.items[index]; if (!item.row) { - item.row = this.cache.alloc(item.templateId); - const role = this.accessibilityProvider.getRole(item.element) || 'listitem'; - item.row!.domNode!.setAttribute('role', role); - const checked = this.accessibilityProvider.isChecked(item.element); - if (typeof checked !== 'undefined') { - item.row!.domNode!.setAttribute('aria-checked', String(!!checked)); - } + item.row = row ?? this.cache.alloc(item.templateId); } - if (!item.row.domNode!.parentElement) { + const role = this.accessibilityProvider.getRole(item.element) || 'listitem'; + item.row.domNode.setAttribute('role', role); + + const checked = this.accessibilityProvider.isChecked(item.element); + if (typeof checked !== 'undefined') { + item.row.domNode.setAttribute('aria-checked', String(!!checked)); + } + + if (!item.row.domNode.parentElement) { if (beforeElement) { - this.rowsContainer.insertBefore(item.row.domNode!, beforeElement); + this.rowsContainer.insertBefore(item.row.domNode, beforeElement); } else { - this.rowsContainer.appendChild(item.row.domNode!); + this.rowsContainer.appendChild(item.row.domNode); } } @@ -734,10 +769,10 @@ export class ListView implements ISpliceable, IDisposable { const uri = this.dnd.getDragURI(item.element); item.dragStartDisposable.dispose(); - item.row.domNode!.draggable = !!uri; + item.row.domNode.draggable = !!uri; if (uri) { - const onDragStart = domEvent(item.row.domNode!, 'dragstart'); + const onDragStart = domEvent(item.row.domNode, 'dragstart'); item.dragStartDisposable = onDragStart(event => this.onDragStart(item.element, uri, event)); } @@ -768,36 +803,39 @@ export class ListView implements ISpliceable, IDisposable { } private updateItemInDOM(item: IItem, index: number): void { - item.row!.domNode!.style.top = `${this.elementTop(index)}px`; + item.row!.domNode.style.top = `${this.elementTop(index)}px`; if (this.setRowHeight) { - item.row!.domNode!.style.height = `${item.size}px`; + item.row!.domNode.style.height = `${item.size}px`; } if (this.setRowLineHeight) { - item.row!.domNode!.style.lineHeight = `${item.size}px`; + item.row!.domNode.style.lineHeight = `${item.size}px`; } - item.row!.domNode!.setAttribute('data-index', `${index}`); - item.row!.domNode!.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false'); - item.row!.domNode!.setAttribute('aria-setsize', String(this.accessibilityProvider.getSetSize(item.element, index, this.length))); - item.row!.domNode!.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index))); - item.row!.domNode!.setAttribute('id', this.getElementDomId(index)); + item.row!.domNode.setAttribute('data-index', `${index}`); + item.row!.domNode.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false'); + item.row!.domNode.setAttribute('aria-setsize', String(this.accessibilityProvider.getSetSize(item.element, index, this.length))); + item.row!.domNode.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index))); + item.row!.domNode.setAttribute('id', this.getElementDomId(index)); - item.row!.domNode!.classList.toggle('drop-target', item.dropTarget); + item.row!.domNode.classList.toggle('drop-target', item.dropTarget); } private removeItemFromDOM(index: number): void { const item = this.items[index]; item.dragStartDisposable.dispose(); - const renderer = this.renderers.get(item.templateId); - if (item.row && renderer && renderer.disposeElement) { - renderer.disposeElement(item.element, index, item.row.templateData, item.size); - } + if (item.row) { + const renderer = this.renderers.get(item.templateId); - this.cache.release(item.row!); - item.row = null; + if (renderer && renderer.disposeElement) { + renderer.disposeElement(item.element, index, item.row.templateData, item.size); + } + + this.cache.release(item.row); + item.row = null; + } if (this.horizontalScrolling) { this.eventuallyUpdateScrollWidth(); @@ -1025,7 +1063,7 @@ export class ListView implements ISpliceable, IDisposable { const item = this.items[index]!; item.dropTarget = true; - if (item.row && item.row.domNode) { + if (item.row) { item.row.domNode.classList.add('drop-target'); } } @@ -1035,7 +1073,7 @@ export class ListView implements ISpliceable, IDisposable { const item = this.items[index]!; item.dropTarget = false; - if (item.row && item.row.domNode) { + if (item.row) { item.row.domNode.classList.remove('drop-target'); } } @@ -1261,7 +1299,7 @@ export class ListView implements ISpliceable, IDisposable { const size = item.size; - if (!this.setRowHeight && item.row && item.row.domNode) { + if (!this.setRowHeight && item.row) { let newSize = item.row.domNode.offsetHeight; item.size = newSize; item.lastDynamicHeightWidth = this.renderWidth; @@ -1270,8 +1308,8 @@ export class ListView implements ISpliceable, IDisposable { const row = this.cache.alloc(item.templateId); - row.domNode!.style.height = ''; - this.rowsContainer.appendChild(row.domNode!); + row.domNode.style.height = ''; + this.rowsContainer.appendChild(row.domNode); const renderer = this.renderers.get(item.templateId); if (renderer) { @@ -1282,14 +1320,14 @@ export class ListView implements ISpliceable, IDisposable { } } - item.size = row.domNode!.offsetHeight; + item.size = row.domNode.offsetHeight; if (this.virtualDelegate.setDynamicHeight) { this.virtualDelegate.setDynamicHeight(item.element, item.size); } item.lastDynamicHeightWidth = this.renderWidth; - this.rowsContainer.removeChild(row.domNode!); + this.rowsContainer.removeChild(row.domNode); this.cache.release(row); return item.size - size; diff --git a/src/vs/base/browser/ui/list/rowCache.ts b/src/vs/base/browser/ui/list/rowCache.ts index 953a11d13b4..2c49f3a415a 100644 --- a/src/vs/base/browser/ui/list/rowCache.ts +++ b/src/vs/base/browser/ui/list/rowCache.ts @@ -8,7 +8,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { $ } from 'vs/base/browser/dom'; export interface IRow { - domNode: HTMLElement | null; + domNode: HTMLElement; templateId: string; templateData: any; } @@ -84,7 +84,6 @@ export class RowCache implements IDisposable { for (const cachedRow of cachedRows) { const renderer = this.getRenderer(templateId); renderer.disposeTemplate(cachedRow.templateData); - cachedRow.domNode = null; cachedRow.templateData = null; } }); diff --git a/src/vs/base/test/browser/ui/tree/objectTree.test.ts b/src/vs/base/test/browser/ui/tree/objectTree.test.ts index 166a99c00b3..bb54623b864 100644 --- a/src/vs/base/test/browser/ui/tree/objectTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/objectTree.test.ts @@ -59,30 +59,30 @@ suite('ObjectTree', function () { const navigator = tree.navigate(); - assert.equal(navigator.current(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.current(), 0); - assert.equal(navigator.next(), 10); - assert.equal(navigator.current(), 10); - assert.equal(navigator.next(), 11); - assert.equal(navigator.current(), 11); - assert.equal(navigator.next(), 12); - assert.equal(navigator.current(), 12); - assert.equal(navigator.next(), 1); - assert.equal(navigator.current(), 1); - assert.equal(navigator.next(), 2); - assert.equal(navigator.current(), 2); - assert.equal(navigator.previous(), 1); - assert.equal(navigator.current(), 1); - assert.equal(navigator.previous(), 12); - assert.equal(navigator.previous(), 11); - assert.equal(navigator.previous(), 10); - assert.equal(navigator.previous(), 0); - assert.equal(navigator.previous(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.next(), 10); - assert.equal(navigator.first(), 0); - assert.equal(navigator.last(), 2); + assert.strictEqual(navigator.current(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.current(), 0); + assert.strictEqual(navigator.next(), 10); + assert.strictEqual(navigator.current(), 10); + assert.strictEqual(navigator.next(), 11); + assert.strictEqual(navigator.current(), 11); + assert.strictEqual(navigator.next(), 12); + assert.strictEqual(navigator.current(), 12); + assert.strictEqual(navigator.next(), 1); + assert.strictEqual(navigator.current(), 1); + assert.strictEqual(navigator.next(), 2); + assert.strictEqual(navigator.current(), 2); + assert.strictEqual(navigator.previous(), 1); + assert.strictEqual(navigator.current(), 1); + assert.strictEqual(navigator.previous(), 12); + assert.strictEqual(navigator.previous(), 11); + assert.strictEqual(navigator.previous(), 10); + assert.strictEqual(navigator.previous(), 0); + assert.strictEqual(navigator.previous(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.next(), 10); + assert.strictEqual(navigator.first(), 0); + assert.strictEqual(navigator.last(), 2); }); test('should skip collapsed nodes', () => { @@ -100,18 +100,18 @@ suite('ObjectTree', function () { const navigator = tree.navigate(); - assert.equal(navigator.current(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.next(), 1); - assert.equal(navigator.next(), 2); - assert.equal(navigator.next(), null); - assert.equal(navigator.previous(), 2); - assert.equal(navigator.previous(), 1); - assert.equal(navigator.previous(), 0); - assert.equal(navigator.previous(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.first(), 0); - assert.equal(navigator.last(), 2); + assert.strictEqual(navigator.current(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.next(), 1); + assert.strictEqual(navigator.next(), 2); + assert.strictEqual(navigator.next(), null); + assert.strictEqual(navigator.previous(), 2); + assert.strictEqual(navigator.previous(), 1); + assert.strictEqual(navigator.previous(), 0); + assert.strictEqual(navigator.previous(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.first(), 0); + assert.strictEqual(navigator.last(), 2); }); test('should skip filtered elements', () => { @@ -131,21 +131,21 @@ suite('ObjectTree', function () { const navigator = tree.navigate(); - assert.equal(navigator.current(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.next(), 10); - assert.equal(navigator.next(), 12); - assert.equal(navigator.next(), 2); - assert.equal(navigator.next(), null); - assert.equal(navigator.previous(), 2); - assert.equal(navigator.previous(), 12); - assert.equal(navigator.previous(), 10); - assert.equal(navigator.previous(), 0); - assert.equal(navigator.previous(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.next(), 10); - assert.equal(navigator.first(), 0); - assert.equal(navigator.last(), 2); + assert.strictEqual(navigator.current(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.next(), 10); + assert.strictEqual(navigator.next(), 12); + assert.strictEqual(navigator.next(), 2); + assert.strictEqual(navigator.next(), null); + assert.strictEqual(navigator.previous(), 2); + assert.strictEqual(navigator.previous(), 12); + assert.strictEqual(navigator.previous(), 10); + assert.strictEqual(navigator.previous(), 0); + assert.strictEqual(navigator.previous(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.next(), 10); + assert.strictEqual(navigator.first(), 0); + assert.strictEqual(navigator.last(), 2); }); test('should be able to start from node', () => { @@ -163,20 +163,20 @@ suite('ObjectTree', function () { const navigator = tree.navigate(1); - assert.equal(navigator.current(), 1); - assert.equal(navigator.next(), 2); - assert.equal(navigator.current(), 2); - assert.equal(navigator.previous(), 1); - assert.equal(navigator.current(), 1); - assert.equal(navigator.previous(), 12); - assert.equal(navigator.previous(), 11); - assert.equal(navigator.previous(), 10); - assert.equal(navigator.previous(), 0); - assert.equal(navigator.previous(), null); - assert.equal(navigator.next(), 0); - assert.equal(navigator.next(), 10); - assert.equal(navigator.first(), 0); - assert.equal(navigator.last(), 2); + assert.strictEqual(navigator.current(), 1); + assert.strictEqual(navigator.next(), 2); + assert.strictEqual(navigator.current(), 2); + assert.strictEqual(navigator.previous(), 1); + assert.strictEqual(navigator.current(), 1); + assert.strictEqual(navigator.previous(), 12); + assert.strictEqual(navigator.previous(), 11); + assert.strictEqual(navigator.previous(), 10); + assert.strictEqual(navigator.previous(), 0); + assert.strictEqual(navigator.previous(), null); + assert.strictEqual(navigator.next(), 0); + assert.strictEqual(navigator.next(), 10); + assert.strictEqual(navigator.first(), 0); + assert.strictEqual(navigator.last(), 2); }); }); @@ -219,10 +219,10 @@ suite('ObjectTree', function () { }); }); -function toArray(list: NodeList): Node[] { - const result: Node[] = []; - list.forEach(node => result.push(node)); - return result; +function getRowsTextContent(container: HTMLElement): string[] { + const rows = [...container.querySelectorAll('.monaco-list-row')]; + rows.sort((a, b) => parseInt(a.getAttribute('data-index')!) - parseInt(b.getAttribute('data-index')!)); + return rows.map(row => row.querySelector('.monaco-tl-contents')!.textContent!); } suite('CompressibleObjectTree', function () { @@ -254,8 +254,7 @@ suite('CompressibleObjectTree', function () { const tree = new CompressibleObjectTree('test', container, new Delegate(), [new Renderer()]); tree.layout(200); - const rows = toArray(container.querySelectorAll('.monaco-tl-contents')); - assert.equal(rows.length, 0); + assert.strictEqual(getRowsTextContent(container).length, 0); }); test('simple', function () { @@ -278,8 +277,7 @@ suite('CompressibleObjectTree', function () { { element: 2 } ]); - const rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['0', '10', '11', '12', '1', '2']); + assert.deepStrictEqual(getRowsTextContent(container), ['0', '10', '11', '12', '1', '2']); }); test('compressed', () => { @@ -304,8 +302,7 @@ suite('CompressibleObjectTree', function () { } ]); - let rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11/111', '1111', '1112', '1113']); tree.setChildren(11, [ { element: 111 }, @@ -313,30 +310,26 @@ suite('CompressibleObjectTree', function () { { element: 113 }, ]); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11', '111', '112', '113']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11', '111', '112', '113']); tree.setChildren(113, [ { element: 1131 } ]); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11', '111', '112', '113/1131']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11', '111', '112', '113/1131']); tree.setChildren(1131, [ { element: 1132 } ]); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11', '111', '112', '113/1131/1132']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11', '111', '112', '113/1131/1132']); tree.setChildren(1131, [ { element: 1132 }, { element: 1133 }, ]); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11', '111', '112', '113/1131', '1132', '1133']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11', '111', '112', '113/1131', '1132', '1133']); }); test('enableCompression', () => { @@ -361,15 +354,12 @@ suite('CompressibleObjectTree', function () { } ]); - let rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11/111', '1111', '1112', '1113']); tree.updateOptions({ compressionEnabled: false }); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1', '11', '111', '1111', '1112', '1113']); + assert.deepStrictEqual(getRowsTextContent(container), ['1', '11', '111', '1111', '1112', '1113']); tree.updateOptions({ compressionEnabled: true }); - rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent); - assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']); + assert.deepStrictEqual(getRowsTextContent(container), ['1/11/111', '1111', '1112', '1113']); }); }); diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 83ddb8e7f2d..c23ca4e9fd3 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -954,8 +954,6 @@ class ViewModel { } private refresh(item?: IRepositoryItem | IGroupItem): void { - const focusedInput = this.inputRenderer.getFocusedInput(); - if (!this.alwaysShowRepositories && (this.items.size === 1 && (!item || isRepositoryItem(item)))) { const item = Iterable.first(this.items.values())!; this.tree.setChildren(null, this.render(item, this._treeViewState).children); @@ -966,14 +964,6 @@ class ViewModel { this.tree.setChildren(null, items.map(item => this.render(item, this._treeViewState))); } - if (focusedInput) { - const inputWidget = this.inputRenderer.getRenderedInputWidget(focusedInput); - - if (inputWidget) { - inputWidget.focus(); - } - } - this._onDidChangeRepositoryCollapseState.fire(); } From 174259eec8f8480898af80077f47056d6ff3e78e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 8 Jan 2021 05:46:44 -0800 Subject: [PATCH 1725/1837] Log when lsof fails and return initial Fixes #113662 --- src/vs/workbench/contrib/terminal/node/terminalProcess.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 1230e376a81..e0abbb31873 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -341,8 +341,11 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } this._logService.trace('IPty#pid'); exec('lsof -OPln -p ' + this._ptyProcess.pid + ' | grep cwd', (error, stdout, stderr) => { - if (stdout !== '') { + if (!error && stdout !== '') { resolve(stdout.substring(stdout.indexOf('/'), stdout.length - 1)); + } else { + this._logService.error('lsof did not run successfully, it may not be on the $PATH?', error, stdout, stderr); + resolve(this._initialCwd); } }); }); From 2042a0e4c23ebcfe0d497fa2064fc1ede3eb24fa Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 15:15:54 +0100 Subject: [PATCH 1726/1837] Add new terminal link text for tunnels (#114033) Fixes microsoft/vscode-internalbacklog#1709 --- .../terminal/browser/links/terminalLinkManager.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index 06071137a57..f3fb0158be9 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -27,6 +27,7 @@ import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { TerminalHover, ILinkHoverTargetOptions } from 'vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget'; import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink'; import { TerminalExternalLinkProviderAdapter } from 'vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter'; +import { ITunnelService } from 'vs/platform/remote/common/tunnel'; export type XtermLinkMatcherHandler = (event: MouseEvent | undefined, link: string) => Promise; export type XtermLinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; @@ -53,7 +54,8 @@ export class TerminalLinkManager extends DisposableStore { @IEditorService private readonly _editorService: IEditorService, @IConfigurationService private readonly _configurationService: IConfigurationService, @IFileService private readonly _fileService: IFileService, - @IInstantiationService private readonly _instantiationService: IInstantiationService + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ITunnelService private readonly _tunnelService: ITunnelService ) { super(); @@ -229,6 +231,13 @@ export class TerminalLinkManager extends DisposableStore { } } + let fallbackLabel: string; + if (this._tunnelService.canTunnel(URI.parse(uri))) { + fallbackLabel = nls.localize('followForwardedLink', "Follow Link using Forwarded Port"); + } else { + fallbackLabel = nls.localize('followLink', "Follow Link"); + } + const markdown = new MarkdownString('', true); // Escapes markdown in label & uri if (label) { @@ -240,7 +249,7 @@ export class TerminalLinkManager extends DisposableStore { markdown.value = ''; } - label = label || nls.localize('followLink', "Follow Link"); + label = label || fallbackLabel; // Use the label when uri is '' so the link displays correctly uri = uri || label; // Although if there is a space in the uri, just replace it completely From 114e38f175e6ba5fca5a5d9b6d4698099ae3bb24 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 15:17:16 +0100 Subject: [PATCH 1727/1837] suggest - add min height when persisting widget height --- src/vs/editor/contrib/suggest/suggestWidget.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index be2697eaf7a..af0c4f6e415 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -701,6 +701,14 @@ export class SuggestWidget implements IDisposable { this._loadingTimeout?.dispose(); this._setState(State.Hidden); this._onDidHide.fire(this); + + // ensure that a reasonable widget height is persisted so that + // accidential "resize-to-single-items" cases aren't happening + const dim = this._persistedSize.restore(); + const minPersistedHeight = Math.ceil(this.getLayoutInfo().itemHeight * 4.3); + if (dim && dim.height < minPersistedHeight) { + this._persistedSize.store(dim.with(undefined, minPersistedHeight)); + } } isFrozen(): boolean { From 61187660af31ae8c567ca39d2f2c16492b7c34c6 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 15:19:14 +0100 Subject: [PATCH 1728/1837] Fix #114031 --- .../test/common/synchronizer.test.ts | 102 +++++++++--------- .../common/userDataAutoSyncService.test.ts | 32 +++--- .../test/common/userDataSyncClient.ts | 24 ++--- .../common/userDataSyncStoreService.test.ts | 6 +- 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/vs/platform/userDataSync/test/common/synchronizer.test.ts b/src/vs/platform/userDataSync/test/common/synchronizer.test.ts index 5d2731d5e13..247391119e1 100644 --- a/src/vs/platform/userDataSync/test/common/synchronizer.test.ts +++ b/src/vs/platform/userDataSync/test/common/synchronizer.test.ts @@ -181,7 +181,7 @@ suite('TestSynchronizer - Auto Sync', () => { teardown(() => disposableStore.clear()); test('status is syncing', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); const actual: SyncStatus[] = []; disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status))); @@ -198,7 +198,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('status is set correctly when sync is finished', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); const actual: SyncStatus[] = []; @@ -210,7 +210,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('status is set correctly when sync has errors', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasError: true, hasConflicts: false }; testObject.syncBarrier.open(); @@ -227,7 +227,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('status is set to hasConflicts when asked to sync if there are conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -238,7 +238,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('sync should not run if syncing already', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); const promise = Event.toPromise(testObject.onDoSyncCall.event); testObject.sync(await client.manifest()); @@ -255,7 +255,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('sync should not run if disabled', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); client.instantiationService.get(IUserDataSyncResourceEnablementService).setResourceEnablement(testObject.resource, false); const actual: SyncStatus[] = []; @@ -268,7 +268,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('sync should not run if there are conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -282,7 +282,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept preview during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -300,7 +300,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept remote during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); const fileService = client.instantiationService.get(IFileService); @@ -323,7 +323,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept local during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); const fileService = client.instantiationService.get(IFileService); @@ -345,7 +345,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept new content during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); const fileService = client.instantiationService.get(IFileService); @@ -368,7 +368,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept delete during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); const fileService = client.instantiationService.get(IFileService); @@ -390,7 +390,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept deleted local during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); const fileService = client.instantiationService.get(IFileService); @@ -411,7 +411,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('accept deleted remote during conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); const fileService = client.instantiationService.get(IFileService); await fileService.writeFile(testObject.localResource, VSBuffer.fromString('some content')); @@ -431,7 +431,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('request latest data on precondition failure', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); // Sync once testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -458,7 +458,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('no requests are made to server when local change is triggered', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -471,7 +471,7 @@ suite('TestSynchronizer - Auto Sync', () => { }); test('status is reset when getting latest remote data fails', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.failWhenGettingLatestRemoteUserData = true; try { @@ -502,7 +502,7 @@ suite('TestSynchronizer - Manual Sync', () => { teardown(() => disposableStore.clear()); test('preview', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -514,7 +514,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> merge', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -528,7 +528,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -542,7 +542,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> merge -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -557,7 +557,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> merge -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -577,7 +577,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -597,7 +597,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> merge -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -617,7 +617,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -630,7 +630,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preview -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -650,7 +650,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> merge -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -665,7 +665,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> merge -> discard -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -681,7 +681,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> accept -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -696,7 +696,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> accept -> discard -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -712,7 +712,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> accept -> discard -> merge', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -728,7 +728,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> merge -> accept -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -744,7 +744,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> merge -> discard -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -764,7 +764,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> accept -> discard -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -785,7 +785,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('preivew -> accept -> discard -> merge -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -808,7 +808,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -820,7 +820,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> merge', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -834,7 +834,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> merge -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -849,7 +849,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -864,7 +864,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> merge -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -887,7 +887,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -901,7 +901,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preview -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -923,7 +923,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> merge -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -938,7 +938,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> merge -> discard -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -954,7 +954,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> accept -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -969,7 +969,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> accept -> discard -> accept', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -985,7 +985,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> accept -> discard -> merge', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -1001,7 +1001,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> merge -> discard -> merge', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: true, hasError: false }; testObject.syncBarrier.open(); @@ -1017,7 +1017,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> merge -> accept -> discard', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); @@ -1033,7 +1033,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> merge -> discard -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); @@ -1053,7 +1053,7 @@ suite('TestSynchronizer - Manual Sync', () => { }); test('conflicts: preivew -> accept -> discard -> accept -> apply', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); + const testObject: TestSynchroniser = disposableStore.add(client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings)); testObject.syncResult = { hasConflicts: false, hasError: false }; testObject.syncBarrier.open(); await testObject.sync(await client.manifest()); diff --git a/src/vs/platform/userDataSync/test/common/userDataAutoSyncService.test.ts b/src/vs/platform/userDataSync/test/common/userDataAutoSyncService.test.ts index 49df9ea7e0f..a12085fe7e6 100644 --- a/src/vs/platform/userDataSync/test/common/userDataAutoSyncService.test.ts +++ b/src/vs/platform/userDataSync/test/common/userDataAutoSyncService.test.ts @@ -40,7 +40,7 @@ suite('UserDataAutoSyncService', () => { await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run(); target.reset(); - const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: UserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Trigger auto sync with settings change await testObject.triggerSync([SyncResource.Settings], false, false); @@ -62,7 +62,7 @@ suite('UserDataAutoSyncService', () => { await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run(); target.reset(); - const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: UserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Trigger auto sync with settings change multiple times for (let counter = 0; counter < 2; counter++) { @@ -88,7 +88,7 @@ suite('UserDataAutoSyncService', () => { await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run(); target.reset(); - const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: UserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Trigger auto sync with window focus once await testObject.triggerSync(['windowFocus'], true, false); @@ -110,7 +110,7 @@ suite('UserDataAutoSyncService', () => { await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run(); target.reset(); - const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: UserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Trigger auto sync with window focus multiple times for (let counter = 0; counter < 2; counter++) { @@ -129,7 +129,7 @@ suite('UserDataAutoSyncService', () => { const target = new UserDataSyncTestServer(); const client = disposableStore.add(new UserDataSyncClient(target)); await client.setUp(); - const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.sync(); @@ -165,7 +165,7 @@ suite('UserDataAutoSyncService', () => { const target = new UserDataSyncTestServer(); const client = disposableStore.add(new UserDataSyncClient(target)); await client.setUp(); - const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Sync once and reset requests await testObject.sync(); @@ -185,7 +185,7 @@ suite('UserDataAutoSyncService', () => { const target = new UserDataSyncTestServer(); const client = disposableStore.add(new UserDataSyncClient(target)); await client.setUp(); - const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Sync once and reset requests await testObject.sync(); @@ -220,7 +220,7 @@ suite('UserDataAutoSyncService', () => { const target = new UserDataSyncTestServer(); const client = disposableStore.add(new UserDataSyncClient(target)); await client.setUp(); - const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(client.instantiationService.createInstance(TestUserDataAutoSyncService)); // Sync once and reset requests await testObject.sync(); @@ -250,7 +250,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.sync(); // Reset from the first client @@ -279,7 +279,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.sync(); // Disable current machine @@ -311,7 +311,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.sync(); // Remove current machine @@ -339,7 +339,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.sync(); // Reset from the first client @@ -371,7 +371,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); const errorPromise = Event.toPromise(testObject.onError); while (target.requests.length < 5) { @@ -389,7 +389,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); while (target.requests.length < 5) { await testObject.sync(); @@ -407,7 +407,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.triggerSync(['some reason'], true, true); assert.equal(target.requestsWithAllHeaders[0].headers!['Cache-Control'], 'no-cache'); @@ -419,7 +419,7 @@ suite('UserDataAutoSyncService', () => { // Set up and sync from the test client const testClient = disposableStore.add(new UserDataSyncClient(target)); await testClient.setUp(); - const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService); + const testObject: TestUserDataAutoSyncService = disposableStore.add(testClient.instantiationService.createInstance(TestUserDataAutoSyncService)); await testObject.triggerSync(['some reason'], true, false); assert.equal(target.requestsWithAllHeaders[0].headers!['Cache-Control'], undefined); diff --git a/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts b/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts index 3220469767a..b9d4381d7b7 100644 --- a/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts +++ b/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts @@ -83,9 +83,9 @@ export class UserDataSyncClient extends Disposable { fileService.registerProvider(Schemas.inMemory, new InMemoryFileSystemProvider()); this.instantiationService.stub(IFileService, fileService); - this.instantiationService.stub(IStorageService, new InMemoryStorageService()); + this.instantiationService.stub(IStorageService, this._register(new InMemoryStorageService())); - const configurationService = new ConfigurationService(environmentService.settingsResource, fileService); + const configurationService = this._register(new ConfigurationService(environmentService.settingsResource, fileService)); await configurationService.initialize(); this.instantiationService.stub(IConfigurationService, configurationService); @@ -93,20 +93,20 @@ export class UserDataSyncClient extends Disposable { this.instantiationService.stub(IUserDataSyncLogService, logService); this.instantiationService.stub(ITelemetryService, NullTelemetryService); - this.instantiationService.stub(IUserDataSyncStoreManagementService, this.instantiationService.createInstance(UserDataSyncStoreManagementService)); - this.instantiationService.stub(IUserDataSyncStoreService, this.instantiationService.createInstance(UserDataSyncStoreService)); + this.instantiationService.stub(IUserDataSyncStoreManagementService, this._register(this.instantiationService.createInstance(UserDataSyncStoreManagementService))); + this.instantiationService.stub(IUserDataSyncStoreService, this._register(this.instantiationService.createInstance(UserDataSyncStoreService))); - const userDataSyncAccountService: IUserDataSyncAccountService = this.instantiationService.createInstance(UserDataSyncAccountService); + const userDataSyncAccountService: IUserDataSyncAccountService = this._register(this.instantiationService.createInstance(UserDataSyncAccountService)); await userDataSyncAccountService.updateAccount({ authenticationProviderId: 'authenticationProviderId', token: 'token' }); this.instantiationService.stub(IUserDataSyncAccountService, userDataSyncAccountService); - this.instantiationService.stub(IUserDataSyncMachinesService, this.instantiationService.createInstance(UserDataSyncMachinesService)); - this.instantiationService.stub(IUserDataSyncBackupStoreService, this.instantiationService.createInstance(UserDataSyncBackupStoreService)); + this.instantiationService.stub(IUserDataSyncMachinesService, this._register(this.instantiationService.createInstance(UserDataSyncMachinesService))); + this.instantiationService.stub(IUserDataSyncBackupStoreService, this._register(this.instantiationService.createInstance(UserDataSyncBackupStoreService))); this.instantiationService.stub(IUserDataSyncUtilService, new TestUserDataSyncUtilService()); - this.instantiationService.stub(IUserDataSyncResourceEnablementService, this.instantiationService.createInstance(UserDataSyncResourceEnablementService)); + this.instantiationService.stub(IUserDataSyncResourceEnablementService, this._register(this.instantiationService.createInstance(UserDataSyncResourceEnablementService))); - this.instantiationService.stub(IGlobalExtensionEnablementService, this.instantiationService.createInstance(GlobalExtensionEnablementService)); - this.instantiationService.stub(IExtensionsStorageSyncService, this.instantiationService.createInstance(ExtensionsStorageSyncService)); + this.instantiationService.stub(IGlobalExtensionEnablementService, this._register(this.instantiationService.createInstance(GlobalExtensionEnablementService))); + this.instantiationService.stub(IExtensionsStorageSyncService, this._register(this.instantiationService.createInstance(ExtensionsStorageSyncService))); this.instantiationService.stub(IIgnoredExtensionsManagementService, this.instantiationService.createInstance(IgnoredExtensionsManagementService)); this.instantiationService.stub(IExtensionManagementService, >{ async getInstalled() { return []; }, @@ -118,8 +118,8 @@ export class UserDataSyncClient extends Disposable { async getCompatibleExtension() { return null; } }); - this.instantiationService.stub(IUserDataAutoSyncEnablementService, this.instantiationService.createInstance(UserDataAutoSyncEnablementService)); - this.instantiationService.stub(IUserDataSyncService, this.instantiationService.createInstance(UserDataSyncService)); + this.instantiationService.stub(IUserDataAutoSyncEnablementService, this._register(this.instantiationService.createInstance(UserDataAutoSyncEnablementService))); + this.instantiationService.stub(IUserDataSyncService, this._register(this.instantiationService.createInstance(UserDataSyncService))); if (!empty) { await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({}))); diff --git a/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts b/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts index 2c7d1734d71..4550c939bb5 100644 --- a/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts +++ b/src/vs/platform/userDataSync/test/common/userDataSyncStoreService.test.ts @@ -58,7 +58,7 @@ suite('UserDataSyncStoreManagementService', () => { authenticationProviders: [{ id: 'configuredAuthProvider', scopes: [] }] }; - const testObject: IUserDataSyncStoreManagementService = client.instantiationService.createInstance(UserDataSyncStoreManagementService); + const testObject: IUserDataSyncStoreManagementService = disposableStore.add(client.instantiationService.createInstance(UserDataSyncStoreManagementService)); assert.equal(testObject.userDataSyncStore?.url.toString(), expected.url.toString()); assert.equal(testObject.userDataSyncStore?.defaultUrl.toString(), expected.defaultUrl.toString()); @@ -419,7 +419,7 @@ suite('UserDataSyncStoreService', () => { await testObject.manifest(); } catch (e) { } - const target = client.instantiationService.createInstance(UserDataSyncStoreService); + const target = disposableStore.add(client.instantiationService.createInstance(UserDataSyncStoreService)); assert.equal(target.donotMakeRequestsUntil?.getTime(), testObject.donotMakeRequestsUntil?.getTime()); }); @@ -434,7 +434,7 @@ suite('UserDataSyncStoreService', () => { } catch (e) { } await timeout(300); - const target = client.instantiationService.createInstance(UserDataSyncStoreService); + const target = disposableStore.add(client.instantiationService.createInstance(UserDataSyncStoreService)); assert.ok(!target.donotMakeRequestsUntil); }); From e7c84aab5b172cdc59f53141f3e5679ebae13a96 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 15:52:43 +0100 Subject: [PATCH 1729/1837] Fix privileged port elevation flow from UI --- src/vs/base/browser/ui/inputbox/inputBox.ts | 4 ++-- .../workbench/contrib/files/browser/views/explorerViewer.ts | 2 +- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 113a953e831..c726b9b76d6 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -398,7 +398,7 @@ export class InputBox extends Widget { return !!this.validation && !this.validation(this.value); } - public validate(): boolean { + public validate(): MessageType | undefined { let errorMsg: IMessage | null = null; if (this.validation) { @@ -414,7 +414,7 @@ export class InputBox extends Widget { } } - return !errorMsg; + return errorMsg?.type; } public stylesForType(type: MessageType | undefined): { border: Color | undefined; background: Color | undefined; foreground: Color | undefined } { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 9e8330b3dd8..a76120d91af 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -451,7 +451,7 @@ export class FilesRenderer implements ICompressibleTreeRenderer { if (e.equals(KeyCode.Enter)) { - if (inputBox.validate()) { + if (!inputBox.validate()) { done(true, true); } } else if (e.equals(KeyCode.Escape)) { diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 7b2e4a85e03..3cd8e109498 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -348,15 +348,17 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer { if (e.equals(KeyCode.Enter)) { - if (inputBox.validate()) { + if (inputBox.validate() !== MessageType.ERROR) { done(true, true); + } else { + done(false, true); } } else if (e.equals(KeyCode.Escape)) { done(false, true); } }), dom.addDisposableListener(inputBox.inputElement, dom.EventType.BLUR, () => { - done(inputBox.isInputValid(), true); + done(inputBox.validate() !== MessageType.ERROR, true); }), styler ]; From 29e0cfd8bebeade508121dc93efbe37159a01d1c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 15:54:23 +0100 Subject: [PATCH 1730/1837] Always elevate (if needed) for openTunnel API --- src/vs/workbench/api/browser/mainThreadTunnelService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index d5cf75289a0..afa43e93fc2 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -28,7 +28,7 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun } async $openTunnel(tunnelOptions: TunnelOptions, source: string): Promise { - const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label, source); + const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label, source, true); if (tunnel) { return TunnelDto.fromServiceTunnel(tunnel); } From bebd06640734c37f6d5f1a82b13297ce1d297dd1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 8 Jan 2021 16:04:47 +0100 Subject: [PATCH 1731/1837] Fix gulp task provider so that it doesn't always try to run --- extensions/gulp/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index 65398439ca0..a144531d9c3 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -209,7 +209,7 @@ class FolderDetector { return emptyTasks; } - if (!this.hasGulpfile(rootPath)) { + if (!await this.hasGulpfile(rootPath)) { return emptyTasks; } From 10592747998e9ad72079b72df9e9952da857fd70 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Fri, 8 Jan 2021 15:27:15 +0000 Subject: [PATCH 1732/1837] refs #102361 mnemonic as command model property --- src/vs/platform/actions/common/actions.ts | 11 +++++++++-- .../contrib/debug/browser/breakpointsView.ts | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index df9f439a736..26284fc7be4 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -28,11 +28,18 @@ export interface ILocalizedString { original: string; } +export interface ILocalizedTitle extends ILocalizedString { + /** + * The title with a mnemonic designation. && precedes the mnemonic. + */ + mnemonicTitle?: string; +} + export type Icon = { dark?: URI; light?: URI; } | ThemeIcon; export interface ICommandAction { id: string; - title: string | ILocalizedString | ILocalizedString & { mnemonicedTitle: string }; + title: string | ILocalizedTitle; category?: string | ILocalizedString; tooltip?: string; icon?: Icon; @@ -357,7 +364,7 @@ export class MenuItemAction extends ExecuteCommandAction { @IContextKeyService contextKeyService: IContextKeyService, @ICommandService commandService: ICommandService ) { - typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.value, commandService); + typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.mnemonicTitle ?? item.title.value, commandService); this._cssClass = undefined; this._enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition); diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index dd273f63015..67c84e430db 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -939,7 +939,7 @@ registerAction2(class extends Action2 { title: { original: 'Remove All Breakpoints', value: localize('removeAllBreakpoints', "Remove All Breakpoints"), - mnemonicedTitle: localize({ key: 'miRemoveAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Remove &&All Breakpoints") + mnemonicTitle: localize({ key: 'miRemoveAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Remove &&All Breakpoints") }, f1: true, icon: icons.breakpointsRemoveAll, @@ -977,7 +977,7 @@ registerAction2(class extends Action2 { title: { original: '', value: localize('enableAllBreakpoints', "Enable All Breakpoints"), - mnemonicedTitle: localize({ key: 'miEnableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "&&Enable All Breakpoints"), + mnemonicTitle: localize({ key: 'miEnableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "&&Enable All Breakpoints"), }, f1: true, precondition: CONTEXT_DEBUGGERS_AVAILABLE, @@ -1008,7 +1008,7 @@ registerAction2(class extends Action2 { title: { original: 'Disable All Breakpoints', value: localize('disableAllBreakpoints', "Disable All Breakpoints"), - mnemonicedTitle: localize({ key: 'miDisableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Disable A&&ll Breakpoints") + mnemonicTitle: localize({ key: 'miDisableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Disable A&&ll Breakpoints") }, f1: true, precondition: CONTEXT_DEBUGGERS_AVAILABLE, From 3898af5db3d4d1bcd22369aa9a7378e8815f8b16 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 16:35:28 +0100 Subject: [PATCH 1733/1837] typos --- src/vs/vscode.d.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 31276a2f588..54d833d90f6 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3870,8 +3870,8 @@ declare module 'vscode' { * * Note that `sortText` is only used for the initial ordering of completion * items. When having a leading word (prefix) ordering is based on how - * well completion match that prefix and the initial ordering is only used - * when completions match equal. The prefix is defined by the + * well completions match that prefix and the initial ordering is only used + * when completions match equally well. The prefix is defined by the * [`range`](#CompletionItem.range)-property and can therefore be different * for each completion. */ @@ -3884,7 +3884,6 @@ declare module 'vscode' { * * Note that the filter text is matched against the leading word (prefix) which is defined * by the [`range`](#CompletionItem.range)-property. - * prefix. */ filterText?: string; From a2251a3b6b9ee686b7700ae0e44ee028ea00a3cc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 16:45:24 +0100 Subject: [PATCH 1734/1837] do not use mnemonicTitle for all action titles, #102361 --- src/vs/platform/actions/common/actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 26284fc7be4..fc6440d8fbf 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -364,7 +364,7 @@ export class MenuItemAction extends ExecuteCommandAction { @IContextKeyService contextKeyService: IContextKeyService, @ICommandService commandService: ICommandService ) { - typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.mnemonicTitle ?? item.title.value, commandService); + typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.value, commandService); this._cssClass = undefined; this._enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition); From d6a63fc79eaf4040587e1d9cafb1bc77fd83d6e9 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 8 Jan 2021 16:53:43 +0100 Subject: [PATCH 1735/1837] FS improvements for unit tests (#114026) * Use RimRafMode.UNLINK in tests to avoid filesystem contention (#114024) * Add `rimrafWithRetries` for tests which incorrectly continue writing to the fixture directory even after the test signals completion * :lipstick: No need to pass in RimRafMode.UNLINK since that is the default * Also retry in case of EPERM * Add some logging to check if rimraf really fails 5 times * Fix retry logic * Improve BackupTracker disposing to avoid fs writes after the test finishes --- .../parts/storage/test/node/storage.test.ts | 34 +++++----- src/vs/base/test/node/crypto.test.ts | 4 +- src/vs/base/test/node/extpath.test.ts | 6 +- src/vs/base/test/node/pfs/pfs.test.ts | 10 +-- .../electron-main/backupMainService.test.ts | 4 +- .../test/node/extensionGalleryService.test.ts | 6 +- .../electron-browser/diskFileService.test.ts | 4 +- src/vs/platform/state/test/node/state.test.ts | 4 +- .../test/electron-browser/storage.test.ts | 4 +- .../storage/test/node/storageService.test.ts | 4 +- .../workspacesMainService.test.ts | 4 +- .../contrib/backup/common/backupTracker.ts | 2 +- .../electron-browser/backupRestorer.test.ts | 4 +- .../electron-browser/backupTracker.test.ts | 66 ++++++++++--------- .../extensionRecommendationsService.test.ts | 4 +- .../backupFileService.test.ts | 24 +++++-- .../configurationEditingService.test.ts | 4 +- .../configurationService.test.ts | 14 ++-- .../keybindingEditing.test.ts | 4 +- .../electron-browser/commonProperties.test.ts | 4 +- .../nativeTextFileService.io.test.ts | 4 +- 21 files changed, 117 insertions(+), 97 deletions(-) diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index 36fb0f567e1..8be2408b199 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -9,7 +9,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { equal, ok } from 'assert'; -import { mkdirp, writeFile, exists, unlink, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, writeFile, exists, unlink, rimraf } from 'vs/base/node/pfs'; import { timeout } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; import { isWindows } from 'vs/base/common/platform'; @@ -100,7 +100,7 @@ flakySuite('Storage Library', function () { equal(deletePromiseResolved, true); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('external changes', async () => { @@ -155,7 +155,7 @@ flakySuite('Storage Library', function () { equal(changes.size, 0); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('close flushes data', async () => { @@ -213,7 +213,7 @@ flakySuite('Storage Library', function () { ok(!storage.get('bar')); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('conflicting updates', async () => { @@ -259,7 +259,7 @@ flakySuite('Storage Library', function () { ok(setAndDeletePromiseResolved); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('corrupt DB recovers', async () => { @@ -289,7 +289,7 @@ flakySuite('Storage Library', function () { equal(storage.get('foo'), 'bar'); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); }); @@ -387,7 +387,7 @@ flakySuite('SQLite Storage Library', function () { await testDBBasics(join(storageDir, 'storage.db')); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('basics (open multiple times)', async () => { @@ -398,7 +398,7 @@ flakySuite('SQLite Storage Library', function () { await testDBBasics(join(storageDir, 'storage.db')); await testDBBasics(join(storageDir, 'storage.db')); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('basics (corrupt DB falls back to empty DB)', async () => { @@ -416,7 +416,7 @@ flakySuite('SQLite Storage Library', function () { ok(expectedError); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('basics (corrupt DB restores from previous backup)', async () => { @@ -454,7 +454,7 @@ flakySuite('SQLite Storage Library', function () { equal(recoveryCalled, false); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('basics (corrupt DB falls back to empty DB if backup is corrupt)', async () => { @@ -483,7 +483,7 @@ flakySuite('SQLite Storage Library', function () { await testDBBasics(storagePath); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('basics (DB that becomes corrupt during runtime stores all state from cache on close)', async () => { @@ -551,7 +551,7 @@ flakySuite('SQLite Storage Library', function () { equal(recoveryCalled, false); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('real world example', async function () { @@ -640,7 +640,7 @@ flakySuite('SQLite Storage Library', function () { await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('very large item value', async function () { @@ -693,7 +693,7 @@ flakySuite('SQLite Storage Library', function () { await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('multiple concurrent writes execute in sequence', async () => { @@ -750,7 +750,7 @@ flakySuite('SQLite Storage Library', function () { await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('lots of INSERT & DELETE (below inline max)', async () => { @@ -782,7 +782,7 @@ flakySuite('SQLite Storage Library', function () { await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); test('lots of INSERT & DELETE (above inline max)', async () => { @@ -814,6 +814,6 @@ flakySuite('SQLite Storage Library', function () { await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); }); diff --git a/src/vs/base/test/node/crypto.test.ts b/src/vs/base/test/node/crypto.test.ts index ad8dc4fa5af..a5c5c68e512 100644 --- a/src/vs/base/test/node/crypto.test.ts +++ b/src/vs/base/test/node/crypto.test.ts @@ -7,7 +7,7 @@ import { checksum } from 'vs/base/node/crypto'; import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; -import { mkdirp, rimraf, RimRafMode, writeFile } from 'vs/base/node/pfs'; +import { mkdirp, rimraf, writeFile } from 'vs/base/node/pfs'; suite('Crypto', () => { @@ -22,6 +22,6 @@ suite('Crypto', () => { await checksum(testFile, '0a4d55a8d778e5022fab701977c5d840bbc486d0'); - await rimraf(testDir, RimRafMode.MOVE); + await rimraf(testDir); }); }); diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts index e435d624801..ea9d130c754 100644 --- a/src/vs/base/test/node/extpath.test.ts +++ b/src/vs/base/test/node/extpath.test.ts @@ -37,7 +37,7 @@ suite('Extpath', () => { assert.equal(real, newDir); } - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); test('realpath', async () => { @@ -50,7 +50,7 @@ suite('Extpath', () => { const realpathVal = await realpath(newDir); assert.ok(realpathVal); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); test('realpathSync', async () => { @@ -68,6 +68,6 @@ suite('Extpath', () => { } assert.ok(realpath!); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); }); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 85a5644646d..6e4a0983185 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -30,7 +30,7 @@ flakySuite('PFS', function () { await pfs.writeFile(testFile, 'Hello World', (null!)); assert.equal(fs.readFileSync(testFile), 'Hello World'); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); test('writeFile - parallel write on different files works', async () => { @@ -59,7 +59,7 @@ flakySuite('PFS', function () { assert.equal(fs.readFileSync(testFile4), 'Hello World 4'); assert.equal(fs.readFileSync(testFile5), 'Hello World 5'); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); test('writeFile - parallel write on same files works and is sequentalized', async () => { @@ -80,7 +80,7 @@ flakySuite('PFS', function () { ]); assert.equal(fs.readFileSync(testFile), 'Hello World 5'); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); }); test('rimraf - simple - unlink', async () => { @@ -254,7 +254,7 @@ flakySuite('PFS', function () { assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html'))); assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html'))); - await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await pfs.rimraf(parentDir); assert.ok(!fs.existsSync(parentDir)); }); @@ -268,7 +268,7 @@ flakySuite('PFS', function () { assert.ok(fs.existsSync(newDir)); - return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentDir); }); test('readDirsInDir', async () => { diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index a127e68d236..4ce1fa7d9c1 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -119,7 +119,7 @@ flakySuite('BackupMainService', () => { setup(async () => { // Delete any existing backups completely and then re-create it. - await pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + await pfs.rimraf(backupHome); await pfs.mkdirp(backupHome); configService = new TestConfigurationService(); @@ -129,7 +129,7 @@ flakySuite('BackupMainService', () => { }); teardown(() => { - return pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + return pfs.rimraf(backupHome); }); test('service validates backup workspaces on startup and cleans up (folder workspaces)', async function () { diff --git a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts index e2a7ed43a35..fc8ad8a00db 100644 --- a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts @@ -9,7 +9,7 @@ import { NativeEnvironmentService } from 'vs/platform/environment/node/environme import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { join } from 'vs/base/common/path'; -import { mkdirp, RimRafMode, rimraf } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService'; import { isUUID } from 'vs/base/common/uuid'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -39,7 +39,7 @@ suite('Extension Gallery Service', () => { fileService.registerProvider(Schemas.file, diskFileSystemProvider); // Delete any existing backups completely and then re-create it. - rimraf(marketplaceHome, RimRafMode.MOVE).then(() => { + rimraf(marketplaceHome).then(() => { mkdirp(marketplaceHome).then(() => { done(); }, error => done(error)); @@ -48,7 +48,7 @@ suite('Extension Gallery Service', () => { teardown(done => { disposables.clear(); - rimraf(marketplaceHome, RimRafMode.MOVE).then(done, done); + rimraf(marketplaceHome).then(done, done); }); test('marketplace machine id', () => { diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index e17d0d1d8cb..0a5f54206bf 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -12,7 +12,7 @@ import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { generateUuid } from 'vs/base/common/uuid'; import { join, basename, dirname, posix } from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; -import { copy, rimraf, symlink, RimRafMode, rimrafSync } from 'vs/base/node/pfs'; +import { copy, rimraf, symlink, rimrafSync } from 'vs/base/node/pfs'; import { URI } from 'vs/base/common/uri'; import { existsSync, statSync, readdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, mkdirSync, createReadStream } from 'fs'; import { FileOperation, FileOperationEvent, IFileStat, FileOperationResult, FileSystemProviderCapabilities, FileChangeType, IFileChange, FileChangesEvent, FileOperationError, etag, IStat, IFileStatWithMetadata } from 'vs/platform/files/common/files'; @@ -154,7 +154,7 @@ flakySuite('Disk File Service', function () { teardown(async () => { disposables.clear(); - await rimraf(parentDir, RimRafMode.MOVE); + await rimraf(parentDir); }); test('createFolder', async () => { diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index 2f5f68fe685..ec36550cf56 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -8,7 +8,7 @@ import * as os from 'os'; import * as path from 'vs/base/common/path'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { FileStorage } from 'vs/platform/state/node/stateService'; -import { mkdirp, rimraf, RimRafMode, writeFileSync } from 'vs/base/node/pfs'; +import { mkdirp, rimraf, writeFileSync } from 'vs/base/node/pfs'; flakySuite('StateService', () => { const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); @@ -43,6 +43,6 @@ flakySuite('StateService', () => { service.setItem('some.null.key', null); assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default'); - await rimraf(parentDir, RimRafMode.MOVE); + await rimraf(parentDir); }); }); diff --git a/src/vs/platform/storage/test/electron-browser/storage.test.ts b/src/vs/platform/storage/test/electron-browser/storage.test.ts index 4e5e10a4e13..fcc17053339 100644 --- a/src/vs/platform/storage/test/electron-browser/storage.test.ts +++ b/src/vs/platform/storage/test/electron-browser/storage.test.ts @@ -8,7 +8,7 @@ import { FileStorageDatabase } from 'vs/platform/storage/browser/storageService' import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; -import { rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { rimraf } from 'vs/base/node/pfs'; import { NullLogService } from 'vs/platform/log/common/log'; import { Storage } from 'vs/base/parts/storage/common/storage'; import { URI } from 'vs/base/common/uri'; @@ -45,7 +45,7 @@ suite('Storage', () => { teardown(async () => { disposables.clear(); - await rimraf(parentDir, RimRafMode.MOVE); + await rimraf(parentDir); }); test('File Based Storage', async () => { diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index 294eb3add7c..54d2d3d30c1 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -9,7 +9,7 @@ import { NativeStorageService } from 'vs/platform/storage/node/storageService'; import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; -import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { NullLogService } from 'vs/platform/log/common/log'; import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; @@ -63,6 +63,6 @@ flakySuite('NativeStorageService', function () { equal(storage.getBoolean('barBoolean', StorageScope.GLOBAL), true); await storage.close(); - await rimraf(storageDir, RimRafMode.MOVE); + await rimraf(storageDir); }); }); diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 87d39b226cb..81ad5663841 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -147,13 +147,13 @@ suite('WorkspacesMainService', () => { service = new WorkspacesMainService(environmentService, logService, new TestBackupMainService(), new TestDialogMainService()); // Delete any existing backups completely and then re-create it. - await pfs.rimraf(untitledWorkspacesHomePath, pfs.RimRafMode.MOVE); + await pfs.rimraf(untitledWorkspacesHomePath); return pfs.mkdirp(untitledWorkspacesHomePath); }); teardown(() => { - return pfs.rimraf(untitledWorkspacesHomePath, pfs.RimRafMode.MOVE); + return pfs.rimraf(untitledWorkspacesHomePath); }); function assertPathEquals(p1: string, p2: string): void { diff --git a/src/vs/workbench/contrib/backup/common/backupTracker.ts b/src/vs/workbench/contrib/backup/common/backupTracker.ts index 463d69e2355..f9767e53486 100644 --- a/src/vs/workbench/contrib/backup/common/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/common/backupTracker.ts @@ -18,7 +18,7 @@ export abstract class BackupTracker extends Disposable { private readonly mapWorkingCopyToContentVersion = new Map(); // A map of scheduled pending backups for working copies - private readonly pendingBackups = new Map(); + protected readonly pendingBackups = new Map(); constructor( protected readonly backupFileService: IBackupFileService, diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index 4f87b27e3e5..6d3e6584fe3 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -67,7 +67,7 @@ flakySuite('BackupRestorer', () => { )); // Delete any existing backups completely and then re-create it. - await pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + await pfs.rimraf(backupHome); await pfs.mkdirp(backupHome); return pfs.writeFile(workspacesJsonPath, ''); @@ -79,7 +79,7 @@ flakySuite('BackupRestorer', () => { (accessor.textFileService.files).dispose(); - return pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + return pfs.rimraf(backupHome); }); test('Restore backups', async function () { diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts index 5218fd3fc0f..90db67a7a15 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts @@ -73,6 +73,13 @@ class TestBackupTracker extends NativeBackupTracker { protected getBackupScheduleDelay(): number { return 10; // Reduce timeout for tests } + + dispose() { + super.dispose(); + for (const [_, disposable] of this.pendingBackups) { + disposable.dispose(); + } + } } class BeforeShutdownEventImpl implements BeforeShutdownEvent { @@ -124,10 +131,10 @@ flakySuite('BackupTracker', function () { (accessor.textFileService.files).dispose(); - return pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + return pfs.rimraf(backupHome); }); - async function createTracker(autoSaveEnabled = false): Promise<[TestServiceAccessor, EditorPart, BackupTracker, IInstantiationService]> { + async function createTracker(autoSaveEnabled = false): Promise<{ accessor: TestServiceAccessor, part: EditorPart, tracker: BackupTracker, instantiationService: IInstantiationService, cleanup: () => Promise }> { const backupFileService = new NodeTestBackupFileService(workspaceBackupPath); const instantiationService = workbenchInstantiationService(); instantiationService.stub(IBackupFileService, backupFileService); @@ -158,11 +165,19 @@ flakySuite('BackupTracker', function () { const tracker = instantiationService.createInstance(TestBackupTracker); - return [accessor, part, tracker, instantiationService]; + const cleanup = async () => { + // File changes could also schedule some backup operations so we need to wait for them before finishing the test + await accessor.backupFileService.waitForAllBackups(); + + part.dispose(); + tracker.dispose(); + }; + + return { accessor, part, tracker, instantiationService, cleanup }; } async function untitledBackupTest(untitled: IUntitledTextResourceEditorInput = {}): Promise { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const untitledEditor = (await accessor.editorService.openEditor(untitled))?.input as UntitledTextEditorInput; @@ -182,8 +197,7 @@ flakySuite('BackupTracker', function () { assert.equal(accessor.backupFileService.hasBackupSync(untitledEditor.resource), false); - part.dispose(); - tracker.dispose(); + await cleanup(); } test('Track backups (untitled)', function () { @@ -195,7 +209,7 @@ flakySuite('BackupTracker', function () { }); test('Track backups (file)', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -213,12 +227,11 @@ flakySuite('BackupTracker', function () { assert.equal(accessor.backupFileService.hasBackupSync(resource), false); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('Track backups (custom)', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); class TestBackupWorkingCopy extends TestWorkingCopy { @@ -262,12 +275,11 @@ flakySuite('BackupTracker', function () { assert.equal(accessor.backupFileService.hasBackupSync(resource), false); customWorkingCopy.dispose(); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('onWillShutdown - no veto if no dirty files', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -278,12 +290,11 @@ flakySuite('BackupTracker', function () { const veto = await event.value; assert.ok(!veto); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('onWillShutdown - veto if user cancels (hot.exit: off)', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -303,12 +314,11 @@ flakySuite('BackupTracker', function () { const veto = await event.value; assert.ok(veto); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('onWillShutdown - no veto if auto save is on', async function () { - const [accessor, part, tracker] = await createTracker(true /* auto save enabled */); + const { accessor, cleanup } = await createTracker(true /* auto save enabled */); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -327,12 +337,11 @@ flakySuite('BackupTracker', function () { assert.equal(accessor.workingCopyService.dirtyCount, 0); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('onWillShutdown - no veto and backups cleaned up if user does not want to save (hot.exit: off)', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -352,12 +361,11 @@ flakySuite('BackupTracker', function () { assert.ok(!veto); assert.ok(accessor.backupFileService.discardedBackups.length > 0); - part.dispose(); - tracker.dispose(); + await cleanup(); }); test('onWillShutdown - save (hot.exit: off)', async function () { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -377,8 +385,7 @@ flakySuite('BackupTracker', function () { assert.ok(!veto); assert.ok(!model?.isDirty()); - part.dispose(); - tracker.dispose(); + await cleanup(); }); suite('Hot Exit', () => { @@ -485,7 +492,7 @@ flakySuite('BackupTracker', function () { }); async function hotExitTest(this: any, setting: string, shutdownReason: ShutdownReason, multipleWindows: boolean, workspace: boolean, shouldVeto: boolean): Promise { - const [accessor, part, tracker] = await createTracker(); + const { accessor, cleanup } = await createTracker(); const resource = toResource.call(this, '/path/index.txt'); await accessor.editorService.openEditor({ resource, options: { pinned: true } }); @@ -520,8 +527,7 @@ flakySuite('BackupTracker', function () { assert.equal(accessor.backupFileService.discardedBackups.length, 0); // When hot exit is set, backups should never be cleaned since the confirm result is cancel assert.equal(veto, shouldVeto); - part.dispose(); - tracker.dispose(); + await cleanup(); } }); }); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts index 51b7b0043a7..ed1a42f764b 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts @@ -9,7 +9,7 @@ import * as path from 'vs/base/common/path'; import * as fs from 'fs'; import * as os from 'os'; import * as uuid from 'vs/base/common/uuid'; -import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { IExtensionGalleryService, IGalleryExtensionAssets, IGalleryExtension, IExtensionManagementService, DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, IExtensionTipsService @@ -284,7 +284,7 @@ suite('ExtensionRecommendationsService Test', () => { teardown(done => { (testObject).dispose(); if (parentResource) { - rimraf(parentResource, RimRafMode.MOVE).then(done, done); + rimraf(parentResource).then(done, done); } else { done(); } diff --git a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts index 1835f277590..9c0ad4a8718 100644 --- a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts @@ -29,6 +29,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { TestProductService } from 'vs/workbench/test/browser/workbenchTestServices'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { insert } from 'vs/base/common/arrays'; const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); const backupHome = path.join(userdataDir, 'Backups'); @@ -60,6 +61,7 @@ export class NodeTestBackupFileService extends NativeBackupFileService { private backupResourceJoiners: Function[]; private discardBackupJoiners: Function[]; discardedBackups: URI[]; + private pendingBackupsArr: Promise[]; constructor(workspaceBackupPath: string) { const environmentService = new TestWorkbenchEnvironmentService(workspaceBackupPath); @@ -75,6 +77,11 @@ export class NodeTestBackupFileService extends NativeBackupFileService { this.backupResourceJoiners = []; this.discardBackupJoiners = []; this.discardedBackups = []; + this.pendingBackupsArr = []; + } + + async waitForAllBackups(): Promise { + await Promise.all(this.pendingBackupsArr); } joinBackupResource(): Promise { @@ -82,7 +89,14 @@ export class NodeTestBackupFileService extends NativeBackupFileService { } async backup(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: any, token?: CancellationToken): Promise { - await super.backup(resource, content, versionId, meta, token); + const p = super.backup(resource, content, versionId, meta, token); + const removeFromPendingBackups = insert(this.pendingBackupsArr, p.then(undefined, undefined)); + + try { + await p; + } finally { + removeFromPendingBackups(); + } while (this.backupResourceJoiners.length) { this.backupResourceJoiners.pop()!(); @@ -118,14 +132,14 @@ suite('BackupFileService', () => { service = new NodeTestBackupFileService(workspaceBackupPath); // Delete any existing backups completely and then re-create it. - await pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + await pfs.rimraf(backupHome); await pfs.mkdirp(backupHome); return pfs.writeFile(workspacesJsonPath, ''); }); teardown(() => { - return pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + return pfs.rimraf(backupHome); }); suite('hashPath', () => { @@ -573,14 +587,14 @@ suite('BackupFilesModel', () => { service = new NodeTestBackupFileService(workspaceBackupPath); // Delete any existing backups completely and then re-create it. - await pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + await pfs.rimraf(backupHome); await pfs.mkdirp(backupHome); return pfs.writeFile(workspacesJsonPath, ''); }); teardown(() => { - return pfs.rimraf(backupHome, pfs.RimRafMode.MOVE); + return pfs.rimraf(backupHome); }); test('simple', () => { diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index f33ff608801..92ef17d4eb8 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -24,7 +24,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; -import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { CommandService } from 'vs/workbench/services/commands/common/commandService'; @@ -128,7 +128,7 @@ suite('ConfigurationEditingService', () => { teardown(() => { disposables.clear(); if (workspaceDir) { - return rimraf(workspaceDir, RimRafMode.MOVE); + return rimraf(workspaceDir); } return undefined; }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index b7af2928773..45fa59844ad 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -127,7 +127,7 @@ flakySuite('WorkspaceContextService - Folder', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -200,7 +200,7 @@ flakySuite('WorkspaceContextService - Workspace', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -263,7 +263,7 @@ flakySuite('WorkspaceContextService - Workspace Editing', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -524,7 +524,7 @@ flakySuite('WorkspaceService - Initialization', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -803,7 +803,7 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -1338,7 +1338,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); @@ -1965,7 +1965,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { teardown(() => { disposables.clear(); if (parentResource) { - return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + return pfs.rimraf(parentResource); } return undefined; }); diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index 4b4bc13a963..e441c52507f 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -11,7 +11,7 @@ import * as json from 'vs/base/common/json'; import { ChordKeybinding, KeyCode, SimpleKeybinding } from 'vs/base/common/keyCodes'; import { OS } from 'vs/base/common/platform'; import * as uuid from 'vs/base/common/uuid'; -import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { IModeService } from 'vs/editor/common/services/modeService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -138,7 +138,7 @@ suite('KeybindingsEditing', () => { teardown(() => { return new Promise((c) => { if (testDir) { - rimraf(testDir, RimRafMode.MOVE).then(c, c); + rimraf(testDir).then(c, c); } else { c(undefined); } diff --git a/src/vs/workbench/services/telemetry/test/electron-browser/commonProperties.test.ts b/src/vs/workbench/services/telemetry/test/electron-browser/commonProperties.test.ts index 5e32c886f1c..521110e2a3f 100644 --- a/src/vs/workbench/services/telemetry/test/electron-browser/commonProperties.test.ts +++ b/src/vs/workbench/services/telemetry/test/electron-browser/commonProperties.test.ts @@ -9,7 +9,7 @@ import * as fs from 'fs'; import { resolveWorkbenchCommonProperties } from 'vs/workbench/services/telemetry/electron-browser/workbenchCommonProperties'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { IStorageService, StorageScope, InMemoryStorageService, StorageTarget } from 'vs/platform/storage/common/storage'; -import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { timeout } from 'vs/base/common/async'; suite('Telemetry - common properties', function () { @@ -25,7 +25,7 @@ suite('Telemetry - common properties', function () { }); teardown(done => { - rimraf(parentDir, RimRafMode.MOVE).then(done, done); + rimraf(parentDir).then(done, done); }); test('default', async function () { diff --git a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts index 26e22260a42..c62769293d1 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts @@ -8,7 +8,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { Schemas } from 'vs/base/common/network'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { rimraf, RimRafMode, copy, readFile, exists, stat } from 'vs/base/node/pfs'; +import { rimraf, copy, readFile, exists, stat } from 'vs/base/node/pfs'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -65,7 +65,7 @@ flakySuite('Files - NativeTextFileService i/o', function () { disposables.clear(); - await rimraf(parentDir, RimRafMode.MOVE); + await rimraf(parentDir); }, exists, From aa5064d4fd47e3e0b6cd177f0a69cbf23c06d90e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 8 Jan 2021 17:06:54 +0100 Subject: [PATCH 1736/1837] Lift some tests to browser (#114041) * :lipstick: node tests * lift some tests to browser * fix tests * fix tests --- .../parts/storage/test/node/storage.test.ts | 115 ++++-------------- .../base/test/{node => common}/buffer.test.ts | 3 +- .../test/{node => common}/console.test.ts | 2 +- .../base/test/{node => common}/glob.test.ts | 0 .../base/test/{node => common}/path.test.ts | 8 +- src/vs/base/test/node/keytar.test.ts | 42 +++---- src/vs/base/test/node/port.test.ts | 5 +- src/vs/base/test/node/zip/zip.test.ts | 11 +- .../debugANSIHandling.test.ts | 0 .../terminalEnvironment.test.ts | 0 .../extensionService.test.ts | 0 .../browserKeyboardMapper.test.ts | 2 +- .../keybindingIO.test.ts | 0 13 files changed, 57 insertions(+), 131 deletions(-) rename src/vs/base/test/{node => common}/buffer.test.ts (98%) rename src/vs/base/test/{node => common}/console.test.ts (99%) rename src/vs/base/test/{node => common}/glob.test.ts (100%) rename src/vs/base/test/{node => common}/path.test.ts (99%) rename src/vs/workbench/contrib/debug/test/{electron-browser => browser}/debugANSIHandling.test.ts (100%) rename src/vs/workbench/contrib/terminal/test/{node => common}/terminalEnvironment.test.ts (100%) rename src/vs/workbench/services/extensions/test/{electron-browser => browser}/extensionService.test.ts (100%) rename src/vs/workbench/services/keybinding/test/{electron-browser => browser}/browserKeyboardMapper.test.ts (99%) rename src/vs/workbench/services/keybinding/test/{electron-browser => browser}/keybindingIO.test.ts (100%) diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index 8be2408b199..d557b117e35 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -23,10 +23,19 @@ flakySuite('Storage Library', function () { return join(tmpdir(), 'vsctests', id, 'storage2', id); } - test('basics', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); + let storageDir: string; + setup(function () { + storageDir = uniqueStorageDir(); + + return mkdirp(storageDir); + }); + + teardown(function () { + return rimraf(storageDir); + }); + + test('basics', async () => { const storage = new Storage(new SQLiteStorageDatabase(join(storageDir, 'storage.db'))); await storage.init(); @@ -100,12 +109,9 @@ flakySuite('Storage Library', function () { equal(deletePromiseResolved, true); await storage.close(); - await rimraf(storageDir); }); test('external changes', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); class TestSQLiteStorageDatabase extends SQLiteStorageDatabase { private readonly _onDidChangeItemsExternal = new Emitter(); @@ -155,13 +161,9 @@ flakySuite('Storage Library', function () { equal(changes.size, 0); await storage.close(); - await rimraf(storageDir); }); test('close flushes data', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); - let storage = new Storage(new SQLiteStorageDatabase(join(storageDir, 'storage.db'))); await storage.init(); @@ -213,13 +215,9 @@ flakySuite('Storage Library', function () { ok(!storage.get('bar')); await storage.close(); - await rimraf(storageDir); }); test('conflicting updates', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); - let storage = new Storage(new SQLiteStorageDatabase(join(storageDir, 'storage.db'))); await storage.init(); @@ -259,13 +257,9 @@ flakySuite('Storage Library', function () { ok(setAndDeletePromiseResolved); await storage.close(); - await rimraf(storageDir); }); test('corrupt DB recovers', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); - const storageFile = join(storageDir, 'storage.db'); let storage = new Storage(new SQLiteStorageDatabase(storageFile)); @@ -289,7 +283,6 @@ flakySuite('Storage Library', function () { equal(storage.get('foo'), 'bar'); await storage.close(); - await rimraf(storageDir); }); }); @@ -308,6 +301,18 @@ flakySuite('SQLite Storage Library', function () { return set; } + let storageDir: string; + + setup(function () { + storageDir = uniqueStorageDir(); + + return mkdirp(storageDir); + }); + + teardown(function () { + return rimraf(storageDir); + }); + async function testDBBasics(path: string, logError?: (error: Error | string) => void) { let options!: ISQLiteStorageDatabaseOptions; if (logError) { @@ -381,31 +386,15 @@ flakySuite('SQLite Storage Library', function () { } test('basics', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - await testDBBasics(join(storageDir, 'storage.db')); - - await rimraf(storageDir); }); test('basics (open multiple times)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - await testDBBasics(join(storageDir, 'storage.db')); await testDBBasics(join(storageDir, 'storage.db')); - - await rimraf(storageDir); }); test('basics (corrupt DB falls back to empty DB)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - const corruptDBPath = join(storageDir, 'broken.db'); await writeFile(corruptDBPath, 'This is a broken DB'); @@ -415,15 +404,9 @@ flakySuite('SQLite Storage Library', function () { }); ok(expectedError); - - await rimraf(storageDir); }); test('basics (corrupt DB restores from previous backup)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - const storagePath = join(storageDir, 'storage.db'); let storage = new SQLiteStorageDatabase(storagePath); @@ -453,15 +436,9 @@ flakySuite('SQLite Storage Library', function () { }); equal(recoveryCalled, false); - - await rimraf(storageDir); }); test('basics (corrupt DB falls back to empty DB if backup is corrupt)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - const storagePath = join(storageDir, 'storage.db'); let storage = new SQLiteStorageDatabase(storagePath); @@ -482,21 +459,9 @@ flakySuite('SQLite Storage Library', function () { equal(storedItems.size, 0); await testDBBasics(storagePath); - - await rimraf(storageDir); }); - test('basics (DB that becomes corrupt during runtime stores all state from cache on close)', async () => { - if (isWindows) { - await Promise.resolve(); // Windows will fail to write to open DB due to locking - - return; - } - - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - + (isWindows ? test.skip /* Windows will fail to write to open DB due to locking */ : test)('basics (DB that becomes corrupt during runtime stores all state from cache on close)', async () => { const storagePath = join(storageDir, 'storage.db'); let storage = new SQLiteStorageDatabase(storagePath); @@ -550,15 +515,9 @@ flakySuite('SQLite Storage Library', function () { }); equal(recoveryCalled, false); - - await rimraf(storageDir); }); test('real world example', async function () { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - let storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); const items1 = new Map(); @@ -639,15 +598,9 @@ flakySuite('SQLite Storage Library', function () { equal(storedItems.size, items1.size + items2.size + items3.size); await storage.close(); - - await rimraf(storageDir); }); test('very large item value', async function () { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - let storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); const items = new Map(); @@ -692,13 +645,9 @@ flakySuite('SQLite Storage Library', function () { ok(!storedItems.get('super.large.string')); await storage.close(); - - await rimraf(storageDir); }); test('multiple concurrent writes execute in sequence', async () => { - const storageDir = uniqueStorageDir(); - await mkdirp(storageDir); class TestStorage extends Storage { getStorage(): IStorageDatabase { @@ -749,15 +698,9 @@ flakySuite('SQLite Storage Library', function () { equal(items.get('some/foo3/path'), 'some/bar/path'); await storage.close(); - - await rimraf(storageDir); }); test('lots of INSERT & DELETE (below inline max)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - const storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); const items = new Map(); @@ -781,15 +724,9 @@ flakySuite('SQLite Storage Library', function () { equal(storedItems.size, 0); await storage.close(); - - await rimraf(storageDir); }); test('lots of INSERT & DELETE (above inline max)', async () => { - const storageDir = uniqueStorageDir(); - - await mkdirp(storageDir); - const storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); const items = new Map(); @@ -813,7 +750,5 @@ flakySuite('SQLite Storage Library', function () { equal(storedItems.size, 0); await storage.close(); - - await rimraf(storageDir); }); }); diff --git a/src/vs/base/test/node/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts similarity index 98% rename from src/vs/base/test/node/buffer.test.ts rename to src/vs/base/test/common/buffer.test.ts index 4c7d0ba3a2f..a5a2bccb436 100644 --- a/src/vs/base/test/node/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import { VSBuffer, bufferToReadable, readableToBuffer, bufferToStream, streamToBuffer, newWriteableBufferStream, bufferedStreamToBuffer } from 'vs/base/common/buffer'; import { timeout } from 'vs/base/common/async'; import { peekStream } from 'vs/base/common/stream'; +import { isWeb } from 'vs/base/common/platform'; suite('Buffer', () => { @@ -373,7 +374,7 @@ suite('Buffer', () => { assert.equal(errors.length, 0); }); - test('Performance issue with VSBuffer#slice #76076', function () { + (isWeb ? test.skip : test)('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web // Buffer#slice creates a view { const buff = Buffer.from([10, 20, 30, 40]); diff --git a/src/vs/base/test/node/console.test.ts b/src/vs/base/test/common/console.test.ts similarity index 99% rename from src/vs/base/test/node/console.test.ts rename to src/vs/base/test/common/console.test.ts index e7a243a2d42..178c303732e 100644 --- a/src/vs/base/test/node/console.test.ts +++ b/src/vs/base/test/common/console.test.ts @@ -45,4 +45,4 @@ suite('Console', () => { assert.equal(frame.line, 18); assert.equal(frame.column, 17); }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/node/glob.test.ts b/src/vs/base/test/common/glob.test.ts similarity index 100% rename from src/vs/base/test/node/glob.test.ts rename to src/vs/base/test/common/glob.test.ts diff --git a/src/vs/base/test/node/path.test.ts b/src/vs/base/test/common/path.test.ts similarity index 99% rename from src/vs/base/test/node/path.test.ts rename to src/vs/base/test/common/path.test.ts index 3150f8d6094..d74ce9f7c3f 100644 --- a/src/vs/base/test/node/path.test.ts +++ b/src/vs/base/test/common/path.test.ts @@ -29,10 +29,11 @@ import * as assert from 'assert'; import * as path from 'vs/base/common/path'; -import { isWindows } from 'vs/base/common/platform'; +import { isWeb, isWindows } from 'vs/base/common/platform'; import * as process from 'vs/base/common/process'; suite('Paths (Node Implementation)', () => { + const __filename = 'path.test.js'; test('join', () => { const failures = [] as string[]; const backslashRE = /\\/g; @@ -175,9 +176,6 @@ suite('Paths (Node Implementation)', () => { }); test('dirname', () => { - assert.strictEqual(path.dirname(path.normalize(__filename)).substr(-9), - isWindows ? 'test\\node' : 'test/node'); - assert.strictEqual(path.posix.dirname('/a/b/'), '/a'); assert.strictEqual(path.posix.dirname('/a/b'), '/a'); assert.strictEqual(path.posix.dirname('/a'), '/'); @@ -362,7 +360,7 @@ suite('Paths (Node Implementation)', () => { assert.equal(path.extname('far.boo/boo'), ''); }); - test('resolve', () => { + (isWeb && isWindows ? test.skip : test)('resolve', () => { // TODO@sbatten fails on windows & browser only const failures = [] as string[]; const slashRE = /\//g; const backslashRE = /\\/g; diff --git a/src/vs/base/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts index c27a3286bb1..1a5a7b41529 100644 --- a/src/vs/base/test/node/keytar.test.ts +++ b/src/vs/base/test/node/keytar.test.ts @@ -2,36 +2,30 @@ * 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 * as platform from 'vs/base/common/platform'; +import { isLinux } from 'vs/base/common/platform'; suite('Keytar', () => { - test('loads and is functional', function (done) { - if (platform.isLinux) { - // Skip test due to set up issue with Travis. - done(); - return; - } - (async () => { - const keytar = await import('keytar'); - const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`; + (isLinux ? test.skip : test)('loads and is functional', async () => { // TODO@RMacfarlane test seems to fail on Linux (Error: Unknown or unsupported transport 'disabled' for address 'disabled:') + const keytar = await import('keytar'); + const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`; + try { + await keytar.setPassword(name, 'foo', 'bar'); + assert.equal(await keytar.findPassword(name), 'bar'); + assert.equal((await keytar.findCredentials(name)).length, 1); + assert.equal(await keytar.getPassword(name, 'foo'), 'bar'); + await keytar.deletePassword(name, 'foo'); + assert.equal(await keytar.getPassword(name, 'foo'), undefined); + } catch (err) { + // try to clean up try { - await keytar.setPassword(name, 'foo', 'bar'); - assert.equal(await keytar.findPassword(name), 'bar'); - assert.equal((await keytar.findCredentials(name)).length, 1); - assert.equal(await keytar.getPassword(name, 'foo'), 'bar'); await keytar.deletePassword(name, 'foo'); - assert.equal(await keytar.getPassword(name, 'foo'), undefined); - } catch (err) { - // try to clean up - try { - await keytar.deletePassword(name, 'foo'); - } finally { - // eslint-disable-next-line no-unsafe-finally - throw err; - } + } finally { + // eslint-disable-next-line no-unsafe-finally + throw err; } - })().then(done, done); + } }); }); diff --git a/src/vs/base/test/node/port.test.ts b/src/vs/base/test/node/port.test.ts index 3ec46e37102..120044651b5 100644 --- a/src/vs/base/test/node/port.test.ts +++ b/src/vs/base/test/node/port.test.ts @@ -9,10 +9,7 @@ import * as ports from 'vs/base/node/ports'; import { flakySuite } from 'vs/base/test/node/testUtils'; flakySuite('Ports', () => { - test('Finds a free port (no timeout)', function (done) { - if (process.env['VSCODE_PID']) { - return done(); // this test fails when run from within VS Code - } + (process.env['VSCODE_PID'] ? test.skip /* this test fails when run from within VS Code */ : test)('Finds a free port (no timeout)', function (done) { // get an initial freeport >= 7000 ports.findFreePort(7000, 100, 300000).then(initialPort => { diff --git a/src/vs/base/test/node/zip/zip.test.ts b/src/vs/base/test/node/zip/zip.test.ts index f79bddaa98c..9be5ae76acd 100644 --- a/src/vs/base/test/node/zip/zip.test.ts +++ b/src/vs/base/test/node/zip/zip.test.ts @@ -16,13 +16,14 @@ const fixtures = getPathFromAmdModule(require, './fixtures'); suite('Zip', () => { - test('extract should handle directories', () => { + test('extract should handle directories', async () => { const fixture = path.join(fixtures, 'extract.zip'); const target = path.join(os.tmpdir(), generateUuid()); - return createCancelablePromise(token => extract(fixture, target, {}, token) - .then(() => exists(path.join(target, 'extension'))) - .then(exists => assert(exists)) - .then(() => rimraf(target))); + await createCancelablePromise(token => extract(fixture, target, {}, token)); + const doesExist = await exists(path.join(target, 'extension')); + assert(doesExist); + + return rimraf(target); }); }); diff --git a/src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts b/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts similarity index 100% rename from src/vs/workbench/contrib/debug/test/electron-browser/debugANSIHandling.test.ts rename to src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts similarity index 100% rename from src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts rename to src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts diff --git a/src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts similarity index 100% rename from src/vs/workbench/services/extensions/test/electron-browser/extensionService.test.ts rename to src/vs/workbench/services/extensions/test/browser/extensionService.test.ts diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/browserKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts similarity index 99% rename from src/vs/workbench/services/keybinding/test/electron-browser/browserKeyboardMapper.test.ts rename to src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts index 320ddbada35..ec5c902be90 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/browserKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import 'vs/workbench/services/keybinding/browser/keyboardLayouts/en.darwin'; // 15% +import 'vs/workbench/services/keybinding/browser/keyboardLayouts/en.darwin'; import 'vs/workbench/services/keybinding/browser/keyboardLayouts/de.darwin'; import { KeyboardLayoutContribution } from 'vs/workbench/services/keybinding/browser/keyboardLayouts/_.contribution'; import { BrowserKeyboardMapperFactoryBase } from 'vs/workbench/services/keybinding/browser/keyboardLayoutService'; diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingIO.test.ts b/src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts similarity index 100% rename from src/vs/workbench/services/keybinding/test/electron-browser/keybindingIO.test.ts rename to src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts From 15cd2a1abd2c49bf542dbecb956a1673e939adb7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 8 Jan 2021 17:01:00 +0100 Subject: [PATCH 1737/1837] #115025 hash the uri and create css rule --- .../browser/parts/activitybar/activitybarPart.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index ae19d9af659..9a5f0d6da3f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -43,6 +43,7 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; +import { StringSHA1 } from 'vs/base/common/hash'; interface IPlaceholderViewContainer { readonly id: string; @@ -653,7 +654,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } else { const cachedComposite = this.cachedViewContainers.filter(c => c.id === compositeId)[0]; compositeActions = { - activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined, true)), + activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined)), pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar) }; } @@ -720,15 +721,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private toActivity({ id, focusCommand }: ViewContainer, { icon, title: name }: IViewContainerModel): IActivity { - return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id, false); + return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id); } - private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined, placeholder: boolean): IActivity { + private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined): IActivity { let cssClass: string | undefined = undefined; let iconUrl: URI | undefined = undefined; if (URI.isUri(icon)) { iconUrl = icon; - cssClass = `${placeholder ? 'placeholder-' : ''}activity-${id.replace(/\./g, '-')}`; + const hash = new StringSHA1(); + hash.update(icon.toString()); + cssClass = `activity-${id.replace(/\./g, '-')}-${hash.digest()}`; const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`; createCSSRule(iconClass, ` mask: ${asCSSUrl(icon)} no-repeat 50% 50%; From 832afd1276d09609647e0598845ca8421bd17029 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 17:16:30 +0100 Subject: [PATCH 1738/1837] :lipstick: --- src/vs/platform/actions/common/actions.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index fc6440d8fbf..033ab0687dc 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -28,7 +28,7 @@ export interface ILocalizedString { original: string; } -export interface ILocalizedTitle extends ILocalizedString { +export interface ICommandActionTitle extends ILocalizedString { /** * The title with a mnemonic designation. && precedes the mnemonic. */ @@ -39,7 +39,7 @@ export type Icon = { dark?: URI; light?: URI; } | ThemeIcon; export interface ICommandAction { id: string; - title: string | ILocalizedTitle; + title: string | ICommandActionTitle; category?: string | ILocalizedString; tooltip?: string; icon?: Icon; @@ -387,9 +387,7 @@ export class MenuItemAction extends ExecuteCommandAction { } dispose(): void { - if (this.alt) { - this.alt.dispose(); - } + this.alt?.dispose(); super.dispose(); } From 8d46328a4070f29bdbfe6ccd8f2138ec4fac4e26 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 17:20:27 +0100 Subject: [PATCH 1739/1837] more :lipstick: --- src/vs/platform/actions/common/actions.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 033ab0687dc..3d37abc6651 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -355,7 +355,7 @@ export class MenuItemAction extends ExecuteCommandAction { readonly item: ICommandAction; readonly alt: MenuItemAction | undefined; - private _options: IMenuActionOptions; + private readonly _options: IMenuActionOptions | undefined; constructor( item: ICommandAction, @@ -380,10 +380,9 @@ export class MenuItemAction extends ExecuteCommandAction { } } - this._options = options || {}; - this.item = item; - this.alt = alt ? new MenuItemAction(alt, undefined, this._options, contextKeyService, commandService) : undefined; + this.alt = alt ? new MenuItemAction(alt, undefined, options, contextKeyService, commandService) : undefined; + this._options = options; } dispose(): void { @@ -394,11 +393,11 @@ export class MenuItemAction extends ExecuteCommandAction { run(...args: any[]): Promise { let runArgs: any[] = []; - if (this._options.arg) { + if (this._options?.arg) { runArgs = [...runArgs, this._options.arg]; } - if (this._options.shouldForwardArgs) { + if (this._options?.shouldForwardArgs) { runArgs = [...runArgs, ...args]; } From c45eac1a819ac593bbce9671cb8ce57b297ab487 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 8 Jan 2021 17:48:55 +0100 Subject: [PATCH 1740/1837] tests - use explicit skip over handling within test --- src/vs/base/test/common/buffer.test.ts | 2 +- src/vs/base/test/common/extpath.test.ts | 22 ++++----- src/vs/base/test/common/labels.test.ts | 28 ++--------- src/vs/base/test/node/pfs/pfs.test.ts | 12 +---- .../test/node/processes/processes.test.ts | 6 +-- .../electron-main/backupMainService.test.ts | 7 +-- .../workspacesMainService.test.ts | 6 +-- .../tasks/test/common/configuration.test.ts | 5 +- .../test/common/terminalEnvironment.test.ts | 10 +--- .../configurationService.test.ts | 5 +- .../test/node/ripgrepFileSearch.test.ts | 12 +---- .../services/search/test/node/search.test.ts | 49 +++---------------- 12 files changed, 34 insertions(+), 130 deletions(-) diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index a5a2bccb436..bac2802d10b 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -374,7 +374,7 @@ suite('Buffer', () => { assert.equal(errors.length, 0); }); - (isWeb ? test.skip : test)('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web + (isWeb ? test.skip : test)('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042) // Buffer#slice creates a view { const buff = Buffer.from([10, 20, 30, 40]); diff --git a/src/vs/base/test/common/extpath.test.ts b/src/vs/base/test/common/extpath.test.ts index 03993437ffc..e90c5d7e78c 100644 --- a/src/vs/base/test/common/extpath.test.ts +++ b/src/vs/base/test/common/extpath.test.ts @@ -32,18 +32,16 @@ suite('Paths', () => { assert.equal(extpath.getRoot('file://foo'), ''); }); - test('isUNC', () => { - if (platform.isWindows) { - assert.ok(!extpath.isUNC('foo')); - assert.ok(!extpath.isUNC('/foo')); - assert.ok(!extpath.isUNC('\\foo')); - assert.ok(!extpath.isUNC('\\\\foo')); - assert.ok(extpath.isUNC('\\\\a\\b')); - assert.ok(!extpath.isUNC('//a/b')); - assert.ok(extpath.isUNC('\\\\server\\share')); - assert.ok(extpath.isUNC('\\\\server\\share\\')); - assert.ok(extpath.isUNC('\\\\server\\share\\path')); - } + (!platform.isWindows ? test.skip : test)('isUNC', () => { + assert.ok(!extpath.isUNC('foo')); + assert.ok(!extpath.isUNC('/foo')); + assert.ok(!extpath.isUNC('\\foo')); + assert.ok(!extpath.isUNC('\\\\foo')); + assert.ok(extpath.isUNC('\\\\a\\b')); + assert.ok(!extpath.isUNC('//a/b')); + assert.ok(extpath.isUNC('\\\\server\\share')); + assert.ok(extpath.isUNC('\\\\server\\share\\')); + assert.ok(extpath.isUNC('\\\\server\\share\\path')); }); test('isValidBasename', () => { diff --git a/src/vs/base/test/common/labels.test.ts b/src/vs/base/test/common/labels.test.ts index a3e54c16232..daba968f26f 100644 --- a/src/vs/base/test/common/labels.test.ts +++ b/src/vs/base/test/common/labels.test.ts @@ -8,11 +8,7 @@ import * as labels from 'vs/base/common/labels'; import * as platform from 'vs/base/common/platform'; suite('Labels', () => { - test('shorten - windows', () => { - if (!platform.isWindows) { - assert.ok(true); - return; - } + (!platform.isWindows ? test.skip : test)('shorten - windows', () => { // nothing to shorten assert.deepEqual(labels.shorten(['a']), ['a']); @@ -63,11 +59,7 @@ suite('Labels', () => { assert.deepEqual(labels.shorten(['src\\vs\\workbench\\parts\\execution\\electron-browser', 'src\\vs\\workbench\\parts\\execution\\electron-browser\\something', 'src\\vs\\workbench\\parts\\terminal\\electron-browser']), ['…\\execution\\electron-browser', '…\\something', '…\\terminal\\…']); }); - test('shorten - not windows', () => { - if (platform.isWindows) { - assert.ok(true); - return; - } + (platform.isWindows ? test.skip : test)('shorten - not windows', () => { // nothing to shorten assert.deepEqual(labels.shorten(['a']), ['a']); @@ -142,23 +134,13 @@ suite('Labels', () => { assert.strictEqual(labels.template(t, { dirty: '* ', activeEditorShort: 'somefile.txt', rootName: 'monaco', appName: 'Visual Studio Code', separator: { label: ' - ' } }), '* somefile.txt - monaco - Visual Studio Code'); }); - test('getBaseLabel - unix', () => { - if (platform.isWindows) { - assert.ok(true); - return; - } - + (platform.isWindows ? test.skip : test)('getBaseLabel - unix', () => { assert.equal(labels.getBaseLabel('/some/folder/file.txt'), 'file.txt'); assert.equal(labels.getBaseLabel('/some/folder'), 'folder'); assert.equal(labels.getBaseLabel('/'), '/'); }); - test('getBaseLabel - windows', () => { - if (!platform.isWindows) { - assert.ok(true); - return; - } - + (!platform.isWindows ? test.skip : test)('getBaseLabel - windows', () => { assert.equal(labels.getBaseLabel('c:'), 'C:'); assert.equal(labels.getBaseLabel('c:\\'), 'C:'); assert.equal(labels.getBaseLabel('c:\\some\\folder\\file.txt'), 'file.txt'); @@ -179,4 +161,4 @@ suite('Labels', () => { assert.equal(labels.mnemonicButtonLabel('Do &¬ Save & Continue'), 'Do _not Save & Continue'); } }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 6e4a0983185..bb62e8117c7 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -293,11 +293,7 @@ flakySuite('PFS', function () { await pfs.rimraf(newDir); }); - test('stat link', async () => { - if (isWindows) { - return; // Symlinks are not the same on win, and we can not create them programitically without admin privileges - } - + (isWindows ? test.skip : test)('stat link', async () => { // Symlinks are not the same on win, and we can not create them programmatically without admin privileges const id1 = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id1); const directory = path.join(parentDir, 'pfs', id1); @@ -319,11 +315,7 @@ flakySuite('PFS', function () { pfs.rimrafSync(directory); }); - test('stat link (non existing target)', async () => { - if (isWindows) { - return; // Symlinks are not the same on win, and we can not create them programitically without admin privileges - } - + (isWindows ? test.skip : test)('stat link (non existing target)', async () => { // Symlinks are not the same on win, and we can not create them programmatically without admin privileges const id1 = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id1); const directory = path.join(parentDir, 'pfs', id1); diff --git a/src/vs/base/test/node/processes/processes.test.ts b/src/vs/base/test/node/processes/processes.test.ts index fb9444fb6d3..e9f922f3360 100644 --- a/src/vs/base/test/node/processes/processes.test.ts +++ b/src/vs/base/test/node/processes/processes.test.ts @@ -59,11 +59,7 @@ suite('Processes', () => { }); }); - test('buffered sending - lots of data (potential deadlock on win32)', function (done: () => void) { - if (!platform.isWindows || process.env['VSCODE_PID']) { - return done(); // test is only relevant for Windows and seems to crash randomly on some Linux builds - } - + (!platform.isWindows || process.env['VSCODE_PID'] ? test.skip : test)('buffered sending - lots of data (potential deadlock on win32)', function (done: () => void) { // test is only relevant for Windows and seems to crash randomly on some Linux builds const child = fork('vs/base/test/node/processes/fixtures/fork_large'); const sender = processes.createQueuedSender(child); diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 4ce1fa7d9c1..72f3569ae01 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -606,12 +606,7 @@ flakySuite('BackupMainService', () => { flakySuite('getWorkspaceHash', () => { - test('should ignore case on Windows and Mac', () => { - // Skip test on Linux - if (platform.isLinux) { - return; - } - + (platform.isLinux ? test.skip : test)('should ignore case on Windows and Mac', () => { if (platform.isMacintosh) { assert.equal(service.getFolderHash(URI.file('/foo')), service.getFolderHash(URI.file('/FOO'))); } diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 81ad5663841..b012919b829 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -387,11 +387,7 @@ suite('WorkspacesMainService', () => { service.deleteUntitledWorkspaceSync(workspace); }); - test('rewriteWorkspaceFileForNewLocation (unc paths)', async () => { - if (!isWindows) { - return; - } - + (!isWindows ? test.skip : test)('rewriteWorkspaceFileForNewLocation (unc paths)', async () => { const workspaceLocation = path.join(os.tmpdir(), 'wsloc'); const folder1Location = 'x:\\foo'; const folder2Location = '\\\\server\\share2\\some\\path'; diff --git a/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts b/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts index 9e1ecd64050..57ada139d9a 100644 --- a/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts +++ b/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts @@ -1650,10 +1650,7 @@ suite('Tasks version 2.0.0', () => { }); suite('Bugs / regression tests', () => { - test('Bug 19548', () => { - if (Platform.isLinux) { - return; - } + (Platform.isLinux ? test.skip : test)('Bug 19548', () => { let external: ExternalTaskRunnerConfiguration = { version: '0.1.0', windows: { diff --git a/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts index 29a042b4ea2..a06b75e037e 100644 --- a/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/terminalEnvironment.test.ts @@ -132,10 +132,7 @@ suite('Workbench - TerminalEnvironment', () => { }); }); - test('should add keys ignoring case on Windows', () => { - if (!platform.isWindows) { - return; - } + (!platform.isWindows ? test.skip : test)('should add keys ignoring case on Windows', () => { const parent = { a: 'b' }; @@ -162,10 +159,7 @@ suite('Workbench - TerminalEnvironment', () => { }); }); - test('null values should delete keys from the parent env ignoring case on Windows', () => { - if (!platform.isWindows) { - return; - } + (!platform.isWindows ? test.skip : test)('null values should delete keys from the parent env ignoring case on Windows', () => { const parent = { a: 'b', c: 'd' diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 45fa59844ad..a1789f050e7 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -1238,10 +1238,7 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); }); - test('deleting workspace settings', async () => { - if (!isMacintosh) { - return; - } + (!isMacintosh ? test.skip : test)('deleting workspace settings', async () => { fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); const workspaceSettingsResource = URI.file(path.join(workspaceDir, '.vscode', 'settings.json')); await fileService.writeFile(workspaceSettingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); diff --git a/src/vs/workbench/services/search/test/node/ripgrepFileSearch.test.ts b/src/vs/workbench/services/search/test/node/ripgrepFileSearch.test.ts index 14b96505122..9b3d7cfa7ff 100644 --- a/src/vs/workbench/services/search/test/node/ripgrepFileSearch.test.ts +++ b/src/vs/workbench/services/search/test/node/ripgrepFileSearch.test.ts @@ -13,11 +13,7 @@ suite('RipgrepFileSearch - etc', () => { assert.equal(fixDriveC(getAbsoluteGlob(folder, glob)), expectedResult, JSON.stringify(params)); } - test('getAbsoluteGlob_win', () => { - if (!platform.isWindows) { - return; - } - + (!platform.isWindows ? test.skip : test)('getAbsoluteGlob_win', () => { [ ['C:/foo/bar', 'glob/**', '/foo\\bar\\glob\\**'], ['c:/', 'glob/**', '/glob\\**'], @@ -32,11 +28,7 @@ suite('RipgrepFileSearch - etc', () => { ].forEach(testGetAbsGlob); }); - test('getAbsoluteGlob_posix', () => { - if (platform.isWindows) { - return; - } - + (platform.isWindows ? test.skip : test)('getAbsoluteGlob_posix', () => { [ ['/foo/bar', 'glob/**', '/foo/bar/glob/**'], ['/', 'glob/**', '/glob/**'], diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 20c8dc47a1f..33a9868c1c3 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -721,12 +721,7 @@ flakySuite('FileSearchEngine', () => { flakySuite('FileWalker', () => { - test('Find: exclude subfolder', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude subfolder', function (done: () => void) { const file0 = './more/file.txt'; const file1 = './examples/subfolder/subfile.txt'; @@ -756,12 +751,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: folder excludes', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: folder excludes', function (done: () => void) { const folderQueries: IFolderQuery[] = [ { folder: URI.file(TEST_FIXTURES), @@ -782,12 +772,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: exclude multiple folders', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude multiple folders', function (done: () => void) { const file0 = './index.html'; const file1 = './examples/small.js'; const file2 = './more/file.txt'; @@ -812,12 +797,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: exclude folder path suffix', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude folder path suffix', function (done: () => void) { const file0 = './examples/company.js'; const file1 = './examples/subfolder/subfile.txt'; @@ -839,12 +819,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: exclude subfolder path suffix', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude subfolder path suffix', function (done: () => void) { const file0 = './examples/subfolder/subfile.txt'; const file1 = './examples/subfolder/anotherfolder/anotherfile.txt'; @@ -866,12 +841,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: exclude folder path', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude folder path', function (done: () => void) { const file0 = './examples/company.js'; const file1 = './examples/subfolder/subfile.txt'; @@ -893,12 +863,7 @@ flakySuite('FileWalker', () => { }); }); - test('Find: exclude combination of paths', function (done: () => void) { - if (platform.isWindows) { - done(); - return; - } - + (platform.isWindows ? test.skip : test)('Find: exclude combination of paths', function (done: () => void) { const filesIn = [ './examples/subfolder/subfile.txt', './examples/company.js', From 6828ae1ab50a2785aefc49353da037faf92f7fed Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 8 Jan 2021 11:52:41 -0500 Subject: [PATCH 1741/1837] Removes trim & fixes regex --- extensions/git/src/git.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 9c907162b98..7f78d9543c1 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1915,18 +1915,18 @@ export class Repository { const fn = (line: string): Ref | null => { let match: RegExpExecArray | null; - if (match = /^refs\/heads\/([^ ]+) ([0-9a-f]{40}) ?([0-9a-f]{40})?$/.exec(line)) { + if (match = /^refs\/heads\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) { return { name: match[1], commit: match[2], type: RefType.Head }; - } else if (match = /^refs\/remotes\/([^/]+)\/([^ ]+) ?([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) { + } else if (match = /^refs\/remotes\/([^/]+)\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) { return { name: `${match[1]}/${match[2]}`, commit: match[3], type: RefType.RemoteHead, remote: match[1] }; - } else if (match = /^refs\/tags\/([^ ]+) ([0-9a-f]{40}) ?([0-9a-f]{40})?$/.exec(line)) { + } else if (match = /^refs\/tags\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) { return { name: match[1], commit: match[3] ?? match[2], type: RefType.Tag }; } return null; }; - return result.stdout.trim().split('\n') + return result.stdout.split('\n') .filter(line => !!line) .map(fn) .filter(ref => !!ref) as Ref[]; From c88c207e6c0641129a9672c289b2039da310830b Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 8 Jan 2021 17:57:07 +0100 Subject: [PATCH 1742/1837] fixes #114028 --- .../debug/test/browser/callStack.test.ts | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts index b637ac7db35..dd694374635 100644 --- a/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/callStack.test.ts @@ -99,7 +99,7 @@ suite('Debug - CallStack', () => { assert.equal(model.getSessions(true).length, 1); }); - test('threads multiple wtih allThreadsStopped', () => { + test('threads multiple wtih allThreadsStopped', async () => { const threadId1 = 1; const threadName1 = 'firstThread'; const threadId2 = 2; @@ -153,19 +153,16 @@ suite('Debug - CallStack', () => { // after calling getCallStack, the callstack becomes available // and results in a request for the callstack in the debug adapter - thread1.fetchCallStack().then(() => { - assert.notEqual(thread1.getCallStack().length, 0); - }); + await thread1.fetchCallStack(); + assert.notEqual(thread1.getCallStack().length, 0); - thread2.fetchCallStack().then(() => { - assert.notEqual(thread2.getCallStack().length, 0); - }); + await thread2.fetchCallStack(); + assert.notEqual(thread2.getCallStack().length, 0); // calling multiple times getCallStack doesn't result in multiple calls // to the debug adapter - thread1.fetchCallStack().then(() => { - return thread2.fetchCallStack(); - }); + await thread1.fetchCallStack(); + await thread2.fetchCallStack(); // clearing the callstack results in the callstack not being available thread1.clearCallStack(); @@ -182,7 +179,7 @@ suite('Debug - CallStack', () => { assert.equal(session.getAllThreads().length, 0); }); - test('threads mutltiple without allThreadsStopped', () => { + test('threads mutltiple without allThreadsStopped', async () => { const sessionStub = sinon.spy(rawSession, 'stackTrace'); const stoppedThreadId = 1; @@ -238,19 +235,17 @@ suite('Debug - CallStack', () => { // after calling getCallStack, the callstack becomes available // and results in a request for the callstack in the debug adapter - stoppedThread.fetchCallStack().then(() => { - assert.notEqual(stoppedThread.getCallStack().length, 0); - assert.equal(runningThread.getCallStack().length, 0); - assert.equal(sessionStub.callCount, 1); - }); + await stoppedThread.fetchCallStack(); + assert.notEqual(stoppedThread.getCallStack().length, 0); + assert.equal(runningThread.getCallStack().length, 0); + assert.equal(sessionStub.callCount, 1); // calling getCallStack on the running thread returns empty array // and does not return in a request for the callstack in the debug // adapter - runningThread.fetchCallStack().then(() => { - assert.equal(runningThread.getCallStack().length, 0); - assert.equal(sessionStub.callCount, 1); - }); + await runningThread.fetchCallStack(); + assert.equal(runningThread.getCallStack().length, 0); + assert.equal(sessionStub.callCount, 1); // clearing the callstack results in the callstack not being available stoppedThread.clearCallStack(); From 8d8ee9574188548370935efed778589bbb99c9c0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 18:34:52 +0100 Subject: [PATCH 1743/1837] options for getActions() are optional --- src/vs/platform/actions/common/menuService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/actions/common/menuService.ts b/src/vs/platform/actions/common/menuService.ts index b86e4462e7f..924e4acf24d 100644 --- a/src/vs/platform/actions/common/menuService.ts +++ b/src/vs/platform/actions/common/menuService.ts @@ -109,7 +109,7 @@ class Menu implements IMenu { this._onDidChange.fire(this); } - getActions(options: IMenuActionOptions): [string, Array][] { + getActions(options?: IMenuActionOptions): [string, Array][] { const result: [string, Array][] = []; for (let group of this._menuGroups) { const [id, items] = group; From d95e22d0a8d0b5e8f5cf291a08be1ccff67f0755 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 18:37:40 +0100 Subject: [PATCH 1744/1837] make menubarControl prefer mnemonicTitle, make MenuItemAction only implement IAction --- src/vs/platform/actions/common/actions.ts | 42 ++++++++++++------- .../browser/parts/titlebar/menubarControl.ts | 23 +++++++--- .../parts/titlebar/menubarControl.ts | 6 ++- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 3d37abc6651..ec818b2bb31 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -58,7 +58,7 @@ export interface IMenuItem { } export interface ISubmenuItem { - title: string | ILocalizedString; + title: string | ICommandActionTitle; submenu: MenuId; icon?: Icon; when?: ContextKeyExpression; @@ -350,44 +350,54 @@ export class SubmenuItemAction extends SubmenuAction { } } -export class MenuItemAction extends ExecuteCommandAction { +// implements IAction, does NOT extend Action, so that no one +// subscribes to events of Action or modified properties +export class MenuItemAction implements IAction { readonly item: ICommandAction; readonly alt: MenuItemAction | undefined; private readonly _options: IMenuActionOptions | undefined; + readonly id: string; + readonly label: string; + readonly tooltip: string; + readonly class: string | undefined; + readonly enabled: boolean; + readonly checked: boolean; + constructor( item: ICommandAction, alt: ICommandAction | undefined, - options: IMenuActionOptions, + options: IMenuActionOptions | undefined, @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService + @ICommandService private _commandService: ICommandService ) { - typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.value, commandService); - - this._cssClass = undefined; - this._enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition); - this._tooltip = item.tooltip; + this.id = item.id; + this.label = typeof item.title === 'string' ? item.title : item.title.value; + this.tooltip = item.tooltip ?? ''; + this.enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition); + this.checked = false; if (item.toggled) { const toggled = ((item.toggled as { condition: ContextKeyExpression }).condition ? item.toggled : { condition: item.toggled }) as { condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString }; - this._checked = contextKeyService.contextMatchesRules(toggled.condition); - if (this._checked && toggled.tooltip) { - this._tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value; + this.checked = contextKeyService.contextMatchesRules(toggled.condition); + if (this.checked && toggled.tooltip) { + this.tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value; } } this.item = item; - this.alt = alt ? new MenuItemAction(alt, undefined, options, contextKeyService, commandService) : undefined; + this.alt = alt ? new MenuItemAction(alt, undefined, options, contextKeyService, _commandService) : undefined; this._options = options; } dispose(): void { - this.alt?.dispose(); - super.dispose(); + // there is NOTHING to dispose and the MenuItemAction should + // never have anything to dispose as it is a convenience type + // to bridge into the rendering world. } run(...args: any[]): Promise { @@ -401,7 +411,7 @@ export class MenuItemAction extends ExecuteCommandAction { runArgs = [...runArgs, ...args]; } - return super.run(...runArgs); + return this._commandService.executeCommand(this.id, ...runArgs); } } diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index e1b66f2a64e..f58b20387cb 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -37,6 +37,7 @@ import { BrowserFeatures } from 'vs/base/browser/canIUse'; import { KeyCode } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; +import { ICommandService } from 'vs/platform/commands/common/commands'; export abstract class MenubarControl extends Disposable { @@ -91,7 +92,8 @@ export abstract class MenubarControl extends Disposable { protected readonly preferencesService: IPreferencesService, protected readonly environmentService: IWorkbenchEnvironmentService, protected readonly accessibilityService: IAccessibilityService, - protected readonly hostService: IHostService + protected readonly hostService: IHostService, + protected readonly commandService: ICommandService ) { super(); @@ -308,9 +310,10 @@ export class CustomMenubarControl extends MenubarControl { @IAccessibilityService accessibilityService: IAccessibilityService, @IThemeService private readonly themeService: IThemeService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IHostService protected readonly hostService: IHostService + @IHostService protected readonly hostService: IHostService, + @ICommandService commandService: ICommandService ) { - super(menuService, workspacesService, contextKeyService, keybindingService, configurationService, labelService, updateService, storageService, notificationService, preferencesService, environmentService, accessibilityService, hostService); + super(menuService, workspacesService, contextKeyService, keybindingService, configurationService, labelService, updateService, storageService, notificationService, preferencesService, environmentService, accessibilityService, hostService, commandService); this._onVisibilityChange = this._register(new Emitter()); this._onFocusStateChange = this._register(new Emitter()); @@ -592,6 +595,12 @@ export class CustomMenubarControl extends MenubarControl { for (let action of actions) { this.insertActionsBefore(action, target); + + // use mnemonicTitle whenever possible + const title = typeof action.item.title === 'string' + ? action.item.title + : action.item.title.mnemonicTitle ?? action.item.title.value; + if (action instanceof SubmenuItemAction) { let submenu = this.menus[action.item.submenu.id]; if (!submenu) { @@ -609,10 +618,12 @@ export class CustomMenubarControl extends MenubarControl { const submenuActions: SubmenuAction[] = []; updateActions(submenu, submenuActions, topLevelTitle); - target.push(new SubmenuAction(action.id, mnemonicMenuLabel(action.label), submenuActions)); + target.push(new SubmenuAction(action.id, mnemonicMenuLabel(title), submenuActions)); } else { - action.label = mnemonicMenuLabel(this.calculateActionLabel(action)); - target.push(action); + const newAction = new Action(action.id, mnemonicMenuLabel(title), action.class, action.enabled, () => this.commandService.executeCommand(action.id)); + newAction.tooltip = action.tooltip; + newAction.checked = action.checked; + target.push(newAction); } } diff --git a/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts b/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts index ab6bd7b5bed..cdef7df235e 100644 --- a/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts @@ -25,6 +25,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { ICommandService } from 'vs/platform/commands/common/commands'; export class NativeMenubarControl extends MenubarControl { @@ -43,9 +44,10 @@ export class NativeMenubarControl extends MenubarControl { @IAccessibilityService accessibilityService: IAccessibilityService, @IMenubarService private readonly menubarService: IMenubarService, @IHostService hostService: IHostService, - @INativeHostService private readonly nativeHostService: INativeHostService + @INativeHostService private readonly nativeHostService: INativeHostService, + @ICommandService commandService: ICommandService, ) { - super(menuService, workspacesService, contextKeyService, keybindingService, configurationService, labelService, updateService, storageService, notificationService, preferencesService, environmentService, accessibilityService, hostService); + super(menuService, workspacesService, contextKeyService, keybindingService, configurationService, labelService, updateService, storageService, notificationService, preferencesService, environmentService, accessibilityService, hostService, commandService); if (isMacintosh) { this.menus['Preferences'] = this._register(this.menuService.createMenu(MenuId.MenubarPreferencesMenu, this.contextKeyService)); From 0fafaab62e2087df60e5a4989059507e9b38dcd8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 8 Jan 2021 18:59:16 +0100 Subject: [PATCH 1745/1837] mnemonicTitle in native menubarControl --- .../electron-sandbox/parts/titlebar/menubarControl.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts b/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts index cdef7df235e..802b1f9c598 100644 --- a/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/electron-sandbox/parts/titlebar/menubarControl.ts @@ -112,6 +112,11 @@ export class NativeMenubarControl extends MenubarControl { actions.forEach(menuItem => { + // use mnemonicTitle whenever possible + const title = typeof menuItem.item.title === 'string' + ? menuItem.item.title + : menuItem.item.title.mnemonicTitle ?? menuItem.item.title.value; + if (menuItem instanceof SubmenuItemAction) { const submenu = { items: [] }; @@ -125,7 +130,7 @@ export class NativeMenubarControl extends MenubarControl { let menubarSubmenuItem: IMenubarMenuItemSubmenu = { id: menuItem.id, - label: menuItem.label, + label: title, submenu: submenu }; @@ -139,7 +144,7 @@ export class NativeMenubarControl extends MenubarControl { let menubarMenuItem: IMenubarMenuItemAction = { id: menuItem.id, - label: menuItem.label + label: title }; if (menuItem.checked) { @@ -150,7 +155,6 @@ export class NativeMenubarControl extends MenubarControl { menubarMenuItem.enabled = false; } - menubarMenuItem.label = this.calculateActionLabel(menubarMenuItem); keybindings[menuItem.id] = this.getMenubarKeybinding(menuItem.id); menuToPopulate.items.push(menubarMenuItem); } From d8a3dd44be13762f1a2125d82fcc8d54b5c24e9a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 7 Jan 2021 18:19:34 -0800 Subject: [PATCH 1746/1837] Removed unused param --- .../contrib/webview/electron-browser/webviewElement.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 5a749df2fd3..918671def3a 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -15,7 +15,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { ILogService } from 'vs/platform/log/common/log'; -import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { webviewPartitionId } from 'vs/platform/webview/common/resourceLoader'; @@ -63,7 +62,6 @@ export class ElectronWebviewBasedWebview extends BaseWebview impleme @IConfigurationService configurationService: IConfigurationService, @IMainProcessService mainProcessService: IMainProcessService, @INotificationService noficationService: INotificationService, - @INativeHostService nativeHostService: INativeHostService, ) { super(id, options, contentOptions, extension, _webviewThemeDataProvider, noficationService, _myLogService, telemetryService, environmentService); From 50dd2dd3f9ef798ffe29351cbc36966c7d628044 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 7 Jan 2021 18:43:39 -0800 Subject: [PATCH 1747/1837] Add context for when the webview supports find Use this to disable the webview find command in those cases --- .../webview/browser/dynamicWebviewEditorOverlay.ts | 9 ++++++++- src/vs/workbench/contrib/webview/browser/webview.ts | 2 ++ .../contrib/webviewPanel/browser/webviewCommands.ts | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index 142650d375f..955f53ecbb4 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri'; import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; /** @@ -38,6 +38,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv private readonly _scopedContextKeyService = this._register(new MutableDisposable()); private _findWidgetVisible: IContextKey | undefined; + private _findWidgetEnabled: IContextKey | undefined; public constructor( public readonly id: string, @@ -97,6 +98,10 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv this._findWidgetVisible?.reset(); this._findWidgetVisible = KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE.bindTo(contextKeyService); + + this._findWidgetEnabled?.reset(); + this._findWidgetEnabled = KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED.bindTo(contextKeyService); + this._findWidgetEnabled.set(!!this.options.enableFindWidget); } } @@ -144,6 +149,8 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv webview.initialScrollProgress = this._initialScrollProgress; } + this._findWidgetEnabled?.set(!!this.options.enableFindWidget); + webview.mountTo(this.container); // Forward events from inner webview to outer listeners diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index 945817c5d63..3471066d6d0 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -18,6 +18,8 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' */ export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE = new RawContextKey('webviewFindWidgetVisible', false); export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED = new RawContextKey('webviewFindWidgetFocused', false); +export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED = new RawContextKey('webviewFindWidgetEnabled', false); + export const webviewHasOwnEditFunctionsContextKey = 'webviewHasOwnEditFunctions'; export const webviewHasOwnEditFunctionsContext = new RawContextKey(webviewHasOwnEditFunctionsContextKey, false); diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewCommands.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewCommands.ts index ede437c814c..84a4336e6f4 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewCommands.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewCommands.ts @@ -10,7 +10,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { CATEGORIES } from 'vs/workbench/common/actions'; -import { KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview } from 'vs/workbench/contrib/webview/browser/webview'; +import { KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewEditor } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditor'; import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -26,7 +26,7 @@ export class ShowWebViewEditorFindWidgetAction extends Action2 { id: ShowWebViewEditorFindWidgetAction.ID, title: ShowWebViewEditorFindWidgetAction.LABEL, keybinding: { - when: webviewActiveContextKeyExpr, + when: ContextKeyExpr.and(webviewActiveContextKeyExpr, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED), primary: KeyMod.CtrlCmd | KeyCode.KEY_F, weight: KeybindingWeight.EditorContrib } From d110d503425448494fae15b65f7c8de871b02ca1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 7 Jan 2021 18:45:15 -0800 Subject: [PATCH 1748/1837] Remove webviewHasOwnEditFunctions context This is no longer being used --- .../workbench/contrib/customEditor/browser/customEditors.ts | 6 +----- src/vs/workbench/contrib/webview/browser/webview.ts | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index c57aa6dd36b..340ea95e03d 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -28,7 +28,7 @@ import { EditorInput, EditorOptions, Extensions as EditorInputExtensions, GroupI import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { CONTEXT_CUSTOM_EDITORS, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CustomEditorCapabilities, CustomEditorInfo, CustomEditorInfoCollection, CustomEditorPriority, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager'; -import { IWebviewService, webviewHasOwnEditFunctionsContext } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CustomEditorAssociation, CustomEditorsAssociations, customEditorsAssociationsSettingId } from 'vs/workbench/services/editor/common/editorOpenWith'; import { ICustomEditorInfo, ICustomEditorViewTypesHandler, IEditorService, IOpenEditorOverride, IOpenEditorOverrideEntry } from 'vs/workbench/services/editor/common/editorService'; @@ -45,7 +45,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ private readonly _customEditorContextKey: IContextKey; private readonly _focusedCustomEditorIsEditable: IContextKey; - private readonly _webviewHasOwnEditFunctions: IContextKey; private readonly _onDidChangeViewTypes = new Emitter(); onDidChangeViewTypes: Event = this._onDidChangeViewTypes.event; @@ -66,7 +65,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ this._customEditorContextKey = CONTEXT_CUSTOM_EDITORS.bindTo(contextKeyService); this._focusedCustomEditorIsEditable = CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE.bindTo(contextKeyService); - this._webviewHasOwnEditFunctions = webviewHasOwnEditFunctionsContext.bindTo(contextKeyService); this._contributedEditors = this._register(new ContributedCustomEditors(storageService)); this._register(this._contributedEditors.onChange(() => { @@ -317,7 +315,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ if (!resource) { this._customEditorContextKey.reset(); this._focusedCustomEditorIsEditable.reset(); - this._webviewHasOwnEditFunctions.reset(); return; } @@ -325,7 +322,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ this._customEditorContextKey.set(possibleEditors.map(x => x.id).join(',')); this._focusedCustomEditorIsEditable.set(activeEditorPane?.input instanceof CustomEditorInput); - this._webviewHasOwnEditFunctions.set(possibleEditors.length > 0); } private async handleMovedFileInOpenedFileEditors(oldResource: URI, newResource: URI): Promise { diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index 3471066d6d0..189e52c3a16 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -20,10 +20,6 @@ export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE = new RawContextKey< export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED = new RawContextKey('webviewFindWidgetFocused', false); export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED = new RawContextKey('webviewFindWidgetEnabled', false); - -export const webviewHasOwnEditFunctionsContextKey = 'webviewHasOwnEditFunctions'; -export const webviewHasOwnEditFunctionsContext = new RawContextKey(webviewHasOwnEditFunctionsContextKey, false); - export const IWebviewService = createDecorator('webviewService'); export interface WebviewIcons { From e3509b62fe6aeeadcfb29cb2a6c5a771e1f7a870 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Fri, 8 Jan 2021 12:22:38 -0800 Subject: [PATCH 1749/1837] Add search.mode option to control default search experience (#114015) * Add search.mode option to control default search experience * Move resource serializer to Query Builder --- .../search/browser/search.contribution.ts | 78 +++++++++++++------ .../contrib/search/browser/searchActions.ts | 48 ++++++++---- .../contrib/search/browser/searchView.ts | 41 +--------- .../contrib/search/common/queryBuilder.ts | 47 ++++++++++- .../browser/searchEditor.contribution.ts | 4 +- .../searchEditor/browser/searchEditor.ts | 22 +++--- .../browser/searchEditorActions.ts | 5 +- .../services/search/common/search.ts | 1 + 8 files changed, 154 insertions(+), 92 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 4b99bee21d6..8834497c4ff 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Action } from 'vs/base/common/actions'; -import { distinct } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; @@ -13,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { ToggleCaseSensitiveKeybinding, TogglePreserveCaseKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/findModel'; import * as nls from 'vs/nls'; import { ICommandAction, MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; +import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -40,7 +39,7 @@ import { getWorkspaceSymbols } from 'vs/workbench/contrib/search/common/search'; import { ISearchHistoryService, SearchHistoryService } from 'vs/workbench/contrib/search/common/searchHistoryService'; import { FileMatchOrMatch, ISearchWorkbenchService, RenderableMatch, SearchWorkbenchService, FileMatch, Match, FolderMatch } from 'vs/workbench/contrib/search/common/searchModel'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { VIEWLET_ID, VIEW_ID, SEARCH_EXCLUDE_CONFIG, SearchSortOrder } from 'vs/workbench/services/search/common/search'; +import { VIEWLET_ID, VIEW_ID, SEARCH_EXCLUDE_CONFIG, SearchSortOrder, ISearchConfiguration } from 'vs/workbench/services/search/common/search'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; @@ -55,6 +54,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess'; import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; import { searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; +import { resolveResourcesForSearchIncludes } from 'vs/workbench/contrib/search/common/queryBuilder'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true); registerSingleton(ISearchHistoryService, SearchHistoryService, true); @@ -404,29 +404,40 @@ const FocusSearchListCommand: ICommandAction = { }; MenuRegistry.addCommand(FocusSearchListCommand); -const searchInFolderCommand: ICommandHandler = (accessor, resource?: URI) => { + +const searchInFolderCommand: ICommandHandler = async (accessor, resource?: URI) => { const listService = accessor.get(IListService); const fileService = accessor.get(IFileService); const viewsService = accessor.get(IViewsService); + const contextService = accessor.get(IWorkspaceContextService); + const commandService = accessor.get(ICommandService); const resources = getMultiSelectedResources(resource, listService, accessor.get(IEditorService), accessor.get(IExplorerService)); + const searchConfig = accessor.get(IConfigurationService).getValue().search; + const mode = searchConfig.mode; - return openSearchView(viewsService, true).then(searchView => { - if (resources && resources.length && searchView) { - return fileService.resolveAll(resources.map(resource => ({ resource }))).then(results => { - const folders: URI[] = []; - - results.forEach(result => { - if (result.success && result.stat) { - folders.push(result.stat.isDirectory ? result.stat.resource : dirname(result.stat.resource)); - } - }); - - searchView.searchInFolders(distinct(folders, folder => folder.toString())); - }); - } - - return undefined; + const resolvedResources = fileService.resolveAll(resources.map(resource => ({ resource }))).then(results => { + const folders: URI[] = []; + results.forEach(result => { + if (result.success && result.stat) { + folders.push(result.stat.isDirectory ? result.stat.resource : dirname(result.stat.resource)); + } + }); + return resolveResourcesForSearchIncludes(folders, contextService); }); + + if (mode === 'view') { + const searchView = await openSearchView(viewsService, true); + if (resources && resources.length && searchView) { + searchView.searchInFolders(await resolvedResources); + } + return undefined; + } else { + return commandService.executeCommand(SearchEditorConstants.OpenEditorCommandId, { + filesToInclude: (await resolvedResources).join(', '), + showIncludesExcludes: true, + location: mode === 'newEditor' ? 'new' : 'reuse', + }); + } }; const FIND_IN_FOLDER_ID = 'filesExplorer.findInFolder'; @@ -455,12 +466,22 @@ CommandsRegistry.registerCommand({ const FIND_IN_WORKSPACE_ID = 'filesExplorer.findInWorkspace'; CommandsRegistry.registerCommand({ id: FIND_IN_WORKSPACE_ID, - handler: (accessor) => { - return openSearchView(accessor.get(IViewsService), true).then(searchView => { + handler: async (accessor) => { + const searchConfig = accessor.get(IConfigurationService).getValue().search; + const mode = searchConfig.mode; + + if (mode === 'view') { + const searchView = await openSearchView(accessor.get(IViewsService), true); if (searchView) { searchView.searchInFolders(); } - }); + } + else { + return accessor.get(ICommandService).executeCommand(SearchEditorConstants.OpenEditorCommandId, { + location: mode === 'newEditor' ? 'new' : 'reuse', + filesToInclude: '', + }); + } } }); @@ -724,6 +745,17 @@ configurationRegistry.registerConfiguration({ }, scope: ConfigurationScope.RESOURCE }, + 'search.mode': { + type: 'string', + enum: ['view', 'reuseEditor', 'newEditor'], + default: 'view', + markdownDescription: nls.localize('search.mode', "Controls where new `Search: Find in Files` and `Find in Folder` operations occur: either in the sidebar's search view, or in a search editor"), + enumDescriptions: [ + nls.localize('search.mode.view', "Search in the search view, either in the panel or sidebar."), + nls.localize('search.mode.reuseEditor', "Search in an existing search editor if present, otherwise in a new search editor"), + nls.localize('search.mode.newEditor', "Search in a new search editor"), + ] + }, 'search.useRipgrep': { type: 'boolean', description: nls.localize('useRipgrep', "This setting is deprecated and now falls back on \"search.usePCRE2\"."), diff --git a/src/vs/workbench/contrib/search/browser/searchActions.ts b/src/vs/workbench/contrib/search/browser/searchActions.ts index 4e136901b2b..00bdbc81b0e 100644 --- a/src/vs/workbench/contrib/search/browser/searchActions.ts +++ b/src/vs/workbench/contrib/search/browser/searchActions.ts @@ -10,7 +10,7 @@ import { isWindows, OS } from 'vs/base/common/platform'; import * as nls from 'vs/nls'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ILabelService } from 'vs/platform/label/common/label'; -import { ICommandHandler } from 'vs/platform/commands/common/commands'; +import { ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -30,6 +30,8 @@ import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEd import { searchRefreshIcon, searchCollapseAllIcon, searchExpandAllIcon, searchClearIcon, searchReplaceAllIcon, searchReplaceIcon, searchRemoveIcon, searchStopIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/searchEditor.contribution'; +import { OpenEditorCommandId } from 'vs/workbench/contrib/searchEditor/browser/constants'; export function isSearchViewFocused(viewsService: IViewsService): boolean { const searchView = getSearchView(viewsService); @@ -173,21 +175,37 @@ export interface IFindInFilesArgs { useExcludeSettingsAndIgnoreFiles?: boolean; } export const FindInFilesCommand: ICommandHandler = (accessor, args: IFindInFilesArgs = {}) => { - - const viewsService = accessor.get(IViewsService); - openSearchView(viewsService, false).then(openedView => { - if (openedView) { - const searchAndReplaceWidget = openedView.searchAndReplaceWidget; - searchAndReplaceWidget.toggleReplace(typeof args.replace === 'string'); - let updatedText = false; - if (typeof args.query === 'string') { - openedView.setSearchParameters(args); - } else { - updatedText = openedView.updateTextFromFindWidgetOrSelection({ allowUnselectedWord: typeof args.replace !== 'string' }); + const searchConfig = accessor.get(IConfigurationService).getValue().search; + const mode = searchConfig.mode; + if (mode === 'view') { + const viewsService = accessor.get(IViewsService); + openSearchView(viewsService, false).then(openedView => { + if (openedView) { + const searchAndReplaceWidget = openedView.searchAndReplaceWidget; + searchAndReplaceWidget.toggleReplace(typeof args.replace === 'string'); + let updatedText = false; + if (typeof args.query === 'string') { + openedView.setSearchParameters(args); + } else { + updatedText = openedView.updateTextFromFindWidgetOrSelection({ allowUnselectedWord: typeof args.replace !== 'string' }); + } + openedView.searchAndReplaceWidget.focus(undefined, updatedText, updatedText); } - openedView.searchAndReplaceWidget.focus(undefined, updatedText, updatedText); - } - }); + }); + } else { + const convertArgs = (args: IFindInFilesArgs): OpenSearchEditorArgs => ({ + location: mode === 'newEditor' ? 'new' : 'reuse', + query: args.query, + filesToInclude: args.filesToInclude, + filesToExclude: args.filesToExclude, + matchWholeWord: args.matchWholeWord, + isCaseSensitive: args.isCaseSensitive, + isRegexp: args.isRegex, + useExcludeSettingsAndIgnoreFiles: args.useExcludeSettingsAndIgnoreFiles, + showIncludesExcludes: !!(args.filesToExclude || args.filesToExclude || !args.useExcludeSettingsAndIgnoreFiles), + }); + accessor.get(ICommandService).executeCommand(OpenEditorCommandId, convertArgs(args)); + } }; export class OpenSearchViewletAction extends FindOrReplaceInFilesAction { diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 408270cc7a6..c1c16e601a1 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -55,7 +55,6 @@ import { FileMatch, FileMatchOrMatch, IChangeEvent, ISearchWorkbenchService, Mat import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { relativePath } from 'vs/base/common/resources'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -1269,45 +1268,7 @@ export class SearchView extends ViewPane { } } - searchInFolders(resources?: URI[]): void { - const folderPaths: string[] = []; - const workspace = this.contextService.getWorkspace(); - - if (resources) { - resources.forEach(resource => { - let folderPath: string | undefined; - if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { - // Show relative path from the root for single-root mode - folderPath = relativePath(workspace.folders[0].uri, resource); // always uses forward slashes - if (folderPath && folderPath !== '.') { - folderPath = './' + folderPath; - } - } else { - const owningFolder = this.contextService.getWorkspaceFolder(resource); - if (owningFolder) { - const owningRootName = owningFolder.name; - - // If this root is the only one with its basename, use a relative ./ path. If there is another, use an absolute path - const isUniqueFolder = workspace.folders.filter(folder => folder.name === owningRootName).length === 1; - if (isUniqueFolder) { - const relPath = relativePath(owningFolder.uri, resource); // always uses forward slashes - if (relPath === '') { - folderPath = `./${owningFolder.name}`; - } else { - folderPath = `./${owningFolder.name}/${relPath}`; - } - } else { - folderPath = resource.fsPath; // TODO rob: handle on-file URIs - } - } - } - - if (folderPath) { - folderPaths.push(folderPath); - } - }); - } - + searchInFolders(folderPaths: string[] = []): void { if (!folderPaths.length || folderPaths.some(folderPath => folderPath === '.')) { this.inputPatternIncludes.setValue(''); this.searchWidget.focus(); diff --git a/src/vs/workbench/contrib/search/common/queryBuilder.ts b/src/vs/workbench/contrib/search/common/queryBuilder.ts index d75b404e499..d8a1a911e45 100644 --- a/src/vs/workbench/contrib/search/common/queryBuilder.ts +++ b/src/vs/workbench/contrib/search/common/queryBuilder.ts @@ -9,7 +9,7 @@ import * as glob from 'vs/base/common/glob'; import { untildify } from 'vs/base/common/labels'; import { Schemas } from 'vs/base/common/network'; import * as path from 'vs/base/common/path'; -import { isEqual, basename } from 'vs/base/common/resources'; +import { isEqual, basename, relativePath } from 'vs/base/common/resources'; import * as strings from 'vs/base/common/strings'; import { URI, URI as uri } from 'vs/base/common/uri'; import { isMultilineRegexSource } from 'vs/editor/common/model/textModelSearch'; @@ -517,3 +517,48 @@ function normalizeGlobPattern(pattern: string): string { .replace(/^\.\//, '') .replace(/\/+$/g, ''); } + +/** + * Construct an include pattern from a list of folders uris to search in. + */ +export function resolveResourcesForSearchIncludes(resources: URI[], contextService: IWorkspaceContextService): string[] { + resources = arrays.distinct(resources, resource => resource.toString()); + + const folderPaths: string[] = []; + const workspace = contextService.getWorkspace(); + + if (resources) { + resources.forEach(resource => { + let folderPath: string | undefined; + if (contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + // Show relative path from the root for single-root mode + folderPath = relativePath(workspace.folders[0].uri, resource); // always uses forward slashes + if (folderPath && folderPath !== '.') { + folderPath = './' + folderPath; + } + } else { + const owningFolder = contextService.getWorkspaceFolder(resource); + if (owningFolder) { + const owningRootName = owningFolder.name; + // If this root is the only one with its basename, use a relative ./ path. If there is another, use an absolute path + const isUniqueFolder = workspace.folders.filter(folder => folder.name === owningRootName).length === 1; + if (isUniqueFolder) { + const relPath = relativePath(owningFolder.uri, resource); // always uses forward slashes + if (relPath === '') { + folderPath = `./${owningFolder.name}`; + } else { + folderPath = `./${owningFolder.name}/${relPath}`; + } + } else { + folderPath = resource.fsPath; // TODO rob: handle non-file URIs + } + } + } + + if (folderPath) { + folderPaths.push(folderPath); + } + }); + } + return folderPaths; +} diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index cc6faa97d74..44b8afd2708 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -261,7 +261,7 @@ registerAction2(class extends Action2 { }); } async run(accessor: ServicesAccessor, args: LegacySearchEditorArgs | OpenSearchEditorArgs) { - await accessor.get(IInstantiationService).invokeFunction(openNewSearchEditor, translateLegacyConfig({ ...args, location: 'new' })); + await accessor.get(IInstantiationService).invokeFunction(openNewSearchEditor, translateLegacyConfig({ location: 'new', ...args })); } }); @@ -276,7 +276,7 @@ registerAction2(class extends Action2 { }); } async run(accessor: ServicesAccessor, args: LegacySearchEditorArgs | OpenSearchEditorArgs) { - await accessor.get(IInstantiationService).invokeFunction(openNewSearchEditor, translateLegacyConfig({ ...args, location: 'reuse' })); + await accessor.get(IInstantiationService).invokeFunction(openNewSearchEditor, translateLegacyConfig({ location: 'reuse', ...args })); } }); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index caf6d801243..9a4f7b0e09e 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -567,6 +567,18 @@ export class SearchEditor extends BaseTextEditor { return this._input as SearchEditorInput; } + setSearchConfig(config: Partial>) { + if (config.query !== undefined) { this.queryEditorWidget.setValue(config.query); } + if (config.isCaseSensitive !== undefined) { this.queryEditorWidget.searchInput.setCaseSensitive(config.isCaseSensitive); } + if (config.isRegexp !== undefined) { this.queryEditorWidget.searchInput.setRegex(config.isRegexp); } + if (config.matchWholeWord !== undefined) { this.queryEditorWidget.searchInput.setWholeWords(config.matchWholeWord); } + if (config.contextLines !== undefined) { this.queryEditorWidget.setContextLines(config.contextLines); } + if (config.filesToExclude !== undefined) { this.inputPatternExcludes.setValue(config.filesToExclude); } + if (config.filesToInclude !== undefined) { this.inputPatternIncludes.setValue(config.filesToInclude); } + if (config.useExcludeSettingsAndIgnoreFiles !== undefined) { this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(config.useExcludeSettingsAndIgnoreFiles); } + if (config.showIncludesExcludes !== undefined) { this.toggleIncludesExcludes(config.showIncludesExcludes); } + } + async setInput(newInput: SearchEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.saveViewState(); @@ -581,15 +593,7 @@ export class SearchEditor extends BaseTextEditor { this.toggleRunAgainMessage(body.getLineCount() === 1 && body.getValue() === '' && config.query !== ''); - this.queryEditorWidget.setValue(config.query); - this.queryEditorWidget.searchInput.setCaseSensitive(config.isCaseSensitive); - this.queryEditorWidget.searchInput.setRegex(config.isRegexp); - this.queryEditorWidget.searchInput.setWholeWords(config.matchWholeWord); - this.queryEditorWidget.setContextLines(config.contextLines); - this.inputPatternExcludes.setValue(config.filesToExclude); - this.inputPatternIncludes.setValue(config.filesToInclude); - this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(config.useExcludeSettingsAndIgnoreFiles); - this.toggleIncludesExcludes(config.showIncludesExcludes); + this.setSearchConfig(config); this.restoreViewState(); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index a935fe640ab..ff5292c46c3 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -80,8 +80,8 @@ export const selectAllSearchEditorMatchesCommand = (accessor: ServicesAccessor) } }; +// Handler for the action bar entry in the search view. export class OpenSearchEditorAction extends Action { - static readonly ID: string = OpenNewEditorCommandId; static readonly LABEL = localize('search.openNewEditor', "Open New Search Editor"); @@ -156,7 +156,7 @@ export const openNewSearchEditor = telemetryService.publicLog2('searchEditor/openNewSearchEditor'); - const args: OpenSearchEditorArgs = { query: selected }; + const args: OpenSearchEditorArgs = { query: selected || undefined }; Object.entries(_args).forEach(([name, value]) => { (args as any)[name as any] = (typeof value === 'string') ? configurationResolverService.resolve(lastActiveWorkspaceRoot, value) : value; }); @@ -167,6 +167,7 @@ export const openNewSearchEditor = editor = assertIsDefined(await assertIsDefined(editorGroupsService.getGroup(existing.groupId)).openEditor(input)) as SearchEditor; if (selected) { editor.setQuery(selected); } else { editor.selectQuery(); } + editor.setSearchConfig(args); } else { const input = instantiationService.invokeFunction(getOrMakeSearchEditorInput, { config: args, text: '' }); editor = await editorService.openEditor(input, { pinned: true }, toSide ? SIDE_GROUP : ACTIVE_GROUP) as SearchEditor; diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index cfa4b7f2b06..f6af1abf865 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -365,6 +365,7 @@ export interface ISearchConfigurationProperties { seedOnFocus: boolean; seedWithNearestWord: boolean; searchOnTypeDebouncePeriod: number; + mode: 'view' | 'reuseEditor' | 'newEditor'; searchEditor: { doubleClickBehaviour: 'selectWord' | 'goToLocation' | 'openLocationToSide', reusePriorSearchConfiguration: boolean, From 5f2036033c0286bfc16fbd65b33c6290712177bd Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 7 Jan 2021 18:26:09 -0800 Subject: [PATCH 1750/1837] testing: improve projection logic, add state grouping --- src/vs/base/common/iterator.ts | 12 +- .../hierarchalByLocation.ts | 238 ++++++ .../explorerProjections/hierarchalByName.ts | 135 ++++ .../explorerProjections/hierarchalNodes.ts | 154 ++++ .../browser/explorerProjections/index.ts | 92 +++ .../explorerProjections/locationStore.ts | 80 ++ .../browser/explorerProjections/nodeHelper.ts | 67 ++ .../explorerProjections/stateByLocation.ts | 316 ++++++++ .../explorerProjections/stateByName.ts | 296 ++++++++ .../browser/explorerProjections/stateNodes.ts | 39 + .../testing/browser/testExplorerActions.ts | 89 ++- .../testing/browser/testExplorerTree.ts | 4 + .../testing/browser/testing.contribution.ts | 3 + .../testing/browser/testingExplorerView.ts | 689 +++--------------- .../contrib/testing/common/constants.ts | 13 + .../contrib/testing/common/testService.ts | 5 + .../contrib/testing/common/testServiceImpl.ts | 28 + 17 files changed, 1649 insertions(+), 611 deletions(-) create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/locationStore.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts diff --git a/src/vs/base/common/iterator.ts b/src/vs/base/common/iterator.ts index 3415ec26796..a7368df6420 100644 --- a/src/vs/base/common/iterator.ts +++ b/src/vs/base/common/iterator.ts @@ -22,8 +22,8 @@ export namespace Iterable { return iterable || _empty; } - export function isEmpty(iterable: Iterable): boolean { - return iterable[Symbol.iterator]().next().done === true; + export function isEmpty(iterable: Iterable | undefined | null): boolean { + return !iterable || iterable[Symbol.iterator]().next().done === true; } export function first(iterable: Iterable): T | undefined { @@ -61,6 +61,14 @@ export namespace Iterable { } } + export function* concatNested(iterables: Iterable>): Iterable { + for (const iterable of iterables) { + for (const element of iterable) { + yield element; + } + } + } + /** * Consumes `atMost` elements from iterable and returns the consumed elements, * and an iterable for the rest of the elements. diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts new file mode 100644 index 00000000000..3731594fbe9 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts @@ -0,0 +1,238 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; +import { Emitter } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { Iterable } from 'vs/base/common/iterator'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { IWorkspaceFolder, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; +import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { HierarchicalElement, HierarchicalFolder } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; +import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; +import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { InternalTestItem, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; + +/** + * Projection that lists tests in their traditional tree view. + */ +export class HierarchicalByLocationProjection extends Disposable implements ITestTreeProjection { + private readonly updateEmitter = new Emitter(); + private lastHadMultipleFolders = true; + private newlyRenderedNodes = new Set(); + private updatedNodes = new Set(); + private removedNodes = new Set(); + private readonly locations = new TestLocationStore(); + + /** + * Map of item IDs to test item objects. + */ + protected readonly items = new Map(); + + /** + * Root folders + */ + protected readonly folders = new Map(); + + /** + * @inheritdoc + */ + public readonly onUpdate = this.updateEmitter.event; + + constructor(listener: TestSubscriptionListener) { + super(); + this._register(listener.onDiff(([folder, diff]) => this.applyDiff(folder, diff))); + this._register(listener.onFolderChange(this.applyFolderChange, this)); + + for (const [folder, collection] of listener.workspaceFolderCollections) { + const queue = [collection.rootNodes]; + while (queue.length) { + for (const id of queue.pop()!) { + const node = collection.getNodeById(id)!; + const item = this.createItem(node, folder.folder); + this.storeItem(item); + queue.push(node.children); + } + } + } + + for (const folder of this.folders.values()) { + this.newlyRenderedNodes.add(folder); + } + } + + private applyFolderChange(evt: IWorkspaceFoldersChangeEvent) { + for (const folder of evt.removed) { + const existing = this.folders.get(folder.uri.toString()); + if (existing) { + this.folders.delete(folder.uri.toString()); + this.removedNodes.add(existing); + } + this.updateEmitter.fire(); + } + } + + /** + * @inheritdoc + */ + public getTestAtPosition(uri: URI, position: Position) { + return this.locations.getTestAtPosition(uri, position); + } + + /** + * @inheritdoc + */ + private applyDiff(folder: IWorkspaceFolder, diff: TestsDiff) { + for (const op of diff) { + switch (op[0]) { + case TestDiffOpType.Add: { + const item = this.createItem(op[1], folder); + this.storeItem(item); + this.newlyRenderedNodes.add(item); + break; + } + + case TestDiffOpType.Update: { + const item = op[1]; + const existing = this.items.get(item.id); + if (!existing) { + break; + } + + const locationChanged = !locationsEqual(existing.location, item.item.location); + if (locationChanged) { this.locations.remove(existing); } + existing.update(item, this.addUpdated); + if (locationChanged) { this.locations.add(existing); } + this.addUpdated(existing); + break; + } + + case TestDiffOpType.Remove: { + const toRemove = this.items.get(op[1]); + if (!toRemove) { + break; + } + + this.deleteItem(toRemove); + toRemove.parentItem.children.delete(toRemove); + this.removedNodes.add(toRemove); + + const queue: Iterable[] = [[toRemove]]; + while (queue.length) { + for (const item of queue.pop()!) { + this.unstoreItem(item); + this.newlyRenderedNodes.delete(item); + } + } + } + } + } + + for (const [key, folder] of this.folders) { + if (folder.children.size === 0) { + this.removedNodes.add(folder); + this.folders.delete(key); + } + } + + if (diff.length !== 0) { + this.updateEmitter.fire(); + } + } + + /** + * @inheritdoc + */ + public applyTo(tree: ObjectTree) { + const firstFolder = Iterable.first(this.folders.values()); + + if (!this.lastHadMultipleFolders && this.folders.size !== 1) { + tree.setChildren(null, Iterable.map(this.folders.values(), this.renderNode)); + this.lastHadMultipleFolders = true; + } else if (this.lastHadMultipleFolders && this.folders.size === 1) { + tree.setChildren(null, Iterable.map(firstFolder!.children, this.renderNode)); + this.lastHadMultipleFolders = false; + } else { + for (const node of this.updatedNodes) { + if (tree.hasElement(node)) { + tree.rerender(node); + } + } + + const alreadyUpdatedChildren = new Set(); + for (const nodeList of [this.newlyRenderedNodes, this.removedNodes]) { + for (let { parentItem, children } of nodeList) { + if (!alreadyUpdatedChildren.has(parentItem)) { + if (!this.lastHadMultipleFolders && parentItem === firstFolder) { + tree.setChildren(null, Iterable.map(firstFolder.children, this.renderNode)); + } else { + const pchildren: Iterable = parentItem?.children ?? this.folders.values(); + tree.setChildren(parentItem, Iterable.map(pchildren, this.renderNode)); + } + + alreadyUpdatedChildren.add(parentItem); + } + + for (const child of children) { + alreadyUpdatedChildren.add(child); + } + } + } + } + + this.newlyRenderedNodes.clear(); + this.removedNodes.clear(); + this.updatedNodes.clear(); + } + + protected createItem(item: InternalTestItem, folder: IWorkspaceFolder): HierarchicalElement { + const parent = item.parent ? this.items.get(item.parent)! : this.getOrCreateFolderElement(folder); + return new HierarchicalElement(item, parent); + } + + protected deleteItem(item: HierarchicalElement) { + // no-op + } + + protected getOrCreateFolderElement(folder: IWorkspaceFolder) { + let f = this.folders.get(folder.uri.toString()); + if (!f) { + f = new HierarchicalFolder(folder); + this.newlyRenderedNodes.add(f); + this.folders.set(folder.uri.toString(), f); + } + + return f; + } + + protected readonly addUpdated = (item: ITestTreeElement) => { + const cast = item as HierarchicalElement | HierarchicalFolder; + if (!this.newlyRenderedNodes.has(cast)) { + this.updatedNodes.add(cast); + } + }; + + private readonly renderNode = (node: HierarchicalElement | HierarchicalFolder): ICompressedTreeElement => { + return { + element: node, + incompressible: true, + children: Iterable.map(node.children, this.renderNode), + }; + }; + + private unstoreItem(item: HierarchicalElement) { + this.items.delete(item.test.id); + this.locations.add(item); + } + + protected storeItem(item: HierarchicalElement) { + item.parentItem.children.add(item); + this.items.set(item.test.id, item); + this.locations.add(item); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts new file mode 100644 index 00000000000..4ac51337298 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts @@ -0,0 +1,135 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Iterable } from 'vs/base/common/iterator'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { HierarchicalByLocationProjection as HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation'; +import { HierarchicalElement, HierarchicalFolder } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; +import { InternalTestItem } from 'vs/workbench/contrib/testing/common/testCollection'; + +/** + * Type of test element in the list. + */ +export const enum ListElementType { + /** The element is a leaf test that should be shown in the list */ + TestLeaf, + /** The element is not runnable, but doesn't have any nested leaf tests */ + BranchWithLeaf, + /** The element has nested leaf tests */ + BranchWithoutLeaf, + /** State not yet computed */ + Unset, +} + +/** + * Version of the HierarchicalElement that is displayed as a list. + */ +export class HierarchicalByNameElement extends HierarchicalElement { + public elementType: ListElementType = ListElementType.Unset; + public readonly isTestRoot = !this.actualParent; + private readonly actualChildren = new Set(); + + public get description() { + let description: string | undefined; + for (let parent = this.actualParent; parent && !parent.isTestRoot; parent = parent.actualParent) { + description = description ? `${parent.label} › ${description}` : parent.label; + } + + return description; + } + + /** + * @param actualParent Parent of the item in the test heirarchy + */ + constructor( + internal: InternalTestItem, + parentItem: HierarchicalFolder | HierarchicalElement, + private readonly addUpdated: (n: ITestTreeElement) => void, + private readonly actualParent?: HierarchicalByNameElement, + ) { + super(internal, parentItem); + actualParent?.addChild(this); + this.updateLeafTestState(); + } + + /** + * @override + */ + public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { + const wasRunnable = this.test.item.runnable; + super.update(actual, addUpdated); + + if (this.test.item.runnable !== wasRunnable) { + this.updateLeafTestState(); + } + } + + /** + * Should be called when the list element is removed. + */ + public remove() { + this.actualParent?.removeChild(this); + } + + private removeChild(element: HierarchicalByNameElement) { + this.actualChildren.delete(element); + this.updateLeafTestState(); + } + + private addChild(element: HierarchicalByNameElement) { + this.actualChildren.add(element); + this.updateLeafTestState(); + } + + /** + * Updates the test leaf state for this node. Should be called when a child + * or this node is modified. Note that we never need to look at the children + * here, the children will already be leaves, or not. + */ + private updateLeafTestState() { + const newType = Iterable.some(this.actualChildren, c => c.elementType !== ListElementType.BranchWithoutLeaf) + ? ListElementType.BranchWithLeaf + : this.test.item.runnable + ? ListElementType.TestLeaf + : ListElementType.BranchWithoutLeaf; + + if (newType !== this.elementType) { + this.elementType = newType; + this.addUpdated(this); + } + + this.actualParent?.updateLeafTestState(); + } +} + +/** + * Projection that shows tests in a flat list (grouped by provider). The only + * change is that, while creating the item, the item parent is set to the + * test root rather than the heirarchal parent. + */ +export class HierarchicalByNameProjection extends HierarchicalByLocationProjection { + /** + * @override + */ + protected createItem(item: InternalTestItem, folder: IWorkspaceFolder): HierarchicalElement { + const parent = this.getOrCreateFolderElement(folder); + const actualParent = item.parent ? this.items.get(item.parent) as HierarchicalByNameElement : undefined; + for (const testRoot of parent.children) { + if (testRoot.test.providerId === item.providerId) { + return new HierarchicalByNameElement(item, testRoot, this.addUpdated, actualParent); + } + } + + return new HierarchicalByNameElement(item, parent, this.addUpdated); + } + + /** + * @override + */ + protected deleteItem(item: HierarchicalElement) { + (item as HierarchicalByNameElement).remove(); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts new file mode 100644 index 00000000000..7df3f7cd1e9 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts @@ -0,0 +1,154 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Iterable } from 'vs/base/common/iterator'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { maxPriority, statePriority } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; +import { InternalTestItem, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; + +/** + * Test tree element element that groups be hierarchy. + */ +export class HierarchicalElement implements ITestTreeElement { + public readonly children = new Set(); + public computedState: TestRunState | undefined; + public readonly depth: number = this.parentItem.depth + 1; + + public get treeId() { + return `test:${this.test.id}`; + } + + public get label() { + return this.test.item.label; + } + + public get state() { + return this.test.item.state.runState; + } + + public get location() { + return this.test.item.location; + } + + public get runnable(): Iterable { + return this.test.item.runnable + ? [{ providerId: this.test.providerId, testId: this.test.id }] + : Iterable.empty(); + } + + public get debuggable() { + return this.test.item.debuggable + ? [{ providerId: this.test.providerId, testId: this.test.id }] + : Iterable.empty(); + } + + constructor(public readonly test: InternalTestItem, public readonly parentItem: HierarchicalFolder | HierarchicalElement) { + this.test = { ...test, item: { ...test.item } }; // clone since we Object.assign updatese + } + + public getChildren() { + return this.children; + } + + public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { + const stateChange = actual.item.state.runState !== this.state; + Object.assign(this.test, actual); + if (stateChange) { + refreshComputedState(this, addUpdated); + } + } +} + +/** + * Workspace folder in the hierarcha view. + */ +export class HierarchicalFolder implements ITestTreeElement { + public readonly children = new Set(); + public readonly parentItem = null; + public readonly depth = 0; + public computedState: TestRunState | undefined; + + public get treeId() { + return `folder:${this.folder.index}`; + } + + public get runnable() { + return Iterable.concatNested(Iterable.map(this.children, c => c.runnable)); + } + + public get debuggable() { + return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); + } + + constructor(private readonly folder: IWorkspaceFolder) { } + + public get label() { + return this.folder.name; + } + + public getChildren() { + return this.children; + } +} + +/** + * Gets the computed state for the node. + */ +export const getComputedState = (node: ITestTreeElement) => { + if (node.computedState === undefined) { + node.computedState = node.state ?? TestRunState.Unset; + for (const child of node.getChildren()) { + node.computedState = maxPriority(node.computedState, getComputedState(child)); + } + } + + return node.computedState; +}; + +/** + * Refreshes the computed state for the node and its parents. Any changes + * elements cause `addUpdated` to be called. + */ +export const refreshComputedState = (node: ITestTreeElement, addUpdated: (n: ITestTreeElement) => void) => { + if (node.computedState === undefined) { + return; + } + + const oldPriority = statePriority[node.computedState]; + node.computedState = undefined; + const newState = getComputedState(node); + const newPriority = statePriority[getComputedState(node)]; + if (newPriority === oldPriority) { + return; + } + + addUpdated(node); + if (newPriority > oldPriority) { + // Update all parents to ensure they're at least this priority. + for (let parent = node.parentItem; parent; parent = parent.parentItem) { + const prev = parent.computedState; + if (prev !== undefined && statePriority[prev] >= newPriority) { + break; + } + + parent.computedState = newState; + addUpdated(parent); + } + } else if (newPriority < oldPriority) { + // Re-render all parents of this node whose computed priority might have come from this node + for (let parent = node.parentItem; parent; parent = parent.parentItem) { + const prev = parent.computedState; + if (prev === undefined || statePriority[prev] > oldPriority) { + break; + } + + parent.computedState = undefined; + parent.computedState = getComputedState(parent); + addUpdated(parent); + } + } +}; diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts new file mode 100644 index 00000000000..1af90023fa2 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CompressibleObjectTree } from 'vs/base/browser/ui/tree/objectTree'; +import { Event } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { InternalTestItem, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; + +/** + * Describes a rendering of tests in the explorer view. Different + * implementations of this are used for trees and lists, and groupings. + * Originally this was implemented as inline logic within the ViewModel and + * using a single IncrementalTestChangeCollector, but this became hairy + * with status projections. + */ +export interface ITestTreeProjection extends IDisposable { + /** + * Event that fires when the projection changes. + */ + onUpdate: Event; + + /** + * Gets the test at the given position in th editor. Should be fast, + * since it is called on each cursor move. + */ + getTestAtPosition(uri: URI, position: Position): ITestTreeElement | undefined; + + /** + * Applies pending update to the tree. + */ + applyTo(tree: CompressibleObjectTree): void; +} + + +export interface ITestTreeElement { + /** + * Computed element state. Will be set automatically if not initially provided. + * The projection is responsible for clearing (or updating) this if it + * becomes invalid. + */ + computedState: TestRunState | undefined; + + /** + * Unique ID of the element in the tree. + */ + readonly treeId: string; + + /** + * Location of the test, if any. + */ + readonly location?: { uri: URI; range: ITextEditorSelection }; + + /** + * Test item, if any. + */ + readonly test?: Readonly; + + /** + * Tree description. + */ + readonly description?: string; + + /** + * Depth of the item in the tree. + */ + readonly depth: number; + + /** + * Tests that can be run using this tree item. + */ + readonly runnable: Iterable; + + /** + * Tests that can be run using this tree item. + */ + readonly debuggable: Iterable; + + /** + * State of of the tree item. Mostly used for deriving the computed state. + */ + readonly state?: TestRunState; + readonly label: string; + readonly parentItem: ITestTreeElement | null; + getChildren(): Iterable; +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/locationStore.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/locationStore.ts new file mode 100644 index 00000000000..ad992771459 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/locationStore.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { findFirstInSorted } from 'vs/base/common/arrays'; +import { URI } from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { Location as ModeLocation } from 'vs/editor/common/modes'; + +export const locationsEqual = (a: ModeLocation | undefined, b: ModeLocation | undefined) => { + if (a === undefined || b === undefined) { + return b === a; + } + + return a.uri.toString() === b.uri.toString() + && a.range.startLineNumber === b.range.startLineNumber + && a.range.startColumn === b.range.startColumn + && a.range.endLineNumber === b.range.endLineNumber + && a.range.endColumn === b.range.endColumn; +}; + +/** + * Stores and looks up test-item-like-objects by their uri/range. Used to + * implement the 'reveal' action efficiently. + */ +export class TestLocationStore { + private readonly itemsByUri = new Map(); + + public getTestAtPosition(uri: URI, position: Position) { + const tests = this.itemsByUri.get(uri.toString()); + if (!tests) { + return; + } + + return tests.find(test => { + const range = test.location?.range; + return range + && new Position(range.startLineNumber, range.startColumn).isBeforeOrEqual(position) + && position.isBefore(new Position( + range.endLineNumber ?? range.startLineNumber, + range.endColumn ?? range.startColumn, + )); + }); + } + + public remove(item: T, fromLocation = item.location) { + if (!fromLocation) { + return; + } + + const key = fromLocation.uri.toString(); + const arr = this.itemsByUri.get(key); + if (!arr) { + return; + } + + for (let i = 0; i < arr.length; i++) { + if (arr[i] === item) { + arr.splice(i, 1); + return; + } + } + } + + public add(item: T) { + if (!item.location) { + return; + } + + const key = item.location.uri.toString(); + const arr = this.itemsByUri.get(key); + if (!arr) { + this.itemsByUri.set(key, [item]); + return; + } + + arr.splice(findFirstInSorted(arr, x => x.depth < item.depth), 0, item); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts new file mode 100644 index 00000000000..402ad544208 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { CompressibleObjectTree, ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; +import { Iterable } from 'vs/base/common/iterator'; +import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; + +/** + * Removes nodes from the set whose parents don't exist in the tree. This is + * useful to remove nodes that are queued to be updated or rendered, who will + * be rendered by a call to setChildren. + */ +export const pruneNodesWithParentsNotInTree = (nodes: Set, tree: ObjectTree) => { + for (const node of nodes) { + if (node && node.parentItem && !tree.hasElement(node.parentItem)) { + nodes.delete(node); + } + } +}; + +/** + * Helper to gather and bulk-apply tree updates. + */ +export class NodeChangeList; parentItem: T | null }> { + private changedParents = new Set(); + private updatedNodes = new Set(); + + public updated(node: T) { + this.updatedNodes.add(node); + } + + public removed(node: T) { + this.changedParents.add(node.parentItem); + } + + public added(node: T) { + this.changedParents.add(node.parentItem); + } + + public applyTo( + tree: CompressibleObjectTree, + renderNode: (n: T) => ICompressedTreeElement, + roots: () => Iterable, + ) { + pruneNodesWithParentsNotInTree(this.changedParents, tree); + pruneNodesWithParentsNotInTree(this.updatedNodes, tree); + + for (const parent of this.changedParents) { + if (parent === null || tree.hasElement(parent)) { + const pchildren: Iterable = parent ? parent.children : roots(); + tree.setChildren(parent, Iterable.map(pchildren, renderNode)); + } + } + + for (const node of this.updatedNodes) { + if (tree.hasElement(node)) { + tree.rerender(node); + } + } + + this.changedParents.clear(); + this.updatedNodes.clear(); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts new file mode 100644 index 00000000000..ca855782405 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts @@ -0,0 +1,316 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { CompressibleObjectTree } from 'vs/base/browser/ui/tree/objectTree'; +import { Emitter } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { Iterable } from 'vs/base/common/iterator'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { Location as ModeLocation } from 'vs/editor/common/modes'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; +import { NodeChangeList } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; +import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; +import { statesInOrder } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; +import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; + +interface IStatusTestItem extends IncrementalTestCollectionItem { + treeElements: Map; + previousState: TestRunState; + depth: number; + parentItem?: IStatusTestItem; + location?: ModeLocation; +} + +type TreeElement = StateElement | TestStateElement; + +class TestStateElement implements ITestTreeElement { + public computedState = this.state; + + public get treeId() { + return `test:${this.test.id}`; + } + + public get label() { + return this.test.item.label; + } + + public get location() { + return this.test.item.location; + } + + public get runnable(): Iterable { + // if this item is runnable and all its children are in the same state, + // we can run all of them in one go. This will eventually be true + // for leaf nodes, whose treeElements contain only their own state. + if (this.test.item.runnable && this.test.treeElements.size === 1) { + return [{ testId: this.test.id, providerId: this.test.providerId }]; + } + + return Iterable.concatNested(Iterable.map(this.children, c => c.runnable)); + } + + public get debuggable(): Iterable { + // same logic as runnable above + if (this.test.item.debuggable && this.test.treeElements.size === 1) { + return [{ testId: this.test.id, providerId: this.test.providerId }]; + } + + return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); + } + + public readonly depth = this.test.depth; + public readonly children = new Set(); + + getChildren(): Iterable { + return this.children; + } + + constructor( + public readonly state: TestRunState, + public readonly test: IStatusTestItem, + public readonly parentItem: TestStateElement | StateElement, + ) { + parentItem.children.add(this); + } + + public remove() { + this.parentItem.children.delete(this); + } +} + +/** + * Shows tests in a hierarchical way, but grouped by status. This is more + * complex than it may look at first glance, because nodes can appear in + * multiple places if they have children with different statuses. + */ +export class StateByLocationProjection extends AbstractIncrementalTestCollection implements ITestTreeProjection { + private readonly updateEmitter = new Emitter(); + private readonly changes = new NodeChangeList(); + private readonly locations = new TestLocationStore(); + private readonly disposable = new DisposableStore(); + + /** + * @inheritdoc + */ + public readonly onUpdate = this.updateEmitter.event; + + /** + * Root elements for states in the tree. + */ + protected readonly stateRoots = new Map>(); + + constructor(listener: TestSubscriptionListener) { + super(); + + this.disposable.add(listener.onDiff(([, diff]) => this.apply(diff))); + + const firstDiff: TestsDiff = []; + for (const [, collection] of listener.workspaceFolderCollections) { + const queue = [collection.rootNodes]; + while (queue.length) { + for (const id of queue.pop()!) { + const node = collection.getNodeById(id)!; + firstDiff.push([TestDiffOpType.Add, node]); + queue.push(node.children); + } + } + } + + this.apply(firstDiff); + } + + /** + * Frees listeners associated with the projection. + */ + public dispose() { + this.disposable.dispose(); + } + + /** + * @inheritdoc + */ + public getTestAtPosition(uri: URI, position: Position) { + const item = this.locations.getTestAtPosition(uri, position); + if (!item) { + return undefined; + } + + for (const state of statesInOrder) { + const element = item.treeElements.get(state); + if (element) { + return element; + } + } + + return undefined; + } + + /** + * @inheritdoc + */ + public applyTo(tree: CompressibleObjectTree) { + this.changes.applyTo(tree, this.renderNode, () => this.stateRoots.values()); + } + + private readonly renderNode = (node: TreeElement): ICompressedTreeElement => { + return { + element: node, + incompressible: node.depth > 0, + children: Iterable.map(node.children, this.renderNode), + }; + }; + + /** + * @override + */ + protected createChangeCollector(): IncrementalChangeCollector { + return { + add: node => { + this.resolveNodesRecursive(node); + this.locations.add(node); + }, + remove: (node, isNested) => { + this.locations.remove(node); + + if (!isNested) { + for (const state of node.treeElements.keys()) { + this.pruneStateElements(node, state, true); + } + } + }, + update: node => { + if (node.item.state.runState !== node.previousState) { + this.pruneStateElements(node, node.previousState); + this.resolveNodesRecursive(node); + } + + const locationChanged = !locationsEqual(node.location, node.item.location); + if (locationChanged) { + this.locations.remove(node); + node.location = node.item.location; + this.locations.add(node); + } + + const treeNode = node.treeElements.get(node.item.state.runState)!; + this.changes.updated(treeNode); + }, + complete: () => { + this.updateEmitter.fire(); + } + }; + } + + /** + * Ensures tree nodes for the item state are present in the tree. + */ + protected resolveNodesRecursive(item: IStatusTestItem) { + const state = item.item.state.runState; + item.previousState = item.item.state.runState; + + // Create a list of items until the current item who don't have a tree node for the status yet + let chain: IStatusTestItem[] = []; + for (let i: IStatusTestItem | undefined = item; i && !i.treeElements.has(state); i = i.parentItem) { + chain.push(i); + } + + for (let i = chain.length - 1; i >= 0; i--) { + const item2 = chain[i]; + // the loop would have stopped pushing parents when either it reaches + // the root, or it reaches a parent who already has a node for this state. + const parent = item2.parentItem?.treeElements.get(state) ?? this.getOrCreateStateElement(state); + const node = this.createElement(state, item2, parent); + + item2.treeElements.set(state, node); + parent.children.add(node); + + if (i === chain.length - 1) { + this.changes.added(node); + } + } + } + + protected createElement(state: TestRunState, item: IStatusTestItem, parent: TreeElement) { + return new TestStateElement(state, item, parent); + } + + + /** + * Recursively (from the leaf to the root) removes tree elements if there's + * no children who have the given state left. + * + * Returns true if it resulted in a node being removed. + */ + protected pruneStateElements(item: IStatusTestItem | undefined, state: TestRunState, force = false) { + if (!item) { + const stateRoot = this.stateRoots.get(state); + if (stateRoot?.children.size === 0) { + this.changes.removed(stateRoot); + this.stateRoots.delete(state); + return true; + } + + return false; + } + + const node = item.treeElements.get(state); + if (!node) { + return false; + } + + // Check to make sure we aren't in the state, and there's no child with the + // state. For the unset state, only show the node if it's a leaf or it + // has children in the unset state. + if (!force) { + if (item.item.state.runState === state && !(state === TestRunState.Unset && item.children.size > 0)) { + return false; + } + + for (const childId of item.children) { + if (this.items.get(childId)?.treeElements.has(state)) { + return false; + } + } + } + + // If so, proceed to deletion and recurse upwards. + item.treeElements.delete(state); + node.remove(); + + if (!this.pruneStateElements(item.parentItem, state)) { + this.changes.removed(node); + } + + return true; + } + + protected getOrCreateStateElement(state: TestRunState) { + let s = this.stateRoots.get(state); + if (!s) { + s = new StateElement(state); + this.changes.added(s); + this.stateRoots.set(state, s); + } + + return s; + } + + protected createItem(item: InternalTestItem, parentItem?: IStatusTestItem): IStatusTestItem { + return { + ...item, + depth: parentItem ? parentItem.depth + 1 : 0, + parentItem: parentItem, + previousState: item.item.state.runState, + location: item.item.location, + children: new Set(), + treeElements: new Map(), + }; + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts new file mode 100644 index 00000000000..7c08a73d038 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts @@ -0,0 +1,296 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { CompressibleObjectTree } from 'vs/base/browser/ui/tree/objectTree'; +import { Emitter } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; +import { Iterable } from 'vs/base/common/iterator'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { Location as ModeLocation } from 'vs/editor/common/modes'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { ListElementType } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName'; +import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; +import { NodeChangeList } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; +import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; +import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; + +class ListTestStateElement implements ITestTreeElement { + public computedState = this.test.item.state.runState; + + public get treeId() { + return `test:${this.test.id}`; + } + + public get label() { + return this.test.item.label; + } + + public get location() { + return this.test.item.location; + } + + public get runnable(): Iterable { + return this.test.item.runnable + ? [{ testId: this.test.id, providerId: this.test.providerId }] + : Iterable.empty(); + } + + public get debuggable(): Iterable { + return this.test.item.debuggable + ? [{ testId: this.test.id, providerId: this.test.providerId }] + : Iterable.empty(); + } + + public get description() { + let description: string | undefined; + for (let parent = this.test.parentItem; parent && parent.depth > 0; parent = parent.parentItem) { + description = description ? `${parent.item.label} › ${description}` : parent.item.label; + } + + return description; + } + + public readonly depth = 1; + public readonly children = Iterable.empty(); + + getChildren(): Iterable { + return Iterable.empty(); + } + + constructor( + public readonly test: IStatusListTestItem, + public readonly parentItem: StateElement, + ) { + parentItem.children.add(this); + } + + public remove() { + this.parentItem.children.delete(this); + } +} + +interface IStatusListTestItem extends IncrementalTestCollectionItem { + node?: ListTestStateElement; + type: ListElementType; + previousState: TestRunState; + depth: number; + parentItem?: IStatusListTestItem; + location?: ModeLocation; +} + +type TreeElement = StateElement | ListTestStateElement; + +/** + * Projection that shows tests in a flat list (grouped by status). + */ +export class StateByNameProjection extends AbstractIncrementalTestCollection implements ITestTreeProjection { + private readonly updateEmitter = new Emitter(); + private readonly changes = new NodeChangeList(); + private readonly locations = new TestLocationStore(); + private readonly disposable = new DisposableStore(); + + /** + * @inheritdoc + */ + public readonly onUpdate = this.updateEmitter.event; + + /** + * Root elements for states in the tree. + */ + protected readonly stateRoots = new Map>(); + + constructor(listener: TestSubscriptionListener) { + super(); + + this.disposable.add(listener.onDiff(([, diff]) => this.apply(diff))); + + const firstDiff: TestsDiff = []; + for (const [, collection] of listener.workspaceFolderCollections) { + const queue = [collection.rootNodes]; + while (queue.length) { + for (const id of queue.pop()!) { + const node = collection.getNodeById(id)!; + firstDiff.push([TestDiffOpType.Add, node]); + queue.push(node.children); + } + } + } + + this.apply(firstDiff); + } + + /** + * Frees listeners associated with the projection. + */ + public dispose() { + this.disposable.dispose(); + } + + /** + * @inheritdoc + */ + public getTestAtPosition(uri: URI, position: Position) { + return this.locations.getTestAtPosition(uri, position)?.node; + } + + /** + * @inheritdoc + */ + public applyTo(tree: CompressibleObjectTree) { + this.changes.applyTo(tree, this.renderNode, () => this.stateRoots.values()); + } + + private readonly renderNode = (node: TreeElement): ICompressedTreeElement => { + return { + element: node, + incompressible: true, + children: node instanceof StateElement ? Iterable.map(node.children, this.renderNode) : undefined, + }; + }; + + /** + * @override + */ + protected createChangeCollector(): IncrementalChangeCollector { + return { + add: node => { + this.resolveNodesRecursive(node); + this.locations.add(node); + }, + remove: (node, isRoot) => { + if (node.node) { + this.locations.remove(node); + } + + // for the top node being deleted, we need to update parents. For + // others we only need to remove them from the tree view. + if (isRoot) { + this.removeNode(node); + } else { + this.removeNodeSingle(node); + } + }, + update: node => { + if (node.item.state.runState !== node.previousState) { + this.removeNode(node); + } + + this.resolveNodesRecursive(node); + + const locationChanged = !locationsEqual(node.location, node.item.location); + if (locationChanged) { + this.locations.remove(node); + node.location = node.item.location; + this.locations.add(node); + } + + if (node.node) { + this.changes.updated(node.node); + } + }, + complete: () => { + this.updateEmitter.fire(); + } + }; + } + + /** + * Ensures tree nodes for the item state are present in the tree. + */ + protected resolveNodesRecursive(item: IStatusListTestItem) { + const newType = Iterable.some(item.children, c => this.items.get(c)!.type !== ListElementType.BranchWithoutLeaf) + ? ListElementType.BranchWithLeaf + : item.item.runnable + ? ListElementType.TestLeaf + : ListElementType.BranchWithoutLeaf; + + if (newType === item.type) { + return; + } + + const isVisible = newType === ListElementType.TestLeaf; + const wasVisible = item.type === ListElementType.TestLeaf; + item.type = newType; + + if (!isVisible && wasVisible && item.node) { + this.removeNodeSingle(item); + } else if (isVisible && !wasVisible) { + const state = item.item.state.runState; + item.node = item.node || new ListTestStateElement(item, this.getOrCreateStateElement(state)); + this.changes.added(item.node); + } + + if (item.parentItem) { + this.resolveNodesRecursive(item.parentItem); + } + } + + /** + * Recursively (from the leaf to the root) removes tree elements if there's + * no children who have the given state left. + * + * Returns true if it resulted in a node being removed. + */ + private removeNode(item: IStatusListTestItem) { + if (!item.node) { + return; + } + + this.removeNodeSingle(item); + + if (item.parentItem) { + this.resolveNodesRecursive(item.parentItem); + } + } + + private removeNodeSingle(item: IStatusListTestItem) { + if (!item.node) { + return; + } + + item.node.remove(); + this.changes.removed(item.node); + + const parent = item.node.parentItem; + item.node = undefined; + item.type = ListElementType.Unset; + + if (parent.children.size === 0) { + this.changes.removed(parent); + this.stateRoots.delete(parent.state); + } + } + + private getOrCreateStateElement(state: TestRunState) { + let s = this.stateRoots.get(state); + if (!s) { + s = new StateElement(state); + this.changes.added(s); + this.stateRoots.set(state, s); + } + + return s; + } + + /** + * @override + */ + protected createItem(item: InternalTestItem, parentItem?: IStatusListTestItem): IStatusListTestItem { + return { + ...item, + type: ListElementType.Unset, + depth: parentItem ? parentItem.depth + 1 : 0, + parentItem: parentItem, + previousState: item.item.state.runState, + location: item.item.location, + children: new Set(), + }; + } +} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts new file mode 100644 index 00000000000..c6f9c83b507 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Iterable } from 'vs/base/common/iterator'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { testStateNames } from 'vs/workbench/contrib/testing/common/constants'; + +/** + * Base state node element, used in both name and location grouping. + */ +export class StateElement implements ITestTreeElement { + public computedState = this.state; + + public get treeId() { + return `state:${this.state}`; + } + + public readonly depth = 0; + public readonly label = testStateNames[this.state]; + public readonly parentItem = null; + public readonly children = new Set(); + + getChildren(): Iterable { + return this.children; + } + + public get runnable() { + return Iterable.concatNested(Iterable.map(this.children, c => c.runnable)); + } + + public get debuggable() { + return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); + } + + constructor(public readonly state: TestRunState) { } +} diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index d90b584d5e1..1f70c910444 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -11,12 +11,11 @@ import { Action2, MenuId } from 'vs/platform/actions/common/actions'; import { ContextKeyAndExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import * as icons from 'vs/workbench/contrib/testing/browser/icons'; import { ITestingCollectionService } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; import { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView'; -import { TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; +import { TestExplorerViewGrouping, TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; import { EMPTY_TEST_RESULT, InternalTestItem, RunTestsResult, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; @@ -40,14 +39,15 @@ export const filterVisibleActions = (actions: ReadonlyArray) => export class DebugAction extends Action { constructor( - private readonly test: InternalTestItem, + private readonly tests: Iterable, + isRunning: boolean, @ITestService private readonly testService: ITestService ) { super( 'action.run', localize('debug test', 'Debug Test'), 'test-action ' + ThemeIcon.asClassName(icons.testingDebugIcon), - /* enabled= */ test.item.state.runState !== TestRunState.Running + /* enabled= */ !isRunning ); } @@ -56,7 +56,7 @@ export class DebugAction extends Action { */ public run(): Promise { return this.testService.runTests({ - tests: [{ testId: this.test.id, providerId: this.test.providerId }], + tests: [...this.tests], debug: true, }); } @@ -64,14 +64,15 @@ export class DebugAction extends Action { export class RunAction extends Action { constructor( - private readonly test: InternalTestItem, + private readonly tests: Iterable, + isRunning: boolean, @ITestService private readonly testService: ITestService ) { super( 'action.run', localize('run test', 'Run Test'), 'test-action ' + ThemeIcon.asClassName(icons.testingRunIcon), - /* enabled= */ test.item.state.runState !== TestRunState.Running, + /* enabled= */ !isRunning, ); } @@ -80,7 +81,7 @@ export class RunAction extends Action { */ public run(): Promise { return this.testService.runTests({ - tests: [{ testId: this.test.id, providerId: this.test.providerId }], + tests: [...this.tests], debug: false, }); } @@ -270,3 +271,75 @@ export class TestingViewAsTreeAction extends ViewAction { view.viewModel.viewMode = TestExplorerViewMode.Tree; } } + + +export class TestingGroupByLocationAction extends ViewAction { + constructor() { + super({ + id: 'testing.groupByLocation', + viewId: Testing.ExplorerViewId, + title: localize('testing.groupByLocation', "Sort by Name"), + f1: false, + toggled: TestingContextKeys.viewGrouping.isEqualTo(TestExplorerViewGrouping.ByLocation), + menu: { + id: MenuId.ViewTitle, + order: 10, + group: 'groupBy', + when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId) + } + }); + } + + /** + * @override + */ + public runInView(_accessor: ServicesAccessor, view: TestingExplorerView) { + view.viewModel.viewGrouping = TestExplorerViewGrouping.ByLocation; + } +} + +export class TestingGroupByStatusAction extends ViewAction { + constructor() { + super({ + id: 'testing.groupByStatus', + viewId: Testing.ExplorerViewId, + title: localize('testing.groupByStatus', "Sort by Status"), + f1: false, + toggled: TestingContextKeys.viewGrouping.isEqualTo(TestExplorerViewGrouping.ByStatus), + menu: { + id: MenuId.ViewTitle, + order: 10, + group: 'groupBy', + when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId) + } + }); + } + + /** + * @override + */ + public runInView(_accessor: ServicesAccessor, view: TestingExplorerView) { + view.viewModel.viewGrouping = TestExplorerViewGrouping.ByStatus; + } +} + +export class RefreshTestsAction extends Action2 { + constructor() { + super({ + id: 'testing.refreshTests', + title: localize('testing.refresh', "Refresh Tests"), + menu: { + id: MenuId.ViewTitle, + order: 0, + when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId) + } + }); + } + + /** + * @override + */ + public run(accessor: ServicesAccessor) { + accessor.get(ITestService).resubscribeToAllTests(); + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerTree.ts b/src/vs/workbench/contrib/testing/browser/testExplorerTree.ts index ee63748274c..791f685e1db 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerTree.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerTree.ts @@ -31,4 +31,8 @@ export const stateNodes = Object.entries(statePriority).reduce( }, {} as { [K in TestRunState]: TreeStateNode } ); +export const cmpPriority = (a: TestRunState, b: TestRunState) => statePriority[b] - statePriority[a]; + export const maxPriority = (a: TestRunState, b: TestRunState) => statePriority[a] > statePriority[b] ? a : b; + +export const statesInOrder = Object.keys(statePriority).map(s => Number(s) as TestRunState).sort(cmpPriority); diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts index 9b9937e2665..a45e123a38e 100644 --- a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -73,6 +73,9 @@ registerAction2(Action.TestingViewAsTreeAction); registerAction2(Action.CancelTestRunAction); registerAction2(Action.RunSelectedAction); registerAction2(Action.DebugSelectedAction); +registerAction2(Action.TestingGroupByLocationAction); +registerAction2(Action.TestingGroupByStatusAction); +registerAction2(Action.RefreshTestsAction); CommandsRegistry.registerCommand({ id: 'vscode.runTests', diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index df0c9239973..53bc0ce7776 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -5,49 +5,51 @@ import * as dom from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; -import { ITreeElement, ITreeEvent, ITreeFilter, ITreeNode, ITreeRenderer, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; -import { findFirstInSorted } from 'vs/base/common/arrays'; +import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { CompressibleObjectTree, ICompressibleKeyboardNavigationLabelProvider, ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; +import { ITreeEvent, ITreeFilter, ITreeNode, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; import { throttle } from 'vs/base/common/decorators'; -import { Emitter, Event } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { FuzzyScore } from 'vs/base/common/filters'; import { Iterable } from 'vs/base/common/iterator'; -import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { URI } from 'vs/base/common/uri'; +import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import 'vs/css!./media/testing'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -import { Position } from 'vs/editor/common/core/position'; import { localize } from 'vs/nls'; import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { MenuItemAction } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { FileKind } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; +import { WorkbenchCompressibleObjectTree } from 'vs/platform/list/browser/listService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { IWorkspaceFolder, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { IResourceLabel, IResourceLabelOptions, IResourceLabelProps, ResourceLabels } from 'vs/workbench/browser/labels'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation'; +import { HierarchicalByNameElement, HierarchicalByNameProjection, ListElementType } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName'; +import { getComputedState } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; +import { StateByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation'; +import { StateByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByName'; +import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; import { testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons'; -import { maxPriority, statePriority } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; +import { cmpPriority } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; import { ITestingCollectionService, TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; -import { TestExplorerViewMode } from 'vs/workbench/contrib/testing/common/constants'; -import { InternalTestItem, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestExplorerViewGrouping, TestExplorerViewMode } from 'vs/workbench/contrib/testing/common/constants'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -142,17 +144,12 @@ export class TestingExplorerView extends ViewPane { } export class TestingExplorerViewModel extends Disposable { - public tree: ObjectTree; + public tree: CompressibleObjectTree; private filter: TestsFilter; public projection!: ITestTreeProjection; private readonly _viewMode = TestingContextKeys.viewMode.bindTo(this.contextKeyService); - private viewModeChangeEmitter = new Emitter(); - - /** - * Fires when the tree view mode changes. - */ - public readonly onViewModeChange = this.viewModeChangeEmitter.event; + private readonly _viewGrouping = TestingContextKeys.viewGrouping.bindTo(this.contextKeyService); /** * Fires when the selected tests change. @@ -171,7 +168,21 @@ export class TestingExplorerViewModel extends Disposable { this._viewMode.set(newMode); this.updatePreferredProjection(); this.storageService.store('testing.viewMode', newMode, StorageScope.WORKSPACE, StorageTarget.USER); - this.viewModeChangeEmitter.fire(newMode); + } + + + public get viewGrouping() { + return this._viewGrouping.get() ?? TestExplorerViewGrouping.ByLocation; + } + + public set viewGrouping(newGrouping: TestExplorerViewGrouping) { + if (newGrouping === this._viewGrouping.get()) { + return; + } + + this._viewGrouping.set(newGrouping); + this.updatePreferredProjection(); + this.storageService.store('testing.viewGrouping', newGrouping, StorageScope.WORKSPACE, StorageTarget.USER); } constructor( @@ -187,11 +198,13 @@ export class TestingExplorerViewModel extends Disposable { super(); this._viewMode.set(this.storageService.get('testing.viewMode', StorageScope.WORKSPACE, TestExplorerViewMode.Tree) as TestExplorerViewMode); + this._viewGrouping.set(this.storageService.get('testing.viewGrouping', StorageScope.WORKSPACE, TestExplorerViewGrouping.ByLocation) as TestExplorerViewGrouping); + const labels = this._register(instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: onDidChangeVisibility })); this.filter = new TestsFilter(); this.tree = instantiationService.createInstance( - WorkbenchObjectTree, + WorkbenchCompressibleObjectTree, 'Test Explorer List', listContainer, new ListDelegate(), @@ -205,7 +218,7 @@ export class TestingExplorerViewModel extends Disposable { keyboardNavigationLabelProvider: instantiationService.createInstance(TreeKeyboardNavigationLabelProvider), accessibilityProvider: instantiationService.createInstance(ListAccessibilityProvider), filter: this.filter, - }) as ObjectTree; + }) as WorkbenchCompressibleObjectTree; this._register(this.tree); this.updatePreferredProjection(); @@ -281,10 +294,18 @@ export class TestingExplorerViewModel extends Disposable { return; } - if (this._viewMode.get() === TestExplorerViewMode.List) { - this.projection = new ListProjection(this.listener); + if (this._viewGrouping.get() === TestExplorerViewGrouping.ByLocation) { + if (this._viewMode.get() === TestExplorerViewMode.List) { + this.projection = new HierarchicalByNameProjection(this.listener); + } else { + this.projection = new HierarchicalByLocationProjection(this.listener); + } } else { - this.projection = new HierarchalProjection(this.listener); + if (this._viewMode.get() === TestExplorerViewMode.List) { + this.projection = new StateByNameProjection(this.listener); + } else { + this.projection = new StateByLocationProjection(this.listener); + } } this.projection.onUpdate(this.deferUpdate, this); @@ -321,14 +342,13 @@ class CodeEditorTracker { const register = (editor: ICodeEditor) => { const store = new DisposableStore(); - const uri = editor.getModel()?.uri; - if (!uri) { - return; - } - store.add(editor.onDidChangeCursorPosition(evt => { - const test = this.model.projection.getTestAtPosition(uri, evt.position); + const uri = editor.getModel()?.uri; + if (!uri) { + return; + } + const test = this.model.projection.getTestAtPosition(uri, evt.position); if (test && test !== this.lastRevealed) { this.model.revealItem(test); this.lastRevealed = test; @@ -355,63 +375,6 @@ class CodeEditorTracker { } } -/** - * Gets the computed state for the node. - */ -const getComputedState = (node: ITestTreeElement) => { - if (node.computedState === undefined) { - node.computedState = node.state ?? TestRunState.Unset; - for (const child of node.getChildren()) { - node.computedState = maxPriority(node.computedState, getComputedState(child)); - } - } - - return node.computedState; -}; - -/** - * Refreshes the computed state for the node and its parents. Any changes - * elements will be added to the `changedNodes` set. - */ -const refreshComputedState = (node: ITestTreeElement, addUpdated: (n: ITestTreeElement) => void) => { - if (node.computedState === undefined) { - return; - } - - const oldPriority = statePriority[node.computedState]; - node.computedState = undefined; - const newState = getComputedState(node); - const newPriority = statePriority[getComputedState(node)]; - if (newPriority === oldPriority) { - return; - } - - addUpdated(node); - if (newPriority > oldPriority) { - // Update all parents to ensure they're at least this priority. - for (let parent = node.parentItem; parent; parent = parent.parentItem) { - const prev = parent.computedState; - if (prev !== undefined && statePriority[prev] >= newPriority) { - break; - } - - parent.computedState = newState; - addUpdated(parent); - } - } else if (newPriority < oldPriority) { - // Re-render all parents of this node whose computed priority might have come from this node - for (let parent = node.parentItem; parent; parent = parent.parentItem) { - const prev = parent.computedState; - if (prev === undefined || statePriority[prev] > oldPriority) { - break; - } - - parent.computedState = undefined; - parent.computedState = getComputedState(parent); - addUpdated(parent); - } - } -}; class TestsFilter implements ITreeFilter { private filterText: string | undefined; @@ -421,7 +384,7 @@ class TestsFilter implements ITreeFilter { } public filter(element: ITestTreeElement): TreeFilterResult { - if (element instanceof ListElement && element.elementType !== ListElementType.TestLeaf && !element.isTestRoot) { + if (element instanceof HierarchicalByNameElement && element.elementType !== ListElementType.TestLeaf && !element.isTestRoot) { return TreeVisibility.Hidden; } @@ -438,6 +401,10 @@ class TestsFilter implements ITreeFilter { } class TreeSorter implements ITreeSorter { public compare(a: ITestTreeElement, b: ITestTreeElement): number { + if (a instanceof StateElement && b instanceof StateElement) { + return cmpPriority(a.computedState, b.computedState); + } + return a.label.localeCompare(b.label); } } @@ -452,7 +419,11 @@ class ListAccessibilityProvider implements IListAccessibilityProvider { +class TreeKeyboardNavigationLabelProvider implements ICompressibleKeyboardNavigationLabelProvider { + getCompressedNodeKeyboardNavigationLabel(elements: ITestTreeElement[]) { + return this.getKeyboardNavigationLabel(elements[elements.length - 1]); + } + getKeyboardNavigationLabel(element: ITestTreeElement) { return element.label; } @@ -480,7 +451,7 @@ interface TestTemplateData { actionBar: ActionBar; } -class TestsRenderer implements ITreeRenderer { +class TestsRenderer implements ICompressibleTreeRenderer { public static readonly ID = 'testExplorer'; constructor( @@ -488,6 +459,11 @@ class TestsRenderer implements ITreeRenderer, FuzzyScore>, index: number, templateData: TestTemplateData): void { + const element = node.element.elements[node.element.elements.length - 1]; + this.renderElementDirect(element, templateData); + } + get templateId(): string { return TestsRenderer.ID; } @@ -510,7 +486,10 @@ class TestsRenderer implements ITreeRenderer, index: number, data: TestTemplateData): void { - const element = node.element; + this.renderElementDirect(node.element, data); + } + + private renderElementDirect(element: ITestTreeElement, data: TestTemplateData) { const label: IResourceLabelProps = { name: element.label }; const options: IResourceLabelOptions = {}; data.actionBar.clear(); @@ -531,19 +510,26 @@ class TestsRenderer implements ITreeRenderer; - - /** - * Gets the test at the given position in th editor. Should be fast, - * since it is called on each cursor move. - */ - getTestAtPosition(uri: URI, position: Position): ITestTreeElement | undefined; - - /** - * Applies pending update to the tree. - */ - applyTo(tree: ObjectTree): void; -} - -export interface ITestTreeElement { - /** - * Computed element state. Will be set automatically if not initially provided. - * The projection is responsible for clearing (or updating) this if it - * becomes invalid. - */ - computedState: TestRunState | undefined; - - /** - * Unique ID of the element in the tree. - */ - readonly treeId: string; - - /** - * Location of the test, if any. - */ - readonly location?: { uri: URI; range: ITextEditorSelection }; - - /** - * Test item, if any. - */ - readonly test?: Readonly; - - /** - * Tree description. - */ - readonly description?: string; - - /** - * Depth of the item in the tree. - */ - readonly depth: number; - - /** - * State of of the tree item. Mostly used for deriving the computed state. - */ - readonly state?: TestRunState; - readonly label: string; - readonly parentItem: ITestTreeElement | null; - getChildren(): Iterable; -} - -class HierarchalElement implements ITestTreeElement { - public readonly children = new Set(); - public computedState: TestRunState | undefined; - public readonly depth: number = this.parentItem.depth + 1; - - public get treeId() { - return `test:${this.test.id}`; - } - - public get label() { - return this.test.item.label; - } - - public get state() { - return this.test.item.state.runState; - } - - public get location() { - return this.test.item.location; - } - - constructor(public readonly test: InternalTestItem, public readonly parentItem: HierarchalFolder | HierarchalElement) { - this.test = { ...test, item: { ...test.item } }; // clone since we Object.assign updatese - } - - public getChildren() { - return this.children; - } - - public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { - const stateChange = actual.item.state.runState !== this.state; - Object.assign(this.test, actual); - if (stateChange) { - refreshComputedState(this, addUpdated); - } - } -} - -class HierarchalFolder implements ITestTreeElement { - public readonly children = new Set(); - public readonly parentItem = null; - public readonly depth = 0; - public computedState: TestRunState | undefined; - - public get treeId() { - return `folder:${this.folder.index}`; - } - - constructor(private readonly folder: IWorkspaceFolder) { } - - public get label() { - return this.folder.name; - } - - public getChildren() { - return this.children; - } -} - -const enum ListElementType { - TestLeaf, - BranchWithLeaf, - BranchWithoutLeaf, - Unset, -} - -class ListElement extends HierarchalElement { - public elementType: ListElementType = ListElementType.Unset; - public readonly isTestRoot = !this.actualParent; - private readonly actualChildren = new Set(); - - public get description() { - let description: string | undefined; - for (let parent = this.actualParent; parent && !parent.isTestRoot; parent = parent.actualParent) { - description = description ? `${parent.label} › ${description}` : parent.label; - } - - return description; - } - - /** - * @param actualParent Parent of the item in the test heirarchy - */ - constructor( - internal: InternalTestItem, - parentItem: HierarchalFolder | HierarchalElement, - private readonly addUpdated: (n: ITestTreeElement) => void, - private readonly actualParent?: ListElement, - ) { - super(internal, parentItem); - actualParent?.addChild(this); - this.updateLeafTestState(); - } - - /** - * @override - */ - public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { - const wasRunnable = this.test.item.runnable; - super.update(actual, addUpdated); - - if (this.test.item.runnable !== wasRunnable) { - this.updateLeafTestState(); - } - } - - /** - * Should be called when the list element is removed. - */ - public remove() { - this.actualParent?.removeChild(this); - } - - private removeChild(element: ListElement) { - this.actualChildren.delete(element); - this.updateLeafTestState(); - } - - private addChild(element: ListElement) { - this.actualChildren.add(element); - this.updateLeafTestState(); - } - - /** - * Updates the test leaf state for this node. Should be called when a child - * or this node is modified. Note that we never need to look at the children - * here, the children will already be leaves, or not. - */ - private updateLeafTestState() { - const newType = Iterable.some(this.actualChildren, c => c.elementType !== ListElementType.BranchWithoutLeaf) - ? ListElementType.BranchWithLeaf - : this.test.item.runnable - ? ListElementType.TestLeaf - : ListElementType.BranchWithoutLeaf; - - if (newType !== this.elementType) { - this.elementType = newType; - this.addUpdated(this); - } - - this.actualParent?.updateLeafTestState(); - } -} - -/** - * Projection that lists tests in their traditional tree view. - */ -class HierarchalProjection extends Disposable implements ITestTreeProjection { - private readonly updateEmitter = new Emitter(); - private lastHadMultipleFolders = true; - private newlyRenderedNodes = new Set(); - private updatedNodes = new Set(); - private removedNodes = new Set(); - private readonly itemsByUri = new Map(); - - /** - * Map of item IDs to test item objects. - */ - protected readonly items = new Map(); - - /** - * Root folders - */ - protected readonly folders = new Map(); - - /** - * @inheritdoc - */ - public readonly onUpdate = this.updateEmitter.event; - - constructor(listener: TestSubscriptionListener) { - super(); - this._register(listener.onDiff(([folder, diff]) => this.applyDiff(folder, diff))); - this._register(listener.onFolderChange(this.applyFolderChange, this)); - - for (const [folder, collection] of listener.workspaceFolderCollections) { - const queue = [collection.rootNodes]; - while (queue.length) { - for (const id of queue.pop()!) { - const node = collection.getNodeById(id)!; - const item = this.createItem(node, folder.folder); - this.storeItem(item); - queue.push(node.children); - } - } - } - - for (const folder of this.folders.values()) { - this.newlyRenderedNodes.add(folder); - } - } - - private applyFolderChange(evt: IWorkspaceFoldersChangeEvent) { - for (const folder of evt.removed) { - const existing = this.folders.get(folder.uri.toString()); - if (existing) { - this.folders.delete(folder.uri.toString()); - this.removedNodes.add(existing); - } - this.updateEmitter.fire(); - } - } - - /** - * @inheritdoc - */ - public getTestAtPosition(uri: URI, position: Position) { - const tests = this.itemsByUri.get(uri.toString()); - if (!tests) { - return; - } - - - return tests.find(test => { - const range = test.location?.range; - return range - && new Position(range.startLineNumber, range.startColumn).isBeforeOrEqual(position) - && position.isBefore(new Position(range.endLineNumber, range.endColumn)); - }); - } - - /** - * @inheritdoc - */ - private applyDiff(folder: IWorkspaceFolder, diff: TestsDiff) { - for (const op of diff) { - switch (op[0]) { - case TestDiffOpType.Add: { - const item = this.createItem(op[1], folder); - this.storeItem(item); - this.newlyRenderedNodes.add(item); - break; - } - - case TestDiffOpType.Update: { - const item = op[1]; - const existing = this.items.get(item.id); - if (!existing) { - break; - } - - const locationChanged = existing.location?.uri.toString() !== item.item.location?.uri.toString(); - if (locationChanged) { this.removeItemFromLocationMap(existing); } - existing.update(item, this.addUpdated); - if (locationChanged) { this.addItemToLocationMap(existing); } - this.addUpdated(existing); - break; - } - - case TestDiffOpType.Remove: { - const toRemove = this.items.get(op[1]); - if (!toRemove) { - break; - } - - this.deleteItem(toRemove); - toRemove.parentItem.children.delete(toRemove); - this.removedNodes.add(toRemove); - - const queue: Iterable[] = [[toRemove]]; - while (queue.length) { - for (const item of queue.pop()!) { - this.unstoreItem(item); - this.newlyRenderedNodes.delete(item); - } - } - } - } - } - - for (const [key, folder] of this.folders) { - if (folder.children.size === 0) { - this.removedNodes.add(folder); - this.folders.delete(key); - } - } - - if (diff.length !== 0) { - this.updateEmitter.fire(); - } - } - - /** - * @inheritdoc - */ - public applyTo(tree: ObjectTree) { - const firstFolder = Iterable.first(this.folders.values()); - - if (!this.lastHadMultipleFolders && this.folders.size !== 1) { - tree.setChildren(null, Iterable.map(this.folders.values(), this.renderNode)); - this.lastHadMultipleFolders = true; - } else if (this.lastHadMultipleFolders && this.folders.size === 1) { - tree.setChildren(null, Iterable.map(firstFolder!.children, this.renderNode)); - this.lastHadMultipleFolders = false; - } else { - const alreadyUpdatedChildren = new Set(); - for (const nodeList of [this.newlyRenderedNodes, this.removedNodes]) { - for (let { parentItem, children } of nodeList) { - if (!alreadyUpdatedChildren.has(parentItem)) { - if (!this.lastHadMultipleFolders && parentItem === firstFolder) { - tree.setChildren(null, Iterable.map(firstFolder.children, this.renderNode)); - } else { - const pchildren: Iterable = parentItem?.children ?? this.folders.values(); - tree.setChildren(parentItem, Iterable.map(pchildren, this.renderNode)); - } - - alreadyUpdatedChildren.add(parentItem); - } - - for (const child of children) { - alreadyUpdatedChildren.add(child); - } - } - } - - if (!this.lastHadMultipleFolders) { - this.updatedNodes.delete(firstFolder!); - } - - for (const node of this.updatedNodes) { - tree.rerender(node); - } - } - - this.newlyRenderedNodes.clear(); - this.removedNodes.clear(); - this.updatedNodes.clear(); - } - - protected createItem(item: InternalTestItem, folder: IWorkspaceFolder): HierarchalElement { - const parent = item.parent ? this.items.get(item.parent)! : this.getOrCreateFolderElement(folder); - return new HierarchalElement(item, parent); - } - - protected deleteItem(item: HierarchalElement) { - // no-op - } - - protected getOrCreateFolderElement(folder: IWorkspaceFolder) { - let f = this.folders.get(folder.uri.toString()); - if (!f) { - f = new HierarchalFolder(folder); - this.newlyRenderedNodes.add(f); - this.folders.set(folder.uri.toString(), f); - } - - return f; - } - - protected readonly addUpdated = (item: ITestTreeElement) => { - const cast = item as HierarchalElement | HierarchalFolder; - if (!this.newlyRenderedNodes.has(cast)) { - this.updatedNodes.add(cast); - } - }; - - private readonly renderNode = (node: HierarchalElement | HierarchalFolder): ITreeElement => { - return { - element: node, - children: Iterable.map(node.children, this.renderNode), - }; - }; - - private unstoreItem(item: HierarchalElement) { - this.items.delete(item.test.id); - this.removeItemFromLocationMap(item); - } - - protected storeItem(item: HierarchalElement) { - item.parentItem.children.add(item); - this.items.set(item.test.id, item); - this.addItemToLocationMap(item); - } - - protected removeItemFromLocationMap(item: HierarchalElement) { - if (!item.location) { - return; - } - - const key = item.location.uri.toString(); - const arr = this.itemsByUri.get(key); - if (!arr) { - return; - } - - for (let i = 0; i < arr.length; i++) { - if (arr[i] === item) { - arr.splice(i, 1); - return; - } - } - } - - protected addItemToLocationMap(item: HierarchalElement) { - if (!item.location) { - return; - } - - const key = item.location.uri.toString(); - const arr = this.itemsByUri.get(key); - if (!arr) { - this.itemsByUri.set(key, [item]); - return; - } - - arr.splice(findFirstInSorted(arr, x => x.depth < item.depth), 0, item); - } -} - -/** - * Projection that shows tests in a flat list (grouped by provider). The only - * change is that, while creating the item, the item parent is set to the - * test root rather than the heirarchal parent. - */ -class ListProjection extends HierarchalProjection { - /** - * @override - */ - protected createItem(item: InternalTestItem, folder: IWorkspaceFolder): HierarchalElement { - const parent = this.getOrCreateFolderElement(folder); - const actualParent = item.parent ? this.items.get(item.parent) as ListElement : undefined; - for (const testRoot of parent.children) { - if (testRoot.test.providerId === item.providerId) { - return new ListElement(item, testRoot, this.addUpdated, actualParent); - } - } - - return new ListElement(item, parent, this.addUpdated); - } - - /** - * @override - */ - protected deleteItem(item: HierarchalElement) { - (item as ListElement).remove(); - } -} diff --git a/src/vs/workbench/contrib/testing/common/constants.ts b/src/vs/workbench/contrib/testing/common/constants.ts index 5a5275a6d52..95c9c661c57 100644 --- a/src/vs/workbench/contrib/testing/common/constants.ts +++ b/src/vs/workbench/contrib/testing/common/constants.ts @@ -3,6 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; + export const enum Testing { ViewletId = 'workbench.view.testing', ExplorerViewId = 'workbench.view.testing', @@ -17,3 +20,13 @@ export const enum TestExplorerViewGrouping { ByLocation = 'location', ByStatus = 'status', } + +export const testStateNames: { [K in TestRunState]: string } = { + [TestRunState.Errored]: localize('testState.errored', 'Errored'), + [TestRunState.Failed]: localize('testState.failed', 'Failed'), + [TestRunState.Passed]: localize('testState.passed', 'Passed'), + [TestRunState.Queued]: localize('testState.queued', 'Queued'), + [TestRunState.Running]: localize('testState.running', 'Running'), + [TestRunState.Skipped]: localize('testState.skipped', 'Skipped'), + [TestRunState.Unset]: localize('testState.unset', 'Unset'), +}; diff --git a/src/vs/workbench/contrib/testing/common/testService.ts b/src/vs/workbench/contrib/testing/common/testService.ts index 4d9d002662b..b29765b0fbe 100644 --- a/src/vs/workbench/contrib/testing/common/testService.ts +++ b/src/vs/workbench/contrib/testing/common/testService.ts @@ -52,4 +52,9 @@ export interface ITestService { * Updates the number of test providers still discovering tests for the given resource. */ updateDiscoveringCount(resource: ExtHostTestingResource, uri: URI, delta: number): void; + + /** + * Requests to resubscribe to all active subscriptions, discarding old tests. + */ + resubscribeToAllTests(): void; } diff --git a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts index 3c6c870ae8d..4bfa4197e07 100644 --- a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts +++ b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts @@ -156,6 +156,18 @@ export class TestService extends Disposable implements ITestService { } } + /** + * @inheritdoc + */ + public resubscribeToAllTests() { + for (const subscription of this.testSubscriptions.values()) { + this.unsubscribeEmitter.fire(subscription.ident); + const diff = subscription.collection.clear(); + subscription.onDiff.fire(diff); + this.subscribeEmitter.fire(subscription.ident); + } + } + /** * @inheritdoc */ @@ -241,6 +253,22 @@ class MainThreadTestCollection extends AbstractIncrementalTestCollection Date: Fri, 8 Jan 2021 15:15:23 -0800 Subject: [PATCH 1751/1837] Retry idb tests. Ref #114025. --- .../platform/files/test/browser/indexedDBFileService.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/platform/files/test/browser/indexedDBFileService.test.ts b/src/vs/platform/files/test/browser/indexedDBFileService.test.ts index 5483b612c67..67ccfd9a6b1 100644 --- a/src/vs/platform/files/test/browser/indexedDBFileService.test.ts +++ b/src/vs/platform/files/test/browser/indexedDBFileService.test.ts @@ -17,6 +17,9 @@ import { bufferToReadable, bufferToStream, VSBuffer, VSBufferReadable, VSBufferR suite('IndexedDB File Service', function () { + // IDB sometimes under pressure in build machines. + this.retries(3); + const logSchema = 'logs'; let service: FileService; From 01c6003c29519f7ba3223797c9bf6a7b6f914729 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 8 Jan 2021 15:57:28 -0800 Subject: [PATCH 1752/1837] Enable webview tests (#114059) These tests were disable due to some occasional failures on build machines. This PR enables them but with flakySuite while I track down possible causes of these failures --- .../src/singlefolder-tests/webview.test.ts | 6 +++--- extensions/vscode-api-tests/src/utils.ts | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index fd97ea91728..3d0ef5c7085 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import 'mocha'; import * as os from 'os'; import * as vscode from 'vscode'; -import { closeAllEditors, delay, disposeAll } from '../utils'; +import { closeAllEditors, delay, disposeAll, flakySuite } from '../utils'; const webviewId = 'myWebview'; @@ -17,7 +17,7 @@ function workspaceFile(...segments: string[]) { const testDocument = workspaceFile('bower.json'); -suite.skip('vscode API - webview', () => { +flakySuite('vscode API - webview', () => { const disposables: vscode.Disposable[] = []; function _register(disposable: T) { @@ -212,7 +212,7 @@ suite.skip('vscode API - webview', () => { assert.strictEqual(Math.round(secondResponse.value), 100); }); - test('webviews with retainContextWhenHidden should be able to recive messages while hidden', async () => { + test('webviews with retainContextWhenHidden should be able to receive messages while hidden', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMesssage(webview); diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts index 392d0be8461..cd4471842b9 100644 --- a/extensions/vscode-api-tests/src/utils.ts +++ b/extensions/vscode-api-tests/src/utils.ts @@ -3,9 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as assert from 'assert'; +import { Suite } from 'mocha'; import * as vscode from 'vscode'; import { TestFS } from './memfs'; -import * as assert from 'assert'; + +export function flakySuite(title: string, fn: (this: Suite) => void): Suite { + return suite(title, function () { + + // Flaky suites need retries and timeout to complete + // e.g. because they access the file system which can + // be unreliable depending on the environment. + this.retries(3); + this.timeout(1000 * 20); + + // Invoke suite ensuring that `this` is + // properly wired in. + fn.call(this); + }); +} export function rndName() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); From ea1b3f27db4cb1c82f9fb10151dca775676957b3 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Fri, 8 Jan 2021 19:40:51 -0500 Subject: [PATCH 1753/1837] Fixes window border causes webviews to be positioned slightly off (#114061) * Fixes #109127 * manually compute content offset in case the window has a border --- .../contrib/webview/browser/dynamicWebviewEditorOverlay.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index 955f53ecbb4..d67cf68e348 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -127,10 +127,12 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv const frameRect = element.getBoundingClientRect(); const containerRect = this.container.parentElement.getBoundingClientRect(); + const parentBorderTop = (containerRect.height - this.container.parentElement.clientHeight) / 2.0; + const parentBorderLeft = (containerRect.width - this.container.parentElement.clientWidth) / 2.0; this.container.style.position = 'absolute'; this.container.style.overflow = 'hidden'; - this.container.style.top = `${frameRect.top - containerRect.top}px`; - this.container.style.left = `${frameRect.left - containerRect.left}px`; + this.container.style.top = `${frameRect.top - containerRect.top - parentBorderTop}px`; + this.container.style.left = `${frameRect.left - containerRect.left - parentBorderLeft}px`; this.container.style.width = `${dimension ? dimension.width : frameRect.width}px`; this.container.style.height = `${dimension ? dimension.height : frameRect.height}px`; } From b0e96922417366d169d1f496e5af1e2f6237d0ca Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 9 Jan 2021 11:21:45 +0100 Subject: [PATCH 1754/1837] tests - selectively enable some previously skipped tests --- .../electron-main/backupMainService.test.ts | 15 +++++++-------- .../electron-browser/diskFileService.test.ts | 18 +++++++++--------- .../test/node/encoding/encoding.test.ts | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 72f3569ae01..5d239dd565d 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -260,7 +260,7 @@ flakySuite('BackupMainService', () => { assert.equal(1, fs.readdirSync(path.join(backupHome, emptyBackups[0].backupFolder!)).length); }); - flakySuite('loadSync', () => { + suite('loadSync', () => { test('getFolderBackupPaths() should return [] when workspaces.json doesn\'t exist', () => { assertEqualUris(service.getFolderBackupPaths(), []); }); @@ -430,7 +430,7 @@ flakySuite('BackupMainService', () => { }); }); - flakySuite('dedupeFolderWorkspaces', () => { + suite('dedupeFolderWorkspaces', () => { test('should ignore duplicates (folder workspace)', async () => { await ensureFolderExists(existingTestFolder1); @@ -493,7 +493,7 @@ flakySuite('BackupMainService', () => { }); }); - flakySuite('registerWindowForBackups', () => { + suite('registerWindowForBackups', () => { test('should persist paths to workspaces.json (folder workspace)', async () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(barFile); @@ -541,7 +541,7 @@ flakySuite('BackupMainService', () => { assert.deepEqual(json.rootURIWorkspaces.map(b => b.configURIPath), [URI.file(upperFooPath).toString()]); }); - flakySuite('removeBackupPathSync', () => { + suite('removeBackupPathSync', () => { test('should remove folder workspaces from workspaces.json (folder workspace)', async () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(barFile); @@ -604,8 +604,7 @@ flakySuite('BackupMainService', () => { }); }); - flakySuite('getWorkspaceHash', () => { - + suite('getWorkspaceHash', () => { (platform.isLinux ? test.skip : test)('should ignore case on Windows and Mac', () => { if (platform.isMacintosh) { assert.equal(service.getFolderHash(URI.file('/foo')), service.getFolderHash(URI.file('/FOO'))); @@ -617,7 +616,7 @@ flakySuite('BackupMainService', () => { }); }); - flakySuite('mixed path casing', () => { + suite('mixed path casing', () => { test('should handle case insensitive paths properly (registerWindowForBackupsSync) (folder workspace)', () => { service.registerFolderBackupSync(fooFile); service.registerFolderBackupSync(URI.file(fooFile.fsPath.toUpperCase())); @@ -659,7 +658,7 @@ flakySuite('BackupMainService', () => { }); }); - flakySuite('getDirtyWorkspaces', () => { + suite('getDirtyWorkspaces', () => { test('should report if a workspace or folder has backups', async () => { const folderBackupPath = service.registerFolderBackupSync(fooFile); diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index 0a5f54206bf..f5d9992ad9a 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -407,7 +407,7 @@ flakySuite('Disk File Service', function () { assert.equal(r2.name, 'deep'); }); - (isWindows /* not reliable on windows */ ? test.skip : test)('resolve - folder symbolic link', async () => { + (isWindows /* symlinks are not reliable on windows */ ? test.skip : test)('resolve - folder symbolic link', async () => { const link = URI.file(join(testDir, 'deep-link')); await symlink(join(testDir, 'deep'), link.fsPath); @@ -417,7 +417,7 @@ flakySuite('Disk File Service', function () { assert.equal(resolved.isSymbolicLink, true); }); - (isWindows /* not reliable on windows */ ? test.skip : test)('resolve - file symbolic link', async () => { + (isWindows /* symlinks are not reliable on windows */ ? test.skip : test)('resolve - file symbolic link', async () => { const link = URI.file(join(testDir, 'lorem.txt-linked')); await symlink(join(testDir, 'lorem.txt'), link.fsPath); @@ -426,7 +426,7 @@ flakySuite('Disk File Service', function () { assert.equal(resolved.isSymbolicLink, true); }); - (isWindows /* not reliable on windows */ ? test.skip : test)('resolve - symbolic link pointing to non-existing file does not break', async () => { + (isWindows /* symlinks are not reliable on windows */ ? test.skip : test)('resolve - symbolic link pointing to non-existing file does not break', async () => { await symlink(join(testDir, 'foo'), join(testDir, 'bar')); const resolved = await service.resolve(URI.file(testDir)); @@ -475,7 +475,7 @@ flakySuite('Disk File Service', function () { assert.equal((error).fileOperationResult, FileOperationResult.FILE_NOT_FOUND); } - (isWindows /* not reliable on windows */ ? test.skip : test)('deleteFile - symbolic link (exists)', async () => { + (isWindows /* symlinks are not reliable on windows */ ? test.skip : test)('deleteFile - symbolic link (exists)', async () => { const target = URI.file(join(testDir, 'lorem.txt')); const link = URI.file(join(testDir, 'lorem.txt-linked')); await symlink(target.fsPath, link.fsPath); @@ -497,7 +497,7 @@ flakySuite('Disk File Service', function () { assert.equal(existsSync(target.fsPath), true); // target the link pointed to is never deleted }); - (isWindows /* not reliable on windows */ ? test.skip : test)('deleteFile - symbolic link (pointing to non-existing file)', async () => { + (isWindows /* symlinks are not reliable on windows */ ? test.skip : test)('deleteFile - symbolic link (pointing to non-existing file)', async () => { const target = URI.file(join(testDir, 'foo')); const link = URI.file(join(testDir, 'bar')); await symlink(target.fsPath, link.fsPath); @@ -1541,23 +1541,23 @@ flakySuite('Disk File Service', function () { assert.equal(error!.fileOperationResult, FileOperationResult.FILE_EXCEEDS_MEMORY_LIMIT); } - (isWindows ? test.skip /* flaky test */ : test)('readFile - FILE_TOO_LARGE - default', async () => { + test('readFile - FILE_TOO_LARGE - default', async () => { return testFileTooLarge(); }); - (isWindows ? test.skip /* flaky test */ : test)('readFile - FILE_TOO_LARGE - buffered', async () => { + test('readFile - FILE_TOO_LARGE - buffered', async () => { setCapabilities(fileProvider, FileSystemProviderCapabilities.FileOpenReadWriteClose); return testFileTooLarge(); }); - (isWindows ? test.skip /* flaky test */ : test)('readFile - FILE_TOO_LARGE - unbuffered', async () => { + test('readFile - FILE_TOO_LARGE - unbuffered', async () => { setCapabilities(fileProvider, FileSystemProviderCapabilities.FileReadWrite); return testFileTooLarge(); }); - (isWindows ? test.skip /* flaky test */ : test)('readFile - FILE_TOO_LARGE - streamed', async () => { + test('readFile - FILE_TOO_LARGE - streamed', async () => { setCapabilities(fileProvider, FileSystemProviderCapabilities.FileReadStream); return testFileTooLarge(); 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 37930430364..f8cc4ac8dbf 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 @@ -351,7 +351,7 @@ suite('Encoding', () => { assert.equal(content.length, 65537); }); - (isWindows /* unsupported OS */ ? test.skip : test)('toDecodeStream - some stream (UTF-8 issue #102202)', async function () { + (isWindows /* TODO@bpasero why does this fail on windows */ ? test.skip : test)('toDecodeStream - some stream (UTF-8 issue #102202)', async function () { const path = getPathFromAmdModule(require, './fixtures/issue_102202.txt'); const source = streamToBufferReadableStream(fs.createReadStream(path)); From 0a3a9ce7bb9a90f284a0f13b28b26f6ae6942d6e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 9 Jan 2021 11:22:54 +0100 Subject: [PATCH 1755/1837] State of tabs is not fully updated when toggling workbench.editor.wrapTabs (fix #113808) --- .../browser/parts/editor/tabsTitleControl.ts | 151 ++++++++++-------- 1 file changed, 86 insertions(+), 65 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index a6a11fe6565..a5e0322396a 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1362,7 +1362,88 @@ export class TabsTitleControl extends TitleControl { } private doLayoutTabs(activeTab: HTMLElement, activeIndex: number, dimensions: ITitleControlDimensions): void { - const [tabsAndActionsContainer, tabsContainer, tabsScrollbar, editorToolbarContainer] = assertAllDefined(this.tabsAndActionsContainer, this.tabsContainer, this.tabsScrollbar, this.editorToolbarContainer); + + // Always first layout tabs with wrapping support even if wrapping + // is disabled. The result indicates if tabs wrap and if not, we + // need to proceed with the layout without wrapping because even + // if wrapping is enabled in settings, there are cases where + // wrapping is disabled (e.g. due to space constraints) + const tabsWrapMultiLine = this.doLayoutTabsWrapping(dimensions); + if (!tabsWrapMultiLine) { + this.doLayoutTabsNonWrapping(activeTab, activeIndex); + } + } + + private doLayoutTabsWrapping(dimensions: ITitleControlDimensions): boolean { + const [tabsAndActionsContainer, tabsContainer, editorToolbarContainer, tabsScrollbar] = assertAllDefined(this.tabsAndActionsContainer, this.tabsContainer, this.editorToolbarContainer, this.tabsScrollbar); + + // Handle wrapping tabs according to setting: + // - enabled: only add class if tabs wrap and don't exceed available dimensions + // - disabled: remove class and margin-right variable + + const didTabsWrapMultiLine = tabsAndActionsContainer.classList.contains('wrapping'); + let tabsWrapMultiLine = didTabsWrapMultiLine; + + function updateTabsWrapping(enabled: boolean): void { + tabsWrapMultiLine = enabled; + + // Toggle the `wrapped` class to enable wrapping + tabsAndActionsContainer.classList.toggle('wrapping', tabsWrapMultiLine); + + // Update `last-tab-margin-right` CSS variable to account for the absolute + // positioned editor actions container when tabs wrap. The margin needs to + // be the width of the editor actions container to avoid screen cheese. + tabsContainer.style.setProperty('--last-tab-margin-right', tabsWrapMultiLine ? `${editorToolbarContainer.offsetWidth}px` : '0'); + } + + // Setting enabled: selectively enable wrapping if possible + if (this.accessor.partOptions.wrapTabs) { + const visibleTabsWidth = tabsContainer.offsetWidth; + const allTabsWidth = tabsContainer.scrollWidth; + + // If tabs wrap or should start to wrap (when width exceeds visible width) + // we must trigger `updateWrapping` to set the `last-tab-margin-right` + // accordingly based on the number of actions. The margin is important to + // properly position the last tab apart from the actions + if (tabsWrapMultiLine || allTabsWidth > visibleTabsWidth) { + updateTabsWrapping(true); + } + + // Tabs wrap multiline: remove wrapping under certain size constraint conditions + if (tabsWrapMultiLine) { + const lastTab = this.getLastTab(); + if ( + (tabsContainer.offsetHeight > dimensions.available.height) || // if height exceeds available height + (allTabsWidth === visibleTabsWidth && tabsContainer.offsetHeight === TabsTitleControl.TAB_HEIGHT) || // if wrapping is not needed anymore + (lastTab && lastTab.offsetWidth > (dimensions.available.width - editorToolbarContainer.offsetWidth)) // if editor actions occupy too much space + ) { + updateTabsWrapping(false); + } + } + } + + // Setting disabled: remove CSS traces only if tabs did wrap + else if (didTabsWrapMultiLine) { + updateTabsWrapping(false); + } + + // If we transitioned from non-wrapping to wrapping, we need + // to update the scrollbar to have an equal `width` and + // `scrollWidth`. Otherwise a scrollbar would appear which is + // never desired when wrapping. + if (tabsWrapMultiLine && !didTabsWrapMultiLine) { + const visibleTabsWidth = tabsContainer.offsetWidth; + tabsScrollbar.setScrollDimensions({ + width: visibleTabsWidth, + scrollWidth: visibleTabsWidth + }); + } + + return tabsWrapMultiLine; + } + + private doLayoutTabsNonWrapping(activeTab: HTMLElement, activeIndex: number): void { + const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar); // // Synopsis @@ -1380,7 +1461,7 @@ export class TabsTitleControl extends TitleControl { // [-- Sticky Tabs Width --] // - const visibleTabsContainerWidth = tabsContainer.offsetWidth; + const visibleTabsWidth = tabsContainer.offsetWidth; const allTabsWidth = tabsContainer.scrollWidth; // Compute width of sticky tabs depending on pinned tab sizing @@ -1409,77 +1490,17 @@ export class TabsTitleControl extends TitleControl { // Special case: we have sticky tabs but the available space for showing tabs // is little enough that we need to disable sticky tabs sticky positioning // so that tabs can be scrolled at naturally. - let availableTabsContainerWidth = visibleTabsContainerWidth - stickyTabsWidth; + let availableTabsContainerWidth = visibleTabsWidth - stickyTabsWidth; if (this.group.stickyCount > 0 && availableTabsContainerWidth < TabsTitleControl.TAB_WIDTH.fit) { tabsContainer.classList.add('disable-sticky-tabs'); - availableTabsContainerWidth = visibleTabsContainerWidth; + availableTabsContainerWidth = visibleTabsWidth; stickyTabsWidth = 0; activeTabPositionStatic = false; } else { tabsContainer.classList.remove('disable-sticky-tabs'); } - // Handle wrapping tabs according to setting: - // - enabled: only add class if tabs wrap and don't exceed available dimensions - // - disabled: remove class - if (this.accessor.partOptions.wrapTabs) { - const oldTabsWrapMultiLine = tabsAndActionsContainer.classList.contains('wrapping'); - - // Tabs do not wrap multiline: add wrapping if tabs exceed the tabs container width - // and the height of the tabs container does not exceed the maximum - let tabsWrapMultiLine = oldTabsWrapMultiLine; - if (!tabsWrapMultiLine && allTabsWidth > visibleTabsContainerWidth) { - tabsAndActionsContainer.classList.add('wrapping'); - tabsWrapMultiLine = true; - } - - // Tabs wrap multiline: remove wrapping if height exceeds available height - if (tabsWrapMultiLine && tabsContainer.offsetHeight > dimensions.available.height) { - tabsAndActionsContainer.classList.remove('wrapping'); - tabsWrapMultiLine = false; - } - - // If we do not exceed the tabs container width, we cannot simply remove - // the wrap class because by wrapping tabs, they reduce their size - // and we would otherwise constantly add and remove the class. As such - // we need to check if the height of the tabs container is back to normal - // and then remove the wrap class. - if (tabsWrapMultiLine && allTabsWidth === visibleTabsContainerWidth && tabsContainer.offsetHeight === TabsTitleControl.TAB_HEIGHT) { - tabsAndActionsContainer.classList.remove('wrapping'); - tabsWrapMultiLine = false; - } - - // Update `last-tab-margin-right` CSS variable to account for the absolute - // positioned editor actions container when tabs wrap. The margin needs to - // be the width of the editor actions container to avoid screen cheese. - tabsContainer.style.setProperty('--last-tab-margin-right', tabsWrapMultiLine ? `${editorToolbarContainer.offsetWidth}px` : '0'); - - // We need to disable wrapping also in case the last tab requires more - // width than what is available accounting for the available width and - // the editor toolbar. - // Workaround for https://github.com/microsoft/vscode/issues/113926 - // An overall better fix is to make the editor toolbar a "fake" last tab - // so that it requires the space it needs, potentially wrapping to the - // next line (see https://github.com/microsoft/vscode/issues/113801) - const lastTab = this.getLastTab(); - if (tabsWrapMultiLine && lastTab && lastTab.offsetWidth > (dimensions.available.width - editorToolbarContainer.offsetWidth)) { - tabsAndActionsContainer.classList.remove('wrapping'); - tabsWrapMultiLine = false; - tabsContainer.style.setProperty('--last-tab-margin-right', '0'); - } - - // When tabs change from wrapping back to normal, we need to indicate this - // to the scrollbar so that revealing the active tab functions properly. - if (oldTabsWrapMultiLine && !tabsWrapMultiLine) { - tabsScrollbar.setScrollPosition({ - scrollLeft: tabsContainer.scrollLeft - }); - } - } else { - tabsAndActionsContainer.classList.remove('wrapping'); - } - let activeTabPosX: number | undefined; let activeTabWidth: number | undefined; @@ -1490,7 +1511,7 @@ export class TabsTitleControl extends TitleControl { // Update scrollbar tabsScrollbar.setScrollDimensions({ - width: visibleTabsContainerWidth, + width: visibleTabsWidth, scrollWidth: allTabsWidth }); From 6bd7b70515d546aba9010d2a0249a1a19205822f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 9 Jan 2021 11:23:34 +0100 Subject: [PATCH 1756/1837] Revert "Enable webview tests (#114059)" This reverts commit 01c6003c29519f7ba3223797c9bf6a7b6f914729. --- .../src/singlefolder-tests/webview.test.ts | 6 +++--- extensions/vscode-api-tests/src/utils.ts | 18 +----------------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index 3d0ef5c7085..fd97ea91728 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import 'mocha'; import * as os from 'os'; import * as vscode from 'vscode'; -import { closeAllEditors, delay, disposeAll, flakySuite } from '../utils'; +import { closeAllEditors, delay, disposeAll } from '../utils'; const webviewId = 'myWebview'; @@ -17,7 +17,7 @@ function workspaceFile(...segments: string[]) { const testDocument = workspaceFile('bower.json'); -flakySuite('vscode API - webview', () => { +suite.skip('vscode API - webview', () => { const disposables: vscode.Disposable[] = []; function _register(disposable: T) { @@ -212,7 +212,7 @@ flakySuite('vscode API - webview', () => { assert.strictEqual(Math.round(secondResponse.value), 100); }); - test('webviews with retainContextWhenHidden should be able to receive messages while hidden', async () => { + test('webviews with retainContextWhenHidden should be able to recive messages while hidden', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMesssage(webview); diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts index cd4471842b9..392d0be8461 100644 --- a/extensions/vscode-api-tests/src/utils.ts +++ b/extensions/vscode-api-tests/src/utils.ts @@ -3,25 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { Suite } from 'mocha'; import * as vscode from 'vscode'; import { TestFS } from './memfs'; - -export function flakySuite(title: string, fn: (this: Suite) => void): Suite { - return suite(title, function () { - - // Flaky suites need retries and timeout to complete - // e.g. because they access the file system which can - // be unreliable depending on the environment. - this.retries(3); - this.timeout(1000 * 20); - - // Invoke suite ensuring that `this` is - // properly wired in. - fn.call(this); - }); -} +import * as assert from 'assert'; export function rndName() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); From 3ceb3a100ed0ad5f3238b5022d9d64353a1cc31e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 9 Jan 2021 14:34:18 +0100 Subject: [PATCH 1757/1837] tabs - improve logic of previously used dimensions and relayout --- .../browser/parts/editor/tabsTitleControl.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index a5e0322396a..1c560417640 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1322,7 +1322,10 @@ export class TabsTitleControl extends TitleControl { }); } - return new Dimension(dimensions.container.width, this.getDimensions().height); + // Compute new dimension of tabs title control and remember it for future usages + this.dimensions.used = new Dimension(dimensions.container.width, this.getDimensions().height); + + return this.dimensions.used; } private doLayout(dimensions: ITitleControlDimensions): void { @@ -1339,18 +1342,13 @@ export class TabsTitleControl extends TitleControl { this.doLayoutTabs(activeTab, activeIndex, dimensions); } - // Compute new dimension of tabs title control and remember it for future usages - const oldDimension = this.dimensions.used; - const newDimension = this.dimensions.used = new Dimension(dimensions.container.width, this.getDimensions().height); - // In case the height of the title control changed from before - // (currently only possible if tabs are set to wrap), we need + // (currently only possible if wrapping changed on/off), we need // to signal this to the outside via a `relayout` call so that // e.g. the editor control can be adjusted accordingly. - if ( - this.accessor.partOptions.wrapTabs && - oldDimension && oldDimension.height !== newDimension.height - ) { + const oldDimension = this.dimensions.used; + const newDimension = new Dimension(dimensions.container.width, this.getDimensions().height); + if (oldDimension && oldDimension.height !== newDimension.height) { this.group.relayout(); } } From db701d281f7fe33b076dce3ec4beb1696ef3dd4b Mon Sep 17 00:00:00 2001 From: shskwmt Date: Sun, 10 Jan 2021 18:16:33 +0900 Subject: [PATCH 1758/1837] Fixed not to skip determination of option type starting with "_" --- src/vs/platform/environment/node/argv.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index c1362f8638f..7b6a60b5728 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -150,10 +150,6 @@ export function parseArgs(args: string[], options: OptionDescriptions, err const string: string[] = []; const boolean: string[] = []; for (let optionId in options) { - if (optionId[0] === '_') { - continue; - } - const o = options[optionId]; if (o.alias) { alias[optionId] = o.alias; From 313f4bfecdc5e2225b5f3b4fa5d395a3c00b6f9e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 07:45:28 +0100 Subject: [PATCH 1759/1837] fix #113620 --- .../services/editor/test/browser/editorsObserver.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index 044d6dd50de..4bc82ab5096 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -204,7 +204,7 @@ suite('EditorsObserver', function () { part.dispose(); }); - test.skip('copy group', async function () { // https://github.com/microsoft/vscode/issues/113620 + test('copy group', async function () { const [part, observer] = await createEditorObserver(); const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); @@ -230,7 +230,9 @@ suite('EditorsObserver', function () { assert.equal(observer.hasEditor(input3.resource), true); const copiedGroup = part.copyGroup(rootGroup, rootGroup, GroupDirection.RIGHT); + await copiedGroup.whenRestored; copiedGroup.setActive(true); + copiedGroup.focus(); currentEditorsMRU = observer.editors; assert.equal(currentEditorsMRU.length, 6); From e71f31abe9c49494efb7385932e9c7965ffac6f3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 07:46:18 +0100 Subject: [PATCH 1760/1837] editors - copied group is missing to register editor listeners --- src/vs/workbench/common/editor/editorGroup.ts | 7 +++++++ .../test/browser/parts/editor/editorGroups.test.ts | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/common/editor/editorGroup.ts b/src/vs/workbench/common/editor/editorGroup.ts index 8d7410ac55e..d1580899ad5 100644 --- a/src/vs/workbench/common/editor/editorGroup.ts +++ b/src/vs/workbench/common/editor/editorGroup.ts @@ -724,12 +724,19 @@ export class EditorGroup extends Disposable { clone(): EditorGroup { const group = this.instantiationService.createInstance(EditorGroup, undefined); + + // Copy over group properties group.editors = this.editors.slice(0); group.mru = this.mru.slice(0); group.preview = this.preview; group.active = this.active; group.sticky = this.sticky; + // Ensure to register listeners for each editor + for (const editor of group.editors) { + group.registerEditorListeners(editor); + } + return group; } diff --git a/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts b/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts index 20ca1df27f6..a75df3f3f87 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts @@ -239,7 +239,7 @@ suite('Workbench editor groups', () => { test('Clone Group', function () { const group = createGroup(); - const input1 = input(); + const input1 = input() as TestEditorInput; const input2 = input(); const input3 = input(); @@ -256,6 +256,11 @@ suite('Workbench editor groups', () => { assert.notEqual(group.id, clone.id); assert.equal(clone.count, 3); + let didEditorLabelChange = false; + const toDispose = clone.onDidEditorLabelChange(() => didEditorLabelChange = true); + input1.setLabel(); + assert.ok(didEditorLabelChange); + assert.equal(clone.isPinned(input1), true); assert.equal(clone.isActive(input1), false); assert.equal(clone.isSticky(input1), false); @@ -267,6 +272,8 @@ suite('Workbench editor groups', () => { assert.equal(clone.isPinned(input3), false); assert.equal(clone.isActive(input3), true); assert.equal(clone.isSticky(input3), false); + + toDispose.dispose(); }); test('contains()', function () { From e114a24d9f9316d97549422378c61ad054bb856e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 8 Jan 2021 23:58:53 +0100 Subject: [PATCH 1761/1837] Improve usage of Disposable --- src/vs/base/common/lifecycle.ts | 2 +- src/vs/editor/common/model/textModel.ts | 5 ++++- src/vs/editor/common/services/modeServiceImpl.ts | 11 ++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 79bbb910aac..efd086d3435 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -98,7 +98,7 @@ export function dispose(arg: T | IterableIterator | un export function combinedDisposable(...disposables: IDisposable[]): IDisposable { disposables.forEach(markTracked); - return trackDisposable({ dispose: () => dispose(disposables) }); + return toDisposable(() => dispose(disposables)); } export function toDisposable(fn: () => void): IDisposable { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 35dd466403a..338b8ad4dd8 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -37,6 +37,7 @@ import { EditorTheme } from 'vs/editor/common/view/viewContext'; import { IUndoRedoService, ResourceEditStackSnapshot } from 'vs/platform/undoRedo/common/undoRedo'; import { TextChange } from 'vs/editor/common/model/textChange'; import { Constants } from 'vs/base/common/uint'; +import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; function createTextBufferBuilder() { return new PieceTreeTextBufferBuilder(); @@ -389,7 +390,9 @@ export class TextModel extends Disposable implements model.ITextModel { this._isDisposing = false; // Manually release reference to previous text buffer to avoid large leaks // in case someone leaks a TextModel reference - this._buffer = createTextBuffer('', this._options.defaultEOL); + const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\n', false, false, true, true); + emptyDisposedTextBuffer.dispose(); + this._buffer = emptyDisposedTextBuffer; } private _assertNotDisposed(): void { diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index 6b2fd6f80f8..f5a6eba1dad 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -40,23 +40,24 @@ class LanguageSelection extends Disposable implements ILanguageSelection { } } -export class ModeServiceImpl implements IModeService { +export class ModeServiceImpl extends Disposable implements IModeService { public _serviceBrand: undefined; private readonly _instantiatedModes: { [modeId: string]: IMode; }; private readonly _registry: LanguagesRegistry; - private readonly _onDidCreateMode = new Emitter(); + private readonly _onDidCreateMode = this._register(new Emitter()); public readonly onDidCreateMode: Event = this._onDidCreateMode.event; - protected readonly _onLanguagesMaybeChanged = new Emitter(); + protected readonly _onLanguagesMaybeChanged = this._register(new Emitter()); public readonly onLanguagesMaybeChanged: Event = this._onLanguagesMaybeChanged.event; constructor(warnOnOverwrite = false) { + super(); this._instantiatedModes = {}; - this._registry = new LanguagesRegistry(true, warnOnOverwrite); - this._registry.onDidChange(() => this._onLanguagesMaybeChanged.fire()); + this._registry = this._register(new LanguagesRegistry(true, warnOnOverwrite)); + this._register(this._registry.onDidChange(() => this._onLanguagesMaybeChanged.fire())); } protected _onReady(): Promise { From 03cb2d2a23650e472abc39a9a90e0f384248e076 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Sat, 9 Jan 2021 00:35:06 +0100 Subject: [PATCH 1762/1837] Dispose `PieceTreeTextBuffer` instances --- src/vs/editor/common/model.ts | 8 +--- .../pieceTreeTextBufferBuilder.ts | 6 ++- src/vs/editor/common/model/textModel.ts | 20 +++++----- .../common/services/modelServiceImpl.ts | 4 +- .../common/model/benchmark/benchmarkUtils.ts | 2 +- .../linesTextBuffer/linesTextBuffer.test.ts | 2 +- .../linesTextBufferBuilder.test.ts | 2 +- .../textBufferAutoTestUtils.ts | 21 +--------- .../pieceTreeTextBuffer.test.ts | 2 +- .../test/common/model/textModel.test.ts | 2 +- .../test/common/services/modelService.test.ts | 12 +++--- .../electron-browser/backupRestorer.test.ts | 8 ++-- .../notebook/browser/notebook.contribution.ts | 2 +- .../view/output/transforms/textHelper.ts | 4 +- .../common/model/notebookCellTextModel.ts | 10 +++-- .../common/services/notebookSimpleWorker.ts | 2 +- .../common/walkThroughContentProvider.ts | 2 +- .../backupFileService.test.ts | 38 +++++++++---------- .../test/common/textFileService.io.test.ts | 12 +++--- .../test/browser/workbenchTestServices.ts | 2 +- 20 files changed, 73 insertions(+), 88 deletions(-) diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 8f4d53a8447..3f1a239dcbf 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -600,12 +600,6 @@ export interface ITextModel { */ setValue(newValue: string): void; - /** - * Replace the entire text buffer value contained in this model. - * @internal - */ - setValueFromTextBuffer(newValue: ITextBuffer): void; - /** * Get the text stored in this model. * @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`. @@ -1276,7 +1270,7 @@ export interface ITextBufferBuilder { * @internal */ export interface ITextBufferFactory { - create(defaultEOL: DefaultEndOfLine): ITextBuffer; + create(defaultEOL: DefaultEndOfLine): { textBuffer: ITextBuffer; disposable: IDisposable; }; getFirstLineText(lengthLimit: number): string; } diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts index d134517ba15..b65b87a0cbd 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { CharCode } from 'vs/base/common/charCode'; +import { IDisposable } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import { DefaultEndOfLine, ITextBuffer, ITextBufferBuilder, ITextBufferFactory } from 'vs/editor/common/model'; import { StringBuffer, createLineStarts, createLineStartsFast } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; @@ -38,7 +39,7 @@ export class PieceTreeTextBufferFactory implements ITextBufferFactory { return '\n'; } - public create(defaultEOL: DefaultEndOfLine): ITextBuffer { + public create(defaultEOL: DefaultEndOfLine): { textBuffer: ITextBuffer; disposable: IDisposable; } { const eol = this._getEOL(defaultEOL); let chunks = this._chunks; @@ -54,7 +55,8 @@ export class PieceTreeTextBufferFactory implements ITextBufferFactory { } } - return new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL); + const textBuffer = new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL); + return { textBuffer: textBuffer, disposable: textBuffer }; } public getFirstLineText(lengthLimit: number): string { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 338b8ad4dd8..aab72a48cd6 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -107,7 +107,7 @@ export function createTextBufferFactoryFromSnapshot(snapshot: model.ITextSnapsho return builder.finish(); } -export function createTextBuffer(value: string | model.ITextBufferFactory, defaultEOL: model.DefaultEndOfLine): model.ITextBuffer { +export function createTextBuffer(value: string | model.ITextBufferFactory, defaultEOL: model.DefaultEndOfLine): { textBuffer: model.ITextBuffer; disposable: IDisposable; } { const factory = (typeof value === 'string' ? createTextBufferFactory(value) : value); return factory.create(defaultEOL); } @@ -269,6 +269,7 @@ export class TextModel extends Disposable implements model.ITextModel { private readonly _undoRedoService: IUndoRedoService; private _attachedEditorCount: number; private _buffer: model.ITextBuffer; + private _bufferDisposable: IDisposable; private _options: model.TextModelResolvedOptions; private _isDisposed: boolean; @@ -329,7 +330,9 @@ export class TextModel extends Disposable implements model.ITextModel { this._undoRedoService = undoRedoService; this._attachedEditorCount = 0; - this._buffer = createTextBuffer(source, creationOptions.defaultEOL); + const { textBuffer, disposable } = createTextBuffer(source, creationOptions.defaultEOL); + this._buffer = textBuffer; + this._bufferDisposable = disposable; this._options = TextModel.resolveOptions(this._buffer, creationOptions); @@ -387,6 +390,7 @@ export class TextModel extends Disposable implements model.ITextModel { this._tokenization.dispose(); this._isDisposed = true; super.dispose(); + this._bufferDisposable.dispose(); this._isDisposing = false; // Manually release reference to previous text buffer to avoid large leaks // in case someone leaks a TextModel reference @@ -426,8 +430,8 @@ export class TextModel extends Disposable implements model.ITextModel { return; } - const textBuffer = createTextBuffer(value, this._options.defaultEOL); - this.setValueFromTextBuffer(textBuffer); + const { textBuffer, disposable } = createTextBuffer(value, this._options.defaultEOL); + this._setValueFromTextBuffer(textBuffer, disposable); } private _createContentChanged2(range: Range, rangeOffset: number, rangeLength: number, text: string, isUndoing: boolean, isRedoing: boolean, isFlush: boolean): IModelContentChangedEvent { @@ -446,18 +450,16 @@ export class TextModel extends Disposable implements model.ITextModel { }; } - public setValueFromTextBuffer(textBuffer: model.ITextBuffer): void { + private _setValueFromTextBuffer(textBuffer: model.ITextBuffer, textBufferDisposable: IDisposable): void { this._assertNotDisposed(); - if (textBuffer === null) { - // There's nothing to do - return; - } const oldFullModelRange = this.getFullModelRange(); const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange); const endLineNumber = this.getLineCount(); const endColumn = this.getLineMaxColumn(endLineNumber); this._buffer = textBuffer; + this._bufferDisposable.dispose(); + this._bufferDisposable = textBufferDisposable; this._increaseVersionId(); // Flush all tokens diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 668c697a39d..17d9d01596f 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -412,10 +412,11 @@ export class ModelServiceImpl extends Disposable implements IModelService { public updateModel(model: ITextModel, value: string | ITextBufferFactory): void { const options = this.getCreationOptions(model.getLanguageIdentifier().language, model.uri, model.isForSimpleWidget); - const textBuffer = createTextBuffer(value, options.defaultEOL); + const { textBuffer, disposable } = createTextBuffer(value, options.defaultEOL); // Return early if the text is already set in that form if (model.equalsTextBuffer(textBuffer)) { + disposable.dispose(); return; } @@ -428,6 +429,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { () => [] ); model.pushStackElement(); + disposable.dispose(); } private static _commonPrefix(a: ILineSequence, aLen: number, aDelta: number, b: ILineSequence, bLen: number, bDelta: number): number { diff --git a/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts index 79d4e1e46c8..357d3bb551e 100644 --- a/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts +++ b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts @@ -58,7 +58,7 @@ export class BenchmarkSuite { let timeDiffTotal = 0; for (let j = 0; j < this.iterations; j++) { let factory = benchmark.buildBuffer(builder); - let buffer = factory.create(DefaultEndOfLine.LF); + let buffer = factory.create(DefaultEndOfLine.LF).textBuffer; benchmark.preCycle(buffer); let start = process.hrtime(); benchmark.fn(buffer); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts index 4c9bd0d183c..7b1491b3e72 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts @@ -282,7 +282,7 @@ suite('PieceTreeTextBuffer._toSingleEditOperation', () => { } function testToSingleEditOperation(original: string[], edits: IValidatedEditOperation[], expected: IValidatedEditOperation): void { - const textBuffer = createTextBufferFactory(original.join('\n')).create(DefaultEndOfLine.LF); + const textBuffer = createTextBufferFactory(original.join('\n')).create(DefaultEndOfLine.LF).textBuffer; const actual = textBuffer._toSingleEditOperation(edits); assert.deepEqual(actual, expected); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts index dafa53c0771..4edebdf68d2 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts @@ -10,7 +10,7 @@ import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/ import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; export function testTextBufferFactory(text: string, eol: string, mightContainNonBasicASCII: boolean, mightContainRTL: boolean): void { - const textBuffer = createTextBufferFactory(text).create(DefaultEndOfLine.LF); + const textBuffer = createTextBufferFactory(text).create(DefaultEndOfLine.LF).textBuffer; assert.equal(textBuffer.mightContainNonBasicASCII(), mightContainNonBasicASCII); assert.equal(textBuffer.mightContainRTL(), mightContainRTL); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts b/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts index 4f87bf6388e..069b5553bf7 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts @@ -6,7 +6,7 @@ import { CharCode } from 'vs/base/common/charCode'; import { splitLines } from 'vs/base/common/strings'; import { Range } from 'vs/editor/common/core/range'; -import { DefaultEndOfLine, ITextBuffer, ITextBufferBuilder, ValidAnnotatedEditOperation } from 'vs/editor/common/model'; +import { ValidAnnotatedEditOperation } from 'vs/editor/common/model'; export function getRandomInt(min: number, max: number): number { return Math.floor(Math.random() * (max - min + 1)) + min; @@ -127,25 +127,6 @@ export function generateRandomReplaces(chunks: string[], editCnt: number, search return ops; } -export function createMockText(lineCount: number, minColumn: number, maxColumn: number) { - let fixedEOL = getRandomEOLSequence(); - let lines: string[] = []; - for (let i = 0; i < lineCount; i++) { - if (i !== 0) { - lines.push(fixedEOL); - } - lines.push(getRandomString(minColumn, maxColumn)); - } - return lines.join(''); -} - -export function createMockBuffer(str: string, bufferBuilder: ITextBufferBuilder): ITextBuffer { - bufferBuilder.acceptChunk(str); - let bufferFactory = bufferBuilder.finish(); - let buffer = bufferFactory.create(DefaultEndOfLine.LF); - return buffer; -} - export function generateRandomChunkWithLF(minLength: number, maxLength: number): string { let length = getRandomInt(minLength, maxLength); let r = ''; diff --git a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts index 019b23f4f3f..a8b46bbe6da 100644 --- a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts @@ -158,7 +158,7 @@ function createTextBuffer(val: string[], normalizeEOL: boolean = true): PieceTre bufferBuilder.acceptChunk(chunk); } let factory = bufferBuilder.finish(normalizeEOL); - return (factory.create(DefaultEndOfLine.LF)).getPieceTree(); + return (factory.create(DefaultEndOfLine.LF).textBuffer).getPieceTree(); } function assertTreeInvariants(T: PieceTreeBase): void { diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 2da334170d2..031a5f36efb 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -75,7 +75,7 @@ suite('TextModelData.fromString', () => { } function testTextModelDataFromString(text: string, expected: ITextBufferData): void { - const textBuffer = createTextBuffer(text, TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL); + const textBuffer = createTextBuffer(text, TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL).textBuffer; let actual: ITextBufferData = { EOL: textBuffer.getEOL(), lines: textBuffer.getLinesContent(), diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index 52672ffe3a1..e6e852f6bb0 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -71,7 +71,7 @@ suite('ModelService', () => { 'and finished with the fourth.', //29 ].join('\n'), DefaultEndOfLine.LF - ); + ).textBuffer; const actual = ModelServiceImpl._computeEdits(model, textBuffer); @@ -97,7 +97,7 @@ suite('ModelService', () => { 'and finished with the fourth.', //29 ].join('\n'), DefaultEndOfLine.LF - ); + ).textBuffer; const actual = ModelServiceImpl._computeEdits(model, textBuffer); @@ -125,7 +125,7 @@ suite('ModelService', () => { 'and finished with the fourth.', //29 ].join('\r\n'), DefaultEndOfLine.LF - ); + ).textBuffer; const actual = ModelServiceImpl._computeEdits(model, textBuffer); @@ -151,7 +151,7 @@ suite('ModelService', () => { 'and finished with the fourth.', //29 ].join('\r\n'), DefaultEndOfLine.LF - ); + ).textBuffer; const actual = ModelServiceImpl._computeEdits(model, textBuffer); @@ -186,7 +186,7 @@ suite('ModelService', () => { '' ].join('\r\n'), DefaultEndOfLine.LF - ); + ).textBuffer; const actual = ModelServiceImpl._computeEdits(model, textBuffer); @@ -380,7 +380,7 @@ suite('ModelService', () => { function assertComputeEdits(lines1: string[], lines2: string[]): void { const model = createTextModel(lines1.join('\n')); - const textBuffer = createTextBuffer(lines2.join('\n'), DefaultEndOfLine.LF); + const textBuffer = createTextBuffer(lines2.join('\n'), DefaultEndOfLine.LF).textBuffer; // compute required edits // let start = Date.now(); diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index 6d3e6584fe3..6a55c3dd51b 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -104,10 +104,10 @@ flakySuite('BackupRestorer', () => { const restorer = instantiationService.createInstance(TestBackupRestorer); // Backup 2 normal files and 2 untitled file - await backupFileService.backup(untitledFile1, createTextBufferFactory('untitled-1').create(DefaultEndOfLine.LF).createSnapshot(false)); - await backupFileService.backup(untitledFile2, createTextBufferFactory('untitled-2').create(DefaultEndOfLine.LF).createSnapshot(false)); - await backupFileService.backup(fooFile, createTextBufferFactory('fooFile').create(DefaultEndOfLine.LF).createSnapshot(false)); - await backupFileService.backup(barFile, createTextBufferFactory('barFile').create(DefaultEndOfLine.LF).createSnapshot(false)); + await backupFileService.backup(untitledFile1, createTextBufferFactory('untitled-1').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); + await backupFileService.backup(untitledFile2, createTextBufferFactory('untitled-2').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); + await backupFileService.backup(fooFile, createTextBufferFactory('fooFile').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); + await backupFileService.backup(barFile, createTextBufferFactory('barFile').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); // Verify backups restored and opened as dirty await restorer.doRestoreBackups(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 7a8f3bd2f49..4f4cf63ff1c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -480,7 +480,7 @@ class CellContentProvider implements ITextModelContentProvider { create: (defaultEOL) => { const newEOL = (defaultEOL === DefaultEndOfLine.CRLF ? '\r\n' : '\n'); (cell.textBuffer as ITextBuffer).setEOL(newEOL); - return cell.textBuffer as ITextBuffer; + return { textBuffer: cell.textBuffer as ITextBuffer, disposable: Disposable.None }; }, getFirstLineText: (limit: number) => { return cell.textBuffer.getLineContent(1).substr(0, limit); diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts index 08e8abf93ae..7bef1d4087a 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper.ts @@ -61,7 +61,7 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[] const bufferBuilder = new PieceTreeTextBufferBuilder(); outputs.forEach(output => bufferBuilder.acceptChunk(output)); const factory = bufferBuilder.finish(); - buffer = factory.create(DefaultEndOfLine.LF); + buffer = factory.create(DefaultEndOfLine.LF).textBuffer; const sizeBufferLimitPosition = buffer.getPositionAt(SIZE_LIMIT); if (sizeBufferLimitPosition.lineNumber < LINES_LIMIT) { const truncatedText = buffer.getValueInRange(new Range(1, 1, sizeBufferLimitPosition.lineNumber, sizeBufferLimitPosition.column), EndOfLinePreference.TextDefined); @@ -83,7 +83,7 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[] const bufferBuilder = new PieceTreeTextBufferBuilder(); outputs.forEach(output => bufferBuilder.acceptChunk(output)); const factory = bufferBuilder.finish(); - buffer = factory.create(DefaultEndOfLine.LF); + buffer = factory.create(DefaultEndOfLine.LF).textBuffer; } if (buffer.getLineCount() < LINES_LIMIT) { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index 709f0a4f72f..061b5023066 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -12,7 +12,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Disposable } from 'vs/base/common/lifecycle'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { hash } from 'vs/base/common/hash'; -import { createTextBuffer } from 'vs/editor/common/model/textModel'; +import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; export class NotebookCellTextModel extends Disposable implements ICell { private _onDidChangeOutputs = new Emitter(); @@ -65,7 +65,9 @@ export class NotebookCellTextModel extends Disposable implements ICell { const builder = new PieceTreeTextBufferBuilder(); builder.acceptChunk(this._source); const bufferFactory = builder.finish(true); - this._textBuffer = bufferFactory.create(model.DefaultEndOfLine.LF); + const { textBuffer, disposable } = bufferFactory.create(model.DefaultEndOfLine.LF); + this._textBuffer = textBuffer; + this._register(disposable); this._register(this._textBuffer.onDidChangeContent(() => { this._hash = null; @@ -174,7 +176,9 @@ export class NotebookCellTextModel extends Disposable implements ICell { dispose() { // Manually release reference to previous text buffer to avoid large leaks // in case someone leaks a CellTextModel reference - this._textBuffer = createTextBuffer('', model.DefaultEndOfLine.LF); + const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\n', false, false, true, true); + emptyDisposedTextBuffer.dispose(); + this._textBuffer = emptyDisposedTextBuffer; super.dispose(); } } diff --git a/src/vs/workbench/contrib/notebook/common/services/notebookSimpleWorker.ts b/src/vs/workbench/contrib/notebook/common/services/notebookSimpleWorker.ts index f0a0fd99461..66d7be20dc1 100644 --- a/src/vs/workbench/contrib/notebook/common/services/notebookSimpleWorker.ts +++ b/src/vs/workbench/contrib/notebook/common/services/notebookSimpleWorker.ts @@ -24,7 +24,7 @@ class MirrorCell { const builder = new PieceTreeTextBufferBuilder(); builder.acceptChunk(Array.isArray(this._source) ? this._source.join('\n') : this._source); const bufferFactory = builder.finish(true); - this._textBuffer = bufferFactory.create(model.DefaultEndOfLine.LF); + this._textBuffer = bufferFactory.create(model.DefaultEndOfLine.LF).textBuffer; return this._textBuffer; } diff --git a/src/vs/workbench/contrib/welcome/walkThrough/common/walkThroughContentProvider.ts b/src/vs/workbench/contrib/welcome/walkThrough/common/walkThroughContentProvider.ts index 57213b63b72..59c60ecc57c 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/common/walkThroughContentProvider.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/common/walkThroughContentProvider.ts @@ -77,7 +77,7 @@ export class WalkThroughSnippetContentProvider implements ITextModelContentProvi if (i === j) { codeEditorModel = model; } return ''; }; - const textBuffer = factory.create(DefaultEndOfLine.LF); + const textBuffer = factory.create(DefaultEndOfLine.LF).textBuffer; const lineCount = textBuffer.getLineCount(); const range = new Range(1, 1, lineCount, textBuffer.getLineLength(lineCount) + 1); const markdown = textBuffer.getValueInRange(range, EndOfLinePreference.TextDefined); diff --git a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts index 9c0ad4a8718..b1f1734bc89 100644 --- a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts @@ -197,7 +197,7 @@ suite('BackupFileService', () => { }); test('text file', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); @@ -205,7 +205,7 @@ suite('BackupFileService', () => { }); test('text file (with version)', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false), 666); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false), 666); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); @@ -214,7 +214,7 @@ suite('BackupFileService', () => { }); test('text file (with meta)', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false), undefined, { etag: '678', orphaned: true }); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false), undefined, { etag: '678', orphaned: true }); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath).toString(), `${fooFile.toString()} {"etag":"678","orphaned":true}\ntest`); @@ -222,7 +222,7 @@ suite('BackupFileService', () => { }); test('untitled file', async () => { - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); assert.equal(fs.existsSync(untitledBackupPath), true); assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\ntest`); @@ -291,7 +291,7 @@ suite('BackupFileService', () => { suite('discardBackup', () => { test('text file', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.ok(service.hasBackupSync(fooFile)); @@ -302,7 +302,7 @@ suite('BackupFileService', () => { }); test('untitled file', async () => { - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); await service.discardBackup(untitledFile); assert.equal(fs.existsSync(untitledBackupPath), false); @@ -312,9 +312,9 @@ suite('BackupFileService', () => { suite('discardBackups', () => { test('text file', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); - await service.backup(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 2); await service.discardBackups(); assert.equal(fs.existsSync(fooBackupPath), false); @@ -323,7 +323,7 @@ suite('BackupFileService', () => { }); test('untitled file', async () => { - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); await service.discardBackups(); assert.equal(fs.existsSync(untitledBackupPath), false); @@ -332,29 +332,29 @@ suite('BackupFileService', () => { test('can backup after discarding all', async () => { await service.discardBackups(); - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(fs.existsSync(workspaceBackupPath), true); }); }); suite('getBackups', () => { test('("file") - text file', async () => { - await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); const textFiles = await service.getBackups(); assert.deepEqual(textFiles.map(f => f.fsPath), [fooFile.fsPath]); - await service.backup(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); const textFiles_1 = await service.getBackups(); assert.deepEqual(textFiles_1.map(f => f.fsPath), [fooFile.fsPath, barFile.fsPath]); }); test('("file") - untitled file', async () => { - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); const textFiles = await service.getBackups(); assert.deepEqual(textFiles.map(f => f.fsPath), [untitledFile.fsPath]); }); test('("untitled") - untitled file', async () => { - await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); + await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); const textFiles = await service.getBackups(); assert.deepEqual(textFiles.map(f => f.fsPath), ['Untitled-1']); }); @@ -465,7 +465,7 @@ suite('BackupFileService', () => { orphaned: false }; - await service.backup(fooFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).createSnapshot(false), 1, meta); + await service.backup(fooFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false), 1, meta); const fileContents = fs.readFileSync(fooBackupPath).toString(); assert.equal(fileContents.indexOf(fooFile.toString()), 0); @@ -476,7 +476,7 @@ suite('BackupFileService', () => { const backup = await service.resolve(fooFile); assert.ok(backup); - assert.equal(contents, snapshotToString(backup!.value.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(true))); + assert.equal(contents, snapshotToString(backup!.value.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(true))); assert.ok(!backup!.meta); }); @@ -537,7 +537,7 @@ suite('BackupFileService', () => { test('should ignore invalid backups', async () => { const contents = 'test\nand more stuff'; - await service.backup(fooBarFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).createSnapshot(false), 1); + await service.backup(fooBarFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false), 1); const backup = await service.resolve(fooBarFile); if (!backup) { @@ -561,11 +561,11 @@ suite('BackupFileService', () => { expectedMeta = meta; } - await service.backup(resource, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).createSnapshot(false), 1, meta); + await service.backup(resource, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false), 1, meta); const backup = await service.resolve(resource); assert.ok(backup); - assert.equal(contents, snapshotToString(backup!.value.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(true))); + assert.equal(contents, snapshotToString(backup!.value.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(true))); if (expectedMeta) { assert.equal(backup!.meta!.etag, expectedMeta.etag); diff --git a/src/vs/workbench/services/textfile/test/common/textFileService.io.test.ts b/src/vs/workbench/services/textfile/test/common/textFileService.io.test.ts index 71f8242e67b..0bee2208bc4 100644 --- a/src/vs/workbench/services/textfile/test/common/textFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/common/textFileService.io.test.ts @@ -216,7 +216,7 @@ export default function createSuite(params: Params) { const resolved = await service.readStream(resource); assert.equal(resolved.encoding, encoding); - assert.equal(snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(false)), expectedContent); + assert.equal(snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(false)), expectedContent); } test('write - use encoding (cp1252)', async () => { @@ -244,18 +244,18 @@ export default function createSuite(params: Params) { async function testEncodingKeepsData(resource: URI, encoding: string, expected: string) { let resolved = await service.readStream(resource, { encoding }); - const content = snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(false)); + const content = snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(content, expected); await service.write(resource, content, { encoding }); resolved = await service.readStream(resource, { encoding }); - assert.equal(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).createSnapshot(false)), content); + assert.equal(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer.createSnapshot(false)), content); await service.write(resource, createTextModel(content).createSnapshot(), { encoding }); resolved = await service.readStream(resource, { encoding }); - assert.equal(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).createSnapshot(false)), content); + assert.equal(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer.createSnapshot(false)), content); } test('write - no encoding - content as string', async () => { @@ -403,7 +403,7 @@ export default function createSuite(params: Params) { const content = (await readFile(resource.fsPath)).toString(); assert.equal( - snapshotToString(result.value.create(DefaultEndOfLine.LF).createSnapshot(false)), + snapshotToString(result.value.create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)), snapshotToString(createTextModel(content).createSnapshot(false))); } @@ -530,7 +530,7 @@ export default function createSuite(params: Params) { const result = await service.readStream(resource, { encoding }); assert.equal(result.encoding, encoding); - const contents = snapshotToString(result.value.create(DefaultEndOfLine.LF).createSnapshot(false)); + const contents = snapshotToString(result.value.create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)); assert.equal(contents.indexOf(needle), 0); assert.ok(contents.indexOf(needle, 10) > 0); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index f7aefffa1d6..6740f453275 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -902,7 +902,7 @@ export class TestBackupFileService implements IBackupFileService { async discardBackup(_resource: URI): Promise { } async discardBackups(): Promise { } parseBackupContent(textBufferFactory: ITextBufferFactory): string { - const textBuffer = textBufferFactory.create(DefaultEndOfLine.LF); + const textBuffer = textBufferFactory.create(DefaultEndOfLine.LF).textBuffer; const lineCount = textBuffer.getLineCount(); const range = new Range(1, 1, lineCount, textBuffer.getLineLength(lineCount) + 1); return textBuffer.getValueInRange(range, EndOfLinePreference.TextDefined); From 11ac71b27220a2354b6bb28966ed3ead183cc495 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 07:49:23 +0100 Subject: [PATCH 1763/1837] editors - cache previously used layout and return it --- .../parts/activitybar/activitybarActions.ts | 4 +-- .../browser/parts/editor/editorGroupView.ts | 6 ++-- .../parts/editor/noTabsTitleControl.ts | 6 ++-- .../browser/parts/editor/tabsTitleControl.ts | 34 +++++++++++-------- .../browser/parts/editor/titleControl.ts | 22 ++++++------ .../notifications/notificationsCenter.ts | 4 +-- .../parts/notifications/notificationsList.ts | 4 +-- .../browser/parts/panel/panelPart.ts | 6 ++-- .../browser/parts/statusbar/statusbarPart.ts | 4 +-- .../browser/parts/titlebar/menubarControl.ts | 4 +-- .../browser/parts/titlebar/titlebarPart.ts | 4 +-- src/vs/workbench/browser/style.ts | 4 +-- 12 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 45cbcab729b..d28964ecb2f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -15,7 +15,7 @@ import { IMenuService, MenuId, IMenu, registerAction2, Action2, IAction2Options import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; -import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { IActivity } from 'vs/workbench/common/activity'; @@ -400,7 +400,7 @@ registerAction2( } ); -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { const activityBarBackgroundColor = theme.getColor(ACTIVITY_BAR_BACKGROUND); if (activityBarBackgroundColor) { collector.addRule(` diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index ed48c489007..277f029c3b8 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -322,8 +322,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView { private createContainerContextMenu(): void { const menu = this._register(this.menuService.createMenu(MenuId.EmptyEditorGroupContext, this.contextKeyService)); - this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, event => this.onShowContainerContextMenu(menu, event))); - this._register(addDisposableListener(this.element, TouchEventType.Contextmenu, event => this.onShowContainerContextMenu(menu))); + this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => this.onShowContainerContextMenu(menu, e))); + this._register(addDisposableListener(this.element, TouchEventType.Contextmenu, () => this.onShowContainerContextMenu(menu))); } private onShowContainerContextMenu(menu: IMenu, e?: MouseEvent): void { @@ -1771,7 +1771,7 @@ export interface EditorReplacement { readonly options?: EditorOptions; } -registerThemingParticipant((theme, collector, environment) => { +registerThemingParticipant((theme, collector) => { // Letterpress const letterpress = `./media/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`; diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index f04002270b1..c779550c14f 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -68,16 +68,16 @@ export class NoTabsTitleControl extends TitleControl { this.enableGroupDragging(titleContainer); // Pin on double click - this._register(addDisposableListener(titleContainer, EventType.DBLCLICK, (e: MouseEvent) => this.onTitleDoubleClick(e))); + this._register(addDisposableListener(titleContainer, EventType.DBLCLICK, e => this.onTitleDoubleClick(e))); // Detect mouse click - this._register(addDisposableListener(titleContainer, EventType.AUXCLICK, (e: MouseEvent) => this.onTitleAuxClick(e))); + this._register(addDisposableListener(titleContainer, EventType.AUXCLICK, e => this.onTitleAuxClick(e))); // Detect touch this._register(addDisposableListener(titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleTap(e))); // Context Menu - this._register(addDisposableListener(titleContainer, EventType.CONTEXT_MENU, (e: Event) => { + this._register(addDisposableListener(titleContainer, EventType.CONTEXT_MENU, e => { if (this.group.activeEditor) { this.onContextMenu(this.group.activeEditor, e, titleContainer); } diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 1c560417640..e08daada1d6 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -24,7 +24,7 @@ import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDispo import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { getOrSet } from 'vs/base/common/map'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER, TAB_LAST_PINNED_BORDER } from 'vs/workbench/common/theme'; import { activeContrastBorder, contrastBorder, editorBackground, breadcrumbsBackground } from 'vs/platform/theme/common/colorRegistry'; import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd'; @@ -255,7 +255,7 @@ export class TabsTitleControl extends TitleControl { }); // Prevent auto-scrolling (https://github.com/microsoft/vscode/issues/16690) - this._register(addDisposableListener(tabsContainer, EventType.MOUSE_DOWN, (e: MouseEvent) => { + this._register(addDisposableListener(tabsContainer, EventType.MOUSE_DOWN, e => { if (e.button === 1) { e.preventDefault(); } @@ -689,7 +689,7 @@ export class TabsTitleControl extends TitleControl { }; // Open on Click / Touch - disposables.add(addDisposableListener(tab, EventType.MOUSE_DOWN, (e: MouseEvent) => handleClickOrTouch(e))); + disposables.add(addDisposableListener(tab, EventType.MOUSE_DOWN, e => handleClickOrTouch(e))); disposables.add(addDisposableListener(tab, TouchEventType.Tap, (e: GestureEvent) => handleClickOrTouch(e))); // Touch Scroll Support @@ -698,14 +698,14 @@ export class TabsTitleControl extends TitleControl { })); // Prevent flicker of focus outline on tab until editor got focus - disposables.add(addDisposableListener(tab, EventType.MOUSE_UP, (e: MouseEvent) => { + disposables.add(addDisposableListener(tab, EventType.MOUSE_UP, e => { EventHelper.stop(e); tab.blur(); })); // Close on mouse middle click - disposables.add(addDisposableListener(tab, EventType.AUXCLICK, (e: MouseEvent) => { + disposables.add(addDisposableListener(tab, EventType.AUXCLICK, e => { if (e.button === 1 /* Middle Button*/) { EventHelper.stop(e, true /* for https://github.com/microsoft/vscode/issues/56715 */); @@ -715,7 +715,7 @@ export class TabsTitleControl extends TitleControl { })); // Context menu on Shift+F10 - disposables.add(addDisposableListener(tab, EventType.KEY_DOWN, (e: KeyboardEvent) => { + disposables.add(addDisposableListener(tab, EventType.KEY_DOWN, e => { const event = new StandardKeyboardEvent(e); if (event.shiftKey && event.keyCode === KeyCode.F10) { showContextMenu(e); @@ -728,7 +728,7 @@ export class TabsTitleControl extends TitleControl { })); // Keyboard accessibility - disposables.add(addDisposableListener(tab, EventType.KEY_UP, (e: KeyboardEvent) => { + disposables.add(addDisposableListener(tab, EventType.KEY_UP, e => { const event = new StandardKeyboardEvent(e); let handled = false; @@ -791,7 +791,7 @@ export class TabsTitleControl extends TitleControl { }); // Context menu - disposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: Event) => { + disposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, e => { EventHelper.stop(e, true); const input = this.group.getEditorByIndex(index); @@ -801,7 +801,7 @@ export class TabsTitleControl extends TitleControl { }, true /* use capture to fix https://github.com/microsoft/vscode/issues/19145 */)); // Drag support - disposables.add(addDisposableListener(tab, EventType.DRAG_START, (e: DragEvent) => { + disposables.add(addDisposableListener(tab, EventType.DRAG_START, e => { const editor = this.group.getEditorByIndex(index); if (!editor) { return; @@ -1322,8 +1322,10 @@ export class TabsTitleControl extends TitleControl { }); } - // Compute new dimension of tabs title control and remember it for future usages - this.dimensions.used = new Dimension(dimensions.container.width, this.getDimensions().height); + // First time layout: compute the dimensions and store it + if (!this.dimensions.used) { + this.dimensions.used = new Dimension(dimensions.container.width, this.getDimensions().height); + } return this.dimensions.used; } @@ -1342,12 +1344,16 @@ export class TabsTitleControl extends TitleControl { this.doLayoutTabs(activeTab, activeIndex, dimensions); } + // Remember the dimensions used in the control so that we can + // return it fast from the `layout` call without having to + // compute it over and over again + const oldDimension = this.dimensions.used; + const newDimension = this.dimensions.used = new Dimension(dimensions.container.width, this.getDimensions().height); + // In case the height of the title control changed from before // (currently only possible if wrapping changed on/off), we need // to signal this to the outside via a `relayout` call so that // e.g. the editor control can be adjusted accordingly. - const oldDimension = this.dimensions.used; - const newDimension = new Dimension(dimensions.container.width, this.getDimensions().height); if (oldDimension && oldDimension.height !== newDimension.height) { this.group.relayout(); } @@ -1691,7 +1697,7 @@ export class TabsTitleControl extends TitleControl { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { // Add border between tabs and breadcrumbs in high contrast mode. if (theme.type === ColorScheme.HIGH_CONTRAST) { diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index d38fb6d9951..d7f535513a6 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -9,8 +9,8 @@ import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; -import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, IActionViewItem } from 'vs/base/common/actions'; -import * as arrays from 'vs/base/common/arrays'; +import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, IActionViewItem } from 'vs/base/common/actions'; +import { equals } from 'vs/base/common/arrays'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -26,7 +26,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { listActiveSelectionBackground, listActiveSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; -import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService'; import { DraggedEditorGroupIdentifier, DraggedEditorIdentifier, fillResourceDataTransfers, LocalSelectionTransfer } from 'vs/workbench/browser/dnd'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; @@ -161,7 +161,7 @@ export abstract class TitleControl extends Themable { this.editorActionsToolbar.context = context; // Action Run Handling - this._register(this.editorActionsToolbar.actionRunner.onDidRun((e: IRunEvent) => { + this._register(this.editorActionsToolbar.actionRunner.onDidRun(e => { // Notify for Error this.notificationService.error(e.error); @@ -201,11 +201,11 @@ export abstract class TitleControl extends Themable { const { primaryEditorActions, secondaryEditorActions } = this.prepareEditorActions(this.getEditorActions()); // Only update if something actually has changed - const primaryEditorActionIds = primaryEditorActions.map(a => a.id); - const secondaryEditorActionIds = secondaryEditorActions.map(a => a.id); + const primaryEditorActionIds = primaryEditorActions.map(action => action.id); + const secondaryEditorActionIds = secondaryEditorActions.map(action => action.id); if ( - !arrays.equals(primaryEditorActionIds, this.currentPrimaryEditorActionIds) || - !arrays.equals(secondaryEditorActionIds, this.currentSecondaryEditorActionIds) || + !equals(primaryEditorActionIds, this.currentPrimaryEditorActionIds) || + !equals(secondaryEditorActionIds, this.currentSecondaryEditorActionIds) || primaryEditorActions.some(action => action instanceof ExecuteCommandAction) || // execute command actions can have the same ID but different arguments secondaryEditorActions.some(action => action instanceof ExecuteCommandAction) // see also https://github.com/microsoft/vscode/issues/16298 ) { @@ -276,7 +276,7 @@ export abstract class TitleControl extends Themable { protected enableGroupDragging(element: HTMLElement): void { // Drag start - this._register(addDisposableListener(element, EventType.DRAG_START, (e: DragEvent) => { + this._register(addDisposableListener(element, EventType.DRAG_START, e => { if (e.target !== element) { return; // only if originating from tabs container } @@ -368,7 +368,7 @@ export abstract class TitleControl extends Themable { getAnchor: () => anchor, getActions: () => actions, getActionsContext: () => ({ groupId: this.group.id, editorIndex: this.group.getIndexOfEditor(editor) }), - getKeyBinding: (action) => this.getKeybinding(action), + getKeyBinding: action => this.getKeybinding(action), onHide: () => { // restore previous contexts @@ -433,7 +433,7 @@ export abstract class TitleControl extends Themable { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { // Drag Feedback const dragImageBackground = theme.getColor(listActiveSelectionBackground); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index d4074bbebc7..8113a026bc2 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/notificationsCenter'; import 'vs/css!./media/notificationsActions'; import { NOTIFICATIONS_BORDER, NOTIFICATIONS_CENTER_HEADER_FOREGROUND, NOTIFICATIONS_CENTER_HEADER_BACKGROUND, NOTIFICATIONS_CENTER_BORDER } from 'vs/workbench/common/theme'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, Themable } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService'; import { INotificationsModel, INotificationChangeEvent, NotificationChangeType, NotificationViewItemContentChangeKind } from 'vs/workbench/common/notifications'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { Emitter } from 'vs/base/common/event'; @@ -313,7 +313,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { const notificationBorderColor = theme.getColor(NOTIFICATIONS_BORDER); if (notificationBorderColor) { collector.addRule(`.monaco-workbench > .notifications-center .notifications-list-container .monaco-list-row[data-last-element="false"] > .notification-list-item { border-bottom: 1px solid ${notificationBorderColor}; }`); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index 7cbfb84f22e..b1e8112ea08 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -10,7 +10,7 @@ import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IListOptions } from 'vs/base/browser/ui/list/listWidget'; import { NOTIFICATIONS_LINKS, NOTIFICATIONS_BACKGROUND, NOTIFICATIONS_FOREGROUND, NOTIFICATIONS_ERROR_ICON_FOREGROUND, NOTIFICATIONS_WARNING_ICON_FOREGROUND, NOTIFICATIONS_INFO_ICON_FOREGROUND } from 'vs/workbench/common/theme'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, Themable } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService'; import { contrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { INotificationViewItem } from 'vs/workbench/common/notifications'; import { NotificationsListDelegate, NotificationRenderer } from 'vs/workbench/browser/parts/notifications/notificationsViewer'; @@ -278,7 +278,7 @@ export class NotificationsList extends Themable { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { const linkColor = theme.getColor(NOTIFICATIONS_LINKS); if (linkColor) { collector.addRule(`.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-message a { color: ${linkColor}; }`); diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index c24cf278f8c..abe4c095397 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -19,7 +19,7 @@ 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 } from 'vs/workbench/browser/parts/panel/panelActions'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant } 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'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; @@ -166,7 +166,7 @@ export class PanelPart extends CompositePart implements IPanelService { dndHandler: this.dndHandler, compositeSize: 0, overflowActionSize: 44, - colors: (theme: IColorTheme) => ({ + colors: theme => ({ activeBackgroundColor: theme.getColor(PANEL_BACKGROUND), // Background color for overflow action inactiveBackgroundColor: theme.getColor(PANEL_BACKGROUND), // Background color for overflow action activeBorderBottomColor: theme.getColor(PANEL_ACTIVE_TITLE_BORDER), @@ -791,7 +791,7 @@ export class PanelPart extends CompositePart implements IPanelService { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { // Panel Background: since panels can host editors, we apply a background rule if the panel background // color is different from the editor background color. This is a bit of a hack though. The better way diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 10ac9fa8ece..0da9015445f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, ThemeColor } from 'vs/platform/theme/common/themeService'; import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -943,7 +943,7 @@ class StatusbarEntryItem extends Disposable { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { if (theme.type !== ColorScheme.HIGH_CONTRAST) { const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND); if (statusBarItemHoverBackground) { diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index f58b20387cb..98fc256def0 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { IMenuService, MenuId, IMenu, SubmenuItemAction, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; -import { registerThemingParticipant, IColorTheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; import { MenuBarVisibility, getTitleBarStyle, IWindowOpenable, getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IAction, Action, SubmenuAction, Separator } from 'vs/base/common/actions'; @@ -326,7 +326,7 @@ export class CustomMenubarControl extends MenubarControl { this.registerActions(); - registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { + registerThemingParticipant((theme, collector) => { const menubarActiveWindowFgColor = theme.getColor(TITLE_BAR_ACTIVE_FOREGROUND); if (menubarActiveWindowFgColor) { collector.addRule(` diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 4d6bf298754..6138e52930a 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -19,7 +19,7 @@ import * as nls from 'vs/nls'; import { EditorResourceAccessor, Verbosity, SideBySideEditor } from 'vs/workbench/common/editor'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND, TITLE_BAR_BORDER, WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; @@ -497,7 +497,7 @@ export class TitlebarPart extends Part implements ITitleService { } } -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { const titlebarActiveFg = theme.getColor(TITLE_BAR_ACTIVE_FOREGROUND); if (titlebarActiveFg) { collector.addRule(` diff --git a/src/vs/workbench/browser/style.ts b/src/vs/workbench/browser/style.ts index 0517f059bd8..4f1ecbcd076 100644 --- a/src/vs/workbench/browser/style.ts +++ b/src/vs/workbench/browser/style.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/style'; -import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry'; import { WORKBENCH_BACKGROUND, TITLE_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme'; import { isWeb, isIOS, isMacintosh, isWindows } from 'vs/base/common/platform'; @@ -13,7 +13,7 @@ import { createMetaElement } from 'vs/base/browser/dom'; import { isSafari, isStandalone } from 'vs/base/browser/browser'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { +registerThemingParticipant((theme, collector) => { // Foreground const windowForeground = theme.getColor(foreground); From 7c3aacb40aa31e72c60ac5c5cc27589bb1d15fdc Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 08:27:07 +0100 Subject: [PATCH 1764/1837] Add a mechanism to track disposables from unit tests --- src/vs/base/common/lifecycle.ts | 65 ++++++++++++++++++---------- src/vs/base/test/common/lifecycle.ts | 36 +++++++++++++++ 2 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 src/vs/base/test/common/lifecycle.ts diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index efd086d3435..fd4a71fc8d5 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -14,34 +14,53 @@ import { Iterable } from 'vs/base/common/iterator'; * extend Disposable or use a DisposableStore. This means there are a lot of false positives. */ const TRACK_DISPOSABLES = false; +let disposableTracker: IDisposableTracker | null = null; -const __is_disposable_tracked__ = '__is_disposable_tracked__'; - -function markTracked(x: T): void { - if (!TRACK_DISPOSABLES) { - return; - } - - if (x && x !== Disposable.None) { - try { - (x as any)[__is_disposable_tracked__] = true; - } catch { - // noop - } - } +export interface IDisposableTracker { + trackDisposable(x: IDisposable): void; + markTracked(x: IDisposable): void; } -function trackDisposable(x: T): T { - if (!TRACK_DISPOSABLES) { +export function setDisposableTracker(tracker: IDisposableTracker | null): void { + disposableTracker = tracker; +} + +if (TRACK_DISPOSABLES) { + const __is_disposable_tracked__ = '__is_disposable_tracked__'; + disposableTracker = new class implements IDisposableTracker { + trackDisposable(x: IDisposable): void { + const stack = new Error('Potentially leaked disposable').stack!; + setTimeout(() => { + if (!(x as any)[__is_disposable_tracked__]) { + console.log(stack); + } + }, 3000); + } + + markTracked(x: IDisposable): void { + if (x && x !== Disposable.None) { + try { + (x as any)[__is_disposable_tracked__] = true; + } catch { + // noop + } + } + } + }; +} + +function markTracked(x: T): void { + if (!disposableTracker) { + return; + } + disposableTracker.markTracked(x); +} + +export function trackDisposable(x: T): T { + if (!disposableTracker) { return x; } - - const stack = new Error('Potentially leaked disposable').stack!; - setTimeout(() => { - if (!(x as any)[__is_disposable_tracked__]) { - console.log(stack); - } - }, 3000); + disposableTracker.trackDisposable(x); return x; } diff --git a/src/vs/base/test/common/lifecycle.ts b/src/vs/base/test/common/lifecycle.ts new file mode 100644 index 00000000000..a6bda7f67a3 --- /dev/null +++ b/src/vs/base/test/common/lifecycle.ts @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, IDisposableTracker, setDisposableTracker } from 'vs/base/common/lifecycle'; + +class DisposableTracker implements IDisposableTracker { + allDisposables: [IDisposable, string][] = []; + trackDisposable(x: IDisposable): void { + this.allDisposables.push([x, new Error().stack!]); + } + markTracked(x: IDisposable): void { + for (let idx = 0; idx < this.allDisposables.length; idx++) { + if (this.allDisposables[idx][0] === x) { + this.allDisposables.splice(idx, 1); + return; + } + } + } +} + +let currentTracker: DisposableTracker | null = null; + +export function beginTrackingDisposables(): void { + currentTracker = new DisposableTracker(); + setDisposableTracker(currentTracker); +} + +export function logTrackedDisposables(): void { + if (currentTracker) { + setDisposableTracker(null); + console.log(currentTracker!.allDisposables.map(e => `${e[0]}\n${e[1]}`).join('\n\n')); + currentTracker = null; + } +} From 57c405c24c3c4ff04eadbac61f4da6871811f2dd Mon Sep 17 00:00:00 2001 From: shskwmt Date: Mon, 11 Jan 2021 16:48:02 +0900 Subject: [PATCH 1765/1837] Change reason for moveWordCommand to CursorChangeReason.Explicit --- src/vs/editor/contrib/multicursor/multicursor.ts | 1 - src/vs/editor/contrib/wordOperations/wordOperations.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index 3606348fb67..792770dd2a0 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -850,7 +850,6 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut this.updateSoon.schedule(); } else { this._setState(null); - } } else { this._update(); diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index 82dcbddc580..ac3f987de36 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -55,7 +55,7 @@ export abstract class MoveWordCommand extends EditorCommand { }); model.pushStackElement(); - editor._getViewModel().setCursorStates('moveWordCommand', CursorChangeReason.NotSet, result.map(r => CursorState.fromModelSelection(r))); + editor._getViewModel().setCursorStates('moveWordCommand', CursorChangeReason.Explicit, result.map(r => CursorState.fromModelSelection(r))); if (result.length === 1) { const pos = new Position(result[0].positionLineNumber, result[0].positionColumn); editor.revealPosition(pos, ScrollType.Smooth); From 2fd00ba9feff480d3ff6dde51201dc1e53fbe7e1 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 09:11:33 +0100 Subject: [PATCH 1766/1837] Add a way to troubleshoot fs calls --- .../{lifecycle.ts => troubleshooting.ts} | 14 ++++- test/unit/electron/renderer.js | 54 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) rename src/vs/base/test/common/{lifecycle.ts => troubleshooting.ts} (79%) diff --git a/src/vs/base/test/common/lifecycle.ts b/src/vs/base/test/common/troubleshooting.ts similarity index 79% rename from src/vs/base/test/common/lifecycle.ts rename to src/vs/base/test/common/troubleshooting.ts index a6bda7f67a3..1d9d99632bd 100644 --- a/src/vs/base/test/common/lifecycle.ts +++ b/src/vs/base/test/common/troubleshooting.ts @@ -27,10 +27,22 @@ export function beginTrackingDisposables(): void { setDisposableTracker(currentTracker); } -export function logTrackedDisposables(): void { +export function endTrackingDisposables(): void { if (currentTracker) { setDisposableTracker(null); console.log(currentTracker!.allDisposables.map(e => `${e[0]}\n${e[1]}`).join('\n\n')); currentTracker = null; } } + +export function beginLoggingFS(withStacks: boolean = false): void { + if ((self).beginLoggingFS) { + (self).beginLoggingFS(withStacks); + } +} + +export function endLoggingFS(): void { + if ((self).endLoggingFS) { + (self).endLoggingFS(); + } +} diff --git a/test/unit/electron/renderer.js b/test/unit/electron/renderer.js index 002ac43da55..dff47ec61c6 100644 --- a/test/unit/electron/renderer.js +++ b/test/unit/electron/renderer.js @@ -5,6 +5,60 @@ /*eslint-env mocha*/ +(function() { + const fs = require('fs'); + const originals = {}; + let logging = false; + let withStacks = false; + + self.beginLoggingFS = (withStacks) => { + logging = true; + withStacks = withStacks || false; + }; + self.endLoggingFS = () => { + logging = false; + withStacks = false; + }; + + function createSpy(element, cnt) { + return function(...args) { + if (logging) { + console.log(`calling ${element}: ` + args.slice(0, cnt).join(',') + (withStacks ? (`\n` + new Error().stack.split('\n').slice(2).join('\n')) : '')); + } + return originals[element].call(this, ...args); + }; + } + + function intercept(element, cnt) { + originals[element] = fs[element]; + fs[element] = createSpy(element, cnt); + } + + [ + ['realpathSync', 1], + ['readFileSync', 1], + ['openSync', 3], + ['readSync', 1], + ['closeSync', 1], + ['readFile', 2], + ['mkdir', 1], + ['lstat', 1], + ['stat', 1], + ['watch', 1], + ['readdir', 1], + ['access', 2], + ['open', 2], + ['write', 1], + ['fdatasync', 1], + ['close', 1], + ['read', 1], + ['unlink', 1], + ['rmdir', 1], + ].forEach((element) => { + intercept(element[0], element[1]); + }) +})(); + const { ipcRenderer } = require('electron'); const assert = require('assert'); const path = require('path'); From e25cbb45e7a999d3131f5b48a0bae9df215a3fa6 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 09:17:17 +0100 Subject: [PATCH 1767/1837] Dispose all Disposables from tests (fixes #114125) --- src/vs/platform/files/common/fileService.ts | 6 +-- .../configuration/browser/configuration.ts | 14 ++++--- .../browser/configurationService.ts | 2 +- .../configurationEditingService.test.ts | 14 +++---- .../common/workingCopyFileService.ts | 4 +- .../test/browser/workbenchTestServices.ts | 41 ++++++++++--------- 6 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index adb0bb16f00..a15a789cb53 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -901,7 +901,7 @@ export class FileService extends Disposable implements IFileService { watch(resource: URI, options: IWatchOptions = { recursive: false, excludes: [] }): IDisposable { let watchDisposed = false; - let watchDisposable = toDisposable(() => watchDisposed = true); + let disposeWatch = () => { watchDisposed = true; }; // Watch and wire in disposable which is async but // check if we got disposed meanwhile and forward @@ -909,11 +909,11 @@ export class FileService extends Disposable implements IFileService { if (watchDisposed) { dispose(disposable); } else { - watchDisposable = disposable; + disposeWatch = () => dispose(disposable); } }, error => this.logService.error(error)); - return toDisposable(() => dispose(watchDisposable)); + return toDisposable(() => disposeWatch()); } async doWatch(resource: URI, options: IWatchOptions): Promise { diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 382eebda143..6defc8442da 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -415,6 +415,11 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfiguration = this._cachedConfiguration = new CachedWorkspaceConfiguration(configurationCache); } + public dispose() { + super.dispose(); + this._workspaceConfiguration.dispose(); + } + async initialize(workspaceIdentifier: IWorkspaceIdentifier): Promise { this._workspaceIdentifier = workspaceIdentifier; if (!this._initialized) { @@ -708,7 +713,6 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat readonly onDidChange: Event = this._onDidChange.event; private folderConfiguration: IFolderConfiguration; - private folderConfigurationDisposable: IDisposable = Disposable.None; private readonly configurationFolder: URI; private cachedFolderConfiguration: CachedFolderConfiguration; @@ -729,14 +733,14 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat whenProviderRegistered(workspaceFolder.uri, fileService) .then(() => { this.folderConfiguration.dispose(); - this.folderConfigurationDisposable.dispose(); - this.folderConfiguration = this.createFileServiceBasedConfiguration(fileService, uriIdentityService); + this.folderConfiguration = this._register(this.createFileServiceBasedConfiguration(fileService, uriIdentityService)); this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); this.onDidFolderConfigurationChange(); }); } else { - this.folderConfiguration = this.createFileServiceBasedConfiguration(fileService, uriIdentityService); - this.folderConfigurationDisposable = this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); + this._register(this.cachedFolderConfiguration); + this.folderConfiguration = this._register(this.createFileServiceBasedConfiguration(fileService, uriIdentityService)); + this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); } } diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index d858cfd0b1a..8195815179a 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -462,7 +462,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat if (!this.localUserConfiguration.hasTasksLoaded) { // Reload local user configuration again to load user tasks - runWhenIdle(() => this.reloadLocalUserConfiguration(), 5000); + this._register(runWhenIdle(() => this.reloadLocalUserConfiguration(), 5000)); } }); } diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index 92ef17d4eb8..fec6587091b 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -104,23 +104,23 @@ suite('ConfigurationEditingService', () => { } async function setUpServices(noWorkspace: boolean = false): Promise { - instantiationService = workbenchInstantiationService(); + instantiationService = workbenchInstantiationService(undefined, disposables); const environmentService = new TestWorkbenchEnvironmentService(URI.file(workspaceDir)); instantiationService.stub(IEnvironmentService, environmentService); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); + const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); const fileService = disposables.add(new FileService(new NullLogService())); const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); + disposables.add(fileService.registerProvider(Schemas.file, diskFileSystemProvider)); + disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService())))); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); await workspaceService.initialize(noWorkspace ? { id: '' } : { folder: URI.file(workspaceDir), id: createHash('md5').update(URI.file(workspaceDir).toString()).digest('hex') }); instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + instantiationService.stub(IKeybindingEditingService, disposables.add(instantiationService.createInstance(KeybindingsEditingService))); + instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); instantiationService.stub(ICommandService, CommandService); testObject = instantiationService.createInstance(ConfigurationEditingService); } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts index 033991e8db3..29503d782a6 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileService.ts @@ -254,7 +254,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi super(); // register a default working copy provider that uses the working copy service - this.registerWorkingCopyProvider(resource => { + this._register(this.registerWorkingCopyProvider(resource => { return this.workingCopyService.workingCopies.filter(workingCopy => { if (this.fileService.canHandleResource(resource)) { // only check for parents if the resource can be handled @@ -265,7 +265,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi return this.uriIdentityService.extUri.isEqual(workingCopy.resource, resource); }); - }); + })); } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 6740f453275..e8424d3318c 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -123,15 +123,18 @@ export interface ITestInstantiationService extends IInstantiationService { stub(service: ServiceIdentifier, ctor: any): T; } -export function workbenchInstantiationService(overrides?: { - textFileService?: (instantiationService: IInstantiationService) => ITextFileService - pathService?: (instantiationService: IInstantiationService) => IPathService, - editorService?: (instantiationService: IInstantiationService) => IEditorService, - contextKeyService?: (instantiationService: IInstantiationService) => IContextKeyService, -}): ITestInstantiationService { +export function workbenchInstantiationService( + overrides?: { + textFileService?: (instantiationService: IInstantiationService) => ITextFileService + pathService?: (instantiationService: IInstantiationService) => IPathService, + editorService?: (instantiationService: IInstantiationService) => IEditorService, + contextKeyService?: (instantiationService: IInstantiationService) => IContextKeyService, + }, + disposables: DisposableStore = new DisposableStore() +): ITestInstantiationService { const instantiationService = new TestInstantiationService(new ServiceCollection([ILifecycleService, new TestLifecycleService()])); - instantiationService.stub(IWorkingCopyService, new TestWorkingCopyService()); + instantiationService.stub(IWorkingCopyService, disposables.add(new TestWorkingCopyService())); instantiationService.stub(IEnvironmentService, TestEnvironmentService); const contextKeyService = overrides?.contextKeyService ? overrides.contextKeyService(instantiationService) : instantiationService.createInstance(MockContextKeyService); instantiationService.stub(IContextKeyService, contextKeyService); @@ -140,10 +143,10 @@ export function workbenchInstantiationService(overrides?: { instantiationService.stub(IWorkspaceContextService, workspaceContextService); const configService = new TestConfigurationService(); instantiationService.stub(IConfigurationService, configService); - instantiationService.stub(IFilesConfigurationService, new TestFilesConfigurationService(contextKeyService, configService)); + instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(contextKeyService, configService))); instantiationService.stub(ITextResourceConfigurationService, new TestTextResourceConfigurationService(configService)); - instantiationService.stub(IUntitledTextEditorService, instantiationService.createInstance(UntitledTextEditorService)); - instantiationService.stub(IStorageService, new TestStorageService()); + instantiationService.stub(IUntitledTextEditorService, disposables.add(instantiationService.createInstance(UntitledTextEditorService))); + instantiationService.stub(IStorageService, disposables.add(new TestStorageService())); instantiationService.stub(IPathService, overrides?.pathService ? overrides.pathService(instantiationService) : new TestPathService()); const layoutService = new TestLayoutService(); instantiationService.stub(IWorkbenchLayoutService, layoutService); @@ -151,39 +154,39 @@ export function workbenchInstantiationService(overrides?: { const accessibilityService = new TestAccessibilityService(); instantiationService.stub(IAccessibilityService, accessibilityService); instantiationService.stub(IFileDialogService, instantiationService.createInstance(TestFileDialogService)); - instantiationService.stub(IModeService, instantiationService.createInstance(ModeServiceImpl)); + instantiationService.stub(IModeService, disposables.add(instantiationService.createInstance(ModeServiceImpl))); instantiationService.stub(IHistoryService, new TestHistoryService()); instantiationService.stub(ITextResourcePropertiesService, new TestTextResourcePropertiesService(configService)); instantiationService.stub(IUndoRedoService, instantiationService.createInstance(UndoRedoService)); const themeService = new TestThemeService(); instantiationService.stub(IThemeService, themeService); - instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); + instantiationService.stub(IModelService, disposables.add(instantiationService.createInstance(ModelServiceImpl))); const fileService = new TestFileService(); instantiationService.stub(IFileService, fileService); instantiationService.stub(IUriIdentityService, new UriIdentityService(fileService)); instantiationService.stub(IBackupFileService, new TestBackupFileService()); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(INotificationService, new TestNotificationService()); - instantiationService.stub(IUntitledTextEditorService, instantiationService.createInstance(UntitledTextEditorService)); + instantiationService.stub(IUntitledTextEditorService, disposables.add(instantiationService.createInstance(UntitledTextEditorService))); instantiationService.stub(IMenuService, new TestMenuService()); const keybindingService = new MockKeybindingService(); instantiationService.stub(IKeybindingService, keybindingService); instantiationService.stub(IDecorationsService, new TestDecorationsService()); instantiationService.stub(IExtensionService, new TestExtensionService()); - instantiationService.stub(IWorkingCopyFileService, instantiationService.createInstance(WorkingCopyFileService)); - instantiationService.stub(ITextFileService, overrides?.textFileService ? overrides.textFileService(instantiationService) : instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(IWorkingCopyFileService, disposables.add(instantiationService.createInstance(WorkingCopyFileService))); + instantiationService.stub(ITextFileService, overrides?.textFileService ? overrides.textFileService(instantiationService) : disposables.add(instantiationService.createInstance(TestTextFileService))); instantiationService.stub(IHostService, instantiationService.createInstance(TestHostService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); instantiationService.stub(ILogService, new NullLogService()); const editorGroupService = new TestEditorGroupsService([new TestEditorGroupView(0)]); instantiationService.stub(IEditorGroupsService, editorGroupService); - instantiationService.stub(ILabelService, instantiationService.createInstance(LabelService)); + instantiationService.stub(ILabelService, disposables.add(instantiationService.createInstance(LabelService))); const editorService = overrides?.editorService ? overrides.editorService(instantiationService) : new TestEditorService(editorGroupService); instantiationService.stub(IEditorService, editorService); - instantiationService.stub(ICodeEditorService, new CodeEditorService(editorService, themeService, configService)); + instantiationService.stub(ICodeEditorService, disposables.add(new CodeEditorService(editorService, themeService, configService))); instantiationService.stub(IViewletService, new TestViewletService()); instantiationService.stub(IListService, new TestListService()); - instantiationService.stub(IQuickInputService, new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, accessibilityService, layoutService)); + instantiationService.stub(IQuickInputService, disposables.add(new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, accessibilityService, layoutService))); return instantiationService; } From cfb2ad879a3a99db1f6837ef169b91d14a80140a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 09:47:00 +0100 Subject: [PATCH 1768/1837] Update src/vs/workbench/services/configuration/browser/configuration.ts Co-authored-by: Benjamin Pasero --- .../workbench/services/configuration/browser/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 6defc8442da..cd8f627d4d0 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -415,7 +415,7 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfiguration = this._cachedConfiguration = new CachedWorkspaceConfiguration(configurationCache); } - public dispose() { + dispose() { super.dispose(); this._workspaceConfiguration.dispose(); } From f6bbc8b68d42fdc6aa9a896adcf712f63f6b51ee Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 11 Jan 2021 09:56:43 +0100 Subject: [PATCH 1769/1837] update tsec tool --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ba7cd3439fb..d9902d6b3d8 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,7 @@ "vscode-debugprotocol": "1.43.0", "vscode-nls-dev": "^3.3.1", "vscode-telemetry-extractor": "^1.6.0", - "vscode-tsec": "0.0.2", + "vscode-tsec": "0.0.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.12", "webpack-stream": "^5.2.1", diff --git a/yarn.lock b/yarn.lock index e4538d0a794..41127ed6b79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10716,10 +10716,10 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-tsec@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/vscode-tsec/-/vscode-tsec-0.0.2.tgz#ce7b8f76469071b63ac25020e31addc142cd8ac6" - integrity sha512-SDS9m1ExvMZHCsdUCMBvlcGBUSqB1xTZduiKCzTsswD0PUTvtyPPC4OAihoNsHtQvhdSP3o4bOcfGZ9L6VvW7Q== +vscode-tsec@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/vscode-tsec/-/vscode-tsec-0.0.3.tgz#2c9b4fbf822a9bcb177cd9e9ab46a782bba4628b" + integrity sha512-qak2mD8+FDRbC9mSjWQumc9vi1f3ATS7oLsROd3mJ9SFg+GTiRlpOmOpPPY+p+JI5AWNgkWDb/ztsFNGRex8jw== dependencies: "@types/glob" "^7.1.1" "@types/node" "^13.13.5" From 60bc00ff63d27985681eb37cdeb008b5e6877c56 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 8 Jan 2021 17:45:27 +0100 Subject: [PATCH 1770/1837] webpack config typing fix --- extensions/shared.webpack.config.js | 2 -- package.json | 3 ++- yarn.lock | 41 ++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index dbec21840ab..b5f908d0c7e 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -69,7 +69,6 @@ function withNodeDefaults(/**@type WebpackConfig*/extConfig) { // yes, really source maps devtool: 'source-map', plugins: [ - // @ts-expect-error new CopyWebpackPlugin({ patterns: [ { from: 'src', to: '.', globOptions: { ignore: ['**/test/**', '**/*.ts'] }, noErrorOnMissing: true } @@ -128,7 +127,6 @@ function withBrowserDefaults(/**@type WebpackConfig*/extConfig) { // yes, really source maps devtool: 'source-map', plugins: [ - // @ts-expect-error new CopyWebpackPlugin({ patterns: [ { from: 'src', to: '.', globOptions: { ignore: ['**/test/**', '**/*.ts'] }, noErrorOnMissing: true } diff --git a/package.json b/package.json index d9902d6b3d8..51af24174dc 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "@types/applicationinsights": "0.20.0", "@types/chokidar": "2.1.3", "@types/cookie": "^0.3.3", + "@types/copy-webpack-plugin": "^6.0.3", "@types/debug": "4.1.5", "@types/graceful-fs": "4.1.2", "@types/http-proxy-agent": "^2.0.1", @@ -103,7 +104,7 @@ "@types/sinon": "^1.16.36", "@types/trusted-types": "^1.0.6", "@types/vscode-windows-registry": "^1.0.0", - "@types/webpack": "^4.4.10", + "@types/webpack": "^4.41.25", "@types/windows-foreground-love": "^0.3.0", "@types/windows-mutex": "^0.4.0", "@types/windows-process-tree": "^0.2.0", diff --git a/yarn.lock b/yarn.lock index 41127ed6b79..7a0a2da0d5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,6 +223,11 @@ dependencies: defer-to-connect "^1.0.1" +"@types/anymatch@*": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" + integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== + "@types/applicationinsights@0.20.0": version "0.20.0" resolved "https://registry.yarnpkg.com/@types/applicationinsights/-/applicationinsights-0.20.0.tgz#fa7b36dc954f635fa9037cad27c378446b1048fb" @@ -254,6 +259,13 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== +"@types/copy-webpack-plugin@^6.0.3": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz#225f86bc60a62052df39a110f7cbf7bc5156a0c1" + integrity sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg== + dependencies: + "@types/webpack" "*" + "@types/debug@4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" @@ -351,6 +363,11 @@ resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-1.16.36.tgz#74bb6ed7928597c1b3fb1b009005e94dc6eae357" integrity sha1-dLtu15KFl8Gz+xsAkAXpTcbq41c= +"@types/source-list-map@*": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" + integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + "@types/tapable@*": version "1.0.4" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370" @@ -373,14 +390,25 @@ resolved "https://registry.yarnpkg.com/@types/vscode-windows-registry/-/vscode-windows-registry-1.0.0.tgz#333eea7fd5743fa4c99dff13af16de2c08a586d0" integrity sha512-gyq9tIMbxry5GL2gY7J30E6R3EUx0cAin/k3wfsQez4C5uDWVJmJw142x6KFXtYX7xYQL/IXmm4cRqi4ghg05A== -"@types/webpack@^4.4.10": - version "4.4.10" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.10.tgz#2ecf12589142bc531549140612815b7d8b076358" - integrity sha512-5vMiKzNcG19go5sR6++7ubRkBA+hjG4yO/2qwDQhAVfTGV8pqqatFqbrRCiJ2P9DbCilcp+tpXxYhPs2Zn7GyA== +"@types/webpack-sources@*": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10" + integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg== dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.7.3" + +"@types/webpack@*", "@types/webpack@^4.41.25": + version "4.41.25" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.25.tgz#4d3b5aecc4e44117b376280fbfd2dc36697968c4" + integrity sha512-cr6kZ+4m9lp86ytQc1jPOJXgINQyz3kLLunZ57jznW+WIAL0JqZbGubQk4GlD42MuQL5JGOABrxdpqqWeovlVQ== + dependencies: + "@types/anymatch" "*" "@types/node" "*" "@types/tapable" "*" "@types/uglify-js" "*" + "@types/webpack-sources" "*" source-map "^0.6.0" "@types/windows-foreground-love@^0.3.0": @@ -9388,6 +9416,11 @@ source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" From 64a14963f7b9a273ebadd51d7efca6cd4604cfd1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 10:10:40 +0100 Subject: [PATCH 1771/1837] Expose actions to duplicate editor groups (fix #114132) --- .../parts/editor/editor.contribution.ts | 6 +- .../browser/parts/editor/editorActions.ts | 98 ++++++++++++++++++- 2 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index dfa92a3a2a4..5fdcc208cb2 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -33,7 +33,7 @@ import { JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction, EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoRowsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction, NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction, - QuickAccessPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickAccessLeastRecentlyUsedEditorAction, QuickAccessLeastRecentlyUsedEditorInGroupAction, ReopenResourcesAction, ToggleEditorTypeAction + QuickAccessPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickAccessLeastRecentlyUsedEditorAction, QuickAccessLeastRecentlyUsedEditorInGroupAction, ReopenResourcesAction, ToggleEditorTypeAction, DuplicateGroupDownAction, DuplicateGroupLeftAction, DuplicateGroupRightAction, DuplicateGroupUpAction } from 'vs/workbench/browser/parts/editor/editorActions'; import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -351,6 +351,10 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupLeftAction, registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupRightAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.RightArrow) }), 'View: Move Editor Group Right', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupUpAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.UpArrow) }), 'View: Move Editor Group Up', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupDownAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.DownArrow) }), 'View: Move Editor Group Down', CATEGORIES.View.value); +registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupLeftAction), 'View: Duplicate Editor Group Left', CATEGORIES.View.value); +registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupRightAction), 'View: Duplicate Editor Group Right', CATEGORIES.View.value); +registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupUpAction), 'View: Duplicate Editor Group Up', CATEGORIES.View.value); +registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupDownAction), 'View: Duplicate Editor Group Down', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToPreviousGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }), 'View: Move Editor into Previous Group', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToNextGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }), 'View: Move Editor into Next Group', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToFirstGroupAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_1, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_1 } }), 'View: Move Editor into First Group', CATEGORIES.View.value); diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 5d1bab0563a..7e901d0ae65 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -747,12 +747,13 @@ export class CloseEditorInAllGroupsAction extends Action { } } -export class BaseMoveGroupAction extends Action { +class BaseMoveCopyGroupAction extends Action { constructor( id: string, label: string, private direction: GroupDirection, + private isMove: boolean, private editorGroupService: IEditorGroupsService ) { super(id, label); @@ -767,9 +768,18 @@ export class BaseMoveGroupAction extends Action { } if (sourceGroup) { - const targetGroup = this.findTargetGroup(sourceGroup); - if (targetGroup) { - this.editorGroupService.moveGroup(sourceGroup, targetGroup, this.direction); + let resultGroup: IEditorGroup | undefined = undefined; + if (this.isMove) { + const targetGroup = this.findTargetGroup(sourceGroup); + if (targetGroup) { + resultGroup = this.editorGroupService.moveGroup(sourceGroup, targetGroup, this.direction); + } + } else { + resultGroup = this.editorGroupService.copyGroup(sourceGroup, sourceGroup, this.direction); + } + + if (resultGroup) { + this.editorGroupService.activateGroup(resultGroup); } } } @@ -802,6 +812,18 @@ export class BaseMoveGroupAction extends Action { } } +class BaseMoveGroupAction extends BaseMoveCopyGroupAction { + + constructor( + id: string, + label: string, + direction: GroupDirection, + editorGroupService: IEditorGroupsService + ) { + super(id, label, direction, true, editorGroupService); + } +} + export class MoveGroupLeftAction extends BaseMoveGroupAction { static readonly ID = 'workbench.action.moveActiveEditorGroupLeft'; @@ -858,6 +880,74 @@ export class MoveGroupDownAction extends BaseMoveGroupAction { } } +class BaseDuplicateGroupAction extends BaseMoveCopyGroupAction { + + constructor( + id: string, + label: string, + direction: GroupDirection, + editorGroupService: IEditorGroupsService + ) { + super(id, label, direction, false, editorGroupService); + } +} + +export class DuplicateGroupLeftAction extends BaseDuplicateGroupAction { + + static readonly ID = 'workbench.action.duplicateActiveEditorGroupLeft'; + static readonly LABEL = nls.localize('duplicateActiveGroupLeft', "Duplicate Editor Group Left"); + + constructor( + id: string, + label: string, + @IEditorGroupsService editorGroupService: IEditorGroupsService + ) { + super(id, label, GroupDirection.LEFT, editorGroupService); + } +} + +export class DuplicateGroupRightAction extends BaseDuplicateGroupAction { + + static readonly ID = 'workbench.action.duplicateActiveEditorGroupRight'; + static readonly LABEL = nls.localize('duplicateActiveGroupRight', "Duplicate Editor Group Right"); + + constructor( + id: string, + label: string, + @IEditorGroupsService editorGroupService: IEditorGroupsService + ) { + super(id, label, GroupDirection.RIGHT, editorGroupService); + } +} + +export class DuplicateGroupUpAction extends BaseDuplicateGroupAction { + + static readonly ID = 'workbench.action.duplicateActiveEditorGroupUp'; + static readonly LABEL = nls.localize('duplicateActiveGroupUp', "Duplicate Editor Group Up"); + + constructor( + id: string, + label: string, + @IEditorGroupsService editorGroupService: IEditorGroupsService + ) { + super(id, label, GroupDirection.UP, editorGroupService); + } +} + +export class DuplicateGroupDownAction extends BaseDuplicateGroupAction { + + static readonly ID = 'workbench.action.duplicateActiveEditorGroupDown'; + static readonly LABEL = nls.localize('duplicateActiveGroupDown', "Duplicate Editor Group Down"); + + constructor( + id: string, + label: string, + @IEditorGroupsService editorGroupService: IEditorGroupsService + ) { + super(id, label, GroupDirection.DOWN, editorGroupService); + } +} + export class MinimizeOtherGroupsAction extends Action { static readonly ID = 'workbench.action.minimizeOtherEditors'; From b57739f4a241fa0e52cf93fa681dc187655ef35f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 11:04:00 +0100 Subject: [PATCH 1772/1837] tests - more use of getRandomTestPath --- .../parts/storage/test/node/storage.test.ts | 20 ++------- src/vs/base/test/node/crypto.test.ts | 8 ++-- src/vs/base/test/node/extpath.test.ts | 17 ++++---- src/vs/base/test/node/pfs/pfs.test.ts | 42 +++++++++---------- .../electron-browser/diskFileService.test.ts | 11 +++-- src/vs/platform/state/test/node/state.test.ts | 5 ++- .../test/electron-browser/storage.test.ts | 11 ++--- .../storage/test/node/storageService.test.ts | 12 +----- .../electron-browser/backupRestorer.test.ts | 25 ++++++----- .../nativeTextFileService.io.test.ts | 11 ++--- 10 files changed, 64 insertions(+), 98 deletions(-) diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index d557b117e35..0f085331a7a 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -5,7 +5,6 @@ import { SQLiteStorageDatabase, ISQLiteStorageDatabaseOptions } from 'vs/base/parts/storage/node/storage'; import { Storage, IStorageDatabase, IStorageItemsChangeEvent } from 'vs/base/parts/storage/common/storage'; -import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { equal, ok } from 'assert'; @@ -13,20 +12,15 @@ import { mkdirp, writeFile, exists, unlink, rimraf } from 'vs/base/node/pfs'; import { timeout } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; import { isWindows } from 'vs/base/common/platform'; -import { flakySuite } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { generateUuid } from 'vs/base/common/uuid'; flakySuite('Storage Library', function () { - function uniqueStorageDir(): string { - const id = generateUuid(); - - return join(tmpdir(), 'vsctests', id, 'storage2', id); - } - let storageDir: string; setup(function () { - storageDir = uniqueStorageDir(); + storageDir = getRandomTestPath(tmpdir(), 'vsctests', 'storagelibrary'); return mkdirp(storageDir); }); @@ -288,12 +282,6 @@ flakySuite('Storage Library', function () { flakySuite('SQLite Storage Library', function () { - function uniqueStorageDir(): string { - const id = generateUuid(); - - return join(tmpdir(), 'vsctests', id, 'storage', id); - } - function toSet(elements: string[]): Set { const set = new Set(); elements.forEach(element => set.add(element)); @@ -304,7 +292,7 @@ flakySuite('SQLite Storage Library', function () { let storageDir: string; setup(function () { - storageDir = uniqueStorageDir(); + storageDir = getRandomTestPath(tmpdir(), 'vsctests', 'storagelibrary'); return mkdirp(storageDir); }); diff --git a/src/vs/base/test/node/crypto.test.ts b/src/vs/base/test/node/crypto.test.ts index a5c5c68e512..e32be0406a2 100644 --- a/src/vs/base/test/node/crypto.test.ts +++ b/src/vs/base/test/node/crypto.test.ts @@ -4,20 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { checksum } from 'vs/base/node/crypto'; -import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { mkdirp, rimraf, writeFile } from 'vs/base/node/pfs'; +import { getRandomTestPath } from 'vs/base/test/node/testUtils'; suite('Crypto', () => { test('checksum', async () => { - const id = generateUuid(); - const testDir = join(tmpdir(), 'vsctests', id); - const testFile = join(testDir, 'checksum.txt'); - + const testDir = getRandomTestPath(tmpdir(), 'vsctests', 'crypto'); await mkdirp(testDir); + const testFile = join(testDir, 'checksum.txt'); await writeFile(testFile, 'Hello World'); await checksum(testFile, '0a4d55a8d778e5022fab701977c5d840bbc486d0'); diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts index ea9d130c754..39c409b4c6b 100644 --- a/src/vs/base/test/node/extpath.test.ts +++ b/src/vs/base/test/node/extpath.test.ts @@ -6,16 +6,15 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; -import * as uuid from 'vs/base/common/uuid'; import * as pfs from 'vs/base/node/pfs'; import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath'; +import { getRandomTestPath } from 'vs/base/test/node/testUtils'; suite('Extpath', () => { test('realcase', async () => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extpath', id); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); + const newDir = path.join(parentDir, 'newdir'); await pfs.mkdirp(newDir, 493); @@ -41,9 +40,8 @@ suite('Extpath', () => { }); test('realpath', async () => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extpath', id); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); + const newDir = path.join(parentDir, 'newdir'); await pfs.mkdirp(newDir, 493); @@ -54,9 +52,8 @@ suite('Extpath', () => { }); test('realpathSync', async () => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extpath', id); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); + const newDir = path.join(parentDir, 'newdir'); await pfs.mkdirp(newDir, 493); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index bb62e8117c7..86cb0be8f85 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -14,13 +14,13 @@ import { getPathFromAmdModule } from 'vs/base/common/amd'; import { isWindows } from 'vs/base/common/platform'; import { canNormalize } from 'vs/base/common/normalization'; import { VSBuffer } from 'vs/base/common/buffer'; -import { flakySuite } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; flakySuite('PFS', function () { test('writeFile', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'writefile.txt'); @@ -34,8 +34,8 @@ flakySuite('PFS', function () { }); test('writeFile - parallel write on different files works', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile1 = path.join(newDir, 'writefile1.txt'); const testFile2 = path.join(newDir, 'writefile2.txt'); @@ -63,8 +63,8 @@ flakySuite('PFS', function () { }); test('writeFile - parallel write on same files works and is sequentalized', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'writefile.txt'); @@ -84,8 +84,8 @@ flakySuite('PFS', function () { }); test('rimraf - simple - unlink', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -97,8 +97,8 @@ flakySuite('PFS', function () { }); test('rimraf - simple - move', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -110,8 +110,8 @@ flakySuite('PFS', function () { }); test('rimraf - recursive folder structure - unlink', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -125,8 +125,8 @@ flakySuite('PFS', function () { }); test('rimraf - recursive folder structure - move', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -140,8 +140,8 @@ flakySuite('PFS', function () { }); test('rimraf - simple ends with dot - move', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = `${uuid.generateUuid()}.`; - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -153,8 +153,8 @@ flakySuite('PFS', function () { }); test('rimraf - simple ends with dot slash/backslash - move', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = `${uuid.generateUuid()}.`; - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -166,8 +166,8 @@ flakySuite('PFS', function () { }); test('rimrafSync - swallows file not found error', function () { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); pfs.rimrafSync(newDir); @@ -176,8 +176,8 @@ flakySuite('PFS', function () { }); test('rimrafSync - simple', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -191,8 +191,8 @@ flakySuite('PFS', function () { }); test('rimrafSync - recursive folder structure', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -208,8 +208,8 @@ flakySuite('PFS', function () { }); test('moveIgnoreError', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -260,8 +260,8 @@ flakySuite('PFS', function () { }); test('mkdirp', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -272,8 +272,8 @@ flakySuite('PFS', function () { }); test('readDirsInDir', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); await pfs.mkdirp(newDir, 493); @@ -336,8 +336,8 @@ flakySuite('PFS', function () { test('readdir', async () => { if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id, 'öäü'); await pfs.mkdirp(newDir, 493); @@ -353,8 +353,8 @@ flakySuite('PFS', function () { test('readdirWithFileTypes', async () => { if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const testDir = path.join(parentDir, 'pfs', id); const newDir = path.join(testDir, 'öäü'); @@ -403,8 +403,8 @@ flakySuite('PFS', function () { bigData: string | Buffer | Uint8Array, bigDataValue: string ): Promise { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'flushed.txt'); @@ -421,8 +421,8 @@ flakySuite('PFS', function () { } test('writeFile (string, error handling)', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'flushed.txt'); @@ -445,8 +445,8 @@ flakySuite('PFS', function () { }); test('writeFileSync', async () => { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'flushed.txt'); diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index f5d9992ad9a..e943415e9de 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -9,7 +9,6 @@ import { FileService } from 'vs/platform/files/common/fileService'; import { Schemas } from 'vs/base/common/network'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; -import { generateUuid } from 'vs/base/common/uuid'; import { join, basename, dirname, posix } from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { copy, rimraf, symlink, rimrafSync } from 'vs/base/node/pfs'; @@ -120,12 +119,12 @@ export class TestDiskFileSystemProvider extends DiskFileSystemProvider { flakySuite('Disk File Service', function () { - const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'diskfileservice'); const testSchema = 'test'; let service: FileService; let fileProvider: TestDiskFileSystemProvider; let testProvider: TestDiskFileSystemProvider; + let testDir: string; const disposables = new DisposableStore(); @@ -144,17 +143,17 @@ flakySuite('Disk File Service', function () { disposables.add(service.registerProvider(testSchema, testProvider)); disposables.add(testProvider); - const id = generateUuid(); - testDir = join(parentDir, id); + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'diskfileservice'); + const sourceDir = getPathFromAmdModule(require, './fixtures/service'); await copy(sourceDir, testDir); }); - teardown(async () => { + teardown(() => { disposables.clear(); - await rimraf(parentDir); + return rimraf(testDir); }); test('createFolder', async () => { diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index ec36550cf56..7bf641e5f74 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -11,11 +11,12 @@ import { FileStorage } from 'vs/platform/state/node/stateService'; import { mkdirp, rimraf, writeFileSync } from 'vs/base/node/pfs'; flakySuite('StateService', () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); - const storageFile = path.join(parentDir, 'storage.json'); test('Basics', async function () { + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); await mkdirp(parentDir); + + const storageFile = path.join(parentDir, 'storage.json'); writeFileSync(storageFile, ''); let service = new FileStorage(storageFile, () => null); diff --git a/src/vs/platform/storage/test/electron-browser/storage.test.ts b/src/vs/platform/storage/test/electron-browser/storage.test.ts index fcc17053339..47457e87f47 100644 --- a/src/vs/platform/storage/test/electron-browser/storage.test.ts +++ b/src/vs/platform/storage/test/electron-browser/storage.test.ts @@ -5,7 +5,6 @@ import { equal } from 'assert'; import { FileStorageDatabase } from 'vs/platform/storage/browser/storageService'; -import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { rimraf } from 'vs/base/node/pfs'; @@ -20,11 +19,10 @@ import { Schemas } from 'vs/base/common/network'; suite('Storage', () => { - const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice'); + let testDir: string; let fileService: FileService; let fileProvider: DiskFileSystemProvider; - let testDir: string; const disposables = new DisposableStore(); @@ -38,14 +36,13 @@ suite('Storage', () => { disposables.add(fileService.registerProvider(Schemas.file, fileProvider)); disposables.add(fileProvider); - const id = generateUuid(); - testDir = join(parentDir, id); + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice'); }); - teardown(async () => { + teardown(() => { disposables.clear(); - await rimraf(parentDir); + return rimraf(testDir); }); test('File Based Storage', async () => { diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index 54d2d3d30c1..a4e15e0061a 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -6,8 +6,6 @@ import { equal } from 'assert'; import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { NativeStorageService } from 'vs/platform/storage/node/storageService'; -import { generateUuid } from 'vs/base/common/uuid'; -import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -15,16 +13,10 @@ import { NativeEnvironmentService } from 'vs/platform/environment/node/environme import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { InMemoryStorageDatabase } from 'vs/base/parts/storage/common/storage'; import { URI } from 'vs/base/common/uri'; -import { flakySuite } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; flakySuite('NativeStorageService', function () { - function uniqueStorageDir(): string { - const id = generateUuid(); - - return join(tmpdir(), 'vsctests', id, 'storage2', id); - } - test('Migrate Data', async function () { class StorageTestEnvironmentService extends NativeEnvironmentService { @@ -42,7 +34,7 @@ flakySuite('NativeStorageService', function () { } } - const storageDir = uniqueStorageDir(); + const storageDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice'); await mkdirp(storageDir); const storage = new NativeStorageService(new InMemoryStorageDatabase(), new NullLogService(), new StorageTestEnvironmentService(URI.file(storageDir), storageDir)); diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index 6a55c3dd51b..03aa09fcbd0 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -34,17 +34,6 @@ import { isEqual } from 'vs/base/common/resources'; import { TestServiceAccessor } from 'vs/workbench/test/browser/workbenchTestServices'; import { BackupRestorer } from 'vs/workbench/contrib/backup/common/backupRestorer'; -const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backuprestorer'); -const backupHome = path.join(userdataDir, 'Backups'); -const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); - -const workspaceResource = URI.file(platform.isWindows ? 'c:\\workspace' : '/workspace'); -const workspaceBackupPath = path.join(backupHome, hashPath(workspaceResource)); -const fooFile = URI.file(platform.isWindows ? 'c:\\Foo' : '/Foo'); -const barFile = URI.file(platform.isWindows ? 'c:\\Bar' : '/Bar'); -const untitledFile1 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' }); -const untitledFile2 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-2' }); - class TestBackupRestorer extends BackupRestorer { async doRestoreBackups(): Promise { return super.doRestoreBackups(); @@ -53,9 +42,19 @@ class TestBackupRestorer extends BackupRestorer { flakySuite('BackupRestorer', () => { let accessor: TestServiceAccessor; - let disposables: IDisposable[] = []; + const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backuprestorer'); + const backupHome = path.join(userdataDir, 'Backups'); + const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); + + const workspaceResource = URI.file(platform.isWindows ? 'c:\\workspace' : '/workspace'); + const workspaceBackupPath = path.join(backupHome, hashPath(workspaceResource)); + const fooFile = URI.file(platform.isWindows ? 'c:\\Foo' : '/Foo'); + const barFile = URI.file(platform.isWindows ? 'c:\\Bar' : '/Bar'); + const untitledFile1 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' }); + const untitledFile2 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-2' }); + setup(async () => { disposables.push(Registry.as(EditorExtensions.Editors).registerEditor( EditorDescriptor.create( @@ -73,7 +72,7 @@ flakySuite('BackupRestorer', () => { return pfs.writeFile(workspacesJsonPath, ''); }); - teardown(async () => { + teardown(() => { dispose(disposables); disposables = []; diff --git a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts index c62769293d1..59579ff1348 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts @@ -15,8 +15,6 @@ import { NullLogService } from 'vs/platform/log/common/log'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { tmpdir } from 'os'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; -import { generateUuid } from 'vs/base/common/uuid'; -import { join } from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { detectEncodingByBOM } from 'vs/workbench/services/textfile/test/node/encoding/encoding.test'; import { workbenchInstantiationService, TestNativeTextFileServiceWithEncodingOverrides } from 'vs/workbench/test/electron-browser/workbenchTestServices'; @@ -26,8 +24,6 @@ import { TestWorkingCopyService } from 'vs/workbench/test/common/workbenchTestSe import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; flakySuite('Files - NativeTextFileService i/o', function () { - const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'textfileservice'); - const disposables = new DisposableStore(); let service: ITextFileService; @@ -51,8 +47,7 @@ flakySuite('Files - NativeTextFileService i/o', function () { service = instantiationService.createChild(collection).createInstance(TestNativeTextFileServiceWithEncodingOverrides); - const id = generateUuid(); - testDir = join(parentDir, id); + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'textfileservice'); const sourceDir = getPathFromAmdModule(require, './fixtures'); await copy(sourceDir, testDir); @@ -60,12 +55,12 @@ flakySuite('Files - NativeTextFileService i/o', function () { return { service, testDir }; }, - teardown: async () => { + teardown: () => { (service.files).dispose(); disposables.clear(); - await rimraf(parentDir); + return rimraf(testDir); }, exists, From 175e2c0b1d1afd6eb2367edc326516eba78e4950 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 11:08:22 +0100 Subject: [PATCH 1773/1837] `yarn` is already installed (fixes #114140) --- build/azure-pipelines/darwin/product-build-darwin.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 7bcca46213e..6113eecf0a1 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -3,10 +3,6 @@ steps: inputs: versionSpec: "12.18.3" - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.x" - - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" inputs: From 31a53bb2427e3eef915a965c87cb636104ed819f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 11 Jan 2021 11:29:20 +0100 Subject: [PATCH 1774/1837] :lipstick: --- src/vs/platform/actions/common/menuService.ts | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/actions/common/menuService.ts b/src/vs/platform/actions/common/menuService.ts index 924e4acf24d..eaabf117bfe 100644 --- a/src/vs/platform/actions/common/menuService.ts +++ b/src/vs/platform/actions/common/menuService.ts @@ -48,21 +48,21 @@ class Menu implements IMenu { // rebuild this menu whenever the menu registry reports an // event for this MenuId - const scheduler1 = new RunOnceScheduler(() => this._build(), 50); - this._dispoables.add(scheduler1); + const rebuildMenuSoon = new RunOnceScheduler(() => this._build(), 50); + this._dispoables.add(rebuildMenuSoon); this._dispoables.add(MenuRegistry.onDidChangeMenu(e => { if (e.has(_id)) { - scheduler1.schedule(); + rebuildMenuSoon.schedule(); } })); // when context keys change we need to check if the menu also // has changed - const scheduler2 = new RunOnceScheduler(() => this._onDidChange.fire(this), 50); - this._dispoables.add(scheduler2); + const fireChangeSoon = new RunOnceScheduler(() => this._onDidChange.fire(this), 50); + this._dispoables.add(fireChangeSoon); this._dispoables.add(_contextKeyService.onDidChangeContext(e => { if (e.affectsSome(this._contextKeys)) { - scheduler2.schedule(); + fireChangeSoon.schedule(); } })); } @@ -95,15 +95,16 @@ class Menu implements IMenu { // keep keys for eventing Menu._fillInKbExprKeys(item.when, this._contextKeys); - // keep precondition keys for event if applicable - if (isIMenuItem(item) && item.command.precondition) { - Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys); - } - - // keep toggled keys for event if applicable - if (isIMenuItem(item) && item.command.toggled) { - const toggledExpression: ContextKeyExpression = (item.command.toggled as { condition: ContextKeyExpression }).condition || item.command.toggled; - Menu._fillInKbExprKeys(toggledExpression, this._contextKeys); + if (isIMenuItem(item)) { + // keep precondition keys for event if applicable + if (item.command.precondition) { + Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys); + } + // keep toggled keys for event if applicable + if (item.command.toggled) { + const toggledExpression: ContextKeyExpression = (item.command.toggled as { condition: ContextKeyExpression }).condition || item.command.toggled; + Menu._fillInKbExprKeys(toggledExpression, this._contextKeys); + } } } this._onDidChange.fire(this); From ea7569075983f6c9af4e2b3aa2f5bcf2a7b8d4d3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 11:58:52 +0100 Subject: [PATCH 1775/1837] - Make cached configurations not disposables - use workspace configuration disposables --- .../configuration/browser/configuration.ts | 56 +++++-------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index cd8f627d4d0..04f37bd3a1a 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import * as errors from 'vs/base/common/errors'; -import { Disposable, IDisposable, dispose, toDisposable, MutableDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, dispose, toDisposable, MutableDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; import { FileChangeType, FileChangesEvent, IFileService, whenProviderRegistered, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { ConfigurationModel, ConfigurationModelParser, UserSettings } from 'vs/platform/configuration/common/configurationModels'; @@ -397,8 +397,8 @@ export class WorkspaceConfiguration extends Disposable { private readonly _fileService: IFileService; private readonly _cachedConfiguration: CachedWorkspaceConfiguration; - private _workspaceConfiguration: IWorkspaceConfiguration; - private _workspaceConfigurationChangeDisposable: IDisposable = Disposable.None; + private _workspaceConfiguration: CachedWorkspaceConfiguration | FileServiceBasedWorkspaceConfiguration; + private _workspaceConfigurationDisposables = this._register(new DisposableStore()); private _workspaceIdentifier: IWorkspaceIdentifier | null = null; private readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); @@ -415,11 +415,6 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfiguration = this._cachedConfiguration = new CachedWorkspaceConfiguration(configurationCache); } - dispose() { - super.dispose(); - this._workspaceConfiguration.dispose(); - } - async initialize(workspaceIdentifier: IWorkspaceIdentifier): Promise { this._workspaceIdentifier = workspaceIdentifier; if (!this._initialized) { @@ -471,10 +466,9 @@ export class WorkspaceConfiguration extends Disposable { } private doInitialize(fileServiceBasedWorkspaceConfiguration: FileServiceBasedWorkspaceConfiguration): void { - this._workspaceConfiguration.dispose(); - this._workspaceConfigurationChangeDisposable.dispose(); - this._workspaceConfiguration = this._register(fileServiceBasedWorkspaceConfiguration); - this._workspaceConfigurationChangeDisposable = this._register(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange(true))); + this._workspaceConfigurationDisposables.clear(); + this._workspaceConfiguration = this._workspaceConfigurationDisposables.add(fileServiceBasedWorkspaceConfiguration); + this._workspaceConfigurationDisposables.add(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange(true))); this._initialized = true; } @@ -495,19 +489,7 @@ export class WorkspaceConfiguration extends Disposable { } } -interface IWorkspaceConfiguration extends IDisposable { - readonly onDidChange: Event; - workspaceConfigurationModelParser: WorkspaceConfigurationModelParser; - workspaceSettings: ConfigurationModel; - workspaceIdentifier: IWorkspaceIdentifier | null; - load(workspaceIdentifier: IWorkspaceIdentifier): Promise; - getConfigurationModel(): ConfigurationModel; - getFolders(): IStoredWorkspaceFolder[]; - getWorkspaceSettings(): ConfigurationModel; - reprocessWorkspaceSettings(): ConfigurationModel; -} - -class FileServiceBasedWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration { +class FileServiceBasedWorkspaceConfiguration extends Disposable { workspaceConfigurationModelParser: WorkspaceConfigurationModelParser; workspaceSettings: ConfigurationModel; @@ -591,16 +573,14 @@ class FileServiceBasedWorkspaceConfiguration extends Disposable implements IWork } } -class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration { +class CachedWorkspaceConfiguration { - private readonly _onDidChange: Emitter = this._register(new Emitter()); - readonly onDidChange: Event = this._onDidChange.event; + readonly onDidChange: Event = Event.None; workspaceConfigurationModelParser: WorkspaceConfigurationModelParser; workspaceSettings: ConfigurationModel; constructor(private readonly configurationCache: IConfigurationCache) { - super(); this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(''); this.workspaceSettings = new ConfigurationModel(); } @@ -656,16 +636,9 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi } } -export interface IFolderConfiguration extends IDisposable { - readonly onDidChange: Event; - loadConfiguration(): Promise; - reprocess(): ConfigurationModel; -} +class CachedFolderConfiguration { -class CachedFolderConfiguration extends Disposable implements IFolderConfiguration { - - private readonly _onDidChange: Emitter = this._register(new Emitter()); - readonly onDidChange: Event = this._onDidChange.event; + readonly onDidChange = Event.None; private configurationModel: ConfigurationModel; private readonly key: ConfigurationKey; @@ -675,7 +648,6 @@ class CachedFolderConfiguration extends Disposable implements IFolderConfigurati configFolderRelativePath: string, private readonly configurationCache: IConfigurationCache ) { - super(); this.key = { type: 'folder', key: hash(join(folder.path, configFolderRelativePath)).toString(16) }; this.configurationModel = new ConfigurationModel(); } @@ -707,12 +679,12 @@ class CachedFolderConfiguration extends Disposable implements IFolderConfigurati } } -export class FolderConfiguration extends Disposable implements IFolderConfiguration { +export class FolderConfiguration extends Disposable { protected readonly _onDidChange: Emitter = this._register(new Emitter()); readonly onDidChange: Event = this._onDidChange.event; - private folderConfiguration: IFolderConfiguration; + private folderConfiguration: CachedFolderConfiguration | FileServiceBasedConfiguration; private readonly configurationFolder: URI; private cachedFolderConfiguration: CachedFolderConfiguration; @@ -732,13 +704,11 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat this.folderConfiguration = this.cachedFolderConfiguration; whenProviderRegistered(workspaceFolder.uri, fileService) .then(() => { - this.folderConfiguration.dispose(); this.folderConfiguration = this._register(this.createFileServiceBasedConfiguration(fileService, uriIdentityService)); this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); this.onDidFolderConfigurationChange(); }); } else { - this._register(this.cachedFolderConfiguration); this.folderConfiguration = this._register(this.createFileServiceBasedConfiguration(fileService, uriIdentityService)); this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); } From d541d7c64c67ce9497285c4ba2d78b7dee219e0c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 11 Jan 2021 11:59:03 +0100 Subject: [PATCH 1776/1837] make SubmenuAction strict: don't allow changing its properties, make it not disposable --- src/vs/base/common/actions.ts | 30 +++++++++++++++---- src/vs/workbench/browser/menuActions.ts | 2 +- .../browser/parts/views/viewPaneContainer.ts | 2 +- .../contrib/scm/browser/scmViewPane.ts | 12 ++++++-- .../electron-sandbox/contextmenuService.ts | 2 +- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 8be6f19aff5..1f24e8e86a2 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -246,15 +246,35 @@ export class ActionWithMenuAction extends Action { } } -export class SubmenuAction extends Action { +export class SubmenuAction implements IAction { - get actions(): IAction[] { + readonly id: string; + readonly label: string; + readonly class: string | undefined; + readonly tooltip: string = ''; + readonly enabled: boolean = true; + readonly checked: boolean = false; + + private readonly _actions: readonly IAction[]; + + constructor(id: string, label: string, actions: readonly IAction[], cssClass?: string) { + this.id = id; + this.label = label; + this.class = cssClass; + this._actions = actions; + } + + dispose(): void { + // there is NOTHING to dispose and the SubmenuAction should + // never have anything to dispose as it is a convenience type + // to bridge into the rendering world. + } + + get actions(): readonly IAction[] { return this._actions; } - constructor(id: string, label: string, private _actions: IAction[], cssClass?: string) { - super(id, label, cssClass, !!_actions?.length); - } + async run(): Promise { } } export class EmptySubmenuAction extends Action { diff --git a/src/vs/workbench/browser/menuActions.ts b/src/vs/workbench/browser/menuActions.ts index ca3cc34b085..2097915143f 100644 --- a/src/vs/workbench/browser/menuActions.ts +++ b/src/vs/workbench/browser/menuActions.ts @@ -46,7 +46,7 @@ class MenuActions extends Disposable { this._onDidChange.fire(); } - private updateSubmenus(actions: IAction[], submenus: { [id: number]: IMenu }): IDisposable { + private updateSubmenus(actions: readonly IAction[], submenus: { [id: number]: IMenu }): IDisposable { const disposables = new DisposableStore(); for (const action of actions) { if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index de6f5ea47b5..f8a3e56dc00 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -599,7 +599,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { menuActions = [menuActions[index], ...menuActions.slice(0, index), ...menuActions.slice(index + 1)]; } if (menuActions.length === 1 && viewPaneContainerActions.length === 0) { - menuActions = (menuActions[0]).actions; + menuActions = (menuActions[0]).actions.slice(); } } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index c23ca4e9fd3..1e6fe4f9435 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1091,7 +1091,7 @@ class ViewModel { } if (this.alwaysShowRepositories || this.scmViewService.visibleRepositories.length !== 1) { - return this.viewSubMenuAction.actions; + return this.viewSubMenuAction.actions.slice(0); } const menus = this.scmViewService.menus.getRepositoryMenus(this.scmViewService.visibleRepositories[0].provider); @@ -1170,7 +1170,9 @@ class SCMViewRepositoriesSubMenuAction extends SubmenuAction { } } -class SCMViewSubMenuAction extends SubmenuAction { +class SCMViewSubMenuAction extends SubmenuAction implements IDisposable { + + private disposable: IDisposable; constructor( viewModel: ViewModel, @@ -1195,7 +1197,11 @@ class SCMViewSubMenuAction extends SubmenuAction { actions ); - this._register(combinedDisposable(listAction, treeAction, sortByNameAction, sortByPathAction, sortByStatusAction)); + this.disposable = combinedDisposable(listAction, treeAction, sortByNameAction, sortByPathAction, sortByStatusAction); + } + + dispose(): void { + this.disposable.dispose(); } } diff --git a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts index 6df1236ff4c..09ea04d89b6 100644 --- a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts +++ b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts @@ -118,7 +118,7 @@ class NativeContextMenuService extends Disposable implements IContextMenuService } } - private createMenu(delegate: IContextMenuDelegate, entries: IAction[], onHide: () => void, submenuIds = new Set()): IContextMenuItem[] { + private createMenu(delegate: IContextMenuDelegate, entries: readonly IAction[], onHide: () => void, submenuIds = new Set()): IContextMenuItem[] { const actionRunner = delegate.actionRunner || new ActionRunner(); return coalesce(entries.map(entry => this.createMenuItem(delegate, entry, actionRunner, onHide, submenuIds))); } From d1cfec444729a9a2c924aab06e5084b5536cccdf Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 12:19:58 +0100 Subject: [PATCH 1777/1837] :lipstick: --- .../preferences/browser/keybindingsEditor.ts | 22 +++++++++---------- .../preferences/common/preferences.ts | 5 +---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index c68ddbf3a88..04fd316a869 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -46,7 +46,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { Color, RGBA } from 'vs/base/common/color'; import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; -import { IKeybindingItemEntry, IKeybindingsEditorPane, IListEntry } from 'vs/workbench/services/preferences/common/preferences'; +import { IKeybindingItemEntry, IKeybindingsEditorPane } from 'vs/workbench/services/preferences/common/preferences'; import { keybindingsRecordKeysIcon, keybindingsSortIcon, keybindingsAddIcon, preferencesClearInputIcon, keybindingsEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; const $ = DOM.$; @@ -96,8 +96,8 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP private columnItems: ColumnItem[] = []; private keybindingsListContainer!: HTMLElement; private unAssignedKeybindingItemToRevealAndFocus: IKeybindingItemEntry | null = null; - private listEntries: IListEntry[] = []; - private keybindingsList!: WorkbenchList; + private listEntries: IKeybindingItemEntry[] = []; + private keybindingsList!: WorkbenchList; private dimension: DOM.Dimension | null = null; private delayedFiltering: Delayer; @@ -479,7 +479,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP private createList(parent: HTMLElement): void { this.keybindingsListContainer = DOM.append(parent, $('.keybindings-list-container')); this.keybindingsList = this._register(this.instantiationService.createInstance(WorkbenchList, 'KeybindingsEditor', this.keybindingsListContainer, new Delegate(), [new KeybindingItemRenderer(this, this.instantiationService)], { - identityProvider: { getId: (e: IListEntry) => e.id }, + identityProvider: { getId: (e: IKeybindingItemEntry) => e.id }, setRowLineHeight: false, horizontalScrolling: false, accessibilityProvider: new AccessibilityProvider(), @@ -487,7 +487,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP overrideStyles: { listBackground: editorBackground } - })) as WorkbenchList; + })) as WorkbenchList; this._register(this.keybindingsList.onContextMenu(e => this.onContextMenu(e))); this._register(this.keybindingsList.onDidChangeFocus(e => this.onFocusChange(e))); @@ -620,7 +620,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP this.keybindingsList.layout(listHeight); } - private getIndexOf(listEntry: IListEntry): number { + private getIndexOf(listEntry: IKeybindingItemEntry): number { const index = this.listEntries.indexOf(listEntry); if (index === -1) { for (let i = 0; i < this.listEntries.length; i++) { @@ -674,7 +674,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP this.sortByPrecedenceAction.checked = !this.sortByPrecedenceAction.checked; } - private onContextMenu(e: IListContextMenuEvent): void { + private onContextMenu(e: IListContextMenuEvent): void { if (!e.element) { return; } @@ -702,7 +702,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP } } - private onFocusChange(e: IListEvent): void { + private onFocusChange(e: IListEvent): void { this.keybindingFocusContextKey.reset(); const element = e.elements[0]; if (!element) { @@ -821,9 +821,9 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP } } -class Delegate implements IListVirtualDelegate { +class Delegate implements IListVirtualDelegate { - getHeight(element: IListEntry) { + getHeight(element: IKeybindingItemEntry) { if (element.templateId === KEYBINDING_ENTRY_TEMPLATE_ID) { const commandIdMatched = (element).keybindingItem.commandLabel && (element).commandIdMatches; const commandDefaultLabelMatched = !!(element).commandDefaultLabelMatches; @@ -837,7 +837,7 @@ class Delegate implements IListVirtualDelegate { return 24; } - getTemplateId(element: IListEntry) { + getTemplateId(element: IKeybindingItemEntry) { return element.templateId; } } diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index eb3ef84b4bc..2e95478161d 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -256,12 +256,9 @@ export interface KeybindingMatches { chordPart: KeybindingMatch; } -export interface IListEntry { +export interface IKeybindingItemEntry { id: string; templateId: string; -} - -export interface IKeybindingItemEntry extends IListEntry { keybindingItem: IKeybindingItem; commandIdMatches?: IMatch[]; commandLabelMatches?: IMatch[]; From acb0a35629d1006f5517bb9c78d56aa68202479b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 12:47:35 +0100 Subject: [PATCH 1778/1837] cache icon paths in web --- .../browser/parts/activitybar/activitybarPart.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 9a5f0d6da3f..3bbcf02b856 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -28,12 +28,11 @@ import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/commo import { assertIsDefined } from 'vs/base/common/types'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; -import { isWeb } from 'vs/base/common/platform'; +import { isNative, isWeb } from 'vs/base/common/platform'; import { Before2D } from 'vs/workbench/browser/dnd'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { Action, Separator } from 'vs/base/common/actions'; @@ -134,7 +133,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { for (const cachedViewContainer of this.cachedViewContainers) { if ( - environmentService.remoteAuthority || // In remote window, hide activity bar entries until registered + (environmentService.remoteAuthority && isNative) || // Hide activity bar entries until registered in desktop with remote connection this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) ) { cachedViewContainer.visible = false; @@ -729,14 +728,15 @@ export class ActivitybarPart extends Part implements IActivityBarService { let iconUrl: URI | undefined = undefined; if (URI.isUri(icon)) { iconUrl = icon; + const cssUrl = asCSSUrl(icon); const hash = new StringSHA1(); - hash.update(icon.toString()); + hash.update(cssUrl); cssClass = `activity-${id.replace(/\./g, '-')}-${hash.digest()}`; const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`; createCSSRule(iconClass, ` - mask: ${asCSSUrl(icon)} no-repeat 50% 50%; + mask: ${cssUrl} no-repeat 50% 50%; mask-size: 24px; - -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; + -webkit-mask: ${cssUrl} no-repeat 50% 50%; -webkit-mask-size: 24px; `); } else if (ThemeIcon.isThemeIcon(icon)) { @@ -925,11 +925,10 @@ export class ActivitybarPart extends Part implements IActivityBarService { for (const { when } of viewContainerModel.allViewDescriptors) { views.push({ when: when ? when.serialize() : undefined }); } - const cacheIcon = URI.isUri(viewContainerModel.icon) ? viewContainerModel.icon.scheme === Schemas.file : true; state.push({ id: compositeItem.id, name: viewContainerModel.title, - icon: cacheIcon ? viewContainerModel.icon : undefined, + icon: this.environmentService.remoteAuthority && isNative ? undefined : viewContainerModel.icon, /* Donot cache icon in desktop with remote connection */ views, pinned: compositeItem.pinned, order: compositeItem.order, From 5755d943ca642efb87fb4e4d472ce1b14d1298d0 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 13:18:55 +0100 Subject: [PATCH 1779/1837] Tests must be compiled even when `yarn` is executed --- build/azure-pipelines/darwin/product-build-darwin.yml | 4 ++-- build/azure-pipelines/linux/product-build-linux.yml | 2 +- build/azure-pipelines/win32/product-build-win32.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 6113eecf0a1..0ed02043210 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -171,7 +171,7 @@ steps: set -e yarn --cwd test/integration/browser compile displayName: Compile integration tests - condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | # Figure out the full absolute path of the product we just built @@ -210,7 +210,7 @@ steps: set -e yarn --cwd test/smoke compile displayName: Compile smoke tests - condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 21a62b4986a..d10924a5546 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -152,7 +152,7 @@ steps: set -e yarn --cwd test/integration/browser compile displayName: Compile integration tests - condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | # Figure out the full absolute path of the product we just built diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index f635e4199fb..f59443d9208 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -155,7 +155,7 @@ steps: $ErrorActionPreference = "Stop" exec { yarn --cwd test/integration/browser compile } displayName: Compile integration tests - condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64')) - powershell: | # Figure out the full absolute path of the product we just built From 088304c996837785780a3025b5d14f2337d66da7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 13:25:53 +0100 Subject: [PATCH 1780/1837] #114144 - Do not cache only uri icon --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 3bbcf02b856..8b32c9a2027 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -133,7 +133,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { for (const cachedViewContainer of this.cachedViewContainers) { if ( - (environmentService.remoteAuthority && isNative) || // Hide activity bar entries until registered in desktop with remote connection + (URI.isUri(cachedViewContainer.icon) && environmentService.remoteAuthority && isNative) || // In desktop with remote connection, hide activity bar entries with uri icons until registered. this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) ) { cachedViewContainer.visible = false; @@ -928,7 +928,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { state.push({ id: compositeItem.id, name: viewContainerModel.title, - icon: this.environmentService.remoteAuthority && isNative ? undefined : viewContainerModel.icon, /* Donot cache icon in desktop with remote connection */ + icon: URI.isUri(viewContainerModel.icon) && this.environmentService.remoteAuthority && isNative ? undefined : viewContainerModel.icon, /* Donot cache uri icons in desktop with remote connection */ views, pinned: compositeItem.pinned, order: compositeItem.order, From c173fb7d72a648cdd81dd44039293c8b9a181162 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 13:28:51 +0100 Subject: [PATCH 1781/1837] #114144 revert showing cached theme icons --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 8b32c9a2027..38033874552 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -133,7 +133,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { for (const cachedViewContainer of this.cachedViewContainers) { if ( - (URI.isUri(cachedViewContainer.icon) && environmentService.remoteAuthority && isNative) || // In desktop with remote connection, hide activity bar entries with uri icons until registered. + (environmentService.remoteAuthority && isNative) || // In desktop with remote connection, hide activity bar entries until registered. this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) ) { cachedViewContainer.visible = false; From ea7b8ddda3ec6d7f0726a98f0ee1da60e8de78e0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 14:57:28 +0100 Subject: [PATCH 1782/1837] Can't open, rename or delete files that contains ":" on linux (fix microsoft/vscode-remote-release#4227) --- src/vs/base/common/labels.ts | 12 +++++++++--- src/vs/base/test/common/labels.test.ts | 1 + src/vs/platform/files/common/fileService.ts | 3 +-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 5c1aac3bc71..3d96a0cec19 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -84,15 +84,21 @@ export function getBaseLabel(resource: URI | string | undefined): string | undef const base = basename(resource) || (resource.scheme === Schemas.file ? resource.fsPath : resource.path) /* can be empty string if '/' is passed in */; // convert c: => C: - if (hasDriveLetter(base)) { + if (isDriveLetter(base)) { return normalizeDriveLetter(base); } return base; } +const WINDOWS_DRIVE_LETTER_SEP = ':'; + function hasDriveLetter(path: string): boolean { - return !!(isWindows && path && path[1] === ':'); + return !!(isWindows && path && path[1] === WINDOWS_DRIVE_LETTER_SEP); +} + +function isDriveLetter(path: string): boolean { + return hasDriveLetter(path) && path.endsWith(WINDOWS_DRIVE_LETTER_SEP); } export function extractDriveLetter(path: string): string | undefined { @@ -225,7 +231,7 @@ export function shorten(paths: string[], pathSeparator: string = sep): string[] let result = ''; // preserve disk drive or root prefix - if (segments[0].endsWith(':') || prefix !== '') { + if (segments[0].endsWith(WINDOWS_DRIVE_LETTER_SEP) || prefix !== '') { if (start === 1) { // extend subpath to include disk drive prefix start = 0; diff --git a/src/vs/base/test/common/labels.test.ts b/src/vs/base/test/common/labels.test.ts index daba968f26f..27f0daab328 100644 --- a/src/vs/base/test/common/labels.test.ts +++ b/src/vs/base/test/common/labels.test.ts @@ -145,6 +145,7 @@ suite('Labels', () => { assert.equal(labels.getBaseLabel('c:\\'), 'C:'); assert.equal(labels.getBaseLabel('c:\\some\\folder\\file.txt'), 'file.txt'); assert.equal(labels.getBaseLabel('c:\\some\\folder'), 'folder'); + assert.equal(labels.getBaseLabel('c:\\some\\f:older'), 'f:older'); // https://github.com/microsoft/vscode-remote-release/issues/4227 }); test('mnemonicButtonLabel', () => { diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index a15a789cb53..b500e925155 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -11,7 +11,6 @@ import { isAbsolutePath, dirname, basename, joinPath, IExtUri, extUri, extUriIgn import { localize } from 'vs/nls'; import { TernarySearchTree } from 'vs/base/common/map'; import { isNonEmptyArray, coalesce } from 'vs/base/common/arrays'; -import { getBaseLabel } from 'vs/base/common/labels'; import { ILogService } from 'vs/platform/log/common/log'; import { VSBuffer, VSBufferReadable, readableToBuffer, bufferToReadable, streamToBuffer, bufferToStream, VSBufferReadableStream, VSBufferReadableBufferedStream, bufferedStreamToBuffer, newWriteableBufferStream } from 'vs/base/common/buffer'; import { isReadableStream, transform, peekReadable, peekStream, isReadableBufferedStream } from 'vs/base/common/stream'; @@ -225,7 +224,7 @@ export class FileService extends Disposable implements IFileService { // convert to file stat const fileStat: IFileStat = { resource, - name: getBaseLabel(resource), + name: basename(resource), isFile: (stat.type & FileType.File) !== 0, isDirectory: (stat.type & FileType.Directory) !== 0, isSymbolicLink: (stat.type & FileType.SymbolicLink) !== 0, From 55bd92dd5389b1cc5d54c4f2d2943441df6855fa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 15:23:09 +0100 Subject: [PATCH 1783/1837] tests - extpath tasks are flaky --- src/vs/base/test/node/extpath.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts index 39c409b4c6b..53fec2ca18d 100644 --- a/src/vs/base/test/node/extpath.test.ts +++ b/src/vs/base/test/node/extpath.test.ts @@ -8,9 +8,9 @@ import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as pfs from 'vs/base/node/pfs'; import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath'; -import { getRandomTestPath } from 'vs/base/test/node/testUtils'; +import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; -suite('Extpath', () => { +flakySuite('Extpath', () => { test('realcase', async () => { const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); From 8ec95fa3b7a928a5d873ea4247b937cdc917045e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 15:28:18 +0100 Subject: [PATCH 1784/1837] tests - improve ext path tests --- src/vs/base/test/node/extpath.test.ts | 49 +++++++++++---------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts index 53fec2ca18d..4c9c396f28b 100644 --- a/src/vs/base/test/node/extpath.test.ts +++ b/src/vs/base/test/node/extpath.test.ts @@ -5,66 +5,55 @@ import * as assert from 'assert'; import * as os from 'os'; -import * as path from 'vs/base/common/path'; import * as pfs from 'vs/base/node/pfs'; import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; flakySuite('Extpath', () => { + let testDir: string; + + setup(() => { + testDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); + + return pfs.mkdirp(testDir, 493); + }); + + teardown(() => { + return pfs.rimraf(testDir); + }); test('realcase', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); - const newDir = path.join(parentDir, 'newdir'); - - await pfs.mkdirp(newDir, 493); // assume case insensitive file system if (process.platform === 'win32' || process.platform === 'darwin') { - const upper = newDir.toUpperCase(); + const upper = testDir.toUpperCase(); const real = realcaseSync(upper); if (real) { // can be null in case of permission errors assert.notEqual(real, upper); assert.equal(real.toUpperCase(), upper); - assert.equal(real, newDir); + assert.equal(real, testDir); } } // linux, unix, etc. -> assume case sensitive file system else { - const real = realcaseSync(newDir); - assert.equal(real, newDir); + const real = realcaseSync(testDir); + assert.equal(real, testDir); } - - await pfs.rimraf(parentDir); }); test('realpath', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); - const newDir = path.join(parentDir, 'newdir'); - - await pfs.mkdirp(newDir, 493); - - const realpathVal = await realpath(newDir); + const realpathVal = await realpath(testDir); assert.ok(realpathVal); - - await pfs.rimraf(parentDir); }); test('realpathSync', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); - const newDir = path.join(parentDir, 'newdir'); - - await pfs.mkdirp(newDir, 493); - - let realpath!: string; try { - realpath = realpathSync(newDir); + const realpath = realpathSync(testDir); + assert.ok(realpath); } catch (error) { - assert.ok(!error); + assert.fail(error); } - assert.ok(realpath!); - - await pfs.rimraf(parentDir); }); }); From 533d094020fe1cafff0fcf82183197cfd6efb2da Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 15:32:24 +0100 Subject: [PATCH 1785/1837] Allow logging FS access with stacks --- test/unit/electron/renderer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/electron/renderer.js b/test/unit/electron/renderer.js index dff47ec61c6..b67ff471e42 100644 --- a/test/unit/electron/renderer.js +++ b/test/unit/electron/renderer.js @@ -11,9 +11,9 @@ let logging = false; let withStacks = false; - self.beginLoggingFS = (withStacks) => { + self.beginLoggingFS = (_withStacks) => { logging = true; - withStacks = withStacks || false; + withStacks = _withStacks || false; }; self.endLoggingFS = () => { logging = false; From 64947067ab73593a62c4daff10bf1db8e451c068 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 16:08:22 +0100 Subject: [PATCH 1786/1837] :lipstick: unit tests --- src/vs/base/test/node/crypto.test.ts | 17 +- src/vs/base/test/node/decoder.test.ts | 6 +- src/vs/base/test/node/extpath.test.ts | 10 +- src/vs/base/test/node/pfs/pfs.test.ts | 400 +++++++++--------- src/vs/base/test/node/zip/zip.test.ts | 28 +- src/vs/platform/state/test/node/state.test.ts | 23 +- .../storage/test/node/storageService.test.ts | 18 +- 7 files changed, 266 insertions(+), 236 deletions(-) diff --git a/src/vs/base/test/node/crypto.test.ts b/src/vs/base/test/node/crypto.test.ts index e32be0406a2..16cfc58fe26 100644 --- a/src/vs/base/test/node/crypto.test.ts +++ b/src/vs/base/test/node/crypto.test.ts @@ -11,15 +11,22 @@ import { getRandomTestPath } from 'vs/base/test/node/testUtils'; suite('Crypto', () => { - test('checksum', async () => { - const testDir = getRandomTestPath(tmpdir(), 'vsctests', 'crypto'); - await mkdirp(testDir); + let testDir: string; + setup(function () { + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'crypto'); + + return mkdirp(testDir); + }); + + teardown(function () { + return rimraf(testDir); + }); + + test('checksum', async () => { const testFile = join(testDir, 'checksum.txt'); await writeFile(testFile, 'Hello World'); await checksum(testFile, '0a4d55a8d778e5022fab701977c5d840bbc486d0'); - - await rimraf(testDir); }); }); diff --git a/src/vs/base/test/node/decoder.test.ts b/src/vs/base/test/node/decoder.test.ts index f4d34d02f9e..199cef9a7bf 100644 --- a/src/vs/base/test/node/decoder.test.ts +++ b/src/vs/base/test/node/decoder.test.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as decoder from 'vs/base/node/decoder'; +import { LineDecoder } from 'vs/base/node/decoder'; suite('Decoder', () => { test('decoding', () => { - const lineDecoder = new decoder.LineDecoder(); + const lineDecoder = new LineDecoder(); let res = lineDecoder.write(Buffer.from('hello')); assert.equal(res.length, 0); @@ -19,4 +19,4 @@ suite('Decoder', () => { assert.equal(lineDecoder.end(), 'world'); }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts index 4c9c396f28b..0ed8864d88d 100644 --- a/src/vs/base/test/node/extpath.test.ts +++ b/src/vs/base/test/node/extpath.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as os from 'os'; -import * as pfs from 'vs/base/node/pfs'; +import { tmpdir } from 'os'; +import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; @@ -13,13 +13,13 @@ flakySuite('Extpath', () => { let testDir: string; setup(() => { - testDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extpath'); + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'extpath'); - return pfs.mkdirp(testDir, 493); + return mkdirp(testDir, 493); }); teardown(() => { - return pfs.rimraf(testDir); + return rimraf(testDir); }); test('realcase', async () => { diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 86cb0be8f85..eda206ac2d9 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as os from 'os'; -import * as path from 'vs/base/common/path'; import * as fs from 'fs'; -import * as uuid from 'vs/base/common/uuid'; -import * as pfs from 'vs/base/node/pfs'; +import { tmpdir } from 'os'; +import { join, sep } from 'vs/base/common/path'; +import { generateUuid } from 'vs/base/common/uuid'; +import { copy, mkdirp, move, readdir, readDirsInDir, readdirWithFileTypes, renameIgnoreError, rimraf, RimRafMode, rimrafSync, statLink, writeFile, writeFileSync } from 'vs/base/node/pfs'; import { timeout } from 'vs/base/common/async'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { isWindows } from 'vs/base/common/platform'; @@ -19,39 +19,39 @@ import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; flakySuite('PFS', function () { test('writeFile', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'writefile.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile = join(newDir, 'writefile.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); - await pfs.writeFile(testFile, 'Hello World', (null!)); + await writeFile(testFile, 'Hello World', (null!)); assert.equal(fs.readFileSync(testFile), 'Hello World'); - await pfs.rimraf(parentDir); + await rimraf(parentDir); }); test('writeFile - parallel write on different files works', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile1 = path.join(newDir, 'writefile1.txt'); - const testFile2 = path.join(newDir, 'writefile2.txt'); - const testFile3 = path.join(newDir, 'writefile3.txt'); - const testFile4 = path.join(newDir, 'writefile4.txt'); - const testFile5 = path.join(newDir, 'writefile5.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile1 = join(newDir, 'writefile1.txt'); + const testFile2 = join(newDir, 'writefile2.txt'); + const testFile3 = join(newDir, 'writefile3.txt'); + const testFile4 = join(newDir, 'writefile4.txt'); + const testFile5 = join(newDir, 'writefile5.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); await Promise.all([ - pfs.writeFile(testFile1, 'Hello World 1', (null!)), - pfs.writeFile(testFile2, 'Hello World 2', (null!)), - pfs.writeFile(testFile3, 'Hello World 3', (null!)), - pfs.writeFile(testFile4, 'Hello World 4', (null!)), - pfs.writeFile(testFile5, 'Hello World 5', (null!)) + writeFile(testFile1, 'Hello World 1', (null!)), + writeFile(testFile2, 'Hello World 2', (null!)), + writeFile(testFile3, 'Hello World 3', (null!)), + writeFile(testFile4, 'Hello World 4', (null!)), + writeFile(testFile5, 'Hello World 5', (null!)) ]); assert.equal(fs.readFileSync(testFile1), 'Hello World 1'); assert.equal(fs.readFileSync(testFile2), 'Hello World 2'); @@ -59,163 +59,163 @@ flakySuite('PFS', function () { assert.equal(fs.readFileSync(testFile4), 'Hello World 4'); assert.equal(fs.readFileSync(testFile5), 'Hello World 5'); - await pfs.rimraf(parentDir); + await rimraf(parentDir); }); test('writeFile - parallel write on same files works and is sequentalized', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'writefile.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile = join(newDir, 'writefile.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); await Promise.all([ - pfs.writeFile(testFile, 'Hello World 1', undefined), - pfs.writeFile(testFile, 'Hello World 2', undefined), - timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', undefined)), - pfs.writeFile(testFile, 'Hello World 4', undefined), - timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', undefined)) + writeFile(testFile, 'Hello World 1', undefined), + writeFile(testFile, 'Hello World 2', undefined), + timeout(10).then(() => writeFile(testFile, 'Hello World 3', undefined)), + writeFile(testFile, 'Hello World 4', undefined), + timeout(10).then(() => writeFile(testFile, 'Hello World 5', undefined)) ]); assert.equal(fs.readFileSync(testFile), 'Hello World 5'); - await pfs.rimraf(parentDir); + await rimraf(parentDir); }); test('rimraf - simple - unlink', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - await pfs.rimraf(newDir); + await rimraf(newDir); assert.ok(!fs.existsSync(newDir)); }); test('rimraf - simple - move', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + await rimraf(newDir, RimRafMode.MOVE); assert.ok(!fs.existsSync(newDir)); }); test('rimraf - recursive folder structure - unlink', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - fs.mkdirSync(path.join(newDir, 'somefolder')); - fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.mkdirSync(join(newDir, 'somefolder')); + fs.writeFileSync(join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - await pfs.rimraf(newDir); + await rimraf(newDir); assert.ok(!fs.existsSync(newDir)); }); test('rimraf - recursive folder structure - move', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - fs.mkdirSync(path.join(newDir, 'somefolder')); - fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.mkdirSync(join(newDir, 'somefolder')); + fs.writeFileSync(join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + await rimraf(newDir, RimRafMode.MOVE); assert.ok(!fs.existsSync(newDir)); }); test('rimraf - simple ends with dot - move', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = `${uuid.generateUuid()}.`; - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = `${generateUuid()}.`; + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + await rimraf(newDir, RimRafMode.MOVE); assert.ok(!fs.existsSync(newDir)); }); test('rimraf - simple ends with dot slash/backslash - move', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = `${uuid.generateUuid()}.`; - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = `${generateUuid()}.`; + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - await pfs.rimraf(`${newDir}${path.sep}`, pfs.RimRafMode.MOVE); + await rimraf(`${newDir}${sep}`, RimRafMode.MOVE); assert.ok(!fs.existsSync(newDir)); }); test('rimrafSync - swallows file not found error', function () { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - pfs.rimrafSync(newDir); + rimrafSync(newDir); assert.ok(!fs.existsSync(newDir)); }); test('rimrafSync - simple', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - pfs.rimrafSync(newDir); + rimrafSync(newDir); assert.ok(!fs.existsSync(newDir)); }); test('rimrafSync - recursive folder structure', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + await mkdirp(newDir, 493); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - fs.mkdirSync(path.join(newDir, 'somefolder')); - fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + fs.mkdirSync(join(newDir, 'somefolder')); + fs.writeFileSync(join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - pfs.rimrafSync(newDir); + rimrafSync(newDir); assert.ok(!fs.existsSync(newDir)); }); test('moveIgnoreError', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); try { - await pfs.renameIgnoreError(path.join(newDir, 'foo'), path.join(newDir, 'bar')); - return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + await renameIgnoreError(join(newDir, 'foo'), join(newDir, 'bar')); + return rimraf(parentDir, RimRafMode.MOVE); } catch (error) { assert.fail(error); @@ -223,148 +223,148 @@ flakySuite('PFS', function () { }); test('copy, move and delete', async () => { - const id = uuid.generateUuid(); - const id2 = uuid.generateUuid(); + const id = generateUuid(); + const id2 = generateUuid(); const sourceDir = getPathFromAmdModule(require, './fixtures'); - const parentDir = path.join(os.tmpdir(), 'vsctests', 'pfs'); - const targetDir = path.join(parentDir, id); - const targetDir2 = path.join(parentDir, id2); + const parentDir = join(tmpdir(), 'vsctests', 'pfs'); + const targetDir = join(parentDir, id); + const targetDir2 = join(parentDir, id2); - await pfs.copy(sourceDir, targetDir); + await copy(sourceDir, targetDir); assert.ok(fs.existsSync(targetDir)); - assert.ok(fs.existsSync(path.join(targetDir, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir, 'site.css'))); - assert.ok(fs.existsSync(path.join(targetDir, 'examples'))); - assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory()); - assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs'))); + assert.ok(fs.existsSync(join(targetDir, 'index.html'))); + assert.ok(fs.existsSync(join(targetDir, 'site.css'))); + assert.ok(fs.existsSync(join(targetDir, 'examples'))); + assert.ok(fs.statSync(join(targetDir, 'examples')).isDirectory()); + assert.ok(fs.existsSync(join(targetDir, 'examples', 'small.jxs'))); - await pfs.move(targetDir, targetDir2); + await move(targetDir, targetDir2); assert.ok(!fs.existsSync(targetDir)); assert.ok(fs.existsSync(targetDir2)); - assert.ok(fs.existsSync(path.join(targetDir2, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'site.css'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'examples'))); - assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory()); - assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs'))); + assert.ok(fs.existsSync(join(targetDir2, 'index.html'))); + assert.ok(fs.existsSync(join(targetDir2, 'site.css'))); + assert.ok(fs.existsSync(join(targetDir2, 'examples'))); + assert.ok(fs.statSync(join(targetDir2, 'examples')).isDirectory()); + assert.ok(fs.existsSync(join(targetDir2, 'examples', 'small.jxs'))); - await pfs.move(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html')); + await move(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html')); - assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html'))); + assert.ok(!fs.existsSync(join(targetDir2, 'index.html'))); + assert.ok(fs.existsSync(join(targetDir2, 'index_moved.html'))); - await pfs.rimraf(parentDir); + await rimraf(parentDir); assert.ok(!fs.existsSync(parentDir)); }); test('mkdirp', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); - return pfs.rimraf(parentDir); + return rimraf(parentDir); }); test('readDirsInDir', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); - fs.mkdirSync(path.join(newDir, 'somefolder1')); - fs.mkdirSync(path.join(newDir, 'somefolder2')); - fs.mkdirSync(path.join(newDir, 'somefolder3')); - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.mkdirSync(join(newDir, 'somefolder1')); + fs.mkdirSync(join(newDir, 'somefolder2')); + fs.mkdirSync(join(newDir, 'somefolder3')); + fs.writeFileSync(join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(join(newDir, 'someOtherFile.txt'), 'Contents'); - const result = await pfs.readDirsInDir(newDir); + const result = await readDirsInDir(newDir); assert.equal(result.length, 3); assert.ok(result.indexOf('somefolder1') !== -1); assert.ok(result.indexOf('somefolder2') !== -1); assert.ok(result.indexOf('somefolder3') !== -1); - await pfs.rimraf(newDir); + await rimraf(newDir); }); (isWindows ? test.skip : test)('stat link', async () => { // Symlinks are not the same on win, and we can not create them programmatically without admin privileges - const id1 = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id1); - const directory = path.join(parentDir, 'pfs', id1); + const id1 = generateUuid(); + const parentDir = join(tmpdir(), 'vsctests', id1); + const directory = join(parentDir, 'pfs', id1); - const id2 = uuid.generateUuid(); - const symbolicLink = path.join(parentDir, 'pfs', id2); + const id2 = generateUuid(); + const symbolicLink = join(parentDir, 'pfs', id2); - await pfs.mkdirp(directory, 493); + await mkdirp(directory, 493); fs.symlinkSync(directory, symbolicLink); - let statAndIsLink = await pfs.statLink(directory); + let statAndIsLink = await statLink(directory); assert.ok(!statAndIsLink?.symbolicLink); - statAndIsLink = await pfs.statLink(symbolicLink); + statAndIsLink = await statLink(symbolicLink); assert.ok(statAndIsLink?.symbolicLink); assert.ok(!statAndIsLink?.symbolicLink?.dangling); - pfs.rimrafSync(directory); + rimrafSync(directory); }); (isWindows ? test.skip : test)('stat link (non existing target)', async () => { // Symlinks are not the same on win, and we can not create them programmatically without admin privileges - const id1 = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id1); - const directory = path.join(parentDir, 'pfs', id1); + const id1 = generateUuid(); + const parentDir = join(tmpdir(), 'vsctests', id1); + const directory = join(parentDir, 'pfs', id1); - const id2 = uuid.generateUuid(); - const symbolicLink = path.join(parentDir, 'pfs', id2); + const id2 = generateUuid(); + const symbolicLink = join(parentDir, 'pfs', id2); - await pfs.mkdirp(directory, 493); + await mkdirp(directory, 493); fs.symlinkSync(directory, symbolicLink); - pfs.rimrafSync(directory); + rimrafSync(directory); - const statAndIsLink = await pfs.statLink(symbolicLink); + const statAndIsLink = await statLink(symbolicLink); assert.ok(statAndIsLink?.symbolicLink); assert.ok(statAndIsLink?.symbolicLink?.dangling); }); test('readdir', async () => { if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id, 'öäü'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id, 'öäü'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); - const children = await pfs.readdir(path.join(parentDir, 'pfs', id)); + const children = await readdir(join(parentDir, 'pfs', id)); assert.equal(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so - await pfs.rimraf(parentDir); + await rimraf(parentDir); } }); test('readdirWithFileTypes', async () => { if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const testDir = path.join(parentDir, 'pfs', id); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const testDir = join(parentDir, 'pfs', id); - const newDir = path.join(testDir, 'öäü'); - await pfs.mkdirp(newDir, 493); + const newDir = join(testDir, 'öäü'); + await mkdirp(newDir, 493); - await pfs.writeFile(path.join(testDir, 'somefile.txt'), 'contents'); + await writeFile(join(testDir, 'somefile.txt'), 'contents'); assert.ok(fs.existsSync(newDir)); - const children = await pfs.readdirWithFileTypes(testDir); + const children = await readdirWithFileTypes(testDir); assert.equal(children.some(n => n.name === 'öäü'), true); // Mac always converts to NFD, so assert.equal(children.some(n => n.isDirectory()), true); @@ -372,7 +372,7 @@ flakySuite('PFS', function () { assert.equal(children.some(n => n.name === 'somefile.txt'), true); assert.equal(children.some(n => n.isFile()), true); - await pfs.rimraf(parentDir); + await rimraf(parentDir); } }); @@ -403,30 +403,30 @@ flakySuite('PFS', function () { bigData: string | Buffer | Uint8Array, bigDataValue: string ): Promise { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'flushed.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile = join(newDir, 'flushed.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); - await pfs.writeFile(testFile, smallData); + await writeFile(testFile, smallData); assert.equal(fs.readFileSync(testFile), smallDataValue); - await pfs.writeFile(testFile, bigData); + await writeFile(testFile, bigData); assert.equal(fs.readFileSync(testFile), bigDataValue); - await pfs.rimraf(parentDir); + await rimraf(parentDir); } test('writeFile (string, error handling)', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'flushed.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile = join(newDir, 'flushed.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); @@ -434,34 +434,34 @@ flakySuite('PFS', function () { let expectedError: Error | undefined; try { - await pfs.writeFile(testFile, 'Hello World'); + await writeFile(testFile, 'Hello World'); } catch (error) { expectedError = error; } assert.ok(expectedError); - await pfs.rimraf(parentDir); + await rimraf(parentDir); }); test('writeFileSync', async () => { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'pfs'); - const id = uuid.generateUuid(); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'flushed.txt'); + const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'pfs'); + const id = generateUuid(); + const newDir = join(parentDir, 'pfs', id); + const testFile = join(newDir, 'flushed.txt'); - await pfs.mkdirp(newDir, 493); + await mkdirp(newDir, 493); assert.ok(fs.existsSync(newDir)); - pfs.writeFileSync(testFile, 'Hello World'); + writeFileSync(testFile, 'Hello World'); assert.equal(fs.readFileSync(testFile), 'Hello World'); const largeString = (new Array(100 * 1024)).join('Large String\n'); - pfs.writeFileSync(testFile, largeString); + writeFileSync(testFile, largeString); assert.equal(fs.readFileSync(testFile), largeString); - await pfs.rimraf(parentDir); + await rimraf(parentDir); }); }); diff --git a/src/vs/base/test/node/zip/zip.test.ts b/src/vs/base/test/node/zip/zip.test.ts index 9be5ae76acd..a98b2609fbb 100644 --- a/src/vs/base/test/node/zip/zip.test.ts +++ b/src/vs/base/test/node/zip/zip.test.ts @@ -5,25 +5,33 @@ import * as assert from 'assert'; import * as path from 'vs/base/common/path'; -import * as os from 'os'; +import { tmpdir } from 'os'; import { extract } from 'vs/base/node/zip'; -import { generateUuid } from 'vs/base/common/uuid'; -import { rimraf, exists } from 'vs/base/node/pfs'; +import { rimraf, exists, mkdirp } from 'vs/base/node/pfs'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { createCancelablePromise } from 'vs/base/common/async'; - -const fixtures = getPathFromAmdModule(require, './fixtures'); +import { getRandomTestPath } from 'vs/base/test/node/testUtils'; suite('Zip', () => { + let testDir: string; + + setup(() => { + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'zip'); + + return mkdirp(testDir); + }); + + teardown(() => { + return rimraf(testDir); + }); + test('extract should handle directories', async () => { + const fixtures = getPathFromAmdModule(require, './fixtures'); const fixture = path.join(fixtures, 'extract.zip'); - const target = path.join(os.tmpdir(), generateUuid()); - await createCancelablePromise(token => extract(fixture, target, {}, token)); - const doesExist = await exists(path.join(target, 'extension')); + await createCancelablePromise(token => extract(fixture, testDir, {}, token)); + const doesExist = await exists(path.join(testDir, 'extension')); assert(doesExist); - - return rimraf(target); }); }); diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index 7bf641e5f74..3920bd0e78a 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -4,19 +4,28 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as os from 'os'; -import * as path from 'vs/base/common/path'; +import { tmpdir } from 'os'; +import { join } from 'vs/base/common/path'; import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; import { FileStorage } from 'vs/platform/state/node/stateService'; import { mkdirp, rimraf, writeFileSync } from 'vs/base/node/pfs'; flakySuite('StateService', () => { - test('Basics', async function () { - const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice'); - await mkdirp(parentDir); + let testDir: string; - const storageFile = path.join(parentDir, 'storage.json'); + setup(() => { + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'stateservice'); + + return mkdirp(testDir); + }); + + teardown(() => { + return rimraf(testDir); + }); + + test('Basics', async function () { + const storageFile = join(testDir, 'storage.json'); writeFileSync(storageFile, ''); let service = new FileStorage(storageFile, () => null); @@ -43,7 +52,5 @@ flakySuite('StateService', () => { service.setItem('some.null.key', null); assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default'); - - await rimraf(parentDir); }); }); diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index a4e15e0061a..e42901b3f87 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -17,6 +17,18 @@ import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils'; flakySuite('NativeStorageService', function () { + let testDir: string; + + setup(() => { + testDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice'); + + return mkdirp(testDir); + }); + + teardown(() => { + return rimraf(testDir); + }); + test('Migrate Data', async function () { class StorageTestEnvironmentService extends NativeEnvironmentService { @@ -34,10 +46,7 @@ flakySuite('NativeStorageService', function () { } } - const storageDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice'); - await mkdirp(storageDir); - - const storage = new NativeStorageService(new InMemoryStorageDatabase(), new NullLogService(), new StorageTestEnvironmentService(URI.file(storageDir), storageDir)); + const storage = new NativeStorageService(new InMemoryStorageDatabase(), new NullLogService(), new StorageTestEnvironmentService(URI.file(testDir), testDir)); await storage.initialize({ id: String(Date.now()) }); storage.store('bar', 'foo', StorageScope.WORKSPACE, StorageTarget.MACHINE); @@ -55,6 +64,5 @@ flakySuite('NativeStorageService', function () { equal(storage.getBoolean('barBoolean', StorageScope.GLOBAL), true); await storage.close(); - await rimraf(storageDir); }); }); From cba1d1b184883f437cf3777030d4a94ba43b7ee2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 11 Jan 2021 16:11:51 +0100 Subject: [PATCH 1787/1837] Prefix all `performance.mark` calls with `code/` --- src/bootstrap-amd.js | 2 +- src/bootstrap-fork.js | 2 +- .../workbench/api/common/extHostExtensionService.ts | 12 ++++++------ .../api/common/extHostRequireInterceptor.ts | 4 ++-- src/vs/workbench/api/node/extHostExtensionService.ts | 8 ++++---- .../workbench/api/worker/extHostExtensionService.ts | 10 +++++----- .../services/extensions/common/extensionHostMain.ts | 2 +- .../extensions/node/extensionHostProcessSetup.ts | 6 +++--- .../extensions/worker/extensionHostWorker.ts | 4 ++-- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/bootstrap-amd.js b/src/bootstrap-amd.js index d9ca4f690cd..1d8a27120d2 100644 --- a/src/bootstrap-amd.js +++ b/src/bootstrap-amd.js @@ -56,6 +56,6 @@ exports.load = function (entrypoint, onLoad, onError) { onLoad = onLoad || function () { }; onError = onError || function (err) { console.error(err); }; - performance.mark(`fork/willLoadCode`); + performance.mark(`code/fork/willLoadCode`); loader([entrypoint], onLoad, onError); }; diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index 6b24907241c..c211ba13701 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -7,7 +7,7 @@ 'use strict'; const performance = require('./vs/base/common/performance'); -performance.mark('fork/start'); +performance.mark('code/fork/start'); const bootstrap = require('./bootstrap'); const bootstrapNode = require('./bootstrap-node'); diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index f21abf591b5..2274a4f12e7 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -190,7 +190,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme this._almostReadyToRunExtensions.open(); await this._extHostWorkspace.waitForInitializeCall(); - performance.mark('extHost/ready'); + performance.mark('code/extHost/ready'); this._readyToStartExtensionHost.open(); if (this._initData.autoStart) { @@ -372,10 +372,10 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme this._loadCommonJSModule(extensionDescription.identifier, joinPath(extensionDescription.extensionLocation, entryPoint), activationTimesBuilder), this._loadExtensionContext(extensionDescription) ]).then(values => { - performance.mark(`extHost/willActivateExtension/${extensionDescription.identifier.value}`); + performance.mark(`code/extHost/willActivateExtension/${extensionDescription.identifier.value}`); return AbstractExtHostExtensionService._callActivate(this._logService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder); }).then((activatedExtension) => { - performance.mark(`extHost/didActivateExtension/${extensionDescription.identifier.value}`); + performance.mark(`code/extHost/didActivateExtension/${extensionDescription.identifier.value}`); return activatedExtension; }); } @@ -666,9 +666,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } try { - performance.mark(`extHost/willResolveAuthority/${authorityPrefix}`); + performance.mark(`code/extHost/willResolveAuthority/${authorityPrefix}`); const result = await resolver.resolve(remoteAuthority, { resolveAttempt }); - performance.mark(`extHost/didResolveAuthorityOK/${authorityPrefix}`); + performance.mark(`code/extHost/didResolveAuthorityOK/${authorityPrefix}`); this._disposables.add(await this._extHostTunnelService.setTunnelExtensionFunctions(resolver)); // Split merged API result into separate authority/options @@ -691,7 +691,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } }; } catch (err) { - performance.mark(`extHost/didResolveAuthorityError/${authorityPrefix}`); + performance.mark(`code/extHost/didResolveAuthorityError/${authorityPrefix}`); if (err instanceof RemoteAuthorityResolverError) { return { type: 'error', diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index 2446cf89b36..f59d41ce891 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -53,9 +53,9 @@ export abstract class RequireInterceptor { this._installInterceptor(); - performance.mark('extHost/willWaitForConfig'); + performance.mark('code/extHost/willWaitForConfig'); const configProvider = await this._extHostConfiguration.getConfigProvider(); - performance.mark('extHost/didWaitForConfig'); + performance.mark('code/extHost/didWaitForConfig'); const extensionPaths = await this._extHostExtensionService.getExtensionPathIndex(); this.register(new VSCodeNodeModuleFactory(this._apiFactory, extensionPaths, this._extensionRegistry, configProvider, this._logService)); diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 85a05c33032..d9377b68cca 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -63,12 +63,12 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { // Module loading tricks const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, this._registry); await interceptor.install(); - performance.mark('extHost/didInitAPI'); + performance.mark('code/extHost/didInitAPI'); // Do this when extension service exists, but extensions are not being activated yet. const configProvider = await this._extHostConfiguration.getConfigProvider(); await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._logService, this._mainThreadTelemetryProxy, this._initData); - performance.mark('extHost/didInitProxyResolver'); + performance.mark('code/extHost/didInitProxyResolver'); // Use IPC messages to forward console-calls, note that the console is // already patched to use`process.send()` @@ -97,14 +97,14 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { this._logService.flush(); try { if (extensionId) { - performance.mark(`extHost/willLoadExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/willLoadExtensionCode/${extensionId.value}`); } r = require.__$__nodeRequire(module.fsPath); } catch (e) { return Promise.reject(e); } finally { if (extensionId) { - performance.mark(`extHost/didLoadExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/didLoadExtensionCode/${extensionId.value}`); } activationTimesBuilder.codeLoadingStop(); } diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index fb48c617355..6ebbb92e442 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -72,7 +72,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, this._registry); await this._fakeModules.install(); - performance.mark('extHost/didInitAPI'); + performance.mark('code/extHost/didInitAPI'); await this._waitForDebuggerAttachment(); } @@ -85,11 +85,11 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { module = module.with({ path: ensureSuffix(module.path, '.js') }); if (extensionId) { - performance.mark(`extHost/willFetchExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/willFetchExtensionCode/${extensionId.value}`); } const response = await fetch(module.toString(true)); if (extensionId) { - performance.mark(`extHost/didFetchExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/didFetchExtensionCode/${extensionId.value}`); } if (response.status !== 200) { @@ -135,13 +135,13 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { try { activationTimesBuilder.codeLoadingStart(); if (extensionId) { - performance.mark(`extHost/willLoadExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/willLoadExtensionCode/${extensionId.value}`); } initFn(_module, _exports, _require); return (_module.exports !== _exports ? _module.exports : _exports); } finally { if (extensionId) { - performance.mark(`extHost/didLoadExtensionCode/${extensionId.value}`); + performance.mark(`code/extHost/didLoadExtensionCode/${extensionId.value}`); } activationTimesBuilder.codeLoadingStop(); } diff --git a/src/vs/workbench/services/extensions/common/extensionHostMain.ts b/src/vs/workbench/services/extensions/common/extensionHostMain.ts index 1f338fd0142..0cb9763625b 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostMain.ts @@ -68,7 +68,7 @@ export class ExtensionHostMain { this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); - performance.mark(`extHost/didCreateServices`); + performance.mark(`code/extHost/didCreateServices`); this._logService.info('extension host started'); this._logService.trace('initData', initData); diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index c7bad89095f..fe69f179c26 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -309,11 +309,11 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise { - performance.mark(`extHost/willConnectToRenderer`); + performance.mark(`code/extHost/willConnectToRenderer`); const protocol = await createExtHostProtocol(); - performance.mark(`extHost/didConnectToRenderer`); + performance.mark(`code/extHost/didConnectToRenderer`); const renderer = await connectToRenderer(protocol); - performance.mark(`extHost/didWaitForInitData`); + performance.mark(`code/extHost/didWaitForInitData`); const { initData } = renderer; // setup things patchProcess(!!initData.environment.extensionTestsLocationURI); // to support other test frameworks like Jasmin that use process.exit (https://github.com/microsoft/vscode/issues/37708) diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 998c5b87c13..0bb6e4bbe5e 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -152,9 +152,9 @@ let onTerminate = (reason: string) => nativeClose(); (function create(): void { const res = new ExtensionWorker(); - performance.mark(`extHost/willConnectToRenderer`); + performance.mark(`code/extHost/willConnectToRenderer`); connectToRenderer(res.protocol).then(data => { - performance.mark(`extHost/didWaitForInitData`); + performance.mark(`code/extHost/didWaitForInitData`); const extHostMain = new ExtensionHostMain( data.protocol, data.initData, From 7cf2ad082f996f1b8ab703a3a3cc3f783589ff13 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 11 Jan 2021 16:33:19 +0100 Subject: [PATCH 1788/1837] Render remote name when reconnecting --- src/vs/workbench/contrib/remote/browser/remoteIndicator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 5ca8a9942c6..b8d02f59019 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -210,7 +210,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr this.renderRemoteStatusIndicator(nls.localize('host.open', "Opening Remote..."), nls.localize('host.open', "Opening Remote..."), undefined, true /* progress */); break; case 'reconnecting': - this.renderRemoteStatusIndicator(nls.localize('host.reconnecting', "Reconnecting..."), nls.localize('host.reconnecting', "Reconnecting..."), undefined, true /* progress */); + this.renderRemoteStatusIndicator(`${nls.localize('host.reconnecting', "Reconnecting to {0}...", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`, nls.localize('host.tooltipReconnecting', "Reconnecting to {0}...", hostLabel), undefined, true); break; case 'disconnected': this.renderRemoteStatusIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from {0}", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`, nls.localize('host.tooltipDisconnected', "Disconnected from {0}", hostLabel)); From c9bae24fb700c69eed27cde71c059a94fe4b459b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 11 Jan 2021 16:36:21 +0100 Subject: [PATCH 1789/1837] More UX feedback --- src/vs/workbench/contrib/remote/browser/remote.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 74c1544c352..3de5bc2862d 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -794,7 +794,7 @@ class RemoteAgentConnectionStatusListener extends Disposable implements IWorkben } break; case PersistentConnectionEventType.ReconnectionWait: - if (visibleProgress || e.millisSinceLastIncomingData > DISCONNECT_PROMPT_TIME) { + if (visibleProgress) { reconnectWaitEvent = e; visibleProgress = showProgress(null, [reconnectButton, reloadButton]); visibleProgress.startTimer(Date.now() + 1000 * e.durationSeconds); @@ -803,7 +803,7 @@ class RemoteAgentConnectionStatusListener extends Disposable implements IWorkben case PersistentConnectionEventType.ReconnectionRunning: if (visibleProgress || e.millisSinceLastIncomingData > DISCONNECT_PROMPT_TIME) { visibleProgress = showProgress(null, [reloadButton]); - visibleProgress.report(nls.localize('reconnectionRunning', "Attempting to reconnect...")); + visibleProgress.report(nls.localize('reconnectionRunning', "Disconnected. Attempting to reconnect...")); // Register to listen for quick input is opened disposableListener = quickInputService.onShow(() => { From 1551d1f1ff07095c64878dd5ecde861c0d0177da Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 11 Jan 2021 16:39:22 +0100 Subject: [PATCH 1790/1837] Fixes microsoft/vscode-remote-release#1485: Make sure to only render Reload Window prompt once --- .../workbench/contrib/remote/browser/remote.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 3de5bc2862d..d227c52a5ba 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -701,6 +701,9 @@ class ReconnectionTimer2 implements IDisposable { const DISCONNECT_PROMPT_TIME = 40 * 1000; // 40 seconds class RemoteAgentConnectionStatusListener extends Disposable implements IWorkbenchContribution { + + private _reloadWindowShown: boolean = false; + constructor( @IRemoteAgentService remoteAgentService: IRemoteAgentService, @IProgressService progressService: IProgressService, @@ -818,12 +821,15 @@ class RemoteAgentConnectionStatusListener extends Disposable implements IWorkben case PersistentConnectionEventType.ReconnectionPermanentFailure: hideProgress(); - dialogService.show(Severity.Error, nls.localize('reconnectionPermanentFailure', "Cannot reconnect. Please reload the window."), [nls.localize('reloadWindow', "Reload Window"), nls.localize('cancel', "Cancel")], { cancelId: 1 }).then(result => { - // Reload the window - if (result.choice === 0) { - commandService.executeCommand(ReloadWindowAction.ID); - } - }); + if (!this._reloadWindowShown) { + this._reloadWindowShown = true; + dialogService.show(Severity.Error, nls.localize('reconnectionPermanentFailure', "Cannot reconnect. Please reload the window."), [nls.localize('reloadWindow', "Reload Window"), nls.localize('cancel', "Cancel")], { cancelId: 1 }).then(result => { + // Reload the window + if (result.choice === 0) { + commandService.executeCommand(ReloadWindowAction.ID); + } + }); + } break; case PersistentConnectionEventType.ConnectionGain: hideProgress(); From 5c1543b556c5e26866302ad8821fbce55885b572 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 11 Jan 2021 17:10:00 +0100 Subject: [PATCH 1791/1837] File name in editor tab reverts casing on save (fix #114096) --- .../workbench/common/editor/textResourceEditorInput.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/common/editor/textResourceEditorInput.ts b/src/vs/workbench/common/editor/textResourceEditorInput.ts index e55b556794c..539f93cc493 100644 --- a/src/vs/workbench/common/editor/textResourceEditorInput.ts +++ b/src/vs/workbench/common/editor/textResourceEditorInput.ts @@ -199,14 +199,14 @@ export abstract class AbstractTextResourceEditorInput extends EditorInput implem } // Normal save - return this.doSave(group, options, false); + return this.doSave(options, false); } saveAs(group: GroupIdentifier, options?: ITextFileSaveOptions): Promise { - return this.doSave(group, options, true); + return this.doSave(options, true); } - private async doSave(group: GroupIdentifier, options: ISaveOptions | undefined, saveAs: boolean): Promise { + private async doSave(options: ISaveOptions | undefined, saveAs: boolean): Promise { // Save / Save As let target: URI | undefined; @@ -220,8 +220,8 @@ export abstract class AbstractTextResourceEditorInput extends EditorInput implem return undefined; // save cancelled } - // If the target is a different resource, return with a new editor input - if (!isEqual(target, this.preferredResource)) { + // If the target is a different resource (from "Save As" operation), return with a new editor input + if (saveAs && !isEqual(target, this.preferredResource)) { return this.editorService.createEditorInput({ resource: target }); } From 3d500ebd8b4a919e8631e916f417e5c68eb90d3f Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 17:31:01 +0100 Subject: [PATCH 1792/1837] Adopt proposed `CancellationError` (#93686) --- .../src/languageFeatures/semanticTokens.ts | 2 +- src/vs/editor/common/services/modelServiceImpl.ts | 3 ++- .../api/common/extHostLanguageFeatures.ts | 14 +++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts index a64f2cc9be4..c19af5b6fb0 100644 --- a/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts +++ b/extensions/typescript-language-features/src/languageFeatures/semanticTokens.ts @@ -95,7 +95,7 @@ class DocumentSemanticTokensProvider implements vscode.DocumentSemanticTokensPro // as the new request will come in right after our response, we first wait for the document activity to stop await waitForDocumentChangesToEnd(document); - throw new Error('busy'); + throw new vscode.CancellationError(); } const tokenSpan = response.body.spans; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 17d9d01596f..0c414a32445 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -807,7 +807,8 @@ class ModelSemanticColoring extends Disposable { contentChangeListener.dispose(); this._setDocumentSemanticTokens(provider, res || null, styling, pendingChanges); }, (err) => { - if (!err || typeof err.message !== 'string' || err.message.indexOf('busy') === -1) { + const isExpectedError = err && (errors.isPromiseCanceledError(err) || (typeof err.message === 'string' && err.message.indexOf('busy') !== -1)); + if (!isExpectedError) { errors.onUnexpectedError(err); } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 49cde88e19c..09f71a4dd79 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -32,6 +32,7 @@ import { IdGenerator } from 'vs/base/common/idGenerator'; import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService'; import { Cache } from './cache'; import { StopWatch } from 'vs/base/common/stopwatch'; +import { CancellationError } from 'vs/base/common/errors'; // --- adapter @@ -1403,7 +1404,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF return ExtHostLanguageFeatures._handlePool++; } - private _withAdapter(handle: number, ctor: { new(...args: any[]): A; }, callback: (adapter: A, extension: IExtensionDescription | undefined) => Promise, fallbackValue: R): Promise { + private _withAdapter(handle: number, ctor: { new(...args: any[]): A; }, callback: (adapter: A, extension: IExtensionDescription | undefined) => Promise, fallbackValue: R, allowCancellationError: boolean = false): Promise { const data = this._adapter.get(handle); if (!data) { return Promise.resolve(fallbackValue); @@ -1421,8 +1422,11 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF Promise.resolve(p).then( () => this._logService.trace(`[${extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`), err => { - this._logService.error(`[${extension.identifier.value}] provider FAILED`); - this._logService.error(err); + const isExpectedError = allowCancellationError && (err instanceof CancellationError); + if (!isExpectedError) { + this._logService.error(`[${extension.identifier.value}] provider FAILED`); + this._logService.error(err); + } } ); } @@ -1711,7 +1715,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF } $provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise { - return this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.provideDocumentSemanticTokens(URI.revive(resource), previousResultId, token), null); + return this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.provideDocumentSemanticTokens(URI.revive(resource), previousResultId, token), null, true); } $releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void { @@ -1725,7 +1729,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF } $provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise { - return this._withAdapter(handle, DocumentRangeSemanticTokensAdapter, adapter => adapter.provideDocumentRangeSemanticTokens(URI.revive(resource), range, token), null); + return this._withAdapter(handle, DocumentRangeSemanticTokensAdapter, adapter => adapter.provideDocumentRangeSemanticTokens(URI.revive(resource), range, token), null, true); } //#endregion From 61c6334a3f8b5affea69e29bfd657aa534193a4e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 17:42:13 +0100 Subject: [PATCH 1793/1837] Fixes #112373: The hover should always consume mouse wheel events --- src/vs/base/browser/ui/hover/hoverWidget.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/hover/hoverWidget.ts b/src/vs/base/browser/ui/hover/hoverWidget.ts index 6162569486e..50f8c83680a 100644 --- a/src/vs/base/browser/ui/hover/hoverWidget.ts +++ b/src/vs/base/browser/ui/hover/hoverWidget.ts @@ -27,7 +27,9 @@ export class HoverWidget extends Disposable { this.contentsDomNode = document.createElement('div'); this.contentsDomNode.className = 'monaco-hover-content'; - this._scrollbar = this._register(new DomScrollableElement(this.contentsDomNode, {})); + this._scrollbar = this._register(new DomScrollableElement(this.contentsDomNode, { + alwaysConsumeMouseWheel: true + })); this.containerDomNode.appendChild(this._scrollbar.getDomNode()); } From 3f3e35bf17ecf423dca5dc613e7c32474a8f9f16 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Mon, 11 Jan 2021 09:03:54 -0800 Subject: [PATCH 1794/1837] Add boundary for right arrow typeahead and fix bug with resetting Terminal (#113863) * initial changes * have public method that terminalinstance uses instead * fix tests * dispose of the event to fix test * move to reset due to lastRow state * remove import * handle backspace --- .../terminal/browser/terminalInstance.ts | 13 +++++--- .../browser/terminalTypeAheadAddon.ts | 31 +++++++++++++++---- .../test/browser/terminalTypeahead.test.ts | 31 +++++++++++++++---- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 8ef61e3bbe0..ff6244ea384 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -89,6 +89,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _wrapperElement: (HTMLElement & { xterm?: XTermTerminal }) | undefined; private _xterm: XTermTerminal | undefined; private _xtermCore: XTermCore | undefined; + private _xtermTypeAhead: TypeAheadAddon | undefined; private _xtermSearch: SearchAddon | undefined; private _xtermUnicode11: Unicode11Addon | undefined; private _xtermElement: HTMLDivElement | undefined; @@ -464,8 +465,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } })); - const typeaheadAddon = this._register(this._instantiationService.createInstance(TypeAheadAddon, this._processManager, this._configHelper)); - this._xterm.loadAddon(typeaheadAddon); + this._xtermTypeAhead = this._register(this._instantiationService.createInstance(TypeAheadAddon, this._processManager, this._configHelper)); + this._xterm.loadAddon(this._xtermTypeAhead); return xterm; } @@ -1160,9 +1161,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._pressAnyKeyToCloseListener?.dispose(); this._pressAnyKeyToCloseListener = undefined; - // Kill and clear up the process, making the process manager ready for a new process - this._processManager.dispose(); - if (this._xterm) { if (reset) { this._xterm.reset(); @@ -1198,6 +1196,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Set the new shell launch config this._shellLaunchConfig = shell; // Must be done before calling _createProcess() + // Kill and clear up the process, making the process manager ready for a new process + this._processManager.dispose(); + // Launch the process unless this is only a renderer. // In the renderer only cases, we still need to set the title correctly. const oldTitle = this._title; @@ -1209,6 +1210,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._processManager.onProcessData(data => this._onProcessData(data)); this._createProcess(); + + this._xtermTypeAhead?.reset(this._processManager); } public relaunch(): void { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts index c83ecb6f4cd..de5793f6646 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts @@ -1224,7 +1224,7 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { private typeaheadStyle?: TypeAheadStyle; private typeaheadThreshold = this.config.config.localEchoLatencyThreshold; private excludeProgramRe = compileExcludeRegexp(this.config.config.localEchoExcludePrograms); - protected lastRow?: { y: number; startingX: number; charState: CharPredictState }; + protected lastRow?: { y: number; startingX: number; endingX: number; charState: CharPredictState }; protected timeline?: PredictionTimeline; private terminalTitle = ''; public stats?: PredictionStats; @@ -1235,7 +1235,7 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { private clearPredictionDebounce?: IDisposable; constructor( - private readonly processManager: ITerminalProcessManager, + private processManager: ITerminalProcessManager, private readonly config: TerminalConfigHelper, @ITelemetryService private readonly telemetryService: ITelemetryService, ) { @@ -1291,6 +1291,12 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { })); } + public reset(processManager: ITerminalProcessManager) { + this.lastRow = undefined; + this.processManager = processManager; + this._register(this.processManager.onBeforeProcessData(e => this.onBeforeProcessData(e))); + } + private deferClearingPredictions() { if (!this.stats || !this.timeline) { return; @@ -1381,9 +1387,10 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { // the user gave input, and mark all additions before that as tentative. const actualY = buffer.baseY + buffer.cursorY; if (actualY !== this.lastRow?.y) { - this.lastRow = { y: actualY, startingX: buffer.cursorX, charState: CharPredictState.Unknown }; + this.lastRow = { y: actualY, startingX: buffer.cursorX, endingX: buffer.cursorX, charState: CharPredictState.Unknown }; } else { this.lastRow.startingX = Math.min(this.lastRow.startingX, buffer.cursorX); + this.lastRow.endingX = Math.max(this.lastRow.endingX, this.timeline.getCursor(buffer).x); } const addLeftNavigating = (p: IPrediction) => @@ -1391,6 +1398,11 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { ? this.timeline!.addBoundary(buffer, new TentativeBoundary(p)) : this.timeline!.addPrediction(buffer, p); + const addRightNavigating = (p: IPrediction) => + this.timeline!.getCursor(buffer).x >= this.lastRow!.endingX - 1 + ? this.timeline!.addBoundary(buffer, new TentativeBoundary(p)) + : this.timeline!.addPrediction(buffer, p); + /** @see https://github.com/xtermjs/xterm.js/blob/1913e9512c048e3cf56bb5f5df51bfff6899c184/src/common/input/Keyboard.ts */ const reader = new StringReader(data); while (reader.remaining > 0) { @@ -1406,7 +1418,14 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { flushOutput(this.timeline.terminal); } - addLeftNavigating(new BackspacePrediction(this.timeline.terminal)); + if (this.timeline!.getCursor(buffer).x <= this.lastRow!.startingX) { + this.timeline!.addBoundary(buffer, new TentativeBoundary(new BackspacePrediction(this.timeline.terminal))); + } else { + // Backspace decrements our ability to go right. + this.lastRow.endingX--; + this.timeline!.addPrediction(buffer, new BackspacePrediction(this.timeline.terminal)); + } + continue; } @@ -1434,13 +1453,13 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { if (direction === CursorMoveDirection.Back) { addLeftNavigating(p); } else { - this.timeline.addPrediction(buffer, p); + addRightNavigating(p); } continue; } if (reader.eatStr(`${ESC}f`)) { - this.timeline.addPrediction(buffer, new CursorMovePrediction(CursorMoveDirection.Forwards, true, 1)); + addRightNavigating(new CursorMovePrediction(CursorMoveDirection.Forwards, true, 1)); continue; } diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts index cc2d09691e3..b7da5f08d69 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts @@ -182,7 +182,7 @@ suite('Workbench - Terminal Typeahead', () => { test('handles left arrow when we hit the boundary', () => { const t = createMockTerminal({ lines: ['|'] }); addon.activate(t.terminal); - addon.unlockLeftNavigating(); + addon.unlockNavigating(); const cursorXBefore = addon.getCursor(t.terminal.buffer.active)?.x!; t.onData(`${CSI}${CursorMoveDirection.Back}`); @@ -198,10 +198,29 @@ suite('Workbench - Terminal Typeahead', () => { cursorXBefore); }); + test('handles right arrow when we hit the boundary', () => { + const t = createMockTerminal({ lines: ['|'] }); + addon.activate(t.terminal); + addon.unlockNavigating(); + + const cursorXBefore = addon.getCursor(t.terminal.buffer.active)?.x!; + t.onData(`${CSI}${CursorMoveDirection.Forwards}`); + t.expectWritten(''); + + // Trigger rollback because we don't expect this data + onBeforeProcessData.fire({ data: 'xy' }); + + assert.strictEqual( + addon.getCursor(t.terminal.buffer.active)?.x, + // The cursor should not have changed because we've hit the + // boundary (end of prompt) + cursorXBefore); + }); + test('internal cursor state is reset when all predictions are undone', () => { const t = createMockTerminal({ lines: ['|'] }); addon.activate(t.terminal); - addon.unlockLeftNavigating(); + addon.unlockNavigating(); const cursorXBefore = addon.getCursor(t.terminal.buffer.active)?.x!; t.onData(`${CSI}${CursorMoveDirection.Back}`); @@ -293,7 +312,7 @@ suite('Workbench - Terminal Typeahead', () => { test('restores old character after invalid backspace', () => { const t = createMockTerminal({ lines: ['hel|lo'] }); addon.activate(t.terminal); - addon.unlockLeftNavigating(); + addon.unlockNavigating(); t.onData('\x7F'); t.expectWritten(`${CSI}2;4H${CSI}X`); expectProcessed('x', `${CSI}?25l${CSI}0ml${CSI}2;5H${CSI}0mx${CSI}?25h`); @@ -354,15 +373,15 @@ suite('Workbench - Terminal Typeahead', () => { class TestTypeAheadAddon extends TypeAheadAddon { public unlockMakingPredictions() { - this.lastRow = { y: 1, startingX: 100, charState: CharPredictState.Validated }; + this.lastRow = { y: 1, startingX: 100, endingX: 100, charState: CharPredictState.Validated }; } public lockMakingPredictions() { this.lastRow = undefined; } - public unlockLeftNavigating() { - this.lastRow = { y: 1, startingX: 1, charState: CharPredictState.Validated }; + public unlockNavigating() { + this.lastRow = { y: 1, startingX: 1, endingX: 1, charState: CharPredictState.Validated }; } public reevaluateNow() { From e9ae008296391a4f29eb9884264076f8b5edff22 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 18:42:54 +0100 Subject: [PATCH 1795/1837] use in-mem fsp in tests --- .../electron-browser/desktop.main.ts | 2 +- .../electron-browser/configurationCache.ts | 41 +- .../configurationEditingService.test.ts | 451 +++++++++--------- .../configurationService.test.ts | 12 +- 4 files changed, 262 insertions(+), 244 deletions(-) diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index 9c7c566c600..0acfacc1a9b 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -393,7 +393,7 @@ class DesktopMain extends Disposable { } private async createWorkspaceService(payload: IWorkspaceInitializationPayload, fileService: FileService, remoteAgentService: IRemoteAgentService, uriIdentityService: IUriIdentityService, logService: ILogService): Promise { - const workspaceService = new WorkspaceService({ remoteAuthority: this.environmentService.remoteAuthority, configurationCache: new ConfigurationCache(this.environmentService) }, this.environmentService, fileService, remoteAgentService, uriIdentityService, logService); + const workspaceService = new WorkspaceService({ remoteAuthority: this.environmentService.remoteAuthority, configurationCache: new ConfigurationCache(this.environmentService, fileService) }, this.environmentService, fileService, remoteAgentService, uriIdentityService, logService); try { await workspaceService.initialize(payload); diff --git a/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts b/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts index 970ef48c7e9..41908807355 100644 --- a/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts +++ b/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts @@ -3,18 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as pfs from 'vs/base/node/pfs'; import { join } from 'vs/base/common/path'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IConfigurationCache, ConfigurationKey } from 'vs/workbench/services/configuration/common/configuration'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; +import { IFileService } from 'vs/platform/files/common/files'; +import { joinPath } from 'vs/base/common/resources'; +import { VSBuffer } from 'vs/base/common/buffer'; export class ConfigurationCache implements IConfigurationCache { private readonly cachedConfigurations: Map = new Map(); - constructor(private readonly environmentService: INativeWorkbenchEnvironmentService) { + constructor(private readonly environmentService: INativeWorkbenchEnvironmentService, private readonly fileService: IFileService) { } needsCaching(resource: URI): boolean { @@ -38,7 +40,7 @@ export class ConfigurationCache implements IConfigurationCache { const k = `${type}:${key}`; let cachedConfiguration = this.cachedConfigurations.get(k); if (!cachedConfiguration) { - cachedConfiguration = new CachedConfiguration({ type, key }, this.environmentService); + cachedConfiguration = new CachedConfiguration({ type, key }, this.environmentService, this.fileService); this.cachedConfigurations.set(k, cachedConfiguration); } return cachedConfiguration; @@ -49,21 +51,22 @@ export class ConfigurationCache implements IConfigurationCache { class CachedConfiguration { - private cachedConfigurationFolderPath: string; - private cachedConfigurationFilePath: string; + private cachedConfigurationFolderResource: URI; + private cachedConfigurationFileResource: URI; constructor( { type, key }: ConfigurationKey, - environmentService: INativeWorkbenchEnvironmentService + environmentService: INativeWorkbenchEnvironmentService, + private readonly fileService: IFileService ) { - this.cachedConfigurationFolderPath = join(environmentService.userDataPath, 'CachedConfigurations', type, key); - this.cachedConfigurationFilePath = join(this.cachedConfigurationFolderPath, type === 'workspaces' ? 'workspace.json' : 'configuration.json'); + this.cachedConfigurationFolderResource = URI.file(join(environmentService.userDataPath, 'CachedConfigurations', type, key)); + this.cachedConfigurationFileResource = joinPath(this.cachedConfigurationFolderResource, type === 'workspaces' ? 'workspace.json' : 'configuration.json'); } async read(): Promise { try { - const content = await pfs.readFile(this.cachedConfigurationFilePath); - return content.toString(); + const content = await this.fileService.readFile(this.cachedConfigurationFileResource); + return content.value.toString(); } catch (e) { return ''; } @@ -72,18 +75,24 @@ class CachedConfiguration { async save(content: string): Promise { const created = await this.createCachedFolder(); if (created) { - await pfs.writeFile(this.cachedConfigurationFilePath, content); + await this.fileService.writeFile(this.cachedConfigurationFileResource, VSBuffer.fromString(content)); } } remove(): Promise { - return pfs.rimraf(this.cachedConfigurationFolderPath); + return this.fileService.del(this.cachedConfigurationFolderResource, { recursive: true, useTrash: false }); } - private createCachedFolder(): Promise { - return Promise.resolve(pfs.exists(this.cachedConfigurationFolderPath)) - .then(undefined, () => false) - .then(exists => exists ? exists : pfs.mkdirp(this.cachedConfigurationFolderPath).then(() => true, () => false)); + private async createCachedFolder(): Promise { + if (await this.fileService.exists(this.cachedConfigurationFolderResource)) { + return true; + } + try { + await this.fileService.createFolder(this.cachedConfigurationFolderResource); + return true; + } catch (error) { + return false; + } } } diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index fec6587091b..292b26d3aea 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -5,9 +5,6 @@ import * as sinon from 'sinon'; import * as assert from 'assert'; -import * as os from 'os'; -import * as path from 'vs/base/common/path'; -import * as fs from 'fs'; import * as json from 'vs/base/common/json'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -17,32 +14,33 @@ import { TestWorkbenchConfiguration, TestTextFileService } from 'vs/workbench/te import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService'; -import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode, EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditingService'; +import { ConfigurationEditingService, ConfigurationEditingErrorCode, EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditingService'; import { WORKSPACE_STANDALONE_CONFIGURATIONS, FOLDER_SETTINGS_PATH, USER_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; -import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { CommandService } from 'vs/workbench/services/commands/common/commandService'; import { URI } from 'vs/base/common/uri'; import { createHash } from 'crypto'; -import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; import { Schemas } from 'vs/base/common/network'; -import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { IFileService } from 'vs/platform/files/common/files'; -import { ConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; import { KeybindingsEditingService, IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; +import { ConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; +import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; +import { joinPath } from 'vs/base/common/resources'; +import { VSBuffer } from 'vs/base/common/buffer'; class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -56,12 +54,10 @@ class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService suite('ConfigurationEditingService', () => { let instantiationService: TestInstantiationService; + let environmentService: NativeWorkbenchEnvironmentService; + let fileService: IFileService; + let workspaceService: WorkspaceService; let testObject: ConfigurationEditingService; - let parentDir: string; - let workspaceDir: string; - let globalSettingsFile: string; - let globalTasksFile: string; - let workspaceSettingsDir; const disposables = new DisposableStore(); @@ -88,284 +84,284 @@ suite('ConfigurationEditingService', () => { }); setup(async () => { - await setUpWorkspace(); - await setUpServices(); - }); + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + disposables.add(fileService.registerProvider(Schemas.file, fileSystemProvider)); - async function setUpWorkspace(): Promise { - const id = uuid.generateUuid(); - parentDir = path.join(os.tmpdir(), 'vsctests', id); - workspaceDir = path.join(parentDir, 'workspaceconfig', id); - globalSettingsFile = path.join(workspaceDir, 'settings.json'); - globalTasksFile = path.join(workspaceDir, 'tasks.json'); - workspaceSettingsDir = path.join(workspaceDir, '.vscode'); + const workspaceFolder = URI.file(uuid.generateUuid()); + await fileService.createFolder(workspaceFolder); - return await mkdirp(workspaceSettingsDir, 493); - } - - async function setUpServices(noWorkspace: boolean = false): Promise { instantiationService = workbenchInstantiationService(undefined, disposables); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(workspaceDir)); + environmentService = new TestWorkbenchEnvironmentService(workspaceFolder); instantiationService.stub(IEnvironmentService, environmentService); const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - disposables.add(fileService.registerProvider(Schemas.file, diskFileSystemProvider)); - disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService())))); + disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, logService)))); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); - await workspaceService.initialize(noWorkspace ? { id: '' } : { folder: URI.file(workspaceDir), id: createHash('md5').update(URI.file(workspaceDir).toString()).digest('hex') }); + + await workspaceService.initialize({ folder: workspaceFolder, id: createHash('md5').update(workspaceFolder.toString()).digest('hex') }); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IKeybindingEditingService, disposables.add(instantiationService.createInstance(KeybindingsEditingService))); instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); instantiationService.stub(ICommandService, CommandService); testObject = instantiationService.createInstance(ConfigurationEditingService); - } + }); - teardown(() => { - disposables.clear(); - if (workspaceDir) { - return rimraf(workspaceDir); + teardown(() => disposables.clear()); + + test('errors cases - invalid key', async () => { + try { + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' }); + assert.fail('Should fail with ERROR_UNKNOWN_KEY'); + } catch (error) { + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY); } - return undefined; }); - test('errors cases - invalid key', () => { - return testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' }) - .then(() => assert.fail('Should fail with ERROR_UNKNOWN_KEY'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY)); + test('errors cases - no workspace', async () => { + await workspaceService.initialize({ id: uuid.generateUuid() }); + try { + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' }); + assert.fail('Should fail with ERROR_NO_WORKSPACE_OPENED'); + } catch (error) { + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED); + } }); - test('errors cases - no workspace', () => { - return setUpServices(true) - .then(() => testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' })) - .then(() => assert.fail('Should fail with ERROR_NO_WORKSPACE_OPENED'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED)); + test('errors cases - invalid configuration', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(',,,,,,,,,,,,,,')); + try { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }); + assert.fail('Should fail with ERROR_INVALID_CONFIGURATION'); + } catch (error) { + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION); + } }); - function errorCasesInvalidConfig(file: string, key: string) { - fs.writeFileSync(file, ',,,,,,,,,,,,,,'); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key, value: 'value' }) - .then(() => assert.fail('Should fail with ERROR_INVALID_CONFIGURATION'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION)); - } - - test('errors cases - invalid configuration', () => { - return errorCasesInvalidConfig(globalSettingsFile, 'configurationEditing.service.testSetting'); + test('errors cases - invalid global tasks configuration', async () => { + const resource = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(resource, VSBuffer.fromString(',,,,,,,,,,,,,,')); + try { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks.configurationEditing.service.testSetting', value: 'value' }); + assert.fail('Should fail with ERROR_INVALID_CONFIGURATION'); + } catch (error) { + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION); + } }); - test('errors cases - invalid global tasks configuration', () => { - return errorCasesInvalidConfig(globalTasksFile, 'tasks.configurationEditing.service.testSetting'); - }); - - test('errors cases - dirty', () => { + test('errors cases - dirty', async () => { instantiationService.stub(ITextFileService, 'isDirty', true); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }) - .then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY)); + try { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }); + assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'); + } catch (error) { + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY); + } }); - test('dirty error is not thrown if not asked to save', () => { + test('dirty error is not thrown if not asked to save', async () => { instantiationService.stub(ITextFileService, 'isDirty', true); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotSave: true }) - .then(() => null, error => assert.fail('Should not fail.')); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotSave: true }); }); - test('do not notify error', () => { + test('do not notify error', async () => { instantiationService.stub(ITextFileService, 'isDirty', true); const target = sinon.stub(); instantiationService.stub(INotificationService, { prompt: target, _serviceBrand: undefined, notify: null!, error: null!, info: null!, warn: null!, status: null!, setFilter: null! }); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true }) - .then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'), - (error: ConfigurationEditingError) => { - assert.equal(false, target.calledOnce); - assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY); - }); + try { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true }); + assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'); + } catch (error) { + assert.equal(false, target.calledOnce); + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY); + } }); - test('write one setting - empty file', () => { - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }) - .then(() => { - const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); - }); + test('write one setting - empty file', async () => { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }); + const contents = await fileService.readFile(environmentService.settingsResource); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); }); - test('write one setting - existing file', () => { - fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }'); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }) - .then(() => { - const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); - assert.equal(parsed['my.super.setting'], 'my.super.value'); - }); + test('write one setting - existing file', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }); + + const contents = await fileService.readFile(environmentService.settingsResource); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); + assert.equal(parsed['my.super.setting'], 'my.super.value'); }); - test('remove an existing setting - existing file', () => { - fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value", "configurationEditing.service.testSetting": "value" }'); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: undefined }) - .then(() => { - const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.deepEqual(Object.keys(parsed), ['my.super.setting']); - assert.equal(parsed['my.super.setting'], 'my.super.value'); - }); + test('remove an existing setting - existing file', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "my.super.setting": "my.super.value", "configurationEditing.service.testSetting": "value" }')); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: undefined }); + + const contents = await fileService.readFile(environmentService.settingsResource); + const parsed = json.parse(contents.value.toString()); + assert.deepEqual(Object.keys(parsed), ['my.super.setting']); + assert.equal(parsed['my.super.setting'], 'my.super.value'); }); - test('remove non existing setting - existing file', () => { - fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }'); - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: undefined }) - .then(() => { - const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.deepEqual(Object.keys(parsed), ['my.super.setting']); - assert.equal(parsed['my.super.setting'], 'my.super.value'); - }); + test('remove non existing setting - existing file', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: undefined }); + + const contents = await fileService.readFile(environmentService.settingsResource); + const parsed = json.parse(contents.value.toString()); + assert.deepEqual(Object.keys(parsed), ['my.super.setting']); + assert.equal(parsed['my.super.setting'], 'my.super.value'); }); - test('write overridable settings to user settings', () => { + test('write overridable settings to user settings', async () => { const key = '[language]'; const value = { 'configurationEditing.service.testSetting': 'overridden value' }; - return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key, value }) - .then(() => { - const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.deepEqual(parsed[key], value); - }); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key, value }); + + const contents = await fileService.readFile(environmentService.settingsResource); + const parsed = json.parse(contents.value.toString()); + assert.deepEqual(parsed[key], value); }); - test('write overridable settings to workspace settings', () => { + test('write overridable settings to workspace settings', async () => { const key = '[language]'; const value = { 'configurationEditing.service.testSetting': 'overridden value' }; - return testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key, value }) - .then(() => { - const target = path.join(workspaceDir, FOLDER_SETTINGS_PATH); - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); - assert.deepEqual(parsed[key], value); - }); + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key, value }); + + const contents = await fileService.readFile(joinPath(workspaceService.getWorkspace().folders[0].uri, FOLDER_SETTINGS_PATH)); + const parsed = json.parse(contents.value.toString()); + assert.deepEqual(parsed[key], value); }); - test('write overridable settings to workspace folder settings', () => { + test('write overridable settings to workspace folder settings', async () => { const key = '[language]'; const value = { 'configurationEditing.service.testSetting': 'overridden value' }; - const folderSettingsFile = path.join(workspaceDir, FOLDER_SETTINGS_PATH); - return testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE_FOLDER, { key, value }, { scopes: { resource: URI.file(folderSettingsFile) } }) - .then(() => { - const contents = fs.readFileSync(folderSettingsFile).toString('utf8'); - const parsed = json.parse(contents); - assert.deepEqual(parsed[key], value); - }); + const folderSettingsFile = joinPath(workspaceService.getWorkspace().folders[0].uri, FOLDER_SETTINGS_PATH); + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE_FOLDER, { key, value }, { scopes: { resource: folderSettingsFile } }); + + const contents = await fileService.readFile(folderSettingsFile); + const parsed = json.parse(contents.value.toString()); + assert.deepEqual(parsed[key], value); }); - function writeStandaloneSettingEmptyFile(configTarget: EditableConfigurationTarget, pathMap: any) { - return testObject.writeConfiguration(configTarget, { key: 'tasks.service.testSetting', value: 'value' }) - .then(() => { - const target = path.join(workspaceDir, pathMap['tasks']); - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); - assert.equal(parsed['service.testSetting'], 'value'); - }); - } + test('write workspace standalone setting - empty file', async () => { + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }); - test('write workspace standalone setting - empty file', () => { - return writeStandaloneSettingEmptyFile(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['service.testSetting'], 'value'); }); - test('write user standalone setting - empty file', () => { - return writeStandaloneSettingEmptyFile(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting - empty file', async () => { + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks.service.testSetting', value: 'value' }); + + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['service.testSetting'], 'value'); }); - function writeStandaloneSettingExitingFile(configTarget: EditableConfigurationTarget, pathMap: any) { - const target = path.join(workspaceDir, pathMap['tasks']); - fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }'); - return testObject.writeConfiguration(configTarget, { key: 'tasks.service.testSetting', value: 'value' }) - .then(() => { - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); - assert.equal(parsed['service.testSetting'], 'value'); - assert.equal(parsed['my.super.setting'], 'my.super.value'); - }); - } + test('write workspace standalone setting - existing file', async () => { + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); - test('write workspace standalone setting - existing file', () => { - return writeStandaloneSettingExitingFile(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }); + + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['service.testSetting'], 'value'); + assert.equal(parsed['my.super.setting'], 'my.super.value'); }); - test('write user standalone setting - existing file', () => { - return writeStandaloneSettingExitingFile(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting - existing file', async () => { + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); + + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks.service.testSetting', value: 'value' }); + + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['service.testSetting'], 'value'); + assert.equal(parsed['my.super.setting'], 'my.super.value'); }); - function writeStandaloneSettingEmptyFileFullJson(configTarget: EditableConfigurationTarget, pathMap: any) { - return testObject.writeConfiguration(configTarget, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }) - .then(() => { - const target = path.join(workspaceDir, pathMap['tasks']); - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); + test('write workspace standalone setting - empty file - full JSON', async () => { + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); - assert.equal(parsed['version'], '1.0.0'); - assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); - }); - } - - test('write workspace standalone setting - empty file - full JSON', () => { - return writeStandaloneSettingEmptyFileFullJson(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - test('write user standalone setting - empty file - full JSON', () => { - return writeStandaloneSettingEmptyFileFullJson(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting - empty file - full JSON', async () => { + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); + + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - function writeStandaloneSettingExistingFileFullJson(configTarget: EditableConfigurationTarget, pathMap: any) { - const target = path.join(workspaceDir, pathMap['tasks']); - fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }'); - return testObject.writeConfiguration(configTarget, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }) - .then(() => { - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); + test('write workspace standalone setting - existing file - full JSON', async () => { + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); - assert.equal(parsed['version'], '1.0.0'); - assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); - }); - } + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); - test('write workspace standalone setting - existing file - full JSON', () => { - return writeStandaloneSettingExistingFileFullJson(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - test('write user standalone setting - existing file - full JSON', () => { - return writeStandaloneSettingExistingFileFullJson(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting - existing file - full JSON', async () => { + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": "my.super.value" }')); + + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); + + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - function writeStandaloneSettingExistingFileWithJsonErrorFullJson(configTarget: EditableConfigurationTarget, pathMap: any) { - const target = path.join(workspaceDir, pathMap['tasks']); - fs.writeFileSync(target, '{ "my.super.setting": '); // invalid JSON - return testObject.writeConfiguration(configTarget, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }) - .then(() => { - const contents = fs.readFileSync(target).toString('utf8'); - const parsed = json.parse(contents); + test('write workspace standalone setting - existing file with JSON errors - full JSON', async () => { + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": ')); // invalid JSON - assert.equal(parsed['version'], '1.0.0'); - assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); - }); - } + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); - test('write workspace standalone setting - existing file with JSON errors - full JSON', () => { - return writeStandaloneSettingExistingFileWithJsonErrorFullJson(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - test('write user standalone setting - existing file with JSON errors - full JSON', () => { - return writeStandaloneSettingExistingFileWithJsonErrorFullJson(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting - existing file with JSON errors - full JSON', async () => { + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString('{ "my.super.setting": ')); // invalid JSON + + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }); + + const contents = await fileService.readFile(target); + const parsed = json.parse(contents.value.toString()); + assert.equal(parsed['version'], '1.0.0'); + assert.equal(parsed['tasks'][0]['taskName'], 'myTask'); }); - function writeStandaloneSettingShouldReplace(configTarget: EditableConfigurationTarget, pathMap: any) { - const target = path.join(workspaceDir, pathMap['tasks']); - fs.writeFileSync(target, `{ + test('write workspace standalone setting should replace complete file', async () => { + const target = joinPath(workspaceService.getWorkspace().folders[0].uri, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString(`{ "version": "1.0.0", "tasks": [ { @@ -375,20 +371,33 @@ suite('ConfigurationEditingService', () => { "taskName": "myTask2" } ] - }`); - return testObject.writeConfiguration(configTarget, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] } }) - .then(() => { - const actual = fs.readFileSync(target).toString('utf8'); - const expected = JSON.stringify({ 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] }, null, '\t'); - assert.equal(actual, expected); - }); - } + }`)); - test('write workspace standalone setting should replace complete file', () => { - return writeStandaloneSettingShouldReplace(EditableConfigurationTarget.WORKSPACE, WORKSPACE_STANDALONE_CONFIGURATIONS); + await testObject.writeConfiguration(EditableConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] } }); + + const actual = await fileService.readFile(target); + const expected = JSON.stringify({ 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] }, null, '\t'); + assert.equal(actual.value.toString(), expected); }); - test('write user standalone setting should replace complete file', () => { - return writeStandaloneSettingShouldReplace(EditableConfigurationTarget.USER_LOCAL, USER_STANDALONE_CONFIGURATIONS); + test('write user standalone setting should replace complete file', async () => { + const target = joinPath(environmentService.appSettingsHome, USER_STANDALONE_CONFIGURATIONS['tasks']); + await fileService.writeFile(target, VSBuffer.fromString(`{ + "version": "1.0.0", + "tasks": [ + { + "taskName": "myTask1" + }, + { + "taskName": "myTask2" + } + ] + }`)); + + await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] } }); + + const actual = await fileService.readFile(target); + const expected = JSON.stringify({ 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] }, null, '\t'); + assert.equal(actual.value.toString(), expected); }); }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index a1789f050e7..a1be5b85a1c 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -119,7 +119,7 @@ flakySuite('WorkspaceContextService - Folder', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, new DiskFileSystemProvider(new NullLogService()), Schemas.userData, new NullLogService()))); - workspaceContextService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); + workspaceContextService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); }); }); @@ -184,7 +184,7 @@ flakySuite('WorkspaceContextService - Workspace', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -243,7 +243,7 @@ flakySuite('WorkspaceContextService - Workspace Editing', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -506,7 +506,7 @@ flakySuite('WorkspaceService - Initialization', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IEnvironmentService, environmentService); @@ -781,7 +781,7 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IEnvironmentService, environmentService); @@ -1311,7 +1311,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); From c85297669eed986d6cff09da6948ede4ef6fe247 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 11 Jan 2021 10:52:55 -0800 Subject: [PATCH 1796/1837] Move id, label, and options to authentication provider registration --- .../github-authentication/src/extension.ts | 7 +- .../microsoft-authentication/src/extension.ts | 7 +- src/vs/vscode.proposed.d.ts | 39 ++++---- .../workbench/api/common/extHost.api.impl.ts | 4 +- .../api/common/extHostAuthentication.ts | 88 +++++++++---------- 5 files changed, 65 insertions(+), 80 deletions(-) diff --git a/extensions/github-authentication/src/extension.ts b/extensions/github-authentication/src/extension.ts index d414545f047..59994b742e3 100644 --- a/extensions/github-authentication/src/extension.ts +++ b/extensions/github-authentication/src/extension.ts @@ -22,10 +22,7 @@ export async function activate(context: vscode.ExtensionContext) { return loginService.manuallyProvideToken(); })); - context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({ - id: 'github', - label: 'GitHub', - supportsMultipleAccounts: false, + context.subscriptions.push(vscode.authentication.registerAuthenticationProvider('github', 'GitHub', { onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), login: async (scopeList: string[]) => { @@ -79,7 +76,7 @@ export async function activate(context: vscode.ExtensionContext) { throw e; } } - })); + }, { supportsMultipleAccounts: false })); return; } diff --git a/extensions/microsoft-authentication/src/extension.ts b/extensions/microsoft-authentication/src/extension.ts index 2c08a789715..23c18d8b954 100644 --- a/extensions/microsoft-authentication/src/extension.ts +++ b/extensions/microsoft-authentication/src/extension.ts @@ -18,10 +18,7 @@ export async function activate(context: vscode.ExtensionContext) { await loginService.initialize(); - context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({ - id: 'microsoft', - label: 'Microsoft', - supportsMultipleAccounts: true, + context.subscriptions.push(vscode.authentication.registerAuthenticationProvider('microsoft', 'Microsoft', { onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), login: async (scopes: string[]) => { @@ -59,7 +56,7 @@ export async function activate(context: vscode.ExtensionContext) { telemetryReporter.sendTelemetryEvent('logoutFailed'); } } - })); + }, { supportsMultipleAccounts: true })); return; } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 490e141ab79..821beb53e2b 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -73,28 +73,9 @@ declare module 'vscode' { } /** - * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's - * API, changing it is a breaking change for all extensions relying on the provider. The id is - * treated case-sensitively. + * A provider for performing authentication to a service. */ export interface AuthenticationProvider { - /** - * Used as an identifier for extensions trying to work with a particular - * provider: 'microsoft', 'github', etc. id must be unique, registering - * another provider with the same id will fail. - */ - readonly id: string; - - /** - * The human-readable name of the provider. - */ - readonly label: string; - - /** - * Whether it is possible to be signed into multiple accounts at once with this provider - */ - readonly supportsMultipleAccounts: boolean; - /** * An [event](#Event) which fires when the array of sessions has changed, or data * within a session has changed. @@ -121,17 +102,31 @@ declare module 'vscode' { logout(sessionId: string): Thenable; } + /** + * Options for creating an [AuthenticationProvider](#AuthentcationProvider). + */ + export interface AuthenticationProviderOptions { + /** + * Whether it is possible to be signed into multiple accounts at once with this provider. + * If not specified, will default to false. + */ + readonly supportsMultipleAccounts?: boolean; + } + export namespace authentication { /** * Register an authentication provider. * * There can only be one provider per id and an error is being thrown when an id - * has already been used by another provider. + * has already been used by another provider. Ids are case-sensitive. * + * @param id The unique identifier of the provider. + * @param label The human-readable name of the provider. * @param provider The authentication provider provider. + * @params options Additional options for the provider. * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ - export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; + export function registerAuthenticationProvider(id: string, label: string, provider: AuthenticationProvider, options?: AuthenticationProviderOptions): Disposable; /** * @deprecated - getSession should now trigger extension activation. diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index a26f0bcc119..00b37af5ad7 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -214,9 +214,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I get onDidChangeSessions(): Event { return extHostAuthentication.onDidChangeSessions; }, - registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable { + registerAuthenticationProvider(id: string, label: string, provider: vscode.AuthenticationProvider, options?: vscode.AuthenticationProviderOptions): vscode.Disposable { checkProposedApiEnabled(extension); - return extHostAuthentication.registerAuthenticationProvider(provider); + return extHostAuthentication.registerAuthenticationProvider(id, label, provider, options); }, get onDidChangeAuthenticationProviders(): Event { checkProposedApiEnabled(extension); diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 3d23cbcde3f..7376e9c66cf 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -15,11 +15,15 @@ interface GetSessionsRequest { result: Promise; } +interface ProviderWithMetadata { + label: string; + provider: vscode.AuthenticationProvider; + options: vscode.AuthenticationProviderOptions; +} + export class ExtHostAuthentication implements ExtHostAuthenticationShape { private _proxy: MainThreadAuthenticationShape; - private _authenticationProviders: Map = new Map(); - - private _providerIds: string[] = []; + private _authenticationProviders: Map = new Map(); private _providers: vscode.AuthenticationProviderInformation[] = []; @@ -79,128 +83,120 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { private async _getSession(requestingExtension: IExtensionDescription, extensionId: string, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise { await this._proxy.$ensureProvider(providerId); - const provider = this._authenticationProviders.get(providerId); + const providerData = this._authenticationProviders.get(providerId); const extensionName = requestingExtension.displayName || requestingExtension.name; - if (!provider) { + if (!providerData) { return this._proxy.$getSession(providerId, scopes, extensionId, extensionName, options); } const orderedScopes = scopes.sort().join(' '); - const sessions = (await provider.getSessions()).filter(session => session.scopes.slice().sort().join(' ') === orderedScopes); + const sessions = (await providerData.provider.getSessions()).filter(session => session.scopes.slice().sort().join(' ') === orderedScopes); let session: vscode.AuthenticationSession | undefined = undefined; if (sessions.length) { - if (!provider.supportsMultipleAccounts) { + if (!providerData.options.supportsMultipleAccounts) { session = sessions[0]; - const allowed = await this._proxy.$getSessionsPrompt(providerId, session.account.label, provider.label, extensionId, extensionName); + const allowed = await this._proxy.$getSessionsPrompt(providerId, session.account.label, providerData.label, extensionId, extensionName); if (!allowed) { throw new Error('User did not consent to login.'); } } else { // On renderer side, confirm consent, ask user to choose between accounts if multiple sessions are valid - const selected = await this._proxy.$selectSession(providerId, provider.label, extensionId, extensionName, sessions, scopes, !!options.clearSessionPreference); + const selected = await this._proxy.$selectSession(providerId, providerData.label, extensionId, extensionName, sessions, scopes, !!options.clearSessionPreference); session = sessions.find(session => session.id === selected.id); } } else { if (options.createIfNone) { - const isAllowed = await this._proxy.$loginPrompt(provider.label, extensionName); + const isAllowed = await this._proxy.$loginPrompt(providerData.label, extensionName); if (!isAllowed) { throw new Error('User did not consent to login.'); } - session = await provider.login(scopes); + session = await providerData.provider.login(scopes); await this._proxy.$setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id); } else { await this._proxy.$requestNewSession(providerId, scopes, extensionId, extensionName); } } - return session; } async logout(providerId: string, sessionId: string): Promise { - const provider = this._authenticationProviders.get(providerId); - if (!provider) { + const providerData = this._authenticationProviders.get(providerId); + if (!providerData) { return this._proxy.$logout(providerId, sessionId); } - return provider.logout(sessionId); + return providerData.provider.logout(sessionId); } - registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable { - if (this._authenticationProviders.get(provider.id)) { - throw new Error(`An authentication provider with id '${provider.id}' is already registered.`); + registerAuthenticationProvider(id: string, label: string, provider: vscode.AuthenticationProvider, options?: vscode.AuthenticationProviderOptions): vscode.Disposable { + if (this._authenticationProviders.get(id)) { + throw new Error(`An authentication provider with id '${id}' is already registered.`); } - this._authenticationProviders.set(provider.id, provider); - if (!this._providerIds.includes(provider.id)) { - this._providerIds.push(provider.id); - } + this._authenticationProviders.set(id, { label, provider, options: options ?? { supportsMultipleAccounts: false } }); - if (!this._providers.find(p => p.id === provider.id)) { + if (!this._providers.find(p => p.id === id)) { this._providers.push({ - id: provider.id, - label: provider.label + id: id, + label: label }); } const listener = provider.onDidChangeSessions(e => { - this._proxy.$sendDidChangeSessions(provider.id, e); + this._proxy.$sendDidChangeSessions(id, e); }); - this._proxy.$registerAuthenticationProvider(provider.id, provider.label, provider.supportsMultipleAccounts); + this._proxy.$registerAuthenticationProvider(id, label, options?.supportsMultipleAccounts ?? false); return new Disposable(() => { listener.dispose(); - this._authenticationProviders.delete(provider.id); - const index = this._providerIds.findIndex(id => id === provider.id); - if (index > -1) { - this._providerIds.splice(index); - } + this._authenticationProviders.delete(id); - const i = this._providers.findIndex(p => p.id === provider.id); + const i = this._providers.findIndex(p => p.id === id); if (i > -1) { this._providers.splice(i); } - this._proxy.$unregisterAuthenticationProvider(provider.id); + this._proxy.$unregisterAuthenticationProvider(id); }); } $login(providerId: string, scopes: string[]): Promise { - const authProvider = this._authenticationProviders.get(providerId); - if (authProvider) { - return Promise.resolve(authProvider.login(scopes)); + const providerData = this._authenticationProviders.get(providerId); + if (providerData) { + return Promise.resolve(providerData.provider.login(scopes)); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); } $logout(providerId: string, sessionId: string): Promise { - const authProvider = this._authenticationProviders.get(providerId); - if (authProvider) { - return Promise.resolve(authProvider.logout(sessionId)); + const providerData = this._authenticationProviders.get(providerId); + if (providerData) { + return Promise.resolve(providerData.provider.logout(sessionId)); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); } $getSessions(providerId: string): Promise> { - const authProvider = this._authenticationProviders.get(providerId); - if (authProvider) { - return Promise.resolve(authProvider.getSessions()); + const providerData = this._authenticationProviders.get(providerId); + if (providerData) { + return Promise.resolve(providerData.provider.getSessions()); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); } async $getSessionAccessToken(providerId: string, sessionId: string): Promise { - const authProvider = this._authenticationProviders.get(providerId); - if (authProvider) { - const sessions = await authProvider.getSessions(); + const providerData = this._authenticationProviders.get(providerId); + if (providerData) { + const sessions = await providerData.provider.getSessions(); const session = sessions.find(session => session.id === sessionId); if (session) { return session.accessToken; From cef7004a46a298e8f652b769dcd25a7e26691f55 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 11 Jan 2021 11:22:17 -0800 Subject: [PATCH 1797/1837] activate search result extension onLanguage:search-result #110031 --- extensions/search-result/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/search-result/package.json b/extensions/search-result/package.json index 9635a6c51df..d80c207ac9e 100644 --- a/extensions/search-result/package.json +++ b/extensions/search-result/package.json @@ -15,7 +15,7 @@ "main": "./out/extension.js", "browser": "./dist/extension.js", "activationEvents": [ - "*" + "onLanguage:search-result" ], "scripts": { "generate-grammar": "node ./syntaxes/generateTMLanguage.js", From 31e33c478e5b2c18436486fb3583099075b5616e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 20:35:29 +0100 Subject: [PATCH 1798/1837] Fixes #114042: Use Buffer only when it is available --- src/vs/base/test/common/buffer.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index bac2802d10b..1de31503e06 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -7,7 +7,6 @@ import * as assert from 'assert'; import { VSBuffer, bufferToReadable, readableToBuffer, bufferToStream, streamToBuffer, newWriteableBufferStream, bufferedStreamToBuffer } from 'vs/base/common/buffer'; import { timeout } from 'vs/base/common/async'; import { peekStream } from 'vs/base/common/stream'; -import { isWeb } from 'vs/base/common/platform'; suite('Buffer', () => { @@ -374,9 +373,9 @@ suite('Buffer', () => { assert.equal(errors.length, 0); }); - (isWeb ? test.skip : test)('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042) + test('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042) // Buffer#slice creates a view - { + if (typeof Buffer !== 'undefined') { const buff = Buffer.from([10, 20, 30, 40]); const b2 = buff.slice(1, 3); assert.equal(buff[1], 20); From 42221c900ba1b5a06ccf7d439104381a5b13d885 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 11 Jan 2021 20:38:30 +0100 Subject: [PATCH 1799/1837] Set override to false when reopening editors after dragging them to a different editor group. This fixes #109000. (#114093) --- src/vs/workbench/browser/parts/editor/editorDropTarget.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 50f571563cd..d3d2258f572 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -283,7 +283,8 @@ class DropOverlay extends Themable { // Open in target group const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true, // always pin dropped editor - sticky: sourceGroup.isSticky(draggedEditor.editor) // preserve sticky state + sticky: sourceGroup.isSticky(draggedEditor.editor), // preserve sticky state + override: false, // Use `draggedEditor.editor` as is. If it is already a custom editor, it will stay so. })); const copyEditor = this.isCopyOperation(event, draggedEditor); targetGroup.openEditor(draggedEditor.editor, options, copyEditor ? OpenEditorContext.COPY_EDITOR : OpenEditorContext.MOVE_EDITOR); From c38c1f497f2d6daae9f3cff6d4c464d65c5cfa25 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 20:46:01 +0100 Subject: [PATCH 1800/1837] use in-mem fsp - workspace folder tests --- .../configurationService.test.ts | 72 +++++++++---------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index a1be5b85a1c..755fd8d5d2c 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -30,7 +30,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService'; import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; -import { originalFSPath, joinPath } from 'vs/base/common/resources'; +import { originalFSPath, joinPath, dirname } from 'vs/base/common/resources'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-sandbox/remoteAuthorityResolverService'; @@ -55,7 +55,7 @@ import { BrowserWorkbenchEnvironmentService } from 'vs/workbench/services/enviro import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { Event } from 'vs/base/common/event'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; -import { flakySuite } from 'vs/base/test/node/testUtils'; +import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -104,68 +104,62 @@ function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configP } -flakySuite('WorkspaceContextService - Folder', () => { +suite('WorkspaceContextService - Folder', () => { - let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceResource: string, workspaceContextService: IWorkspaceContextService; + let folderName = 'Folder A', folder: URI, testObject: WorkspaceService; const disposables = new DisposableStore(); - setup(() => { - return setUpFolderWorkspace(workspaceName) - .then(({ parentDir, folderDir }) => { - parentResource = parentDir; - workspaceResource = folderDir; - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, new DiskFileSystemProvider(new NullLogService()), Schemas.userData, new NullLogService()))); - workspaceContextService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); - return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); - }); + setup(async () => { + const logService = new NullLogService(); + const fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(Schemas.file, fileSystemProvider); + + folder = joinPath(URI.file(uuid.generateUuid()), folderName); + await fileService.createFolder(folder); + + const environmentService = new TestWorkbenchEnvironmentService(folder); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); + await (testObject).initialize(convertToWorkspacePayload(folder)); }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); test('getWorkspace()', () => { - const actual = workspaceContextService.getWorkspace(); + const actual = testObject.getWorkspace(); assert.equal(actual.folders.length, 1); - assert.equal(actual.folders[0].uri.fsPath, URI.file(workspaceResource).fsPath); - assert.equal(actual.folders[0].name, workspaceName); + assert.equal(actual.folders[0].uri.path, folder.path); + assert.equal(actual.folders[0].name, folderName); assert.equal(actual.folders[0].index, 0); assert.ok(!actual.configuration); }); test('getWorkbenchState()', () => { - const actual = workspaceContextService.getWorkbenchState(); + const actual = testObject.getWorkbenchState(); assert.equal(actual, WorkbenchState.FOLDER); }); test('getWorkspaceFolder()', () => { - const actual = workspaceContextService.getWorkspaceFolder(URI.file(path.join(workspaceResource, 'a'))); + const actual = testObject.getWorkspaceFolder(joinPath(folder, 'a')); - assert.equal(actual, workspaceContextService.getWorkspace().folders[0]); + assert.equal(actual, testObject.getWorkspace().folders[0]); }); test('isCurrentWorkspace() => true', () => { - assert.ok(workspaceContextService.isCurrentWorkspace(URI.file(workspaceResource))); + assert.ok(testObject.isCurrentWorkspace(folder)); }); test('isCurrentWorkspace() => false', () => { - assert.ok(!workspaceContextService.isCurrentWorkspace(URI.file(workspaceResource + 'abc'))); + assert.ok(!testObject.isCurrentWorkspace(joinPath(dirname(folder), 'abc'))); }); - test('workspace is complete', () => workspaceContextService.getCompleteWorkspace()); + test('workspace is complete', () => testObject.getCompleteWorkspace()); }); -flakySuite('WorkspaceContextService - Workspace', () => { +suite('WorkspaceContextService - Workspace', () => { let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; const disposables = new DisposableStore(); @@ -224,7 +218,7 @@ flakySuite('WorkspaceContextService - Workspace', () => { }); -flakySuite('WorkspaceContextService - Workspace Editing', () => { +suite('WorkspaceContextService - Workspace Editing', () => { let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; const disposables = new DisposableStore(); @@ -465,7 +459,7 @@ flakySuite('WorkspaceContextService - Workspace Editing', () => { }); -flakySuite('WorkspaceService - Initialization', () => { +suite('WorkspaceService - Initialization', () => { let parentResource: string, workspaceConfigPath: URI, testObject: WorkspaceService, globalSettingsFile: string; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -723,7 +717,7 @@ flakySuite('WorkspaceService - Initialization', () => { }); -flakySuite('WorkspaceConfigurationService - Folder', () => { +suite('WorkspaceConfigurationService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string, globalTasksFile: string, workspaceService: WorkspaceService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -1252,7 +1246,7 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); }); -flakySuite('WorkspaceConfigurationService-Multiroot', () => { +suite('WorkspaceConfigurationService-Multiroot', () => { let parentResource: string, workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService, globalSettingsFile: string; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -1875,7 +1869,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); }); -flakySuite('WorkspaceConfigurationService - Remote Folder', () => { +suite('WorkspaceConfigurationService - Remote Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: WorkspaceService, globalSettingsFile: string, remoteSettingsFile: string, remoteSettingsResource: URI, instantiationService: TestInstantiationService, resolveRemoteEnvironment: () => void; const remoteAuthority = 'configuraiton-tests'; From 00a781f926e9f56f05fd20d9c907ebd1965404b7 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 11 Jan 2021 20:47:56 +0100 Subject: [PATCH 1801/1837] debug: use mnemonicTitle and avoid dupliacte registration --- .../contrib/debug/browser/breakpointsView.ts | 18 ++-- .../debug/browser/debug.contribution.ts | 63 +------------ .../debug/browser/debugEditorActions.ts | 90 ++++++++++++------- .../contrib/debug/browser/debugViewlet.ts | 23 ++++- 4 files changed, 94 insertions(+), 100 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 67c84e430db..1cb9ea96b45 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -861,20 +861,28 @@ export function getBreakpointMessageAndIcon(state: State, breakpointsActivated: }; } -export const FUNCTION_BREAKPOINT_COMMAND_ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; registerAction2(class extends Action2 { constructor() { super({ - id: FUNCTION_BREAKPOINT_COMMAND_ID, - title: localize('addFunctionBreakpoint', "Add Function Breakpoint"), + id: 'workbench.debug.viewlet.action.addFunctionBreakpointAction', + title: { + value: localize('addFunctionBreakpoint', "Add Function Breakpoint"), + original: 'Add Function Breakpoint', + mnemonicTitle: localize({ key: 'miFunctionBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Function Breakpoint...") + }, f1: true, icon: icons.watchExpressionsAddFuncBreakpoint, - menu: { + menu: [{ id: MenuId.ViewTitle, group: 'navigation', order: 10, when: ContextKeyEqualsExpr.create('view', BREAKPOINTS_VIEW_ID) - } + }, { + id: MenuId.MenubarNewBreakpointMenu, + group: '1_breakpoints', + order: 3, + when: CONTEXT_DEBUGGERS_AVAILABLE + }] }); } diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 02dd2427cf3..a2f0090e474 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -12,7 +12,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions, CATEGORIES } from 'vs/workbench/common/actions'; -import { BreakpointsView, FUNCTION_BREAKPOINT_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/breakpointsView'; +import { BreakpointsView } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { @@ -21,7 +21,7 @@ import { } from 'vs/workbench/contrib/debug/common/debug'; import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { DebugService } from 'vs/workbench/contrib/debug/browser/debugService'; -import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_CONFIGURE_COMMAND_ID, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID, DEBUG_RUN_LABEL, DEBUG_RUN_COMMAND_ID, EDIT_EXPRESSION_COMMAND_ID, REMOVE_EXPRESSION_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; +import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL, DEBUG_START_LABEL, DEBUG_START_COMMAND_ID, DEBUG_RUN_LABEL, DEBUG_RUN_COMMAND_ID, EDIT_EXPRESSION_COMMAND_ID, REMOVE_EXPRESSION_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; @@ -31,7 +31,7 @@ import { DebugStatusContribution } from 'vs/workbench/contrib/debug/browser/debu import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { LoadedScriptsView } from 'vs/workbench/contrib/debug/browser/loadedScriptsView'; -import { ADD_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID, RunToCursorAction, registerEditorActions } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; +import { RunToCursorAction, registerEditorActions } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; import { WatchExpressionsView, ADD_WATCH_LABEL, REMOVE_WATCH_EXPRESSIONS_COMMAND_ID, REMOVE_WATCH_EXPRESSIONS_LABEL, ADD_WATCH_ID } from 'vs/workbench/contrib/debug/browser/watchExpressionsView'; import { VariablesView, SET_VARIABLE_ID, COPY_VALUE_ID, BREAK_WHEN_VALUE_CHANGES_ID, COPY_EVALUATE_PATH_ID, ADD_TO_WATCH_ID } from 'vs/workbench/contrib/debug/browser/variablesView'; import { Repl } from 'vs/workbench/contrib/debug/browser/repl'; @@ -202,15 +202,6 @@ function registerDebugMenu(): void { order: 4 }); - MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { - group: '4_panels', - command: { - id: OPEN_REPL_COMMAND_ID, - title: nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console") - }, - order: 2 - }); - // Debug menu MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { @@ -256,15 +247,6 @@ function registerDebugMenu(): void { }); // Configuration - MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { - group: '2_configuration', - command: { - id: DEBUG_CONFIGURE_COMMAND_ID, - title: nls.localize({ key: 'miOpenConfigurations', comment: ['&& denotes a mnemonic'] }, "Open &&Configurations") - }, - order: 1, - when: CONTEXT_DEBUGGERS_AVAILABLE - }); MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { group: '2_configuration', @@ -322,25 +304,6 @@ function registerDebugMenu(): void { }); // New Breakpoints - MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { - group: '4_new_breakpoint', - command: { - id: TOGGLE_BREAKPOINT_ID, - title: nls.localize({ key: 'miToggleBreakpoint', comment: ['&& denotes a mnemonic'] }, "Toggle &&Breakpoint") - }, - order: 1, - when: CONTEXT_DEBUGGERS_AVAILABLE - }); - - MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, { - group: '1_breakpoints', - command: { - id: TOGGLE_CONDITIONAL_BREAKPOINT_ID, - title: nls.localize({ key: 'miConditionalBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Conditional Breakpoint...") - }, - order: 1, - when: CONTEXT_DEBUGGERS_AVAILABLE - }); MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, { group: '1_breakpoints', @@ -352,26 +315,6 @@ function registerDebugMenu(): void { when: CONTEXT_DEBUGGERS_AVAILABLE }); - MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, { - group: '1_breakpoints', - command: { - id: FUNCTION_BREAKPOINT_COMMAND_ID, - title: nls.localize({ key: 'miFunctionBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Function Breakpoint...") - }, - order: 3, - when: CONTEXT_DEBUGGERS_AVAILABLE - }); - - MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, { - group: '1_breakpoints', - command: { - id: ADD_LOG_POINT_ID, - title: nls.localize({ key: 'miLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Logpoint...") - }, - order: 4, - when: CONTEXT_DEBUGGERS_AVAILABLE - }); - MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, { group: '4_new_breakpoint', title: nls.localize({ key: 'miNewBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&New Breakpoint"), diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index d8ba1d55449..bb92347d7d7 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { Range } from 'vs/editor/common/core/range'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { ServicesAccessor, registerEditorAction, EditorAction, IActionOptions } from 'vs/editor/browser/editorExtensions'; +import { registerEditorAction, EditorAction, IActionOptions, EditorAction2 } from 'vs/editor/browser/editorExtensions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, WATCH_VIEW_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_EXCEPTION_WIDGET_VISIBLE } from 'vs/workbench/contrib/debug/common/debug'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -24,24 +24,35 @@ import { Position } from 'vs/editor/common/core/position'; import { URI } from 'vs/base/common/uri'; import { IDisposable } from 'vs/base/common/lifecycle'; import { raceTimeout } from 'vs/base/common/async'; +import { registerAction2, MenuId } from 'vs/platform/actions/common/actions'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -export const TOGGLE_BREAKPOINT_ID = 'editor.debug.action.toggleBreakpoint'; -class ToggleBreakpointAction extends EditorAction { +class ToggleBreakpointAction extends EditorAction2 { constructor() { super({ - id: TOGGLE_BREAKPOINT_ID, - label: nls.localize('toggleBreakpointAction', "Debug: Toggle Breakpoint"), - alias: 'Debug: Toggle Breakpoint', + id: 'editor.debug.action.toggleBreakpoint', + title: { + value: nls.localize('toggleBreakpointAction', "Debug: Toggle Breakpoint"), + original: 'Toggle Breakpoint', + mnemonicTitle: nls.localize({ key: 'miToggleBreakpoint', comment: ['&& denotes a mnemonic'] }, "Toggle &&Breakpoint") + }, + f1: true, precondition: CONTEXT_DEBUGGERS_AVAILABLE, - kbOpts: { - kbExpr: EditorContextKeys.editorTextFocus, + keybinding: { + when: EditorContextKeys.editorTextFocus, primary: KeyCode.F9, weight: KeybindingWeight.EditorContrib + }, + menu: { + when: CONTEXT_DEBUGGERS_AVAILABLE, + id: MenuId.MenubarDebugMenu, + group: '4_new_breakpoint', + order: 1 } }); } - async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise { + async runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: any[]): Promise { if (editor.hasModel()) { const debugService = accessor.get(IDebugService); const modelUri = editor.getModel().uri; @@ -49,33 +60,39 @@ class ToggleBreakpointAction extends EditorAction { // Does not account for multi line selections, Set to remove multiple cursor on the same line const lineNumbers = [...new Set(editor.getSelections().map(s => s.getPosition().lineNumber))]; - return Promise.all(lineNumbers.map(line => { + await Promise.all(lineNumbers.map(async line => { const bps = debugService.getModel().getBreakpoints({ lineNumber: line, uri: modelUri }); if (bps.length) { - return Promise.all(bps.map(bp => debugService.removeBreakpoints(bp.getId()))); + await Promise.all(bps.map(bp => debugService.removeBreakpoints(bp.getId()))); } else if (canSet) { - return (debugService.addBreakpoints(modelUri, [{ lineNumber: line }])); - } else { - return []; + await debugService.addBreakpoints(modelUri, [{ lineNumber: line }]); } })); } } } -export const TOGGLE_CONDITIONAL_BREAKPOINT_ID = 'editor.debug.action.conditionalBreakpoint'; -class ConditionalBreakpointAction extends EditorAction { - +class ConditionalBreakpointAction extends EditorAction2 { constructor() { super({ - id: TOGGLE_CONDITIONAL_BREAKPOINT_ID, - label: nls.localize('conditionalBreakpointEditorAction', "Debug: Add Conditional Breakpoint..."), - alias: 'Debug: Add Conditional Breakpoint...', - precondition: CONTEXT_DEBUGGERS_AVAILABLE + id: 'editor.debug.action.conditionalBreakpoint', + title: { + value: nls.localize('conditionalBreakpointEditorAction', "Debug: Add Conditional Breakpoint..."), + original: 'Debug: Add Conditional Breakpoint...', + mnemonicTitle: nls.localize({ key: 'miConditionalBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Conditional Breakpoint...") + }, + f1: true, + precondition: CONTEXT_DEBUGGERS_AVAILABLE, + menu: { + id: MenuId.MenubarNewBreakpointMenu, + group: '1_breakpoints', + order: 1, + when: CONTEXT_DEBUGGERS_AVAILABLE + } }); } - public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: any[]): void { const debugService = accessor.get(IDebugService); const position = editor.getPosition(); @@ -85,19 +102,28 @@ class ConditionalBreakpointAction extends EditorAction { } } -export const ADD_LOG_POINT_ID = 'editor.debug.action.addLogPoint'; -class LogPointAction extends EditorAction { +class LogPointAction extends EditorAction2 { constructor() { super({ - id: ADD_LOG_POINT_ID, - label: nls.localize('logPointEditorAction', "Debug: Add Logpoint..."), - alias: 'Debug: Add Logpoint...', - precondition: CONTEXT_DEBUGGERS_AVAILABLE + id: 'editor.debug.action.addLogPoint', + title: { + value: nls.localize('logPointEditorAction', "Debug: Add Logpoint..."), + original: 'Debug: Add Logpoint...', + mnemonicTitle: nls.localize({ key: 'miLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Logpoint...") + }, + precondition: CONTEXT_DEBUGGERS_AVAILABLE, + f1: true, + menu: { + id: MenuId.MenubarNewBreakpointMenu, + group: '1_breakpoints', + order: 4, + when: CONTEXT_DEBUGGERS_AVAILABLE + } }); } - public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: any[]): void { const debugService = accessor.get(IDebugService); const position = editor.getPosition(); @@ -476,9 +502,9 @@ class CloseExceptionWidgetAction extends EditorAction { } export function registerEditorActions(): void { - registerEditorAction(ToggleBreakpointAction); - registerEditorAction(ConditionalBreakpointAction); - registerEditorAction(LogPointAction); + registerAction2(ToggleBreakpointAction); + registerAction2(ConditionalBreakpointAction); + registerAction2(LogPointAction); registerEditorAction(RunToCursorAction); registerEditorAction(StepIntoTargetsAction); registerEditorAction(SelectionToReplAction); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 7a7a02001bd..d432d7678ff 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; import { IAction, IActionViewItem } from 'vs/base/common/actions'; -import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch, getStateLabel } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch, getStateLabel, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -193,7 +193,11 @@ registerAction2(class extends Action2 { constructor() { super({ id: DEBUG_CONFIGURE_COMMAND_ID, - title: DEBUG_CONFIGURE_LABEL, + title: { + value: DEBUG_CONFIGURE_LABEL, + original: DEBUG_CONFIGURE_LABEL, + mnemonicTitle: nls.localize({ key: 'miOpenConfigurations', comment: ['&& denotes a mnemonic'] }, "Open &&Configurations") + }, f1: true, icon: debugConfigure, precondition: CONTEXT_DEBUG_UX.notEqualsTo('simple'), @@ -208,6 +212,11 @@ registerAction2(class extends Action2 { order: 20, // Show in debug viewlet secondary actions when debugging and debug toolbar is docked when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID), CONTEXT_DEBUG_STATE.notEqualsTo('inactive'), ContextKeyExpr.equals('config.debug.toolBarLocation', 'docked')) + }, { + id: MenuId.MenubarDebugMenu, + group: '2_configuration', + order: 1, + when: CONTEXT_DEBUGGERS_AVAILABLE }] }); } @@ -246,7 +255,11 @@ registerAction2(class extends Action2 { constructor() { super({ id: OPEN_REPL_COMMAND_ID, - title: nls.localize('debugPanel', "Debug Console"), + title: { + value: nls.localize('debugPanel', "Debug Console"), + original: 'Debug Console', + mnemonicTitle: nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console") + }, f1: true, keybinding: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y, @@ -258,6 +271,10 @@ registerAction2(class extends Action2 { id: ViewsSubMenu, order: 30, when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('viewContainer', VIEWLET_ID)) + }, { + id: MenuId.MenubarViewMenu, + group: '4_panels', + order: 2 }] }); } From 990906a16554f59318e6c1fb65b45ea0c62d5ce0 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Mon, 11 Jan 2021 21:24:26 +0100 Subject: [PATCH 1802/1837] Adopt strict assertions --- .../base/parts/ipc/test/node/ipc.net.test.ts | 56 +- .../ui/scrollbar/scrollableElement.test.ts | 16 +- .../ui/scrollbar/scrollbarState.test.ts | 64 +- src/vs/base/test/common/buffer.test.ts | 138 +- src/vs/base/test/common/charCode.test.ts | 2 +- src/vs/base/test/common/diff/diff.test.ts | 14 +- src/vs/base/test/common/keyCodes.test.ts | 2 +- src/vs/base/test/common/scrollable.test.ts | 2 +- src/vs/base/test/common/strings.test.ts | 124 +- .../test/bracketMatching.test.ts | 56 +- .../comment/test/lineCommentCommand.test.ts | 62 +- .../cursorUndo/test/cursorUndo.test.ts | 14 +- src/vs/editor/contrib/find/test/find.test.ts | 18 +- .../contrib/find/test/findController.test.ts | 68 +- .../contrib/find/test/findModel.test.ts | 302 +-- .../contrib/find/test/replacePattern.test.ts | 18 +- .../test/copyLinesCommand.test.ts | 4 +- .../test/linesOperations.test.ts | 328 ++-- .../multicursor/test/multicursor.test.ts | 86 +- .../test/wordOperations.test.ts | 162 +- .../test/wordPartOperations.test.ts | 22 +- .../test/browser/standaloneLanguages.test.ts | 4 +- .../standalone/test/monarch/monarch.test.ts | 44 +- .../browser/commands/shiftCommand.test.ts | 4 +- .../test/browser/commands/sideEditing.test.ts | 6 +- .../trimTrailingWhitespaceCommand.test.ts | 4 +- .../test/browser/controller/cursor.test.ts | 658 +++---- .../controller/cursorMoveCommand.test.ts | 4 +- .../browser/controller/textAreaState.test.ts | 26 +- .../test/browser/core/editorState.test.ts | 12 +- .../services/decorationRenderOptions.test.ts | 14 +- .../browser/view/minimapCharRenderer.test.ts | 4 +- .../test/browser/view/viewLayer.test.ts | 10 +- .../common/config/commonEditorConfig.test.ts | 40 +- .../controller/cursorMoveHelper.test.ts | 60 +- .../common/core/characterClassifier.test.ts | 34 +- .../test/common/core/lineTokens.test.ts | 106 +- src/vs/editor/test/common/core/range.test.ts | 100 +- .../test/common/diff/diffComputer.test.ts | 2 +- .../common/model/editableTextModel.test.ts | 22 +- .../test/common/model/intervalTree.test.ts | 8 +- .../linesTextBuffer/linesTextBuffer.test.ts | 4 +- .../linesTextBufferBuilder.test.ts | 6 +- .../test/common/model/model.line.test.ts | 6 +- .../test/common/model/model.modes.test.ts | 6 +- src/vs/editor/test/common/model/model.test.ts | 188 +- .../common/model/modelDecorations.test.ts | 68 +- .../common/model/modelEditOperation.test.ts | 18 +- .../pieceTreeTextBuffer.test.ts | 356 ++-- .../test/common/model/textChange.test.ts | 4 +- .../test/common/model/textModel.test.ts | 438 ++--- .../test/common/model/textModelSearch.test.ts | 30 +- .../common/model/textModelWithTokens.test.ts | 24 +- .../test/common/model/tokensStore.test.ts | 16 +- .../modes/languageConfiguration.test.ts | 80 +- .../common/modes/languageSelector.test.ts | 90 +- .../test/common/modes/linkComputer.test.ts | 4 +- .../modes/supports/characterPair.test.ts | 104 +- .../modes/supports/electricCharacter.test.ts | 6 +- .../common/modes/supports/onEnter.test.ts | 14 +- .../modes/supports/richEditBrackets.test.ts | 38 +- .../modes/supports/tokenization.test.ts | 46 +- .../common/modes/textToHtmlTokenizer.test.ts | 26 +- .../services/editorSimpleWorker.test.ts | 38 +- .../common/services/languagesRegistry.test.ts | 136 +- .../test/common/services/modelService.test.ts | 36 +- .../common/view/overviewZoneManager.test.ts | 6 +- .../viewLayout/editorLayoutProvider.test.ts | 2 +- .../common/viewLayout/lineDecorations.test.ts | 22 +- .../common/viewLayout/linesLayout.test.ts | 1666 ++++++++--------- .../viewLayout/viewLineRenderer.test.ts | 82 +- .../monospaceLineBreaksComputer.test.ts | 24 +- .../viewModel/prefixSumComputer.test.ts | 206 +- .../viewModel/splitLinesCollection.test.ts | 232 +-- .../viewModel/viewModelDecorations.test.ts | 228 +-- .../common/viewModel/viewModelImpl.test.ts | 18 +- .../node/classification/typescript.test.ts | 2 +- .../test/browser/contextkey.test.ts | 8 +- .../contextkey/test/common/contextkey.test.ts | 30 +- .../common/abstractKeybindingService.test.ts | 110 +- .../test/common/keybindingLabels.test.ts | 8 +- .../test/common/keybindingResolver.test.ts | 44 +- .../test/common/undoRedoService.test.ts | 158 +- .../test/browser/extensionService.test.ts | 128 +- .../test/common/extensionsUtil.test.ts | 2 +- .../test/common/rpcProtocol.test.ts | 32 +- .../browser/browserKeyboardMapper.test.ts | 20 +- .../test/browser/keybindingIO.test.ts | 16 +- .../macLinuxKeyboardMapper.test.ts | 4 +- .../test/common/api/semanticTokensDto.test.ts | 4 +- 90 files changed, 3713 insertions(+), 3841 deletions(-) diff --git a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts index 0f395deb96e..d572f52f1f5 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts @@ -135,13 +135,13 @@ suite('IPC, Socket Protocol', () => { a.send(VSBuffer.fromString('foobarfarboo')); const msg1 = await bMessages.waitForOne(); - assert.equal(msg1.toString(), 'foobarfarboo'); + assert.strictEqual(msg1.toString(), 'foobarfarboo'); const buffer = VSBuffer.alloc(1); buffer.writeUInt8(123, 0); a.send(buffer); const msg2 = await bMessages.waitForOne(); - assert.equal(msg2.readUInt8(0), 123); + assert.strictEqual(msg2.readUInt8(0), 123); }); @@ -160,7 +160,7 @@ suite('IPC, Socket Protocol', () => { a.send(VSBuffer.fromString(JSON.stringify(data))); const msg = await bMessages.waitForOne(); - assert.deepEqual(JSON.parse(msg.toString()), data); + assert.deepStrictEqual(JSON.parse(msg.toString()), data); }); }); @@ -179,49 +179,49 @@ suite('PersistentProtocol reconnection', () => { const bMessages = new MessageStream(b); a.send(VSBuffer.fromString('a1')); - assert.equal(a.unacknowledgedCount, 1); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a.unacknowledgedCount, 1); + assert.strictEqual(b.unacknowledgedCount, 0); a.send(VSBuffer.fromString('a2')); - assert.equal(a.unacknowledgedCount, 2); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a.unacknowledgedCount, 2); + assert.strictEqual(b.unacknowledgedCount, 0); a.send(VSBuffer.fromString('a3')); - assert.equal(a.unacknowledgedCount, 3); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a.unacknowledgedCount, 3); + assert.strictEqual(b.unacknowledgedCount, 0); const a1 = await bMessages.waitForOne(); - assert.equal(a1.toString(), 'a1'); - assert.equal(a.unacknowledgedCount, 3); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a1.toString(), 'a1'); + assert.strictEqual(a.unacknowledgedCount, 3); + assert.strictEqual(b.unacknowledgedCount, 0); const a2 = await bMessages.waitForOne(); - assert.equal(a2.toString(), 'a2'); - assert.equal(a.unacknowledgedCount, 3); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a2.toString(), 'a2'); + assert.strictEqual(a.unacknowledgedCount, 3); + assert.strictEqual(b.unacknowledgedCount, 0); const a3 = await bMessages.waitForOne(); - assert.equal(a3.toString(), 'a3'); - assert.equal(a.unacknowledgedCount, 3); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(a3.toString(), 'a3'); + assert.strictEqual(a.unacknowledgedCount, 3); + assert.strictEqual(b.unacknowledgedCount, 0); b.send(VSBuffer.fromString('b1')); - assert.equal(a.unacknowledgedCount, 3); - assert.equal(b.unacknowledgedCount, 1); + assert.strictEqual(a.unacknowledgedCount, 3); + assert.strictEqual(b.unacknowledgedCount, 1); const b1 = await aMessages.waitForOne(); - assert.equal(b1.toString(), 'b1'); - assert.equal(a.unacknowledgedCount, 0); - assert.equal(b.unacknowledgedCount, 1); + assert.strictEqual(b1.toString(), 'b1'); + assert.strictEqual(a.unacknowledgedCount, 0); + assert.strictEqual(b.unacknowledgedCount, 1); a.send(VSBuffer.fromString('a4')); - assert.equal(a.unacknowledgedCount, 1); - assert.equal(b.unacknowledgedCount, 1); + assert.strictEqual(a.unacknowledgedCount, 1); + assert.strictEqual(b.unacknowledgedCount, 1); const b2 = await bMessages.waitForOne(); - assert.equal(b2.toString(), 'a4'); - assert.equal(a.unacknowledgedCount, 1); - assert.equal(b.unacknowledgedCount, 0); + assert.strictEqual(b2.toString(), 'a4'); + assert.strictEqual(a.unacknowledgedCount, 1); + assert.strictEqual(b.unacknowledgedCount, 0); }); }); diff --git a/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts b/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts index 46fc3edf1a7..14de7bb4599 100644 --- a/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts +++ b/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts @@ -53,7 +53,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, false); + assert.strictEqual(actual, false); } }); @@ -142,7 +142,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, false); + assert.strictEqual(actual, false); } }); @@ -202,7 +202,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, true); + assert.strictEqual(actual, true); } }); @@ -241,7 +241,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, true); + assert.strictEqual(actual, true); } }); @@ -285,7 +285,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, false); + assert.strictEqual(actual, false); } }); @@ -374,7 +374,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, true); + assert.strictEqual(actual, true); } }); @@ -464,7 +464,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, true); + assert.strictEqual(actual, true); } }); @@ -518,7 +518,7 @@ suite('MouseWheelClassifier', () => { classifier.accept(timestamp, deltaX, deltaY); const actual = classifier.isPhysicalMouseWheel(); - assert.equal(actual, true); + assert.strictEqual(actual, true); } }); }); diff --git a/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts b/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts index 4d3c0944a0c..f5813d84446 100644 --- a/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts +++ b/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts @@ -10,52 +10,52 @@ suite('ScrollbarState', () => { test('inflates slider size', () => { let actual = new ScrollbarState(0, 14, 0, 339, 42423, 32787); - assert.equal(actual.getArrowSize(), 0); - assert.equal(actual.getScrollPosition(), 32787); - assert.equal(actual.getRectangleLargeSize(), 339); - assert.equal(actual.getRectangleSmallSize(), 14); - assert.equal(actual.isNeeded(), true); - assert.equal(actual.getSliderSize(), 20); - assert.equal(actual.getSliderPosition(), 249); + assert.strictEqual(actual.getArrowSize(), 0); + assert.strictEqual(actual.getScrollPosition(), 32787); + assert.strictEqual(actual.getRectangleLargeSize(), 339); + assert.strictEqual(actual.getRectangleSmallSize(), 14); + assert.strictEqual(actual.isNeeded(), true); + assert.strictEqual(actual.getSliderSize(), 20); + assert.strictEqual(actual.getSliderPosition(), 249); - assert.equal(actual.getDesiredScrollPositionFromOffset(259), 32849); + assert.strictEqual(actual.getDesiredScrollPositionFromOffset(259), 32849); // 259 is greater than 230 so page down, 32787 + 339 = 33126 - assert.equal(actual.getDesiredScrollPositionFromOffsetPaged(259), 33126); + assert.strictEqual(actual.getDesiredScrollPositionFromOffsetPaged(259), 33126); actual.setScrollPosition(32849); - assert.equal(actual.getArrowSize(), 0); - assert.equal(actual.getScrollPosition(), 32849); - assert.equal(actual.getRectangleLargeSize(), 339); - assert.equal(actual.getRectangleSmallSize(), 14); - assert.equal(actual.isNeeded(), true); - assert.equal(actual.getSliderSize(), 20); - assert.equal(actual.getSliderPosition(), 249); + assert.strictEqual(actual.getArrowSize(), 0); + assert.strictEqual(actual.getScrollPosition(), 32849); + assert.strictEqual(actual.getRectangleLargeSize(), 339); + assert.strictEqual(actual.getRectangleSmallSize(), 14); + assert.strictEqual(actual.isNeeded(), true); + assert.strictEqual(actual.getSliderSize(), 20); + assert.strictEqual(actual.getSliderPosition(), 249); }); test('inflates slider size with arrows', () => { let actual = new ScrollbarState(12, 14, 0, 339, 42423, 32787); - assert.equal(actual.getArrowSize(), 12); - assert.equal(actual.getScrollPosition(), 32787); - assert.equal(actual.getRectangleLargeSize(), 339); - assert.equal(actual.getRectangleSmallSize(), 14); - assert.equal(actual.isNeeded(), true); - assert.equal(actual.getSliderSize(), 20); - assert.equal(actual.getSliderPosition(), 230); + assert.strictEqual(actual.getArrowSize(), 12); + assert.strictEqual(actual.getScrollPosition(), 32787); + assert.strictEqual(actual.getRectangleLargeSize(), 339); + assert.strictEqual(actual.getRectangleSmallSize(), 14); + assert.strictEqual(actual.isNeeded(), true); + assert.strictEqual(actual.getSliderSize(), 20); + assert.strictEqual(actual.getSliderPosition(), 230); - assert.equal(actual.getDesiredScrollPositionFromOffset(240 + 12), 32811); + assert.strictEqual(actual.getDesiredScrollPositionFromOffset(240 + 12), 32811); // 240 + 12 = 252; greater than 230 so page down, 32787 + 339 = 33126 - assert.equal(actual.getDesiredScrollPositionFromOffsetPaged(240 + 12), 33126); + assert.strictEqual(actual.getDesiredScrollPositionFromOffsetPaged(240 + 12), 33126); actual.setScrollPosition(32811); - assert.equal(actual.getArrowSize(), 12); - assert.equal(actual.getScrollPosition(), 32811); - assert.equal(actual.getRectangleLargeSize(), 339); - assert.equal(actual.getRectangleSmallSize(), 14); - assert.equal(actual.isNeeded(), true); - assert.equal(actual.getSliderSize(), 20); - assert.equal(actual.getSliderPosition(), 230); + assert.strictEqual(actual.getArrowSize(), 12); + assert.strictEqual(actual.getScrollPosition(), 32811); + assert.strictEqual(actual.getRectangleLargeSize(), 339); + assert.strictEqual(actual.getRectangleSmallSize(), 14); + assert.strictEqual(actual.isNeeded(), true); + assert.strictEqual(actual.getSliderSize(), 20); + assert.strictEqual(actual.getSliderPosition(), 230); }); }); diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index 1de31503e06..e0a03caf2eb 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -13,28 +13,28 @@ suite('Buffer', () => { test('issue #71993 - VSBuffer#toString returns numbers', () => { const data = new Uint8Array([1, 2, 3, 'h'.charCodeAt(0), 'i'.charCodeAt(0), 4, 5]).buffer; const buffer = VSBuffer.wrap(new Uint8Array(data, 3, 2)); - assert.deepEqual(buffer.toString(), 'hi'); + assert.deepStrictEqual(buffer.toString(), 'hi'); }); test('bufferToReadable / readableToBuffer', () => { const content = 'Hello World'; const readable = bufferToReadable(VSBuffer.fromString(content)); - assert.equal(readableToBuffer(readable).toString(), content); + assert.strictEqual(readableToBuffer(readable).toString(), content); }); test('bufferToStream / streamToBuffer', async () => { const content = 'Hello World'; const stream = bufferToStream(VSBuffer.fromString(content)); - assert.equal((await streamToBuffer(stream)).toString(), content); + assert.strictEqual((await streamToBuffer(stream)).toString(), content); }); test('bufferedStreamToBuffer', async () => { const content = 'Hello World'; const stream = await peekStream(bufferToStream(VSBuffer.fromString(content)), 1); - assert.equal((await bufferedStreamToBuffer(stream)).toString(), content); + assert.strictEqual((await bufferedStreamToBuffer(stream)).toString(), content); }); test('bufferWriteableStream - basics (no error)', async () => { @@ -60,11 +60,11 @@ suite('Buffer', () => { await timeout(0); stream.end(VSBuffer.fromString('World')); - assert.equal(chunks.length, 2); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(chunks[1].toString(), 'World'); - assert.equal(ended, true); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 2); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(chunks[1].toString(), 'World'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 0); }); test('bufferWriteableStream - basics (error)', async () => { @@ -90,10 +90,10 @@ suite('Buffer', () => { await timeout(0); stream.end(new Error()); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(ended, true); - assert.equal(errors.length, 1); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 1); }); test('bufferWriteableStream - buffers data when no listener', async () => { @@ -119,10 +119,10 @@ suite('Buffer', () => { errors.push(error); }); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'HelloWorld'); - assert.equal(ended, true); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'HelloWorld'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 0); }); test('bufferWriteableStream - buffers errors when no listener', async () => { @@ -150,10 +150,10 @@ suite('Buffer', () => { stream.end(); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(ended, true); - assert.equal(errors.length, 1); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 1); }); test('bufferWriteableStream - buffers end when no listener', async () => { @@ -179,10 +179,10 @@ suite('Buffer', () => { errors.push(error); }); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'HelloWorld'); - assert.equal(ended, true); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'HelloWorld'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 0); }); test('bufferWriteableStream - nothing happens after end()', async () => { @@ -220,13 +220,13 @@ suite('Buffer', () => { await timeout(0); stream.end(VSBuffer.fromString('World')); - assert.equal(dataCalledAfterEnd, false); - assert.equal(errorCalledAfterEnd, false); - assert.equal(endCalledAfterEnd, false); + assert.strictEqual(dataCalledAfterEnd, false); + assert.strictEqual(errorCalledAfterEnd, false); + assert.strictEqual(endCalledAfterEnd, false); - assert.equal(chunks.length, 2); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(chunks[1].toString(), 'World'); + assert.strictEqual(chunks.length, 2); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(chunks[1].toString(), 'World'); }); test('bufferWriteableStream - pause/resume (simple)', async () => { @@ -254,16 +254,16 @@ suite('Buffer', () => { await timeout(0); stream.end(VSBuffer.fromString('World')); - assert.equal(chunks.length, 0); - assert.equal(errors.length, 0); - assert.equal(ended, false); + assert.strictEqual(chunks.length, 0); + assert.strictEqual(errors.length, 0); + assert.strictEqual(ended, false); stream.resume(); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'HelloWorld'); - assert.equal(ended, true); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'HelloWorld'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 0); }); test('bufferWriteableStream - pause/resume (pause after first write)', async () => { @@ -292,18 +292,18 @@ suite('Buffer', () => { await timeout(0); stream.end(VSBuffer.fromString('World')); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(errors.length, 0); - assert.equal(ended, false); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(errors.length, 0); + assert.strictEqual(ended, false); stream.resume(); - assert.equal(chunks.length, 2); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(chunks[1].toString(), 'World'); - assert.equal(ended, true); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 2); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(chunks[1].toString(), 'World'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 0); }); test('bufferWriteableStream - pause/resume (error)', async () => { @@ -331,16 +331,16 @@ suite('Buffer', () => { await timeout(0); stream.end(new Error()); - assert.equal(chunks.length, 0); - assert.equal(ended, false); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 0); + assert.strictEqual(ended, false); + assert.strictEqual(errors.length, 0); stream.resume(); - assert.equal(chunks.length, 1); - assert.equal(chunks[0].toString(), 'Hello'); - assert.equal(ended, true); - assert.equal(errors.length, 1); + assert.strictEqual(chunks.length, 1); + assert.strictEqual(chunks[0].toString(), 'Hello'); + assert.strictEqual(ended, true); + assert.strictEqual(errors.length, 1); }); test('bufferWriteableStream - destroy', async () => { @@ -368,9 +368,9 @@ suite('Buffer', () => { await timeout(0); stream.end(VSBuffer.fromString('World')); - assert.equal(chunks.length, 0); - assert.equal(ended, false); - assert.equal(errors.length, 0); + assert.strictEqual(chunks.length, 0); + assert.strictEqual(ended, false); + assert.strictEqual(errors.length, 0); }); test('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042) @@ -378,36 +378,36 @@ suite('Buffer', () => { if (typeof Buffer !== 'undefined') { const buff = Buffer.from([10, 20, 30, 40]); const b2 = buff.slice(1, 3); - assert.equal(buff[1], 20); - assert.equal(b2[0], 20); + assert.strictEqual(buff[1], 20); + assert.strictEqual(b2[0], 20); buff[1] = 17; // modify buff AND b2 - assert.equal(buff[1], 17); - assert.equal(b2[0], 17); + assert.strictEqual(buff[1], 17); + assert.strictEqual(b2[0], 17); } // TypedArray#slice creates a copy { const unit = new Uint8Array([10, 20, 30, 40]); const u2 = unit.slice(1, 3); - assert.equal(unit[1], 20); - assert.equal(u2[0], 20); + assert.strictEqual(unit[1], 20); + assert.strictEqual(u2[0], 20); unit[1] = 17; // modify unit, NOT b2 - assert.equal(unit[1], 17); - assert.equal(u2[0], 20); + assert.strictEqual(unit[1], 17); + assert.strictEqual(u2[0], 20); } // TypedArray#subarray creates a view { const unit = new Uint8Array([10, 20, 30, 40]); const u2 = unit.subarray(1, 3); - assert.equal(unit[1], 20); - assert.equal(u2[0], 20); + assert.strictEqual(unit[1], 20); + assert.strictEqual(u2[0], 20); unit[1] = 17; // modify unit AND b2 - assert.equal(unit[1], 17); - assert.equal(u2[0], 17); + assert.strictEqual(unit[1], 17); + assert.strictEqual(u2[0], 17); } }); }); diff --git a/src/vs/base/test/common/charCode.test.ts b/src/vs/base/test/common/charCode.test.ts index a47ed336a2f..bf877878e1b 100644 --- a/src/vs/base/test/common/charCode.test.ts +++ b/src/vs/base/test/common/charCode.test.ts @@ -10,7 +10,7 @@ suite('CharCode', () => { test('has good values', () => { function assertValue(actual: CharCode, expected: string): void { - assert.equal(actual, expected.charCodeAt(0), 'char code ok for <<' + expected + '>>'); + assert.strictEqual(actual, expected.charCodeAt(0), 'char code ok for <<' + expected + '>>'); } assertValue(CharCode.Tab, '\t'); diff --git a/src/vs/base/test/common/diff/diff.test.ts b/src/vs/base/test/common/diff/diff.test.ts index ca40c679297..aa870c16e1a 100644 --- a/src/vs/base/test/common/diff/diff.test.ts +++ b/src/vs/base/test/common/diff/diff.test.ts @@ -49,11 +49,11 @@ function assertAnswer(originalStr: string, modifiedStr: string, changes: IDiffCh let modifiedAnswer = maskBasedSubstring(modifiedStr, modifiedMask); if (onlyLength) { - assert.equal(originalAnswer.length, answerStr.length); - assert.equal(modifiedAnswer.length, answerStr.length); + assert.strictEqual(originalAnswer.length, answerStr.length); + assert.strictEqual(modifiedAnswer.length, answerStr.length); } else { - assert.equal(originalAnswer, answerStr); - assert.equal(modifiedAnswer, answerStr); + assert.strictEqual(originalAnswer, answerStr); + assert.strictEqual(modifiedAnswer, answerStr); } } @@ -106,18 +106,18 @@ suite('Diff - Ported from VS', () => { let predicateCallCount = 0; let diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { - assert.equal(predicateCallCount, 0); + assert.strictEqual(predicateCallCount, 0); predicateCallCount++; - assert.equal(leftIndex, 1); + assert.strictEqual(leftIndex, 1); // cancel processing return false; }); let changes = diff.ComputeDiff(true).changes; - assert.equal(predicateCallCount, 1); + assert.strictEqual(predicateCallCount, 1); // Doesn't include 'c', 'd', or 'e', since we quit on the first request assertAnswer(left, right, changes, 'abf'); diff --git a/src/vs/base/test/common/keyCodes.test.ts b/src/vs/base/test/common/keyCodes.test.ts index f8b2b55a452..f5c5bcdcc31 100644 --- a/src/vs/base/test/common/keyCodes.test.ts +++ b/src/vs/base/test/common/keyCodes.test.ts @@ -10,7 +10,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; suite('keyCodes', () => { function testBinaryEncoding(expected: Keybinding | null, k: number, OS: OperatingSystem): void { - assert.deepEqual(createKeybinding(k, OS), expected); + assert.deepStrictEqual(createKeybinding(k, OS), expected); } test('MAC binary encoding', () => { diff --git a/src/vs/base/test/common/scrollable.test.ts b/src/vs/base/test/common/scrollable.test.ts index 820862f2f65..bf8e6cb000a 100644 --- a/src/vs/base/test/common/scrollable.test.ts +++ b/src/vs/base/test/common/scrollable.test.ts @@ -57,7 +57,7 @@ suite('SmoothScrollingOperation', () => { function assertSmoothScroll(from: number, to: number, expected: [number, number][]): void { const actual = simulateSmoothScroll(from, to); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('scroll 25 lines (40 fit)', () => { diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index d3366a1e5be..dc8d9da5e90 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -52,7 +52,7 @@ suite('Strings', () => { let expected = strings.compare(a.toLowerCase(), b.toLowerCase()); expected = expected > 0 ? 1 : expected < 0 ? -1 : expected; - assert.equal(actual, expected, `${a} <> ${b}`); + assert.strictEqual(actual, expected, `${a} <> ${b}`); if (recurse) { assertCompareIgnoreCase(b, a, false); @@ -89,7 +89,7 @@ suite('Strings', () => { let expected = strings.compare(a.toLowerCase().substring(aStart, aEnd), b.toLowerCase().substring(bStart, bEnd)); expected = expected > 0 ? 1 : expected < 0 ? -1 : expected; - assert.equal(actual, expected, `${a} <> ${b}`); + assert.strictEqual(actual, expected, `${a} <> ${b}`); if (recurse) { assertCompareIgnoreCase(b, a, bStart, bEnd, aStart, aEnd, false); @@ -188,36 +188,36 @@ suite('Strings', () => { }); test('containsRTL', () => { - assert.equal(strings.containsRTL('a'), false); - assert.equal(strings.containsRTL(''), false); - assert.equal(strings.containsRTL(strings.UTF8_BOM_CHARACTER + 'a'), false); - assert.equal(strings.containsRTL('hello world!'), false); - assert.equal(strings.containsRTL('a📚📚b'), false); - assert.equal(strings.containsRTL('هناك حقيقة مثبتة منذ زمن طويل'), true); - assert.equal(strings.containsRTL('זוהי עובדה מבוססת שדעתו'), true); + assert.strictEqual(strings.containsRTL('a'), false); + assert.strictEqual(strings.containsRTL(''), false); + assert.strictEqual(strings.containsRTL(strings.UTF8_BOM_CHARACTER + 'a'), false); + assert.strictEqual(strings.containsRTL('hello world!'), false); + assert.strictEqual(strings.containsRTL('a📚📚b'), false); + assert.strictEqual(strings.containsRTL('هناك حقيقة مثبتة منذ زمن طويل'), true); + assert.strictEqual(strings.containsRTL('זוהי עובדה מבוססת שדעתו'), true); }); test('containsEmoji', () => { - assert.equal(strings.containsEmoji('a'), false); - assert.equal(strings.containsEmoji(''), false); - assert.equal(strings.containsEmoji(strings.UTF8_BOM_CHARACTER + 'a'), false); - assert.equal(strings.containsEmoji('hello world!'), false); - assert.equal(strings.containsEmoji('هناك حقيقة مثبتة منذ زمن طويل'), false); - assert.equal(strings.containsEmoji('זוהי עובדה מבוססת שדעתו'), false); + assert.strictEqual(strings.containsEmoji('a'), false); + assert.strictEqual(strings.containsEmoji(''), false); + assert.strictEqual(strings.containsEmoji(strings.UTF8_BOM_CHARACTER + 'a'), false); + assert.strictEqual(strings.containsEmoji('hello world!'), false); + assert.strictEqual(strings.containsEmoji('هناك حقيقة مثبتة منذ زمن طويل'), false); + assert.strictEqual(strings.containsEmoji('זוהי עובדה מבוססת שדעתו'), false); - assert.equal(strings.containsEmoji('a📚📚b'), true); - assert.equal(strings.containsEmoji('1F600 # 😀 grinning face'), true); - assert.equal(strings.containsEmoji('1F47E # 👾 alien monster'), true); - assert.equal(strings.containsEmoji('1F467 1F3FD # 👧🏽 girl: medium skin tone'), true); - assert.equal(strings.containsEmoji('26EA # ⛪ church'), true); - assert.equal(strings.containsEmoji('231B # ⌛ hourglass'), true); - assert.equal(strings.containsEmoji('2702 # ✂ scissors'), true); - assert.equal(strings.containsEmoji('1F1F7 1F1F4 # 🇷🇴 Romania'), true); + assert.strictEqual(strings.containsEmoji('a📚📚b'), true); + assert.strictEqual(strings.containsEmoji('1F600 # 😀 grinning face'), true); + assert.strictEqual(strings.containsEmoji('1F47E # 👾 alien monster'), true); + assert.strictEqual(strings.containsEmoji('1F467 1F3FD # 👧🏽 girl: medium skin tone'), true); + assert.strictEqual(strings.containsEmoji('26EA # ⛪ church'), true); + assert.strictEqual(strings.containsEmoji('231B # ⌛ hourglass'), true); + assert.strictEqual(strings.containsEmoji('2702 # ✂ scissors'), true); + assert.strictEqual(strings.containsEmoji('1F1F7 1F1F4 # 🇷🇴 Romania'), true); }); test('isBasicASCII', () => { function assertIsBasicASCII(str: string, expected: boolean): void { - assert.equal(strings.isBasicASCII(str), expected, str + ` (${str.charCodeAt(0)})`); + assert.strictEqual(strings.isBasicASCII(str), expected, str + ` (${str.charCodeAt(0)})`); } assertIsBasicASCII('abcdefghijklmnopqrstuvwxyz', true); assertIsBasicASCII('ABCDEFGHIJKLMNOPQRSTUVWXYZ', true); @@ -245,16 +245,16 @@ suite('Strings', () => { assert.throws(() => strings.createRegExp('', false)); // Escapes appropriately - assert.equal(strings.createRegExp('abc', false).source, 'abc'); - assert.equal(strings.createRegExp('([^ ,.]*)', false).source, '\\(\\[\\^ ,\\.\\]\\*\\)'); - assert.equal(strings.createRegExp('([^ ,.]*)', true).source, '([^ ,.]*)'); + assert.strictEqual(strings.createRegExp('abc', false).source, 'abc'); + assert.strictEqual(strings.createRegExp('([^ ,.]*)', false).source, '\\(\\[\\^ ,\\.\\]\\*\\)'); + assert.strictEqual(strings.createRegExp('([^ ,.]*)', true).source, '([^ ,.]*)'); // Whole word - assert.equal(strings.createRegExp('abc', false, { wholeWord: true }).source, '\\babc\\b'); - assert.equal(strings.createRegExp('abc', true, { wholeWord: true }).source, '\\babc\\b'); - assert.equal(strings.createRegExp(' abc', true, { wholeWord: true }).source, ' abc\\b'); - assert.equal(strings.createRegExp('abc ', true, { wholeWord: true }).source, '\\babc '); - assert.equal(strings.createRegExp(' abc ', true, { wholeWord: true }).source, ' abc '); + assert.strictEqual(strings.createRegExp('abc', false, { wholeWord: true }).source, '\\babc\\b'); + assert.strictEqual(strings.createRegExp('abc', true, { wholeWord: true }).source, '\\babc\\b'); + assert.strictEqual(strings.createRegExp(' abc', true, { wholeWord: true }).source, ' abc\\b'); + assert.strictEqual(strings.createRegExp('abc ', true, { wholeWord: true }).source, '\\babc '); + assert.strictEqual(strings.createRegExp(' abc ', true, { wholeWord: true }).source, ' abc '); const regExpWithoutFlags = strings.createRegExp('abc', true); assert(!regExpWithoutFlags.global); @@ -284,15 +284,15 @@ suite('Strings', () => { }); test('getLeadingWhitespace', () => { - assert.equal(strings.getLeadingWhitespace(' foo'), ' '); - assert.equal(strings.getLeadingWhitespace(' foo', 2), ''); - assert.equal(strings.getLeadingWhitespace(' foo', 1, 1), ''); - assert.equal(strings.getLeadingWhitespace(' foo', 0, 1), ' '); - assert.equal(strings.getLeadingWhitespace(' '), ' '); - assert.equal(strings.getLeadingWhitespace(' ', 1), ' '); - assert.equal(strings.getLeadingWhitespace(' ', 0, 1), ' '); - assert.equal(strings.getLeadingWhitespace('\t\tfunction foo(){', 0, 1), '\t'); - assert.equal(strings.getLeadingWhitespace('\t\tfunction foo(){', 0, 2), '\t\t'); + assert.strictEqual(strings.getLeadingWhitespace(' foo'), ' '); + assert.strictEqual(strings.getLeadingWhitespace(' foo', 2), ''); + assert.strictEqual(strings.getLeadingWhitespace(' foo', 1, 1), ''); + assert.strictEqual(strings.getLeadingWhitespace(' foo', 0, 1), ' '); + assert.strictEqual(strings.getLeadingWhitespace(' '), ' '); + assert.strictEqual(strings.getLeadingWhitespace(' ', 1), ' '); + assert.strictEqual(strings.getLeadingWhitespace(' ', 0, 1), ' '); + assert.strictEqual(strings.getLeadingWhitespace('\t\tfunction foo(){', 0, 1), '\t'); + assert.strictEqual(strings.getLeadingWhitespace('\t\tfunction foo(){', 0, 2), '\t\t'); }); test('fuzzyContains', () => { @@ -316,11 +316,11 @@ suite('Strings', () => { }); test('stripUTF8BOM', () => { - assert.equal(strings.stripUTF8BOM(strings.UTF8_BOM_CHARACTER), ''); - assert.equal(strings.stripUTF8BOM(strings.UTF8_BOM_CHARACTER + 'foobar'), 'foobar'); - assert.equal(strings.stripUTF8BOM('foobar' + strings.UTF8_BOM_CHARACTER), 'foobar' + strings.UTF8_BOM_CHARACTER); - assert.equal(strings.stripUTF8BOM('abc'), 'abc'); - assert.equal(strings.stripUTF8BOM(''), ''); + assert.strictEqual(strings.stripUTF8BOM(strings.UTF8_BOM_CHARACTER), ''); + assert.strictEqual(strings.stripUTF8BOM(strings.UTF8_BOM_CHARACTER + 'foobar'), 'foobar'); + assert.strictEqual(strings.stripUTF8BOM('foobar' + strings.UTF8_BOM_CHARACTER), 'foobar' + strings.UTF8_BOM_CHARACTER); + assert.strictEqual(strings.stripUTF8BOM('abc'), 'abc'); + assert.strictEqual(strings.stripUTF8BOM(''), ''); }); test('containsUppercaseCharacter', () => { @@ -340,7 +340,7 @@ suite('Strings', () => { ['FöÖ', true], ['\\Foo', true], ].forEach(([str, result]) => { - assert.equal(strings.containsUppercaseCharacter(str), result, `Wrong result for ${str}`); + assert.strictEqual(strings.containsUppercaseCharacter(str), result, `Wrong result for ${str}`); }); }); @@ -352,7 +352,7 @@ suite('Strings', () => { ['Foo', true], ].forEach(([str, result]) => { - assert.equal(strings.containsUppercaseCharacter(str, true), result, `Wrong result for ${str}`); + assert.strictEqual(strings.containsUppercaseCharacter(str, true), result, `Wrong result for ${str}`); }); }); @@ -364,20 +364,20 @@ suite('Strings', () => { ['123', '123'], ['.a', '.a'], ].forEach(([inStr, result]) => { - assert.equal(strings.uppercaseFirstLetter(inStr), result, `Wrong result for ${inStr}`); + assert.strictEqual(strings.uppercaseFirstLetter(inStr), result, `Wrong result for ${inStr}`); }); }); test('getNLines', () => { - assert.equal(strings.getNLines('', 5), ''); - assert.equal(strings.getNLines('foo', 5), 'foo'); - assert.equal(strings.getNLines('foo\nbar', 5), 'foo\nbar'); - assert.equal(strings.getNLines('foo\nbar', 2), 'foo\nbar'); + assert.strictEqual(strings.getNLines('', 5), ''); + assert.strictEqual(strings.getNLines('foo', 5), 'foo'); + assert.strictEqual(strings.getNLines('foo\nbar', 5), 'foo\nbar'); + assert.strictEqual(strings.getNLines('foo\nbar', 2), 'foo\nbar'); - assert.equal(strings.getNLines('foo\nbar', 1), 'foo'); - assert.equal(strings.getNLines('foo\nbar'), 'foo'); - assert.equal(strings.getNLines('foo\nbar\nsomething', 2), 'foo\nbar'); - assert.equal(strings.getNLines('foo', 0), ''); + assert.strictEqual(strings.getNLines('foo\nbar', 1), 'foo'); + assert.strictEqual(strings.getNLines('foo\nbar'), 'foo'); + assert.strictEqual(strings.getNLines('foo\nbar\nsomething', 2), 'foo\nbar'); + assert.strictEqual(strings.getNLines('foo', 0), ''); }); test('encodeUTF8', function () { @@ -387,12 +387,12 @@ suite('Strings', () => { for (let offset = 0; offset < actual.byteLength; offset++) { actualArr[offset] = actual[offset]; } - assert.deepEqual(actualArr, expected); + assert.deepStrictEqual(actualArr, expected); } function assertDecodeUTF8(data: number[], expected: string): void { const actual = strings.decodeUTF8(new Uint8Array(data)); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } function assertEncodeDecodeUTF8(str: string, buff: number[]): void { @@ -415,11 +415,11 @@ suite('Strings', () => { }); test('getGraphemeBreakType', () => { - assert.equal(strings.getGraphemeBreakType(0xBC1), strings.GraphemeBreakType.SpacingMark); + assert.strictEqual(strings.getGraphemeBreakType(0xBC1), strings.GraphemeBreakType.SpacingMark); }); test('truncate', () => { - assert.equal('hello world', strings.truncate('hello world', 100)); - assert.equal('hello…', strings.truncate('hello world', 5)); + assert.strictEqual('hello world', strings.truncate('hello world', 100)); + assert.strictEqual('hello…', strings.truncate('hello world', 5)); }); }); diff --git a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts index 0a11a1a5f99..c59956eb220 100644 --- a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts +++ b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts @@ -39,20 +39,20 @@ suite('bracket matching', () => { // start on closing bracket editor.setPosition(new Position(1, 20)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 9)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 9)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 19)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 19)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 9)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 9)); // start on opening bracket editor.setPosition(new Position(1, 23)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 31)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 31)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 23)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 23)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 31)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 31)); bracketMatchingController.dispose(); }); @@ -71,25 +71,25 @@ suite('bracket matching', () => { // start position between brackets editor.setPosition(new Position(1, 16)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 18)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 18)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 14)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 14)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 18)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 18)); // skip brackets in comments editor.setPosition(new Position(1, 21)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 23)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 23)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 24)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 24)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 23)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 23)); // do not break if no brackets are available editor.setPosition(new Position(1, 26)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getPosition(), new Position(1, 26)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 26)); bracketMatchingController.dispose(); }); @@ -109,32 +109,32 @@ suite('bracket matching', () => { // start position in open brackets editor.setPosition(new Position(1, 9)); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getPosition(), new Position(1, 20)); - assert.deepEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 20)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); // start position in close brackets editor.setPosition(new Position(1, 20)); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getPosition(), new Position(1, 20)); - assert.deepEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 20)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); // start position between brackets editor.setPosition(new Position(1, 16)); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getPosition(), new Position(1, 19)); - assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 19)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 19)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 14, 1, 19)); // start position outside brackets editor.setPosition(new Position(1, 21)); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getPosition(), new Position(1, 25)); - assert.deepEqual(editor.getSelection(), new Selection(1, 23, 1, 25)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 25)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 23, 1, 25)); // do not break if no brackets are available editor.setPosition(new Position(1, 26)); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getPosition(), new Position(1, 26)); - assert.deepEqual(editor.getSelection(), new Selection(1, 26, 1, 26)); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 26)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 26, 1, 26)); bracketMatchingController.dispose(); }); @@ -159,7 +159,7 @@ suite('bracket matching', () => { editor.setPosition(new Position(3, 5)); bracketMatchingController.jumpToBracket(); - assert.deepEqual(editor.getSelection(), new Selection(5, 1, 5, 1)); + assert.deepStrictEqual(editor.getSelection(), new Selection(5, 1, 5, 1)); bracketMatchingController.dispose(); }); @@ -184,7 +184,7 @@ suite('bracket matching', () => { editor.setPosition(new Position(3, 5)); bracketMatchingController.selectToBracket(false); - assert.deepEqual(editor.getSelection(), new Selection(1, 12, 5, 1)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 12, 5, 1)); bracketMatchingController.dispose(); }); @@ -207,7 +207,7 @@ suite('bracket matching', () => { new Selection(1, 17, 1, 17) ]); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(1, 8, 1, 13), new Selection(1, 16, 1, 19) @@ -220,7 +220,7 @@ suite('bracket matching', () => { new Selection(1, 14, 1, 14) ]); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(1, 8, 1, 13), new Selection(1, 16, 1, 19) @@ -233,7 +233,7 @@ suite('bracket matching', () => { new Selection(1, 19, 1, 19) ]); bracketMatchingController.selectToBracket(true); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(1, 8, 1, 13), new Selection(1, 16, 1, 19) diff --git a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts index b27e6ae5da9..81b47f07584 100644 --- a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts +++ b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts @@ -96,25 +96,25 @@ suite('Editor Contrib - Line Comment Command', () => { throw new Error(`unexpected`); } - assert.equal(r.shouldRemoveComments, false); + assert.strictEqual(r.shouldRemoveComments, false); // Does not change `commentStr` - assert.equal(r.lines[0].commentStr, '//'); - assert.equal(r.lines[1].commentStr, 'rem'); - assert.equal(r.lines[2].commentStr, '!@#'); - assert.equal(r.lines[3].commentStr, '!@#'); + assert.strictEqual(r.lines[0].commentStr, '//'); + assert.strictEqual(r.lines[1].commentStr, 'rem'); + assert.strictEqual(r.lines[2].commentStr, '!@#'); + assert.strictEqual(r.lines[3].commentStr, '!@#'); // Fills in `isWhitespace` - assert.equal(r.lines[0].ignore, true); - assert.equal(r.lines[1].ignore, true); - assert.equal(r.lines[2].ignore, false); - assert.equal(r.lines[3].ignore, false); + assert.strictEqual(r.lines[0].ignore, true); + assert.strictEqual(r.lines[1].ignore, true); + assert.strictEqual(r.lines[2].ignore, false); + assert.strictEqual(r.lines[3].ignore, false); // Fills in `commentStrOffset` - assert.equal(r.lines[0].commentStrOffset, 2); - assert.equal(r.lines[1].commentStrOffset, 4); - assert.equal(r.lines[2].commentStrOffset, 4); - assert.equal(r.lines[3].commentStrOffset, 2); + assert.strictEqual(r.lines[0].commentStrOffset, 2); + assert.strictEqual(r.lines[1].commentStrOffset, 4); + assert.strictEqual(r.lines[2].commentStrOffset, 4); + assert.strictEqual(r.lines[3].commentStrOffset, 2); r = LineCommentCommand._analyzeLines(Type.Toggle, true, createSimpleModel([ @@ -127,31 +127,31 @@ suite('Editor Contrib - Line Comment Command', () => { throw new Error(`unexpected`); } - assert.equal(r.shouldRemoveComments, true); + assert.strictEqual(r.shouldRemoveComments, true); // Does not change `commentStr` - assert.equal(r.lines[0].commentStr, '//'); - assert.equal(r.lines[1].commentStr, 'rem'); - assert.equal(r.lines[2].commentStr, '!@#'); - assert.equal(r.lines[3].commentStr, '!@#'); + assert.strictEqual(r.lines[0].commentStr, '//'); + assert.strictEqual(r.lines[1].commentStr, 'rem'); + assert.strictEqual(r.lines[2].commentStr, '!@#'); + assert.strictEqual(r.lines[3].commentStr, '!@#'); // Fills in `isWhitespace` - assert.equal(r.lines[0].ignore, true); - assert.equal(r.lines[1].ignore, false); - assert.equal(r.lines[2].ignore, false); - assert.equal(r.lines[3].ignore, false); + assert.strictEqual(r.lines[0].ignore, true); + assert.strictEqual(r.lines[1].ignore, false); + assert.strictEqual(r.lines[2].ignore, false); + assert.strictEqual(r.lines[3].ignore, false); // Fills in `commentStrOffset` - assert.equal(r.lines[0].commentStrOffset, 2); - assert.equal(r.lines[1].commentStrOffset, 4); - assert.equal(r.lines[2].commentStrOffset, 4); - assert.equal(r.lines[3].commentStrOffset, 2); + assert.strictEqual(r.lines[0].commentStrOffset, 2); + assert.strictEqual(r.lines[1].commentStrOffset, 4); + assert.strictEqual(r.lines[2].commentStrOffset, 4); + assert.strictEqual(r.lines[3].commentStrOffset, 2); // Fills in `commentStrLength` - assert.equal(r.lines[0].commentStrLength, 2); - assert.equal(r.lines[1].commentStrLength, 4); - assert.equal(r.lines[2].commentStrLength, 4); - assert.equal(r.lines[3].commentStrLength, 3); + assert.strictEqual(r.lines[0].commentStrLength, 2); + assert.strictEqual(r.lines[1].commentStrLength, 4); + assert.strictEqual(r.lines[2].commentStrLength, 4); + assert.strictEqual(r.lines[3].commentStrLength, 3); }); test('_normalizeInsertionPoint', () => { @@ -166,7 +166,7 @@ suite('Editor Contrib - Line Comment Command', () => { }); LineCommentCommand._normalizeInsertionPoint(model, offsets, 1, tabSize); const actual = offsets.map(item => item.commentStrOffset); - assert.deepEqual(actual, expected, testName); + assert.deepStrictEqual(actual, expected, testName); }; // Bug 16696:[comment] comments not aligned in this case diff --git a/src/vs/editor/contrib/cursorUndo/test/cursorUndo.test.ts b/src/vs/editor/contrib/cursorUndo/test/cursorUndo.test.ts index 308484142e9..4a398b4982e 100644 --- a/src/vs/editor/contrib/cursorUndo/test/cursorUndo.test.ts +++ b/src/vs/editor/contrib/cursorUndo/test/cursorUndo.test.ts @@ -29,16 +29,16 @@ suite('FindController', () => { // press Delete CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, {}); - assert.deepEqual(editor.getValue(), 'hell'); - assert.deepEqual(editor.getSelections(), [new Selection(1, 5, 1, 5)]); + assert.deepStrictEqual(editor.getValue(), 'hell'); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 5, 1, 5)]); // press left CoreNavigationCommands.CursorLeft.runEditorCommand(null, editor, {}); - assert.deepEqual(editor.getSelections(), [new Selection(1, 4, 1, 4)]); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 4, 1, 4)]); // press Ctrl+U cursorUndoAction.run(null!, editor, {}); - assert.deepEqual(editor.getSelections(), [new Selection(1, 5, 1, 5)]); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 5, 1, 5)]); }); }); @@ -52,12 +52,12 @@ suite('FindController', () => { // type hello editor.trigger('test', Handler.Type, { text: 'hell' }); editor.trigger('test', Handler.Type, { text: 'o' }); - assert.deepEqual(editor.getValue(), 'hello'); - assert.deepEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); + assert.deepStrictEqual(editor.getValue(), 'hello'); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); // press Ctrl+U cursorUndoAction.run(null!, editor, {}); - assert.deepEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); }); }); }); diff --git a/src/vs/editor/contrib/find/test/find.test.ts b/src/vs/editor/contrib/find/test/find.test.ts index 98f31f328cb..55490860dc4 100644 --- a/src/vs/editor/contrib/find/test/find.test.ts +++ b/src/vs/editor/contrib/find/test/find.test.ts @@ -20,17 +20,17 @@ suite('Find', () => { // The cursor is at the very top, of the file, at the first ABC let searchStringAtTop = getSelectionSearchString(editor); - assert.equal(searchStringAtTop, 'ABC'); + assert.strictEqual(searchStringAtTop, 'ABC'); // Move cursor to the end of ABC editor.setPosition(new Position(1, 3)); let searchStringAfterABC = getSelectionSearchString(editor); - assert.equal(searchStringAfterABC, 'ABC'); + assert.strictEqual(searchStringAfterABC, 'ABC'); // Move cursor to DEF editor.setPosition(new Position(1, 5)); let searchStringInsideDEF = getSelectionSearchString(editor); - assert.equal(searchStringInsideDEF, 'DEF'); + assert.strictEqual(searchStringInsideDEF, 'DEF'); }); }); @@ -44,17 +44,17 @@ suite('Find', () => { // Select A of ABC editor.setSelection(new Range(1, 1, 1, 2)); let searchStringSelectionA = getSelectionSearchString(editor); - assert.equal(searchStringSelectionA, 'A'); + assert.strictEqual(searchStringSelectionA, 'A'); // Select BC of ABC editor.setSelection(new Range(1, 2, 1, 4)); let searchStringSelectionBC = getSelectionSearchString(editor); - assert.equal(searchStringSelectionBC, 'BC'); + assert.strictEqual(searchStringSelectionBC, 'BC'); // Select BC DE editor.setSelection(new Range(1, 2, 1, 7)); let searchStringSelectionBCDE = getSelectionSearchString(editor); - assert.equal(searchStringSelectionBCDE, 'BC DE'); + assert.strictEqual(searchStringSelectionBCDE, 'BC DE'); }); }); @@ -68,17 +68,17 @@ suite('Find', () => { // Select first line and newline editor.setSelection(new Range(1, 1, 2, 1)); let searchStringSelectionWholeLine = getSelectionSearchString(editor); - assert.equal(searchStringSelectionWholeLine, null); + assert.strictEqual(searchStringSelectionWholeLine, null); // Select first line and chunk of second editor.setSelection(new Range(1, 1, 2, 4)); let searchStringSelectionTwoLines = getSelectionSearchString(editor); - assert.equal(searchStringSelectionTwoLines, null); + assert.strictEqual(searchStringSelectionTwoLines, null); // Select end of first line newline and chunk of second editor.setSelection(new Range(1, 7, 2, 4)); let searchStringSelectionSpanLines = getSelectionSearchString(editor); - assert.equal(searchStringSelectionSpanLines, null); + assert.strictEqual(searchStringSelectionSpanLines, null); }); }); diff --git a/src/vs/editor/contrib/find/test/findController.test.ts b/src/vs/editor/contrib/find/test/findController.test.ts index 8d9216ea0c8..3f55711c155 100644 --- a/src/vs/editor/contrib/find/test/findController.test.ts +++ b/src/vs/editor/contrib/find/test/findController.test.ts @@ -102,7 +102,7 @@ suite('FindController', async () => { // I hit Ctrl+F to show the Find dialog startFindAction.run(null, editor); - assert.deepEqual(findController.getGlobalBufferTerm(), findController.getState().searchString); + assert.deepStrictEqual(findController.getGlobalBufferTerm(), findController.getState().searchString); findController.dispose(); }); }); @@ -126,9 +126,9 @@ suite('FindController', async () => { let nextMatchFindAction = new NextMatchFindAction(); nextMatchFindAction.run(null, editor); - assert.equal(findState.searchString, 'ABC'); + assert.strictEqual(findState.searchString, 'ABC'); - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); findController.dispose(); }); @@ -152,7 +152,7 @@ suite('FindController', async () => { findState.change({ searchString: 'ABC' }, true); - assert.deepEqual(findController.getGlobalBufferTerm(), 'ABC'); + assert.deepStrictEqual(findController.getGlobalBufferTerm(), 'ABC'); findController.dispose(); }); @@ -181,14 +181,14 @@ suite('FindController', async () => { findState.change({ searchString: 'ABC' }, true); // The first ABC is highlighted. - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); // I hit Esc to exit the Find dialog. findController.closeFindWidget(); findController.hasFocus = false; // The cursor is now at end of the first line, with ABC on that line highlighted. - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 1, 1, 4]); // I hit delete to remove it and change the text to XYZ. editor.pushUndoStop(); @@ -201,16 +201,16 @@ suite('FindController', async () => { // ABC // XYZ // ABC - assert.equal(editor.getModel()!.getLineContent(1), 'XYZ'); + assert.strictEqual(editor.getModel()!.getLineContent(1), 'XYZ'); // The cursor is at end of the first line. - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 4, 1, 4]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 4, 1, 4]); // I hit F3 to "Find Next" to find the next occurrence of ABC, but instead it searches for XYZ. await nextMatchFindAction.run(null, editor); - assert.equal(findState.searchString, 'ABC'); - assert.equal(findController.hasFocus, false); + assert.strictEqual(findState.searchString, 'ABC'); + assert.strictEqual(findController.hasFocus, false); findController.dispose(); }); @@ -230,10 +230,10 @@ suite('FindController', async () => { }); await nextMatchFindAction.run(null, editor); - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 26, 1, 29]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 26, 1, 29]); await nextMatchFindAction.run(null, editor); - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 8, 1, 11]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 8, 1, 11]); findController.dispose(); }); @@ -256,10 +256,10 @@ suite('FindController', async () => { await startFindAction.run(null, editor); await nextMatchFindAction.run(null, editor); - assert.deepEqual(fromSelection(editor.getSelection()!), [2, 9, 2, 13]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [2, 9, 2, 13]); await nextMatchFindAction.run(null, editor); - assert.deepEqual(fromSelection(editor.getSelection()!), [1, 9, 1, 13]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [1, 9, 1, 13]); findController.dispose(); }); @@ -288,7 +288,7 @@ suite('FindController', async () => { await nextMatchFindAction.run(null, editor); await startFindReplaceAction.run(null, editor); - assert.equal(findController.getState().searchString, testRegexString); + assert.strictEqual(findController.getState().searchString, testRegexString); findController.dispose(); }); @@ -312,16 +312,16 @@ suite('FindController', async () => { loop: true }); - assert.equal(findController.getState().searchScope, null); + assert.strictEqual(findController.getState().searchScope, null); findController.getState().change({ searchScope: [new Range(1, 1, 1, 5)] }, false); - assert.deepEqual(findController.getState().searchScope, [new Range(1, 1, 1, 5)]); + assert.deepStrictEqual(findController.getState().searchScope, [new Range(1, 1, 1, 5)]); findController.closeFindWidget(); - assert.equal(findController.getState().searchScope, null); + assert.strictEqual(findController.getState().searchScope, null); }); }); @@ -338,13 +338,13 @@ suite('FindController', async () => { findController.getState().change({ searchString: '\\b\\s{3}\\b', replaceString: ' ', isRegex: true }, false); findController.moveToNextMatch(); - assert.deepEqual(editor.getSelections()!.map(fromSelection), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromSelection), [ [1, 39, 1, 42] ]); findController.replace(); - assert.deepEqual(editor.getValue(), 'HRESULT OnAmbientPropertyChange(DISPID dispid);'); + assert.deepStrictEqual(editor.getValue(), 'HRESULT OnAmbientPropertyChange(DISPID dispid);'); findController.dispose(); }); @@ -365,13 +365,13 @@ suite('FindController', async () => { findController.getState().change({ searchString: '^', replaceString: 'x', isRegex: true }, false); findController.moveToNextMatch(); - assert.deepEqual(editor.getSelections()!.map(fromSelection), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromSelection), [ [2, 1, 2, 1] ]); findController.replace(); - assert.deepEqual(editor.getValue(), '\nxline2\nline3'); + assert.deepStrictEqual(editor.getValue(), '\nxline2\nline3'); findController.dispose(); }); @@ -396,7 +396,7 @@ suite('FindController', async () => { // cmd+f3 await nextSelectionMatchFindAction.run(null, editor); - assert.deepEqual(editor.getSelections()!.map(fromSelection), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromSelection), [ [3, 1, 3, 9] ]); @@ -427,7 +427,7 @@ suite('FindController', async () => { // cmd+f3 await nextSelectionMatchFindAction.run(null, editor); - assert.deepEqual(editor.getSelections()!.map(fromSelection), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromSelection), [ [3, 1, 3, 9] ]); @@ -458,7 +458,7 @@ suite('FindController', async () => { await startFindWithSelectionAction.run(null, editor); let findState = findController.getState(); - assert.deepEqual(findState.searchString.split(/\r\n|\r|\n/g), ['ABC', 'ABC']); + assert.deepStrictEqual(findState.searchString.split(/\r\n|\r|\n/g), ['ABC', 'ABC']); editor.setSelection(new Selection(3, 1, 3, 1)); await startFindWithSelectionAction.run(null, editor); @@ -483,7 +483,7 @@ suite('FindController', async () => { startFindWithSelectionAction.run(null, editor); let findState = findController.getState(); - assert.deepEqual(findState.searchString, 'ABC'); + assert.deepStrictEqual(findState.searchString, 'ABC'); findController.dispose(); }); }); @@ -531,7 +531,7 @@ suite('FindController query options persistence', async () => { // I type ABC. findState.change({ searchString: 'ABC' }, true); // The second ABC is highlighted as matchCase is true. - assert.deepEqual(fromSelection(editor.getSelection()!), [2, 1, 2, 4]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [2, 1, 2, 4]); findController.dispose(); }); @@ -558,7 +558,7 @@ suite('FindController query options persistence', async () => { // I type AB. findState.change({ searchString: 'AB' }, true); // The second AB is highlighted as wholeWord is true. - assert.deepEqual(fromSelection(editor.getSelection()!), [2, 1, 2, 3]); + assert.deepStrictEqual(fromSelection(editor.getSelection()!), [2, 1, 2, 3]); findController.dispose(); }); @@ -575,7 +575,7 @@ suite('FindController query options persistence', async () => { // The cursor is at the very top, of the file, at the first ABC let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController); findController.toggleRegex(); - assert.equal(queryState['editor.isRegex'], true); + assert.strictEqual(queryState['editor.isRegex'], true); findController.dispose(); }); @@ -601,13 +601,13 @@ suite('FindController query options persistence', async () => { editor.setSelection(new Range(1, 1, 2, 1)); findController.start(findConfig); - assert.deepEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1)]); + assert.deepStrictEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1)]); findController.closeFindWidget(); editor.setSelections([new Selection(1, 1, 2, 1), new Selection(2, 1, 2, 5)]); findController.start(findConfig); - assert.deepEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1), new Selection(2, 1, 2, 5)]); + assert.deepStrictEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1), new Selection(2, 1, 2, 5)]); }); }); @@ -631,7 +631,7 @@ suite('FindController query options persistence', async () => { loop: true }); - assert.deepEqual(findController.getState().searchScope, null); + assert.deepStrictEqual(findController.getState().searchScope, null); }); }); @@ -655,7 +655,7 @@ suite('FindController query options persistence', async () => { loop: true }); - assert.deepEqual(findController.getState().searchScope, [new Selection(1, 2, 1, 3)]); + assert.deepStrictEqual(findController.getState().searchScope, [new Selection(1, 2, 1, 3)]); }); }); @@ -680,7 +680,7 @@ suite('FindController query options persistence', async () => { loop: true }); - assert.deepEqual(findController.getState().searchScope, [new Selection(1, 6, 2, 1)]); + assert.deepStrictEqual(findController.getState().searchScope, [new Selection(1, 6, 2, 1)]); }); }); }); diff --git a/src/vs/editor/contrib/find/test/findModel.test.ts b/src/vs/editor/contrib/find/test/findModel.test.ts index 70c5494985a..10c7ae32628 100644 --- a/src/vs/editor/contrib/find/test/findModel.test.ts +++ b/src/vs/editor/contrib/find/test/findModel.test.ts @@ -81,13 +81,13 @@ suite('FindModel', () => { } function assertFindState(editor: ICodeEditor, cursor: number[], highlighted: number[] | null, findDecorations: number[][]): void { - assert.deepEqual(fromRange(editor.getSelection()!), cursor, 'cursor'); + assert.deepStrictEqual(fromRange(editor.getSelection()!), cursor, 'cursor'); let expectedState = { highlighted: highlighted ? [highlighted] : [], findDecorations: findDecorations }; - assert.deepEqual(_getFindState(editor), expectedState, 'state'); + assert.deepStrictEqual(_getFindState(editor), expectedState, 'state'); } findTest('incremental find from beginning of file', (editor) => { @@ -245,7 +245,7 @@ suite('FindModel', () => { findState.change({ searchString: 'hello' }, false); let findModel = new FindModelBoundToEditorModel(editor, findState); - assert.equal(findState.matchesCount, 5); + assert.strictEqual(findState.matchesCount, 5); assertFindState( editor, [1, 1, 1, 1], @@ -275,7 +275,7 @@ suite('FindModel', () => { findState.change({ searchString: 'hello' }, false); let findModel = new FindModelBoundToEditorModel(editor, findState); - assert.equal(findState.matchesCount, 5); + assert.strictEqual(findState.matchesCount, 5); assertFindState( editor, [1, 1, 1, 1], @@ -290,7 +290,7 @@ suite('FindModel', () => { ); findState.change({ searchString: 'helloo' }, false); - assert.equal(findState.matchesCount, 0); + assert.strictEqual(findState.matchesCount, 0); assertFindState( editor, [1, 1, 1, 1], @@ -1306,7 +1306,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1320,7 +1320,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1333,7 +1333,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, hi!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, hi!" << endl;'); findModel.replace(); assertFindState( @@ -1345,7 +1345,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); findModel.replace(); assertFindState( @@ -1356,7 +1356,7 @@ suite('FindModel', () => { [6, 14, 6, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); findModel.replace(); assertFindState( @@ -1365,7 +1365,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, hi!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, hi!" << endl;'); findModel.dispose(); findState.dispose(); @@ -1398,7 +1398,7 @@ suite('FindModel', () => { [11, 10, 11, 13] ] ); - assert.equal(editor.getModel()!.getLineContent(11), '// blablablaciao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// blablablaciao'); findModel.replace(); assertFindState( @@ -1410,7 +1410,7 @@ suite('FindModel', () => { [11, 11, 11, 14] ] ); - assert.equal(editor.getModel()!.getLineContent(11), '// ciaoblablaciao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// ciaoblablaciao'); findModel.replace(); assertFindState( @@ -1421,7 +1421,7 @@ suite('FindModel', () => { [11, 12, 11, 15] ] ); - assert.equal(editor.getModel()!.getLineContent(11), '// ciaociaoblaciao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// ciaociaoblaciao'); findModel.replace(); assertFindState( @@ -1430,7 +1430,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(11), '// ciaociaociaociao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// ciaociaociaociao'); findModel.dispose(); findState.dispose(); @@ -1467,7 +1467,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); findModel.replaceAll(); assertFindState( @@ -1476,9 +1476,9 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, hi!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, hi!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); findModel.dispose(); findState.dispose(); @@ -1517,10 +1517,10 @@ suite('FindModel', () => { [9, 1, 9, 3] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hello world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "Hello world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(9), ' cout << "helloworld again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hello world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "Hello world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(9), ' cout << "helloworld again" << endl;'); findModel.dispose(); findState.dispose(); @@ -1549,7 +1549,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(11), '// ciaociaociaociao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// ciaociaociaociao'); findModel.dispose(); findState.dispose(); @@ -1578,10 +1578,10 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(11), '// <'); - assert.equal(editor.getModel()!.getLineContent(12), '\t><'); - assert.equal(editor.getModel()!.getLineContent(13), '\t><'); - assert.equal(editor.getModel()!.getLineContent(14), '\t>ciao'); + assert.strictEqual(editor.getModel()!.getLineContent(11), '// <'); + assert.strictEqual(editor.getModel()!.getLineContent(12), '\t><'); + assert.strictEqual(editor.getModel()!.getLineContent(13), '\t><'); + assert.strictEqual(editor.getModel()!.getLineContent(14), '\t>ciao'); findModel.dispose(); findState.dispose(); @@ -1610,8 +1610,8 @@ suite('FindModel', () => { [] ); - assert.equal(editor.getModel()!.getLineContent(2), '#bar "cool.h"'); - assert.equal(editor.getModel()!.getLineContent(3), '#bar '); + assert.strictEqual(editor.getModel()!.getLineContent(2), '#bar "cool.h"'); + assert.strictEqual(editor.getModel()!.getLineContent(3), '#bar '); findModel.dispose(); findState.dispose(); @@ -1665,7 +1665,7 @@ suite('FindModel', () => { findModel.selectAllMatches(); - assert.deepEqual(editor!.getSelections()!.map(s => s.toString()), [ + assert.deepStrictEqual(editor!.getSelections()!.map(s => s.toString()), [ new Selection(6, 14, 6, 19), new Selection(6, 27, 6, 32), new Selection(7, 14, 7, 19), @@ -1709,14 +1709,14 @@ suite('FindModel', () => { findModel.selectAllMatches(); - assert.deepEqual(editor!.getSelections()!.map(s => s.toString()), [ + assert.deepStrictEqual(editor!.getSelections()!.map(s => s.toString()), [ new Selection(7, 14, 7, 19), new Selection(6, 14, 6, 19), new Selection(6, 27, 6, 32), new Selection(8, 14, 8, 19) ].map(s => s.toString())); - assert.deepEqual(editor!.getSelection()!.toString(), new Selection(7, 14, 7, 19).toString()); + assert.deepStrictEqual(editor!.getSelection()!.toString(), new Selection(7, 14, 7, 19).toString()); assertFindState( editor, @@ -1800,7 +1800,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1812,7 +1812,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1823,7 +1823,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); findModel.replace(); assertFindState( @@ -1832,7 +1832,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); findModel.dispose(); findState.dispose(); @@ -1871,7 +1871,7 @@ suite('FindModel', () => { ] ); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "Hello world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "Hello world again" << endl;'); findModel.replace(); assertFindState( @@ -1883,7 +1883,7 @@ suite('FindModel', () => { [7, 14, 7, 19], ] ); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); findModel.replace(); assertFindState( @@ -1894,7 +1894,7 @@ suite('FindModel', () => { [7, 14, 7, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1903,7 +1903,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); findModel.dispose(); findState.dispose(); @@ -1927,9 +1927,9 @@ suite('FindModel', () => { findModel.replaceAll(); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hi world again" << endl;'); assertFindState( editor, @@ -1970,7 +1970,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1982,7 +1982,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hilo world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hilo world, Hello!" << endl;'); findModel.replace(); assertFindState( @@ -1993,7 +1993,7 @@ suite('FindModel', () => { [8, 14, 8, 19] ] ); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hilo world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hilo world again" << endl;'); findModel.replace(); assertFindState( @@ -2002,7 +2002,7 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "hilo world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "hilo world again" << endl;'); findModel.dispose(); findState.dispose(); @@ -2027,10 +2027,10 @@ suite('FindModel', () => { findModel.replaceAll(); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello girl, Hello!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hello girl again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "Hello girl again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(9), ' cout << "hellogirl again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello girl, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hello girl again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "Hello girl again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(9), ' cout << "hellogirl again" << endl;'); assertFindState( editor, @@ -2060,8 +2060,8 @@ suite('FindModel', () => { findModel.replaceAll(); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hello girl, Hello!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "Hello girl again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hello girl, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "Hello girl again" << endl;'); assertFindState( editor, @@ -2094,10 +2094,10 @@ suite('FindModel', () => { findModel.replaceAll(); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "goodbye world, Goodbye!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "goodbye world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << "Goodbye world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(9), ' cout << "goodbyeworld again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "goodbye world, Goodbye!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "goodbye world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << "Goodbye world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(9), ' cout << "goodbyeworld again" << endl;'); assertFindState( editor, @@ -2134,9 +2134,9 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << " world, !" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << " world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(8), ' cout << " world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << " world, !" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << " world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(8), ' cout << " world again" << endl;'); findModel.dispose(); findState.dispose(); @@ -2159,7 +2159,7 @@ suite('FindModel', () => { expectedText += 'a line' + i + '\n'; } expectedText += 'a '; - assert.equal(editor!.getModel()!.getValue(), expectedText); + assert.strictEqual(editor!.getModel()!.getValue(), expectedText); findModel.dispose(); findState.dispose(); @@ -2188,9 +2188,9 @@ suite('FindModel', () => { null, [] ); - assert.equal(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); - assert.equal(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); - assert.equal(editor.getModel()!.getLineContent(9), ' cout << "hiworld again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(6), ' cout << "hi world, Hello!" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(7), ' cout << "hi world again" << endl;'); + assert.strictEqual(editor.getModel()!.getLineContent(9), ' cout << "hiworld again" << endl;'); findModel.dispose(); findState.dispose(); @@ -2219,78 +2219,78 @@ suite('FindModel', () => { findState.change({ searchString: 'hello', loop: false }, false); let findModel = new FindModelBoundToEditorModel(editor, findState); - assert.equal(findState.matchesCount, 5); + assert.strictEqual(findState.matchesCount, 5); // Test next operations - assert.equal(findState.matchesPosition, 0); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 0); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), false); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), false); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 2); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 2); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 3); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 3); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 4); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 4); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 5); - assert.equal(findState.canNavigateForward(), false); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 5); + assert.strictEqual(findState.canNavigateForward(), false); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 5); - assert.equal(findState.canNavigateForward(), false); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 5); + assert.strictEqual(findState.canNavigateForward(), false); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 5); - assert.equal(findState.canNavigateForward(), false); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 5); + assert.strictEqual(findState.canNavigateForward(), false); + assert.strictEqual(findState.canNavigateBack(), true); // Test previous operations findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 4); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 4); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 3); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 3); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 2); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 2); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), false); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), false); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), false); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), false); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), false); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), false); }); @@ -2299,78 +2299,78 @@ suite('FindModel', () => { findState.change({ searchString: 'hello' }, false); let findModel = new FindModelBoundToEditorModel(editor, findState); - assert.equal(findState.matchesCount, 5); + assert.strictEqual(findState.matchesCount, 5); // Test next operations - assert.equal(findState.matchesPosition, 0); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 0); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 2); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 2); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 3); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 3); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 4); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 4); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 5); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 5); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToNextMatch(); - assert.equal(findState.matchesPosition, 2); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 2); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); // Test previous operations findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 5); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 5); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 4); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 4); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 3); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 3); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 2); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 2); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); findModel.moveToPrevMatch(); - assert.equal(findState.matchesPosition, 1); - assert.equal(findState.canNavigateForward(), true); - assert.equal(findState.canNavigateBack(), true); + assert.strictEqual(findState.matchesPosition, 1); + assert.strictEqual(findState.canNavigateForward(), true); + assert.strictEqual(findState.canNavigateBack(), true); }); diff --git a/src/vs/editor/contrib/find/test/replacePattern.test.ts b/src/vs/editor/contrib/find/test/replacePattern.test.ts index 907292fd7ad..d9491864086 100644 --- a/src/vs/editor/contrib/find/test/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/replacePattern.test.ts @@ -13,7 +13,7 @@ suite('Replace Pattern test', () => { let testParse = (input: string, expectedPieces: ReplacePiece[]) => { let actual = parseReplaceString(input); let expected = new ReplacePattern(expectedPieces); - assert.deepEqual(actual, expected, 'Parsing ' + input); + assert.deepStrictEqual(actual, expected, 'Parsing ' + input); }; // no backslash => no treatment @@ -73,14 +73,14 @@ suite('Replace Pattern test', () => { let testParse = (input: string, expectedPieces: ReplacePiece[]) => { let actual = parseReplaceString(input); let expected = new ReplacePattern(expectedPieces); - assert.deepEqual(actual, expected, 'Parsing ' + input); + assert.deepStrictEqual(actual, expected, 'Parsing ' + input); }; function assertReplace(target: string, search: RegExp, replaceString: string, expected: string): void { let replacePattern = parseReplaceString(replaceString); let m = search.exec(target); let actual = replacePattern.buildReplaceString(m); - assert.equal(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); + assert.strictEqual(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); } // \U, \u => uppercase \L, \l => lowercase \E => cancel @@ -107,7 +107,7 @@ suite('Replace Pattern test', () => { let m = search.exec(target); let actual = replacePattern.buildReplaceString(m); - assert.deepEqual(actual, expected, `${target}.replace(${search}, ${replaceString})`); + assert.deepStrictEqual(actual, expected, `${target}.replace(${search}, ${replaceString})`); }; testJSReplaceSemantics('hi', /hi/, 'hello', 'hi'.replace(/hi/, 'hello')); @@ -136,7 +136,7 @@ suite('Replace Pattern test', () => { let m = search.exec(target); let actual = replacePattern.buildReplaceString(m); - assert.equal(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); + assert.strictEqual(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); } assertReplace('bla', /bla/, 'hello', 'hello'); @@ -162,7 +162,7 @@ suite('Replace Pattern test', () => { let m = search.exec(target); let actual = replacePattern.buildReplaceString(m); - assert.equal(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); + assert.strictEqual(actual, expected, `${target}.replace(${search}, ${replaceString}) === ${expected}`); } assertReplace('this is a bla text', /bla/, 'hello', 'hello'); assertReplace('this is a bla text', /this(?=.*bla)/, 'that', 'that'); @@ -184,14 +184,14 @@ suite('Replace Pattern test', () => { let replacePattern = parseReplaceString('a{$1}'); let matches = /a(z)?/.exec('abcd'); let actual = replacePattern.buildReplaceString(matches); - assert.equal(actual, 'a{}'); + assert.strictEqual(actual, 'a{}'); }); test('buildReplaceStringWithCasePreserved test', () => { function assertReplace(target: string[], replaceString: string, expected: string): void { let actual: string = ''; actual = buildReplaceStringWithCasePreserved(target, replaceString); - assert.equal(actual, expected); + assert.strictEqual(actual, expected); } assertReplace(['abc'], 'Def', 'def'); @@ -219,7 +219,7 @@ suite('Replace Pattern test', () => { function assertReplace(target: string[], replaceString: string, expected: string): void { let replacePattern = parseReplaceString(replaceString); let actual = replacePattern.buildReplaceString(target, true); - assert.equal(actual, expected); + assert.strictEqual(actual, expected); } assertReplace(['abc'], 'Def', 'def'); diff --git a/src/vs/editor/contrib/linesOperations/test/copyLinesCommand.test.ts b/src/vs/editor/contrib/linesOperations/test/copyLinesCommand.test.ts index 6777693d4ea..64f3c7a5d96 100644 --- a/src/vs/editor/contrib/linesOperations/test/copyLinesCommand.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/copyLinesCommand.test.ts @@ -207,8 +207,8 @@ suite('Editor Contrib - Duplicate Selection', () => { withTestCodeEditor(lines.join('\n'), {}, (editor) => { editor.setSelections(selections); duplicateSelectionAction.run(null!, editor, {}); - assert.deepEqual(editor.getValue(), expectedLines.join('\n')); - assert.deepEqual(editor.getSelections()!.map(s => s.toString()), expectedSelections.map(s => s.toString())); + assert.deepStrictEqual(editor.getValue(), expectedLines.join('\n')); + assert.deepStrictEqual(editor.getSelections()!.map(s => s.toString()), expectedSelections.map(s => s.toString())); }); } diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index f7b6b002f42..b3cbe4bdc55 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -19,7 +19,7 @@ function assertSelection(editor: ICodeEditor, expected: Selection | Selection[]) if (!Array.isArray(expected)) { expected = [expected]; } - assert.deepEqual(editor.getSelections(), expected); + assert.deepStrictEqual(editor.getSelections(), expected); } function executeAction(action: EditorAction, editor: ICodeEditor): void { @@ -40,7 +40,7 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 3, 5)); executeAction(sortLinesAscendingAction, editor); - assert.deepEqual(model.getLinesContent(), [ + assert.deepStrictEqual(model.getLinesContent(), [ 'alpha', 'beta', 'omicron' @@ -65,7 +65,7 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelections([new Selection(1, 1, 3, 5), new Selection(5, 1, 7, 5)]); executeAction(sortLinesAscendingAction, editor); - assert.deepEqual(model.getLinesContent(), [ + assert.deepStrictEqual(model.getLinesContent(), [ 'alpha', 'beta', 'omicron', @@ -79,7 +79,7 @@ suite('Editor Contrib - Line Operations', () => { new Selection(5, 1, 7, 7) ]; editor.getSelections()!.forEach((actualSelection, index) => { - assert.deepEqual(actualSelection.toString(), expectedSelections[index].toString()); + assert.deepStrictEqual(actualSelection.toString(), expectedSelections[index].toString()); }); }); }); @@ -98,7 +98,7 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 3, 7)); executeAction(sortLinesDescendingAction, editor); - assert.deepEqual(model.getLinesContent(), [ + assert.deepStrictEqual(model.getLinesContent(), [ 'omicron', 'beta', 'alpha' @@ -123,7 +123,7 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelections([new Selection(1, 1, 3, 7), new Selection(5, 1, 7, 7)]); executeAction(sortLinesDescendingAction, editor); - assert.deepEqual(model.getLinesContent(), [ + assert.deepStrictEqual(model.getLinesContent(), [ 'omicron', 'beta', 'alpha', @@ -137,7 +137,7 @@ suite('Editor Contrib - Line Operations', () => { new Selection(5, 1, 7, 5) ]; editor.getSelections()!.forEach((actualSelection, index) => { - assert.deepEqual(actualSelection.toString(), expectedSelections[index].toString()); + assert.deepStrictEqual(actualSelection.toString(), expectedSelections[index].toString()); }); }); }); @@ -157,12 +157,12 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 2, 1, 2)); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(1), 'ne'); + assert.strictEqual(model.getLineContent(1), 'ne'); editor.setSelections([new Selection(2, 2, 2, 2), new Selection(3, 2, 3, 2)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(2), 'wo'); - assert.equal(model.getLineContent(3), 'hree'); + assert.strictEqual(model.getLineContent(2), 'wo'); + assert.strictEqual(model.getLineContent(3), 'hree'); }); }); @@ -178,16 +178,16 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(2, 1, 2, 1)); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(1), 'onetwo'); + assert.strictEqual(model.getLineContent(1), 'onetwo'); editor.setSelections([new Selection(1, 1, 1, 1), new Selection(2, 1, 2, 1)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLinesContent()[0], 'onetwothree'); - assert.equal(model.getLinesContent().length, 1); + assert.strictEqual(model.getLinesContent()[0], 'onetwothree'); + assert.strictEqual(model.getLinesContent().length, 1); editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLinesContent()[0], 'onetwothree'); + assert.strictEqual(model.getLinesContent()[0], 'onetwothree'); }); }); @@ -213,25 +213,25 @@ suite('Editor Contrib - Line Operations', () => { executeAction(deleteAllLeftAction, editor); let selections = editor.getSelections()!; - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), ' waso waso'); - assert.equal(model.getLineContent(5), ''); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), ' waso waso'); + assert.strictEqual(model.getLineContent(5), ''); - assert.deepEqual([ + assert.deepStrictEqual([ selections[0].startLineNumber, selections[0].startColumn, selections[0].endLineNumber, selections[0].endColumn ], [3, 1, 3, 1]); - assert.deepEqual([ + assert.deepStrictEqual([ selections[1].startLineNumber, selections[1].startColumn, selections[1].endLineNumber, selections[1].endColumn ], [2, 1, 2, 1]); - assert.deepEqual([ + assert.deepStrictEqual([ selections[2].startLineNumber, selections[2].startColumn, selections[2].endLineNumber, @@ -241,17 +241,17 @@ suite('Editor Contrib - Line Operations', () => { executeAction(deleteAllLeftAction, editor); selections = editor.getSelections()!; - assert.equal(model.getLineContent(1), 'hi my name is Carlos Matos waso waso'); - assert.equal(selections.length, 2); + assert.strictEqual(model.getLineContent(1), 'hi my name is Carlos Matos waso waso'); + assert.strictEqual(selections.length, 2); - assert.deepEqual([ + assert.deepStrictEqual([ selections[0].startLineNumber, selections[0].startColumn, selections[0].endLineNumber, selections[0].endColumn ], [1, 27, 1, 27]); - assert.deepEqual([ + assert.deepStrictEqual([ selections[1].startLineNumber, selections[1].startColumn, selections[1].endLineNumber, @@ -277,23 +277,23 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelections([new Selection(1, 2, 1, 2), new Selection(1, 4, 1, 4)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(1), 'lo'); + assert.strictEqual(model.getLineContent(1), 'lo'); editor.setSelections([new Selection(2, 2, 2, 2), new Selection(2, 4, 2, 5)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(2), 'd'); + assert.strictEqual(model.getLineContent(2), 'd'); editor.setSelections([new Selection(3, 2, 3, 5), new Selection(3, 7, 3, 7)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(3), 'world'); + assert.strictEqual(model.getLineContent(3), 'world'); editor.setSelections([new Selection(4, 3, 4, 3), new Selection(4, 5, 5, 4)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(4), 'jour'); + assert.strictEqual(model.getLineContent(4), 'jour'); editor.setSelections([new Selection(5, 3, 6, 3), new Selection(6, 5, 7, 5), new Selection(7, 7, 7, 7)]); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(5), 'world'); + assert.strictEqual(model.getLineContent(5), 'world'); }); }); @@ -310,16 +310,16 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 1)); editor.trigger('keyboard', Handler.Type, { text: 'Typing some text here on line ' }); - assert.equal(model.getLineContent(1), 'Typing some text here on line one'); - assert.deepEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); + assert.strictEqual(model.getLineContent(1), 'Typing some text here on line one'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); executeAction(deleteAllLeftAction, editor); - assert.equal(model.getLineContent(1), 'one'); - assert.deepEqual(editor.getSelection(), new Selection(1, 1, 1, 1)); + assert.strictEqual(model.getLineContent(1), 'one'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 1, 1, 1)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Typing some text here on line one'); - assert.deepEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); + assert.strictEqual(model.getLineContent(1), 'Typing some text here on line one'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); }); }); }); @@ -345,27 +345,27 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 2, 1, 2)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(1), 'hello world'); + assert.strictEqual(model.getLineContent(1), 'hello world'); assertSelection(editor, new Selection(1, 6, 1, 6)); editor.setSelection(new Selection(2, 2, 2, 2)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(2), 'hello world'); + assert.strictEqual(model.getLineContent(2), 'hello world'); assertSelection(editor, new Selection(2, 7, 2, 7)); editor.setSelection(new Selection(3, 2, 3, 2)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(3), 'hello world'); + assert.strictEqual(model.getLineContent(3), 'hello world'); assertSelection(editor, new Selection(3, 7, 3, 7)); editor.setSelection(new Selection(4, 2, 5, 3)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(4), 'hello world'); + assert.strictEqual(model.getLineContent(4), 'hello world'); assertSelection(editor, new Selection(4, 2, 4, 8)); editor.setSelection(new Selection(5, 1, 7, 3)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(5), 'hello world'); + assert.strictEqual(model.getLineContent(5), 'hello world'); assertSelection(editor, new Selection(5, 1, 5, 3)); }); }); @@ -381,8 +381,8 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(2, 1, 2, 1)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(1), 'hello'); - assert.equal(model.getLineContent(2), 'world'); + assert.strictEqual(model.getLineContent(1), 'hello'); + assert.strictEqual(model.getLineContent(2), 'world'); assertSelection(editor, new Selection(2, 6, 2, 6)); }); }); @@ -416,7 +416,7 @@ suite('Editor Contrib - Line Operations', () => { ]); executeAction(joinLinesAction, editor); - assert.equal(model.getLinesContent().join('\n'), 'hello world\nhello world\nhello world\nhello world\n\nhello world'); + assert.strictEqual(model.getLinesContent().join('\n'), 'hello world\nhello world\nhello world\nhello world\n\nhello world'); assertSelection(editor, [ /** primary cursor */ new Selection(3, 4, 3, 8), @@ -440,16 +440,16 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 6, 1, 6)); editor.trigger('keyboard', Handler.Type, { text: ' my dear' }); - assert.equal(model.getLineContent(1), 'hello my dear'); - assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + assert.strictEqual(model.getLineContent(1), 'hello my dear'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); executeAction(joinLinesAction, editor); - assert.equal(model.getLineContent(1), 'hello my dear world'); - assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + assert.strictEqual(model.getLineContent(1), 'hello my dear world'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'hello my dear'); - assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + assert.strictEqual(model.getLineContent(1), 'hello my dear'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); }); }); }); @@ -467,27 +467,27 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(1), 'hello world'); + assert.strictEqual(model.getLineContent(1), 'hello world'); assertSelection(editor, new Selection(1, 2, 1, 2)); editor.setSelection(new Selection(1, 6, 1, 6)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(1), 'hell oworld'); + assert.strictEqual(model.getLineContent(1), 'hell oworld'); assertSelection(editor, new Selection(1, 7, 1, 7)); editor.setSelection(new Selection(1, 12, 1, 12)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(1), 'hell oworl'); + assert.strictEqual(model.getLineContent(1), 'hell oworl'); assertSelection(editor, new Selection(2, 2, 2, 2)); editor.setSelection(new Selection(3, 1, 3, 1)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(3), ''); assertSelection(editor, new Selection(4, 1, 4, 1)); editor.setSelection(new Selection(4, 2, 4, 2)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(4), ' '); + assert.strictEqual(model.getLineContent(4), ' '); assertSelection(editor, new Selection(4, 3, 4, 3)); } ); @@ -509,22 +509,22 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(2), ''); assertSelection(editor, new Selection(2, 1, 2, 1)); editor.setSelection(new Selection(3, 6, 3, 6)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(4), 'oworld'); + assert.strictEqual(model.getLineContent(4), 'oworld'); assertSelection(editor, new Selection(4, 2, 4, 2)); editor.setSelection(new Selection(6, 12, 6, 12)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(7), 'd'); + assert.strictEqual(model.getLineContent(7), 'd'); assertSelection(editor, new Selection(7, 2, 7, 2)); editor.setSelection(new Selection(8, 12, 8, 12)); executeAction(transposeAction, editor); - assert.equal(model.getLineContent(8), 'hello world'); + assert.strictEqual(model.getLineContent(8), 'hello world'); assertSelection(editor, new Selection(8, 12, 8, 12)); } ); @@ -559,102 +559,102 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(uppercaseAction, editor); - assert.equal(model.getLineContent(1), 'HELLO WORLD'); + assert.strictEqual(model.getLineContent(1), 'HELLO WORLD'); assertSelection(editor, new Selection(1, 1, 1, 12)); editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(lowercaseAction, editor); - assert.equal(model.getLineContent(1), 'hello world'); + assert.strictEqual(model.getLineContent(1), 'hello world'); assertSelection(editor, new Selection(1, 1, 1, 12)); editor.setSelection(new Selection(1, 3, 1, 3)); executeAction(uppercaseAction, editor); - assert.equal(model.getLineContent(1), 'HELLO world'); + assert.strictEqual(model.getLineContent(1), 'HELLO world'); assertSelection(editor, new Selection(1, 3, 1, 3)); editor.setSelection(new Selection(1, 4, 1, 4)); executeAction(lowercaseAction, editor); - assert.equal(model.getLineContent(1), 'hello world'); + assert.strictEqual(model.getLineContent(1), 'hello world'); assertSelection(editor, new Selection(1, 4, 1, 4)); editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(1), 'Hello World'); + assert.strictEqual(model.getLineContent(1), 'Hello World'); assertSelection(editor, new Selection(1, 1, 1, 12)); editor.setSelection(new Selection(2, 1, 2, 6)); executeAction(uppercaseAction, editor); - assert.equal(model.getLineContent(2), 'ÖÇŞĞÜ'); + assert.strictEqual(model.getLineContent(2), 'ÖÇŞĞÜ'); assertSelection(editor, new Selection(2, 1, 2, 6)); editor.setSelection(new Selection(2, 1, 2, 6)); executeAction(lowercaseAction, editor); - assert.equal(model.getLineContent(2), 'öçşğü'); + assert.strictEqual(model.getLineContent(2), 'öçşğü'); assertSelection(editor, new Selection(2, 1, 2, 6)); editor.setSelection(new Selection(2, 1, 2, 6)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(2), 'Öçşğü'); + assert.strictEqual(model.getLineContent(2), 'Öçşğü'); assertSelection(editor, new Selection(2, 1, 2, 6)); editor.setSelection(new Selection(3, 1, 3, 16)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(3), 'parse_html_string'); + assert.strictEqual(model.getLineContent(3), 'parse_html_string'); assertSelection(editor, new Selection(3, 1, 3, 18)); editor.setSelection(new Selection(4, 1, 4, 15)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(4), 'get_element_by_id'); + assert.strictEqual(model.getLineContent(4), 'get_element_by_id'); assertSelection(editor, new Selection(4, 1, 4, 18)); editor.setSelection(new Selection(5, 1, 5, 11)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(5), 'insert_html'); + assert.strictEqual(model.getLineContent(5), 'insert_html'); assertSelection(editor, new Selection(5, 1, 5, 12)); editor.setSelection(new Selection(6, 1, 6, 11)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(6), 'pascal_case'); + assert.strictEqual(model.getLineContent(6), 'pascal_case'); assertSelection(editor, new Selection(6, 1, 6, 12)); editor.setSelection(new Selection(7, 1, 7, 17)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(7), 'css_selectors_list'); + assert.strictEqual(model.getLineContent(7), 'css_selectors_list'); assertSelection(editor, new Selection(7, 1, 7, 19)); editor.setSelection(new Selection(8, 1, 8, 3)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(8), 'i_d'); + assert.strictEqual(model.getLineContent(8), 'i_d'); assertSelection(editor, new Selection(8, 1, 8, 4)); editor.setSelection(new Selection(9, 1, 9, 5)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(9), 't_est'); + assert.strictEqual(model.getLineContent(9), 't_est'); assertSelection(editor, new Selection(9, 1, 9, 6)); editor.setSelection(new Selection(10, 1, 10, 11)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); + assert.strictEqual(model.getLineContent(10), 'öçş_öç_şğü_ğü'); assertSelection(editor, new Selection(10, 1, 10, 14)); editor.setSelection(new Selection(11, 1, 11, 34)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(11), 'audio_converter.convert_m4a_to_mp3();'); + assert.strictEqual(model.getLineContent(11), 'audio_converter.convert_m4a_to_mp3();'); assertSelection(editor, new Selection(11, 1, 11, 38)); editor.setSelection(new Selection(12, 1, 12, 11)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(12), 'snake_case'); + assert.strictEqual(model.getLineContent(12), 'snake_case'); assertSelection(editor, new Selection(12, 1, 12, 11)); editor.setSelection(new Selection(13, 1, 13, 19)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(13), 'capital_snake_case'); + assert.strictEqual(model.getLineContent(13), 'capital_snake_case'); assertSelection(editor, new Selection(13, 1, 13, 19)); editor.setSelection(new Selection(14, 1, 17, 14)); executeAction(snakecaseAction, editor); - assert.equal(model.getValueInRange(new Selection(14, 1, 17, 15)), `function hello_world() { + assert.strictEqual(model.getValueInRange(new Selection(14, 1, 17, 15)), `function hello_world() { return some_global_object.print_hello_world("en", "utf-8"); } hello_world();`.replace(/^\s+/gm, '')); @@ -676,27 +676,27 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(1), 'Foo Bar Baz'); + assert.strictEqual(model.getLineContent(1), 'Foo Bar Baz'); editor.setSelection(new Selection(2, 1, 2, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(2), 'Foo\'Bar\'Baz'); + assert.strictEqual(model.getLineContent(2), 'Foo\'Bar\'Baz'); editor.setSelection(new Selection(3, 1, 3, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(3), 'Foo[Bar]Baz'); + assert.strictEqual(model.getLineContent(3), 'Foo[Bar]Baz'); editor.setSelection(new Selection(4, 1, 4, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(4), 'Foo`Bar~Baz'); + assert.strictEqual(model.getLineContent(4), 'Foo`Bar~Baz'); editor.setSelection(new Selection(5, 1, 5, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(5), 'Foo^Bar%Baz'); + assert.strictEqual(model.getLineContent(5), 'Foo^Bar%Baz'); editor.setSelection(new Selection(6, 1, 6, 12)); executeAction(titlecaseAction, editor); - assert.equal(model.getLineContent(6), 'Foo$Bar!Baz'); + assert.strictEqual(model.getLineContent(6), 'Foo$Bar!Baz'); } ); @@ -711,22 +711,22 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(uppercaseAction, editor); - assert.equal(model.getLineContent(1), ''); + assert.strictEqual(model.getLineContent(1), ''); assertSelection(editor, new Selection(1, 1, 1, 1)); editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(lowercaseAction, editor); - assert.equal(model.getLineContent(1), ''); + assert.strictEqual(model.getLineContent(1), ''); assertSelection(editor, new Selection(1, 1, 1, 1)); editor.setSelection(new Selection(2, 2, 2, 2)); executeAction(uppercaseAction, editor); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(2), ' '); assertSelection(editor, new Selection(2, 2, 2, 2)); editor.setSelection(new Selection(2, 2, 2, 2)); executeAction(lowercaseAction, editor); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(2), ' '); assertSelection(editor, new Selection(2, 2, 2, 2)); } ); @@ -739,18 +739,18 @@ suite('Editor Contrib - Line Operations', () => { const action = new DeleteAllRightAction(); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); editor.setSelection(new Selection(1, 1, 1, 1)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); editor.setSelections([new Selection(1, 1, 1, 1), new Selection(1, 1, 1, 1), new Selection(1, 1, 1, 1)]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); }); }); @@ -764,18 +764,18 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 2, 1, 5)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['ho', 'world']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 2, 1, 2)]); + assert.deepStrictEqual(model.getLinesContent(), ['ho', 'world']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 2, 1, 2)]); editor.setSelection(new Selection(1, 1, 2, 4)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['ld']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['ld']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); editor.setSelection(new Selection(1, 1, 1, 3)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 1, 1, 1)]); }); }); @@ -789,13 +789,13 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 3, 1, 3)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['he', 'world']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 3, 1, 3)]); + assert.deepStrictEqual(model.getLinesContent(), ['he', 'world']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 3, 1, 3)]); editor.setSelection(new Selection(2, 1, 2, 1)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['he', '']); - assert.deepEqual(editor.getSelections(), [new Selection(2, 1, 2, 1)]); + assert.deepStrictEqual(model.getLinesContent(), ['he', '']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(2, 1, 2, 1)]); }); }); @@ -809,18 +809,18 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(1, 6, 1, 6)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['helloworld']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); + assert.deepStrictEqual(model.getLinesContent(), ['helloworld']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); editor.setSelection(new Selection(1, 6, 1, 6)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['hello']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); + assert.deepStrictEqual(model.getLinesContent(), ['hello']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); editor.setSelection(new Selection(1, 6, 1, 6)); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['hello']); - assert.deepEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); + assert.deepStrictEqual(model.getLinesContent(), ['hello']); + assert.deepStrictEqual(editor.getSelections(), [new Selection(1, 6, 1, 6)]); }); }); @@ -839,35 +839,35 @@ suite('Editor Contrib - Line Operations', () => { new Selection(3, 4, 3, 4), ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['hethere', 'wor']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['hethere', 'wor']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(2, 4, 2, 4) ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['he', 'wor']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['he', 'wor']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(2, 4, 2, 4) ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['hewor']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['hewor']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(1, 6, 1, 6) ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['he']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['he']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3) ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['he']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['he']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3) ]); }); @@ -888,20 +888,20 @@ suite('Editor Contrib - Line Operations', () => { new Selection(3, 4, 3, 4), ]); executeAction(action, editor); - assert.deepEqual(model.getLinesContent(), ['hethere', 'wor']); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(model.getLinesContent(), ['hethere', 'wor']); + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(2, 4, 2, 4) ]); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(1, 6, 1, 6), new Selection(3, 4, 3, 4) ]); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 3, 1, 3), new Selection(2, 4, 2, 4) ]); @@ -926,27 +926,27 @@ suite('Editor Contrib - Line Operations', () => { } testInsertLineBefore(1, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(1, 1, 1, 1)); - assert.equal(model.getLineContent(1), ''); - assert.equal(model.getLineContent(2), 'First line'); - assert.equal(model.getLineContent(3), 'Second line'); - assert.equal(model.getLineContent(4), 'Third line'); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(1, 1, 1, 1)); + assert.strictEqual(model.getLineContent(1), ''); + assert.strictEqual(model.getLineContent(2), 'First line'); + assert.strictEqual(model.getLineContent(3), 'Second line'); + assert.strictEqual(model.getLineContent(4), 'Third line'); }); testInsertLineBefore(2, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(2, 1, 2, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), 'Second line'); - assert.equal(model.getLineContent(4), 'Third line'); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(2, 1, 2, 1)); + assert.strictEqual(model.getLineContent(1), 'First line'); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), 'Second line'); + assert.strictEqual(model.getLineContent(4), 'Third line'); }); testInsertLineBefore(3, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(3, 1, 3, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), 'Second line'); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), 'Third line'); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(3, 1, 3, 1)); + assert.strictEqual(model.getLineContent(1), 'First line'); + assert.strictEqual(model.getLineContent(2), 'Second line'); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), 'Third line'); }); }); @@ -967,27 +967,27 @@ suite('Editor Contrib - Line Operations', () => { } testInsertLineAfter(1, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(2, 1, 2, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), 'Second line'); - assert.equal(model.getLineContent(4), 'Third line'); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(2, 1, 2, 1)); + assert.strictEqual(model.getLineContent(1), 'First line'); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), 'Second line'); + assert.strictEqual(model.getLineContent(4), 'Third line'); }); testInsertLineAfter(2, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(3, 1, 3, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), 'Second line'); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), 'Third line'); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(3, 1, 3, 1)); + assert.strictEqual(model.getLineContent(1), 'First line'); + assert.strictEqual(model.getLineContent(2), 'Second line'); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), 'Third line'); }); testInsertLineAfter(3, 3, (model, viewModel) => { - assert.deepEqual(viewModel.getSelection(), new Selection(4, 1, 4, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), 'Second line'); - assert.equal(model.getLineContent(3), 'Third line'); - assert.equal(model.getLineContent(4), ''); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(4, 1, 4, 1)); + assert.strictEqual(model.getLineContent(1), 'First line'); + assert.strictEqual(model.getLineContent(2), 'Second line'); + assert.strictEqual(model.getLineContent(3), 'Third line'); + assert.strictEqual(model.getLineContent(4), ''); }); }); @@ -1007,11 +1007,11 @@ suite('Editor Contrib - Line Operations', () => { editor.setPosition(new Position(1, 2)); executeAction(indentLinesAction, editor); - assert.equal(model.getLineContent(1), '\tfunction baz() {'); - assert.deepEqual(editor.getSelection(), new Selection(1, 3, 1, 3)); + assert.strictEqual(model.getLineContent(1), '\tfunction baz() {'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 3, 1, 3)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), '\tf\tunction baz() {'); + assert.strictEqual(model.getLineContent(1), '\tf\tunction baz() {'); }); model.dispose(); @@ -1032,8 +1032,8 @@ suite('Editor Contrib - Line Operations', () => { editor.setPosition(new Position(1, 1)); executeAction(indentLinesAction, editor); - assert.equal(model.getLineContent(1), '\tSome text'); - assert.deepEqual(editor.getSelection(), new Selection(1, 2, 1, 2)); + assert.strictEqual(model.getLineContent(1), '\tSome text'); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 2, 1, 2)); }); model.dispose(); @@ -1051,8 +1051,8 @@ suite('Editor Contrib - Line Operations', () => { editor.setPosition(new Position(1, 1)); executeAction(indentLinesAction, editor); - assert.equal(model.getLineContent(1), ' '); - assert.deepEqual(editor.getSelection(), new Selection(1, 5, 1, 5)); + assert.strictEqual(model.getLineContent(1), ' '); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 5, 1, 5)); }); model.dispose(); @@ -1074,7 +1074,7 @@ suite('Editor Contrib - Line Operations', () => { const deleteLinesAction = new DeleteLinesAction(); executeAction(deleteLinesAction, editor); - assert.equal(editor.getValue(), 'a\nc'); + assert.strictEqual(editor.getValue(), 'a\nc'); }); }); @@ -1086,8 +1086,8 @@ suite('Editor Contrib - Line Operations', () => { const deleteLinesAction = new DeleteLinesAction(); executeAction(deleteLinesAction, editor); - assert.equal(editor.getValue(), resultingText.join('\n')); - assert.deepEqual(editor.getSelections(), resultingSelections); + assert.strictEqual(editor.getValue(), resultingText.join('\n')); + assert.deepStrictEqual(editor.getSelections(), resultingSelections); }); } diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts index 6e1e0a9be21..5a0e7e1984e 100644 --- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts @@ -25,7 +25,7 @@ suite('Multicursor', () => { editor.setSelection(new Selection(2, 1, 2, 1)); addCursorUpAction.run(null!, editor, {}); - assert.equal(viewModel.getSelections().length, 2); + assert.strictEqual(viewModel.getSelections().length, 2); editor.trigger('test', Handler.Paste, { text: '1\n2', @@ -35,8 +35,8 @@ suite('Multicursor', () => { ] }); - assert.equal(editor.getModel()!.getLineContent(1), '1abc'); - assert.equal(editor.getModel()!.getLineContent(2), '2def'); + assert.strictEqual(editor.getModel()!.getLineContent(1), '1abc'); + assert.strictEqual(editor.getModel()!.getLineContent(2), '2def'); }); }); @@ -46,7 +46,7 @@ suite('Multicursor', () => { ], {}, (editor, viewModel) => { let addCursorDownAction = new InsertCursorBelow(); addCursorDownAction.run(null!, editor, {}); - assert.equal(viewModel.getSelections().length, 1); + assert.strictEqual(viewModel.getSelections().length, 1); }); }); @@ -90,7 +90,7 @@ suite('Multicursor selection', () => { editor.setSelection(new Selection(2, 9, 2, 16)); selectHighlightsAction.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [2, 9, 2, 16], [1, 9, 1, 16], [3, 9, 3, 16], @@ -98,7 +98,7 @@ suite('Multicursor selection', () => { editor.trigger('test', 'removeSecondaryCursors', null); - assert.deepEqual(fromRange(editor.getSelection()!), [2, 9, 2, 16]); + assert.deepStrictEqual(fromRange(editor.getSelection()!), [2, 9, 2, 16]); multiCursorSelectController.dispose(); findController.dispose(); @@ -121,13 +121,13 @@ suite('Multicursor selection', () => { findController.getState().change({ searchString: 'some+thing', isRegex: true, isRevealed: true }, false); selectHighlightsAction.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [1, 1, 1, 10], [2, 1, 2, 11], [3, 1, 3, 12], ]); - assert.equal(findController.getState().searchString, 'some+thing'); + assert.strictEqual(findController.getState().searchString, 'some+thing'); multiCursorSelectController.dispose(); findController.dispose(); @@ -154,14 +154,14 @@ suite('Multicursor selection', () => { editor.setSelection(new Selection(2, 1, 3, 4)); addSelectionToNextFindMatch.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [2, 1, 3, 4], [8, 1, 9, 4] ]); editor.trigger('test', 'removeSecondaryCursors', null); - assert.deepEqual(fromRange(editor.getSelection()!), [2, 1, 3, 4]); + assert.deepStrictEqual(fromRange(editor.getSelection()!), [2, 1, 3, 4]); multiCursorSelectController.dispose(); findController.dispose(); @@ -182,7 +182,7 @@ suite('Multicursor selection', () => { editor.setSelection(new Selection(1, 1, 1, 4)); addSelectionToNextFindMatch.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [1, 1, 1, 4], [1, 4, 1, 7] ]); @@ -190,7 +190,7 @@ suite('Multicursor selection', () => { addSelectionToNextFindMatch.run(null!, editor); addSelectionToNextFindMatch.run(null!, editor); addSelectionToNextFindMatch.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [1, 1, 1, 4], [1, 4, 1, 7], [2, 1, 2, 4], @@ -199,14 +199,14 @@ suite('Multicursor selection', () => { ]); editor.trigger('test', Handler.Type, { text: 'z' }); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [1, 2, 1, 2], [1, 3, 1, 3], [2, 2, 2, 2], [3, 2, 3, 2], [3, 3, 3, 3] ]); - assert.equal(editor.getValue(), [ + assert.strictEqual(editor.getValue(), [ 'zz', 'z', 'zz', @@ -239,14 +239,14 @@ suite('Multicursor selection', () => { editor.setSelection(new Selection(2, 1, 3, 4)); addSelectionToNextFindMatch.run(null!, editor); - assert.deepEqual(editor.getSelections()!.map(fromRange), [ + assert.deepStrictEqual(editor.getSelections()!.map(fromRange), [ [2, 1, 3, 4], [8, 1, 9, 4] ]); editor.trigger('test', 'removeSecondaryCursors', null); - assert.deepEqual(fromRange(editor.getSelection()!), [2, 1, 3, 4]); + assert.deepStrictEqual(fromRange(editor.getSelection()!), [2, 1, 3, 4]); multiCursorSelectController.dispose(); findController.dispose(); @@ -284,25 +284,25 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), @@ -323,20 +323,20 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), @@ -357,20 +357,20 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), @@ -392,14 +392,14 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), new Selection(3, 1, 3, 4), @@ -421,14 +421,14 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 5, 1, 10), new Selection(2, 5, 2, 10), new Selection(3, 5, 3, 8), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 5, 1, 10), new Selection(2, 5, 2, 10), new Selection(3, 5, 3, 8), @@ -450,20 +450,20 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(2, 1, 2, 5), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(2, 1, 2, 5), new Selection(3, 1, 3, 5), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(2, 1, 2, 5), new Selection(3, 1, 3, 5), @@ -471,7 +471,7 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(2, 1, 2, 5), new Selection(3, 1, 3, 5), @@ -480,7 +480,7 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 5), new Selection(2, 1, 2, 5), new Selection(3, 1, 3, 5), @@ -508,18 +508,18 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(4, 1, 4, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(4, 1, 4, 4), new Selection(6, 2, 6, 5), @@ -534,12 +534,12 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(4, 1, 4, 4), ]); @@ -550,7 +550,7 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(2, 1, 2, 4), ]); @@ -565,14 +565,14 @@ suite('Multicursor selection', () => { ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(4, 1, 4, 4), new Selection(6, 2, 6, 5), ]); action.run(null!, editor); - assert.deepEqual(editor.getSelections(), [ + assert.deepStrictEqual(editor.getSelections(), [ new Selection(1, 1, 1, 4), new Selection(4, 1, 4, 4), new Selection(6, 2, 6, 5), diff --git a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts index 49433e1f6a2..ee2eb0738a3 100644 --- a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts +++ b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts @@ -110,7 +110,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordLeft - with selection', () => { @@ -123,7 +123,7 @@ suite('WordOperations', () => { ], {}, (editor) => { editor.setPosition(new Position(5, 2)); cursorWordLeft(editor, true); - assert.deepEqual(editor.getSelection(), new Selection(5, 2, 5, 1)); + assert.deepStrictEqual(editor.getSelection(), new Selection(5, 2, 5, 1)); }); }); @@ -138,7 +138,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordLeft - issue #48046: Word selection doesn\'t work as usual', () => { @@ -154,7 +154,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordLeftSelect - issue #74369: cursorWordLeft and cursorWordLeftSelect do not behave consistently', () => { @@ -170,7 +170,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordStartLeft', () => { @@ -185,7 +185,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordStartLeft - issue #51119: regression makes VS compatibility impossible', () => { @@ -200,7 +200,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('issue #51275 - cursorWordStartLeft does not push undo/redo stack element', () => { @@ -212,16 +212,16 @@ suite('WordOperations', () => { withTestCodeEditor('', {}, (editor, viewModel) => { type(viewModel, 'foo bar baz'); - assert.equal(editor.getValue(), 'foo bar baz'); + assert.strictEqual(editor.getValue(), 'foo bar baz'); cursorWordStartLeft(editor); cursorWordStartLeft(editor); type(viewModel, 'q'); - assert.equal(editor.getValue(), 'foo qbar baz'); + assert.strictEqual(editor.getValue(), 'foo qbar baz'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(editor.getValue(), 'foo bar baz'); + assert.strictEqual(editor.getValue(), 'foo bar baz'); }); }); @@ -236,7 +236,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordRight - simple', () => { @@ -256,7 +256,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(5, 2)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordRight - selection', () => { @@ -269,7 +269,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { editor.setPosition(new Position(1, 1)); cursorWordRight(editor, true); - assert.deepEqual(editor.getSelection(), new Selection(1, 1, 1, 8)); + assert.deepStrictEqual(editor.getSelection(), new Selection(1, 1, 1, 8)); }); }); @@ -286,7 +286,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 50)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordRight - issue #41199', () => { @@ -302,7 +302,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 17)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('moveWordEndRight', () => { @@ -318,7 +318,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 50)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('moveWordStartRight', () => { @@ -335,7 +335,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 50)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('issue #51119: cursorWordStartRight regression makes VS compatibility impossible', () => { @@ -350,7 +350,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 15)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('issue #64810: cursorWordStartRight skips first word after newline', () => { @@ -365,7 +365,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(2, 12)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordAccessibilityLeft', () => { @@ -379,7 +379,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordAccessibilityRight', () => { @@ -393,7 +393,7 @@ suite('WordOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 50)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordLeft for non-empty selection', () => { @@ -407,8 +407,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setSelection(new Selection(3, 7, 3, 9)); deleteWordLeft(editor); - assert.equal(model.getLineContent(3), ' Thd Line🐶'); - assert.deepEqual(editor.getPosition(), new Position(3, 7)); + assert.strictEqual(model.getLineContent(3), ' Thd Line🐶'); + assert.deepStrictEqual(editor.getPosition(), new Position(3, 7)); }); }); @@ -423,8 +423,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 1)); deleteWordLeft(editor); - assert.equal(model.getLineContent(1), ' \tMy First Line\t '); - assert.deepEqual(editor.getPosition(), new Position(1, 1)); + assert.strictEqual(model.getLineContent(1), ' \tMy First Line\t '); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 1)); }); }); @@ -439,8 +439,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(3, 11)); deleteWordLeft(editor); - assert.equal(model.getLineContent(3), ' Line🐶'); - assert.deepEqual(editor.getPosition(), new Position(3, 5)); + assert.strictEqual(model.getLineContent(3), ' Line🐶'); + assert.deepStrictEqual(editor.getPosition(), new Position(3, 5)); }); }); @@ -455,8 +455,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(2, 11)); deleteWordLeft(editor); - assert.equal(model.getLineContent(2), '\tMy Line'); - assert.deepEqual(editor.getPosition(), new Position(2, 5)); + assert.strictEqual(model.getLineContent(2), '\tMy Line'); + assert.deepStrictEqual(editor.getPosition(), new Position(2, 5)); }); }); @@ -471,8 +471,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 12)); deleteWordLeft(editor); - assert.equal(model.getLineContent(1), ' \tMy st Line\t '); - assert.deepEqual(editor.getPosition(), new Position(1, 9)); + assert.strictEqual(model.getLineContent(1), ' \tMy st Line\t '); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 9)); }); }); @@ -487,8 +487,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setSelection(new Selection(3, 7, 3, 9)); deleteWordRight(editor); - assert.equal(model.getLineContent(3), ' Thd Line🐶'); - assert.deepEqual(editor.getPosition(), new Position(3, 7)); + assert.strictEqual(model.getLineContent(3), ' Thd Line🐶'); + assert.deepStrictEqual(editor.getPosition(), new Position(3, 7)); }); }); @@ -503,8 +503,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(5, 3)); deleteWordRight(editor); - assert.equal(model.getLineContent(5), '1'); - assert.deepEqual(editor.getPosition(), new Position(5, 2)); + assert.strictEqual(model.getLineContent(5), '1'); + assert.deepStrictEqual(editor.getPosition(), new Position(5, 2)); }); }); @@ -519,8 +519,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(3, 1)); deleteWordRight(editor); - assert.equal(model.getLineContent(3), 'Third Line🐶'); - assert.deepEqual(editor.getPosition(), new Position(3, 1)); + assert.strictEqual(model.getLineContent(3), 'Third Line🐶'); + assert.deepStrictEqual(editor.getPosition(), new Position(3, 1)); }); }); @@ -535,8 +535,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(2, 5)); deleteWordRight(editor); - assert.equal(model.getLineContent(2), '\tMy Line'); - assert.deepEqual(editor.getPosition(), new Position(2, 5)); + assert.strictEqual(model.getLineContent(2), '\tMy Line'); + assert.deepStrictEqual(editor.getPosition(), new Position(2, 5)); }); }); @@ -551,8 +551,8 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 11)); deleteWordRight(editor); - assert.equal(model.getLineContent(1), ' \tMy Fi Line\t '); - assert.deepEqual(editor.getPosition(), new Position(1, 11)); + assert.strictEqual(model.getLineContent(1), ' \tMy Fi Line\t '); + assert.deepStrictEqual(editor.getPosition(), new Position(1, 11)); }); }); @@ -569,7 +569,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordStartLeft', () => { @@ -585,7 +585,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordEndLeft', () => { @@ -601,7 +601,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordLeft - issue #24947', () => { @@ -611,7 +611,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(2, 1)); - deleteWordLeft(editor); assert.equal(model.getLineContent(1), '{}'); + deleteWordLeft(editor); assert.strictEqual(model.getLineContent(1), '{}'); }); withTestCodeEditor([ @@ -620,7 +620,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(2, 1)); - deleteWordStartLeft(editor); assert.equal(model.getLineContent(1), '{}'); + deleteWordStartLeft(editor); assert.strictEqual(model.getLineContent(1), '{}'); }); withTestCodeEditor([ @@ -629,7 +629,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(2, 1)); - deleteWordEndLeft(editor); assert.equal(model.getLineContent(1), '{}'); + deleteWordEndLeft(editor); assert.strictEqual(model.getLineContent(1), '{}'); }); }); @@ -644,7 +644,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordRight - issue #3882', () => { @@ -654,7 +654,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(1, 24)); - deleteWordRight(editor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + deleteWordRight(editor); assert.strictEqual(model.getLineContent(1), 'public void Add( int x,int y )', '001'); }); }); @@ -665,7 +665,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(1, 24)); - deleteWordStartRight(editor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + deleteWordStartRight(editor); assert.strictEqual(model.getLineContent(1), 'public void Add( int x,int y )', '001'); }); }); @@ -676,7 +676,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(1, 24)); - deleteWordEndRight(editor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + deleteWordEndRight(editor); assert.strictEqual(model.getLineContent(1), 'public void Add( int x,int y )', '001'); }); }); @@ -691,7 +691,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordEndRight', () => { @@ -705,7 +705,7 @@ suite('WordOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordRight - issue #3882 (1): Ctrl+Delete removing entire line when used at the end of line', () => { @@ -715,7 +715,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(1, 18)); - deleteWordRight(editor); assert.equal(model.getLineContent(1), 'A line with text.And another one', '001'); + deleteWordRight(editor); assert.strictEqual(model.getLineContent(1), 'A line with text.And another one', '001'); }); }); @@ -726,7 +726,7 @@ suite('WordOperations', () => { ], {}, (editor, _) => { const model = editor.getModel()!; editor.setPosition(new Position(2, 1)); - deleteWordLeft(editor); assert.equal(model.getLineContent(1), 'A line with text. And another one', '001'); + deleteWordLeft(editor); assert.strictEqual(model.getLineContent(1), 'A line with text. And another one', '001'); }); }); @@ -748,7 +748,7 @@ suite('WordOperations', () => { withTestCodeEditor(null, { model }, (editor, _) => { editor.setPosition(new Position(1, 4)); - deleteWordLeft(editor); assert.equal(model.getLineContent(1), 'a '); + deleteWordLeft(editor); assert.strictEqual(model.getLineContent(1), 'a '); }); model.dispose(); @@ -764,7 +764,7 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(2, 1)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'Line1\nLine2'); + assert.strictEqual(model.getValue(), 'Line1\nLine2'); }); }); @@ -775,7 +775,7 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 6)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'Justsome text.'); + assert.strictEqual(model.getValue(), 'Justsome text.'); }); }); @@ -786,7 +786,7 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 6)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'Justsome text.'); + assert.strictEqual(model.getValue(), 'Justsome text.'); }); }); @@ -797,19 +797,19 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 6)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'Just"some text.'); + assert.strictEqual(model.getValue(), 'Just"some text.'); deleteInsideWord(editor); - assert.equal(model.getValue(), '"some text.'); + assert.strictEqual(model.getValue(), '"some text.'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'some text.'); + assert.strictEqual(model.getValue(), 'some text.'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'text.'); + assert.strictEqual(model.getValue(), 'text.'); deleteInsideWord(editor); - assert.equal(model.getValue(), '.'); + assert.strictEqual(model.getValue(), '.'); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); }); }); @@ -820,19 +820,19 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 7)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'x=3+45+6'); + assert.strictEqual(model.getValue(), 'x=3+45+6'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'x=3++6'); + assert.strictEqual(model.getValue(), 'x=3++6'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'x=36'); + assert.strictEqual(model.getValue(), 'x=36'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'x='); + assert.strictEqual(model.getValue(), 'x='); deleteInsideWord(editor); - assert.equal(model.getValue(), 'x'); + assert.strictEqual(model.getValue(), 'x'); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); }); }); @@ -843,13 +843,13 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 7)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'This interesting'); + assert.strictEqual(model.getValue(), 'This interesting'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'This'); + assert.strictEqual(model.getValue(), 'This'); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); }); }); @@ -860,13 +860,13 @@ suite('WordOperations', () => { const model = editor.getModel()!; editor.setPosition(new Position(1, 7)); deleteInsideWord(editor); - assert.equal(model.getValue(), 'This interesting'); + assert.strictEqual(model.getValue(), 'This interesting'); deleteInsideWord(editor); - assert.equal(model.getValue(), 'This'); + assert.strictEqual(model.getValue(), 'This'); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); deleteInsideWord(editor); - assert.equal(model.getValue(), ''); + assert.strictEqual(model.getValue(), ''); }); }); }); diff --git a/src/vs/editor/contrib/wordPartOperations/test/wordPartOperations.test.ts b/src/vs/editor/contrib/wordPartOperations/test/wordPartOperations.test.ts index 70e9c87c680..446711f2a5e 100644 --- a/src/vs/editor/contrib/wordPartOperations/test/wordPartOperations.test.ts +++ b/src/vs/editor/contrib/wordPartOperations/test/wordPartOperations.test.ts @@ -49,7 +49,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartLeft - issue #53899: whitespace', () => { @@ -63,7 +63,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartLeft - issue #53899: underscores', () => { @@ -77,7 +77,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartRight - basic', () => { @@ -95,7 +95,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(3, 9)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartRight - issue #53899: whitespace', () => { @@ -109,7 +109,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 52)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartRight - issue #53899: underscores', () => { @@ -123,7 +123,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 52)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordPartRight - issue #53899: second case', () => { @@ -142,7 +142,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(4, 7)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('issue #93239 - cursorWordPartRight', () => { @@ -158,7 +158,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 8)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('issue #93239 - cursorWordPartLeft', () => { @@ -174,7 +174,7 @@ suite('WordPartOperations', () => { ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordPartLeft - basic', () => { @@ -188,7 +188,7 @@ suite('WordPartOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); test('deleteWordPartRight - basic', () => { @@ -202,6 +202,6 @@ suite('WordPartOperations', () => { ed => ed.getValue().length === 0 ); const actual = serializePipePositions(text, actualStops); - assert.deepEqual(actual, EXPECTED); + assert.deepStrictEqual(actual, EXPECTED); }); }); diff --git a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts index d08c075f186..bd4399d6c4f 100644 --- a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts +++ b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts @@ -109,14 +109,14 @@ suite('TokenizationSupport2Adapter', () => { const adapter = new TokenizationSupport2Adapter(new MockThemeService(), languageIdentifier, new BadTokensProvider()); const actualClassicTokens = adapter.tokenize('whatever', true, MockState.INSTANCE, offsetDelta); - assert.deepEqual(actualClassicTokens.tokens, expectedClassicTokens); + assert.deepStrictEqual(actualClassicTokens.tokens, expectedClassicTokens); const actualModernTokens = adapter.tokenize2('whatever', true, MockState.INSTANCE, offsetDelta); const modernTokens: number[] = []; for (let i = 0; i < actualModernTokens.tokens.length; i++) { modernTokens[i] = actualModernTokens.tokens[i]; } - assert.deepEqual(modernTokens, expectedModernTokens); + assert.deepStrictEqual(modernTokens, expectedModernTokens); } test('tokens always start at index 0 (no offset delta)', () => { diff --git a/src/vs/editor/standalone/test/monarch/monarch.test.ts b/src/vs/editor/standalone/test/monarch/monarch.test.ts index 18f777b53ee..61fcafe555e 100644 --- a/src/vs/editor/standalone/test/monarch/monarch.test.ts +++ b/src/vs/editor/standalone/test/monarch/monarch.test.ts @@ -73,30 +73,30 @@ suite('Monarch', () => { state = result.endState; } - assert.deepEqual(actualTokens, [ + assert.deepStrictEqual(actualTokens, [ [ - { 'offset': 0, 'type': 'source.test1', 'language': 'test1' }, - { 'offset': 12, 'type': 'string.quote.test1', 'language': 'test1' }, - { 'offset': 15, 'type': 'token.sql', 'language': 'sql' }, - { 'offset': 61, 'type': 'string.quote.test1', 'language': 'test1' }, - { 'offset': 64, 'type': 'source.test1', 'language': 'test1' } + new Token(0, 'source.test1', 'test1'), + new Token(12, 'string.quote.test1', 'test1'), + new Token(15, 'token.sql', 'sql'), + new Token(61, 'string.quote.test1', 'test1'), + new Token(64, 'source.test1', 'test1') ], [ - { 'offset': 0, 'type': 'source.test1', 'language': 'test1' }, - { 'offset': 12, 'type': 'string.quote.test1', 'language': 'test1' } + new Token(0, 'source.test1', 'test1'), + new Token(12, 'string.quote.test1', 'test1') ], [ - { 'offset': 0, 'type': 'token.sql', 'language': 'sql' } + new Token(0, 'token.sql', 'sql') ], [ - { 'offset': 0, 'type': 'token.sql', 'language': 'sql' } + new Token(0, 'token.sql', 'sql') ], [ - { 'offset': 0, 'type': 'token.sql', 'language': 'sql' } + new Token(0, 'token.sql', 'sql') ], [ - { 'offset': 0, 'type': 'string.quote.test1', 'language': 'test1' }, - { 'offset': 3, 'type': 'source.test1', 'language': 'test1' } + new Token(0, 'string.quote.test1', 'test1'), + new Token(3, 'source.test1', 'test1') ] ]); innerModeTokenizationRegistration.dispose(); @@ -148,19 +148,19 @@ suite('Monarch', () => { state = result.endState; } - assert.deepEqual(actualTokens, [ - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], + assert.deepStrictEqual(actualTokens, [ + [new Token(0, 'comment.test', 'test')], + [new Token(0, 'comment.test', 'test')], [], - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], - [{ 'offset': 0, 'type': 'source.test', 'language': 'test' }], + [new Token(0, 'comment.test', 'test')], + [new Token(0, 'source.test', 'test')], [], - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], + [new Token(0, 'comment.test', 'test')], + [new Token(0, 'comment.test', 'test')], [], - [{ 'offset': 0, 'type': 'comment.test', 'language': 'test' }], + [new Token(0, 'comment.test', 'test')], [], - [{ 'offset': 0, 'type': 'source.test', 'language': 'test' }] + [new Token(0, 'source.test', 'test')] ]); }); diff --git a/src/vs/editor/test/browser/commands/shiftCommand.test.ts b/src/vs/editor/test/browser/commands/shiftCommand.test.ts index 755aac5bc2d..c31f8e4bfc2 100644 --- a/src/vs/editor/test/browser/commands/shiftCommand.test.ts +++ b/src/vs/editor/test/browser/commands/shiftCommand.test.ts @@ -964,7 +964,7 @@ suite('Editor Commands - ShiftCommand', () => { autoIndent: EditorAutoIndentStrategy.Full, }); let actual = getEditOperation(model, op); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); } @@ -979,7 +979,7 @@ suite('Editor Commands - ShiftCommand', () => { autoIndent: EditorAutoIndentStrategy.Full, }); let actual = getEditOperation(model, op); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); } }); diff --git a/src/vs/editor/test/browser/commands/sideEditing.test.ts b/src/vs/editor/test/browser/commands/sideEditing.test.ts index be07a56821e..f8a8bbae532 100644 --- a/src/vs/editor/test/browser/commands/sideEditing.test.ts +++ b/src/vs/editor/test/browser/commands/sideEditing.test.ts @@ -19,10 +19,10 @@ function testCommand(lines: string[], selections: Selection[], edits: IIdentifie model.applyEdits(edits); - assert.deepEqual(model.getLinesContent(), expectedLines); + assert.deepStrictEqual(model.getLinesContent(), expectedLines); let actualSelections = viewModel.getSelections(); - assert.deepEqual(actualSelections.map(s => s.toString()), expectedSelections.map(s => s.toString())); + assert.deepStrictEqual(actualSelections.map(s => s.toString()), expectedSelections.map(s => s.toString())); }); } @@ -202,7 +202,7 @@ suite('SideEditing', () => { forceMoveMarkers: editForceMoveMarkers }]); const actual = viewModel.getSelection(); - assert.deepEqual(actual.toString(), expected.toString(), msg); + assert.deepStrictEqual(actual.toString(), expected.toString(), msg); }); } diff --git a/src/vs/editor/test/browser/commands/trimTrailingWhitespaceCommand.test.ts b/src/vs/editor/test/browser/commands/trimTrailingWhitespaceCommand.test.ts index af0c64e537c..d9fdfc1bd8d 100644 --- a/src/vs/editor/test/browser/commands/trimTrailingWhitespaceCommand.test.ts +++ b/src/vs/editor/test/browser/commands/trimTrailingWhitespaceCommand.test.ts @@ -37,14 +37,14 @@ function assertTrimTrailingWhitespaceCommand(text: string[], expected: IIdentifi return withEditorModel(text, (model) => { let op = new TrimTrailingWhitespaceCommand(new Selection(1, 1, 1, 1), []); let actual = getEditOperation(model, op); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); } function assertTrimTrailingWhitespace(text: string[], cursors: Position[], expected: IIdentifiedSingleEditOperation[]): void { return withEditorModel(text, (model) => { let actual = trimTrailingWhitespace(model, cursors); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); } diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 9175b2e2541..6690a9161fa 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -115,7 +115,7 @@ function assertCursor(viewModel: ViewModel, what: Position | Selection | Selecti let actual = viewModel.getSelections().map(s => s.toString()); let expected = selections.map(s => s.toString()); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } suite('Editor Controller - Cursor', () => { @@ -795,11 +795,11 @@ suite('Editor Controller - Cursor', () => { viewModel.onEvent((e) => { if (e.kind === OutgoingViewModelEventKind.CursorStateChanged) { events++; - assert.deepEqual(e.selections, [new Selection(1, 2, 1, 2)]); + assert.deepStrictEqual(e.selections, [new Selection(1, 2, 1, 2)]); } }); moveTo(editor, viewModel, 1, 2); - assert.equal(events, 1, 'receives 1 event'); + assert.strictEqual(events, 1, 'receives 1 event'); }); }); @@ -809,11 +809,11 @@ suite('Editor Controller - Cursor', () => { viewModel.onEvent((e) => { if (e.kind === OutgoingViewModelEventKind.CursorStateChanged) { events++; - assert.deepEqual(e.selections, [new Selection(1, 1, 1, 2)]); + assert.deepStrictEqual(e.selections, [new Selection(1, 1, 1, 2)]); } }); moveTo(editor, viewModel, 1, 2, true); - assert.equal(events, 1, 'receives 1 event'); + assert.strictEqual(events, 1, 'receives 1 event'); }); }); @@ -1311,7 +1311,7 @@ suite('Editor Controller - Regression tests', () => { // Check that indenting maintains the selection start at column 1 CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.deepEqual(viewModel.getSelection(), new Selection(1, 1, 1, 14)); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(1, 1, 1, 14)); }); model.dispose(); @@ -1330,49 +1330,49 @@ suite('Editor Controller - Regression tests', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\t', 'assert3'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\n\t', 'assert3'); viewModel.type('x'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert4'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert4'); CoreNavigationCommands.CursorLeft.runCoreEditorCommand(viewModel, {}); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert5'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert5'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert6'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert6'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert7'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert7'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert8'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert8'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert9'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'x', 'assert9'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert10'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert10'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert11'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert11'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert12'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert12'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert13'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert13'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert14'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert14'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert15'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'x', 'assert15'); }); model.dispose(); @@ -1387,13 +1387,13 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Position(1, 1)); model.setEOL(EndOfLineSequence.LF); - assert.equal(model.getValue(), 'Hello\nworld'); + assert.strictEqual(model.getValue(), 'Hello\nworld'); model.pushEOL(EndOfLineSequence.CRLF); - assert.equal(model.getValue(), 'Hello\r\nworld'); + assert.strictEqual(model.getValue(), 'Hello\r\nworld'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), 'Hello\nworld'); + assert.strictEqual(model.getValue(), 'Hello\nworld'); }); }); @@ -1415,10 +1415,10 @@ suite('Editor Controller - Regression tests', () => { editor.setSelection(new Selection(1, 1, 1, 2)); viewModel.type('%', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '%\'%👁\'', 'assert1'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '%\'%👁\'', 'assert1'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\'👁\'', 'assert2'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\'👁\'', 'assert2'); }); model.dispose(); @@ -1433,50 +1433,50 @@ suite('Editor Controller - Regression tests', () => { viewModel.type(' ', 'keyboard'); viewModel.type('world', 'keyboard'); viewModel.type(' ', 'keyboard'); - assert.equal(model.getLineContent(1), 'Hello world '); + assert.strictEqual(model.getLineContent(1), 'Hello world '); assertCursor(viewModel, new Position(1, 13)); moveLeft(editor, viewModel); moveRight(editor, viewModel); model.pushEditOperations([], [EditOperation.replaceMove(new Range(1, 12, 1, 13), '')], () => []); - assert.equal(model.getLineContent(1), 'Hello world'); + assert.strictEqual(model.getLineContent(1), 'Hello world'); assertCursor(viewModel, new Position(1, 12)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world '); + assert.strictEqual(model.getLineContent(1), 'Hello world '); assertCursor(viewModel, new Selection(1, 12, 1, 13)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world'); + assert.strictEqual(model.getLineContent(1), 'Hello world'); assertCursor(viewModel, new Position(1, 12)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello'); + assert.strictEqual(model.getLineContent(1), 'Hello'); assertCursor(viewModel, new Position(1, 6)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ''); + assert.strictEqual(model.getLineContent(1), ''); assertCursor(viewModel, new Position(1, 1)); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello'); + assert.strictEqual(model.getLineContent(1), 'Hello'); assertCursor(viewModel, new Position(1, 6)); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world'); + assert.strictEqual(model.getLineContent(1), 'Hello world'); assertCursor(viewModel, new Position(1, 12)); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world '); + assert.strictEqual(model.getLineContent(1), 'Hello world '); assertCursor(viewModel, new Position(1, 13)); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world'); + assert.strictEqual(model.getLineContent(1), 'Hello world'); assertCursor(viewModel, new Position(1, 12)); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'Hello world'); + assert.strictEqual(model.getLineContent(1), 'Hello world'); assertCursor(viewModel, new Position(1, 12)); }); @@ -1498,7 +1498,7 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(1, 6, 1, 6)); CoreEditingCommands.Outdent.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' function baz() {'); + assert.strictEqual(model.getLineContent(1), ' function baz() {'); assertCursor(viewModel, new Selection(1, 5, 1, 5)); }); @@ -1518,7 +1518,7 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(1, 7, 1, 7)); CoreEditingCommands.Outdent.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(1), ' '); assertCursor(viewModel, new Selection(1, 5, 1, 5)); }); @@ -1540,7 +1540,7 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(1, 9, 1, 9)); CoreEditingCommands.Outdent.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(1), ' '); assertCursor(viewModel, new Selection(1, 5, 1, 5)); }); @@ -1568,7 +1568,7 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(7, 1, 7, 1)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(7), '\t'); + assert.strictEqual(model.getLineContent(7), '\t'); assertCursor(viewModel, new Selection(7, 2, 7, 2)); }); @@ -1588,8 +1588,8 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(2, 1, 2, 1)); viewModel.cut('keyboard'); - assert.equal(model.getLineCount(), 1); - assert.equal(model.getLineContent(1), 'asdasd'); + assert.strictEqual(model.getLineCount(), 1); + assert.strictEqual(model.getLineContent(1), 'asdasd'); }); @@ -1604,12 +1604,12 @@ suite('Editor Controller - Regression tests', () => { assertCursor(viewModel, new Selection(2, 1, 2, 1)); viewModel.cut('keyboard'); - assert.equal(model.getLineCount(), 1); - assert.equal(model.getLineContent(1), 'asdasd'); + assert.strictEqual(model.getLineCount(), 1); + assert.strictEqual(model.getLineContent(1), 'asdasd'); viewModel.cut('keyboard'); - assert.equal(model.getLineCount(), 1); - assert.equal(model.getLineContent(1), ''); + assert.strictEqual(model.getLineCount(), 1); + assert.strictEqual(model.getLineContent(1), ''); }); }); @@ -1651,8 +1651,8 @@ suite('Editor Controller - Regression tests', () => { CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); assertCursor(viewModel, new Selection(1, 14, 1, 14)); - assert.equal(model.getLineCount(), 1); - assert.equal(model.getLineContent(1), 'function baz(;'); + assert.strictEqual(model.getLineCount(), 1); + assert.strictEqual(model.getLineContent(1), 'function baz(;'); }); model.dispose(); @@ -1671,9 +1671,9 @@ suite('Editor Controller - Regression tests', () => { viewModel.paste('line1\n', true); - assert.equal(model.getLineContent(1), 'line1'); - assert.equal(model.getLineContent(2), 'line1'); - assert.equal(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(1), 'line1'); + assert.strictEqual(model.getLineContent(2), 'line1'); + assert.strictEqual(model.getLineContent(3), ''); }); }); @@ -1689,10 +1689,10 @@ suite('Editor Controller - Regression tests', () => { viewModel.paste('line1\n', true); - assert.equal(model.getLineContent(1), 'line1'); - assert.equal(model.getLineContent(2), 'line line1'); - assert.equal(model.getLineContent(3), ' 2'); - assert.equal(model.getLineContent(4), 'line3'); + assert.strictEqual(model.getLineContent(1), 'line1'); + assert.strictEqual(model.getLineContent(2), 'line line1'); + assert.strictEqual(model.getLineContent(3), ' 2'); + assert.strictEqual(model.getLineContent(4), 'line3'); }); }); @@ -1715,7 +1715,7 @@ suite('Editor Controller - Regression tests', () => { ] ); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'a', 'bline1', 'c', @@ -1747,7 +1747,7 @@ suite('Editor Controller - Regression tests', () => { null ); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'aaa', 'bbb', 'ccc', @@ -1790,7 +1790,7 @@ suite('Editor Controller - Regression tests', () => { null ); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'aaa', 'bbb', 'ccc', @@ -1815,7 +1815,7 @@ suite('Editor Controller - Regression tests', () => { null ); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'aline1', 'bline2', 'cline3' @@ -1839,7 +1839,7 @@ suite('Editor Controller - Regression tests', () => { null ); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'aline1', 'bline2', 'cline3' @@ -1869,26 +1869,26 @@ suite('Editor Controller - Regression tests', () => { }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ '\t just some text' ].join('\n'), '001'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ ' some lines', ' and more lines', ' just some text', ].join('\n'), '002'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'some lines', 'and more lines', 'just some text', ].join('\n'), '003'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'some lines', 'and more lines', 'just some text', @@ -1911,7 +1911,7 @@ suite('Editor Controller - Regression tests', () => { viewModel.type('😍', 'keyboard'); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'some lines', 'and more lines', '😍just some text', @@ -1933,7 +1933,7 @@ suite('Editor Controller - Regression tests', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { moveTo(editor, viewModel, 3, 2, false); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(3), '\t \tx: 3'); + assert.strictEqual(model.getLineContent(3), '\t \tx: 3'); }); model.dispose(); @@ -1954,7 +1954,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(editor, viewModel, 1, 15, false); moveTo(editor, viewModel, 1, 22, true); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'var foo = 123;\t// this is a comment'); + assert.strictEqual(model.getLineContent(1), 'var foo = 123;\t// this is a comment'); }); model.dispose(); @@ -1982,8 +1982,8 @@ suite('Editor Controller - Regression tests', () => { CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(viewModel, args); } - assert.equal(viewModel.getSelection().startColumn, 1, 'TEST FOR ' + col); - assert.equal(viewModel.getSelection().endColumn, expectedCol, 'TEST FOR ' + col); + assert.strictEqual(viewModel.getSelection().startColumn, 1, 'TEST FOR ' + col); + assert.strictEqual(viewModel.getSelection().endColumn, expectedCol, 'TEST FOR ' + col); } assertWordRight(1, ' '.length + 1); @@ -2048,10 +2048,10 @@ suite('Editor Controller - Regression tests', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { CoreNavigationCommands.WordSelect.runCoreEditorCommand(viewModel, { position: new Position(1, 8) }); - assert.deepEqual(viewModel.getSelection(), new Selection(1, 6, 1, 10)); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(1, 6, 1, 10)); CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(viewModel, { position: new Position(1, 8) }); - assert.deepEqual(viewModel.getSelection(), new Selection(1, 6, 1, 10)); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(1, 6, 1, 10)); }); model.dispose(); @@ -2066,7 +2066,7 @@ suite('Editor Controller - Regression tests', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { CoreNavigationCommands.WordSelect.runCoreEditorCommand(viewModel, { position: new Position(1, 5) }); - assert.deepEqual(viewModel.getSelection(), new Selection(1, 5, 1, 8)); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(1, 5, 1, 8)); }); model.dispose(); @@ -2090,11 +2090,11 @@ suite('Editor Controller - Regression tests', () => { viewModel.replacePreviousChar('せんせい', 4); viewModel.replacePreviousChar('せんせい', 4); - assert.equal(model.getLineContent(1), 'せんせい'); + assert.strictEqual(model.getLineContent(1), 'せんせい'); assertCursor(viewModel, new Position(1, 5)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ''); + assert.strictEqual(model.getLineContent(1), ''); assertCursor(viewModel, new Position(1, 1)); }); }); @@ -2121,11 +2121,11 @@ suite('Editor Controller - Regression tests', () => { viewModel.type('n', 'keyboard'); for (let i = 0; i < LINE_CNT; i++) { - assert.equal(model.getLineContent(i + 1), 'nnasd', 'line #' + (i + 1)); + assert.strictEqual(model.getLineContent(i + 1), 'nnasd', 'line #' + (i + 1)); } - assert.equal(viewModel.getSelections().length, LINE_CNT); - assert.equal(viewModel.getSelections()[LINE_CNT - 1].startLineNumber, LINE_CNT); + assert.strictEqual(viewModel.getSelections().length, LINE_CNT); + assert.strictEqual(viewModel.getSelections()[LINE_CNT - 1].startLineNumber, LINE_CNT); }); }); @@ -2392,10 +2392,10 @@ suite('Editor Controller - Regression tests', () => { range: new Range(1, 1, 1, 1), text: 'Hello world!' }], () => [new Selection(1, 1, 1, 1)]); - assert.equal(model.getValue(EndOfLinePreference.LF), 'Hello world!'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'Hello world!'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'Hello world!'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'Hello world!'); }); model.dispose(); @@ -2457,8 +2457,8 @@ suite('Editor Controller - Regression tests', () => { viewModel.type('\'', 'keyboard'); - assert.equal(model.getLineContent(1), 'const a = \'foo\';'); - assert.equal(model.getLineContent(2), 'const b = \'\''); + assert.strictEqual(model.getLineContent(1), 'const a = \'foo\';'); + assert.strictEqual(model.getLineContent(2), 'const b = \'\''); }); model.dispose(); @@ -2549,7 +2549,7 @@ suite('Editor Controller - Regression tests', () => { new Selection(2, 1, 2, 1) ]); viewModel.paste('something\n', true); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ 'abc123', 'something', '' @@ -2573,22 +2573,22 @@ suite('Editor Controller - Regression tests', () => { ]); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'สวัสด'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัสด'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'สวัส'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัส'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'สวั'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวั'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'สว'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สว'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'ส'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ส'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), ''); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), ''); }); model.dispose(); @@ -2609,8 +2609,8 @@ suite('Editor Controller - Cursor Configuration', () => { }, (editor, model, viewModel) => { CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(1, 21), source: 'keyboard' }); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' \tMy First Line\t '); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(1), ' \tMy First Line\t '); + assert.strictEqual(model.getLineContent(2), ' '); }); }); @@ -2633,56 +2633,56 @@ suite('Editor Controller - Cursor Configuration', () => { // Tab on column 1 CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 1) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' My Second Line123'); + assert.strictEqual(model.getLineContent(2), ' My Second Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 2 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 2) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'M y Second Line123'); + assert.strictEqual(model.getLineContent(2), 'M y Second Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 3 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 3) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 4 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 4) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 5 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 5) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My S econd Line123'); + assert.strictEqual(model.getLineContent(2), 'My S econd Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 5 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 5) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My S econd Line123'); + assert.strictEqual(model.getLineContent(2), 'My S econd Line123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 13 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 13) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My Second Li ne123'); + assert.strictEqual(model.getLineContent(2), 'My Second Li ne123'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); // Tab on column 14 - assert.equal(model.getLineContent(2), 'My Second Line123'); + assert.strictEqual(model.getLineContent(2), 'My Second Line123'); CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 14) }); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'My Second Lin e123'); + assert.strictEqual(model.getLineContent(2), 'My Second Lin e123'); }); model.dispose(); @@ -2700,7 +2700,7 @@ suite('Editor Controller - Cursor Configuration', () => { assertCursor(viewModel, new Selection(1, 7, 1, 7)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); + assert.strictEqual(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); }); mode.dispose(); }); @@ -2717,7 +2717,7 @@ suite('Editor Controller - Cursor Configuration', () => { assertCursor(viewModel, new Selection(1, 7, 1, 7)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); + assert.strictEqual(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); }); mode.dispose(); }); @@ -2734,7 +2734,7 @@ suite('Editor Controller - Cursor Configuration', () => { assertCursor(viewModel, new Selection(1, 7, 1, 7)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thell(\r\n \r\n )'); + assert.strictEqual(model.getValue(EndOfLinePreference.CRLF), '\thell(\r\n \r\n )'); }); mode.dispose(); }); @@ -2752,14 +2752,14 @@ suite('Editor Controller - Cursor Configuration', () => { // Move cursor to the end, verify that we do not trim whitespaces if line has values moveTo(editor, viewModel, 1, model.getLineContent(1).length + 1); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ' '); // Try to enter again, we should trimmed previous line viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ' '); }); }); @@ -2771,13 +2771,13 @@ suite('Editor Controller - Cursor Configuration', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 1, model.getLineContent(1).length + 1); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' '); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(2), ' '); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' '); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), ' '); }); }); @@ -2792,9 +2792,9 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(editor, viewModel, 1, 32); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), 'function foo (params: string) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), '}'); + assert.strictEqual(model.getLineContent(1), 'function foo (params: string) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), '}'); class TestCommand implements ICommand { @@ -2812,9 +2812,9 @@ suite('Editor Controller - Cursor Configuration', () => { } viewModel.executeCommand(new TestCommand(), 'autoFormat'); - assert.equal(model.getLineContent(1), 'function foo(params: string) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), '}'); + assert.strictEqual(model.getLineContent(1), 'function foo(params: string) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), '}'); }); mode.dispose(); }); @@ -2834,27 +2834,27 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(editor, viewModel, 3, 1); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' if (a) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ' '); - assert.equal(model.getLineContent(4), ''); - assert.equal(model.getLineContent(5), ' }'); + assert.strictEqual(model.getLineContent(1), ' if (a) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(4), ''); + assert.strictEqual(model.getLineContent(5), ' }'); moveTo(editor, viewModel, 4, 1); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' if (a) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), ' '); - assert.equal(model.getLineContent(5), ' }'); + assert.strictEqual(model.getLineContent(1), ' if (a) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), ' '); + assert.strictEqual(model.getLineContent(5), ' }'); moveTo(editor, viewModel, 5, model.getLineMaxColumn(5)); viewModel.type('something', 'keyboard'); - assert.equal(model.getLineContent(1), ' if (a) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), ''); - assert.equal(model.getLineContent(5), ' }something'); + assert.strictEqual(model.getLineContent(1), ' if (a) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), ''); + assert.strictEqual(model.getLineContent(5), ' }something'); }); model.dispose(); @@ -2872,46 +2872,46 @@ suite('Editor Controller - Cursor Configuration', () => { // Move cursor to the end, verify that we do not trim whitespaces if line has values moveTo(editor, viewModel, 1, model.getLineContent(1).length + 1); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ' '); // Try to enter again, we should trimmed previous line viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), ' '); // More whitespaces CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), ' '); // Enter and verify that trimmed again viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' some line abc '); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), ' '); + assert.strictEqual(model.getLineContent(1), ' some line abc '); + assert.strictEqual(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), ' '); // Trimmed if we will keep only text moveTo(editor, viewModel, 1, 5); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' '); - assert.equal(model.getLineContent(2), ' some line abc '); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), ''); - assert.equal(model.getLineContent(5), ''); + assert.strictEqual(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(2), ' some line abc '); + assert.strictEqual(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(4), ''); + assert.strictEqual(model.getLineContent(5), ''); // Trimmed if we will keep only text by selection moveTo(editor, viewModel, 2, 5); moveTo(editor, viewModel, 3, 1, true); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(1), ' '); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ' '); - assert.equal(model.getLineContent(4), ''); - assert.equal(model.getLineContent(5), ''); + assert.strictEqual(model.getLineContent(1), ' '); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(4), ''); + assert.strictEqual(model.getLineContent(5), ''); }); model.dispose(); @@ -2932,7 +2932,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(editor, viewModel, 3, model.getLineMaxColumn(3)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ ' function f() {', ' // I\'m gonna copy this line', ' return 3;', @@ -2942,7 +2942,7 @@ suite('Editor Controller - Cursor Configuration', () => { assertCursor(viewModel, new Position(4, model.getLineMaxColumn(4))); viewModel.paste(' // I\'m gonna copy this line\n', true); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ ' function f() {', ' // I\'m gonna copy this line', ' return 3;', @@ -2972,7 +2972,7 @@ suite('Editor Controller - Cursor Configuration', () => { editor.setSelections([new Selection(4, 10, 4, 10)]); viewModel.paste(' // I\'m gonna copy this line\n', true); - assert.equal(model.getValue(), [ + assert.strictEqual(model.getValue(), [ ' function f() {', ' // I\'m gonna copy this line', ' // Another line', @@ -2999,7 +2999,7 @@ suite('Editor Controller - Cursor Configuration', () => { // DeleteLeft removes just one whitespace moveTo(editor, viewModel, 2, 9); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' a '); + assert.strictEqual(model.getLineContent(2), ' a '); }); model.dispose(); @@ -3018,54 +3018,54 @@ suite('Editor Controller - Cursor Configuration', () => { // DeleteLeft does not remove tab size, because some text exists before moveTo(editor, viewModel, 2, model.getLineContent(2).length + 1); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' a '); + assert.strictEqual(model.getLineContent(2), ' a '); // DeleteLeft removes tab size = 4 moveTo(editor, viewModel, 2, 9); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' a '); + assert.strictEqual(model.getLineContent(2), ' a '); // DeleteLeft removes tab size = 4 CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'a '); + assert.strictEqual(model.getLineContent(2), 'a '); // Undo DeleteLeft - get us back to original indentation CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' a '); + assert.strictEqual(model.getLineContent(2), ' a '); // Nothing is broken when cursor is in (1,1) moveTo(editor, viewModel, 1, 1); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' \t \t x'); + assert.strictEqual(model.getLineContent(1), ' \t \t x'); // DeleteLeft stops at tab stops even in mixed whitespace case moveTo(editor, viewModel, 1, 10); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' \t \t x'); + assert.strictEqual(model.getLineContent(1), ' \t \t x'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' \t \tx'); + assert.strictEqual(model.getLineContent(1), ' \t \tx'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' \tx'); + assert.strictEqual(model.getLineContent(1), ' \tx'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'x'); + assert.strictEqual(model.getLineContent(1), 'x'); // DeleteLeft on last line moveTo(editor, viewModel, 3, model.getLineContent(3).length + 1); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(3), ''); + assert.strictEqual(model.getLineContent(3), ''); // DeleteLeft with removing new line symbol CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'x\n a '); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'x\n a '); // In case of selection DeleteLeft only deletes selected text moveTo(editor, viewModel, 2, 3); moveTo(editor, viewModel, 2, 4, true); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' a '); + assert.strictEqual(model.getLineContent(2), ' a '); }); model.dispose(); @@ -3083,55 +3083,55 @@ suite('Editor Controller - Cursor Configuration', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); viewModel.type('y', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty', 'assert2'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty', 'assert2'); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\t', 'assert3'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\n\t', 'assert3'); viewModel.type('x'); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert4'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert4'); CoreNavigationCommands.CursorLeft.runCoreEditorCommand(viewModel, {}); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert5'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert5'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert6'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert6'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tyx', 'assert7'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\tyx', 'assert7'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert8'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert8'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert9'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert9'); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert10'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'x', 'assert10'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert11'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert11'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert12'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert12'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert13'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert13'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert14'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert14'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert15'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\nx', 'assert15'); CoreEditingCommands.Redo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert16'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'x', 'assert16'); }); model.dispose(); @@ -3155,8 +3155,8 @@ suite('Editor Controller - Cursor Configuration', () => { const afterVersion = model.getVersionId(); const afterAltVersion = model.getAlternativeVersionId(); - assert.notEqual(beforeVersion, afterVersion); - assert.equal(beforeAltVersion, afterAltVersion); + assert.notStrictEqual(beforeVersion, afterVersion); + assert.strictEqual(beforeAltVersion, afterAltVersion); }); model.dispose(); @@ -3212,7 +3212,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('}', 'keyboard'); assertCursor(viewModel, new Selection(2, 2, 2, 2)); - assert.equal(model.getLineContent(2), '}', '001'); + assert.strictEqual(model.getLineContent(2), '}', '001'); }); }); @@ -3305,7 +3305,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 1, 4, 1)); - assert.equal(model.getLineContent(3), 'return true;', '001'); + assert.strictEqual(model.getLineContent(3), 'return true;', '001'); }); }); @@ -3326,7 +3326,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(5, 1, 5, 1)); - assert.equal(model.getLineContent(4), '\t}', '001'); + assert.strictEqual(model.getLineContent(4), '\t}', '001'); }); }); @@ -3394,7 +3394,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(3, 16, 3, 16)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(3), ' if (true) {'); + assert.strictEqual(model.getLineContent(3), ' if (true) {'); assertCursor(viewModel, new Selection(4, 9, 4, 9)); }); }); @@ -3419,7 +3419,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(3, 16, 3, 16)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(3), ' if (true) {'); + assert.strictEqual(model.getLineContent(3), ' if (true) {'); assertCursor(viewModel, new Selection(4, 3, 4, 3)); }); }); @@ -3442,7 +3442,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(5, 4, 5, 4)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(5), '\t\t}'); + assert.strictEqual(model.getLineContent(5), '\t\t}'); assertCursor(viewModel, new Selection(6, 3, 6, 3)); }); }); @@ -3463,7 +3463,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 3, 4, 3)); - assert.equal(model.getLineContent(4), '\t\t true;', '001'); + assert.strictEqual(model.getLineContent(4), '\t\t true;', '001'); }); }); @@ -3483,7 +3483,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 3, 4, 3)); - assert.equal(model.getLineContent(4), '\t\treturn true;', '001'); + assert.strictEqual(model.getLineContent(4), '\t\treturn true;', '001'); }); }); @@ -3502,7 +3502,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 5, 4, 5)); - assert.equal(model.getLineContent(4), ' true;', '001'); + assert.strictEqual(model.getLineContent(4), ' true;', '001'); }); }); @@ -3522,14 +3522,14 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 2, 4, 2)); - assert.equal(model.getLineContent(4), '\t\treturn true;', '001'); + assert.strictEqual(model.getLineContent(4), '\t\treturn true;', '001'); moveTo(editor, viewModel, 4, 1, false); assertCursor(viewModel, new Selection(4, 1, 4, 1)); viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(5, 1, 5, 1)); - assert.equal(model.getLineContent(5), '\t\treturn true;', '002'); + assert.strictEqual(model.getLineContent(5), '\t\treturn true;', '002'); }); }); @@ -3549,14 +3549,14 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 3, 4, 3)); - assert.equal(model.getLineContent(4), '\t\t\treturn true;', '001'); + assert.strictEqual(model.getLineContent(4), '\t\t\treturn true;', '001'); moveTo(editor, viewModel, 4, 1, false); assertCursor(viewModel, new Selection(4, 1, 4, 1)); viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(5, 1, 5, 1)); - assert.equal(model.getLineContent(5), '\t\t\treturn true;', '002'); + assert.strictEqual(model.getLineContent(5), '\t\t\treturn true;', '002'); }); }); @@ -3575,12 +3575,12 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 2, 4, 2)); - assert.equal(model.getLineContent(4), ' return true;', '001'); + assert.strictEqual(model.getLineContent(4), ' return true;', '001'); moveTo(editor, viewModel, 4, 3, false); viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(5, 3, 5, 3)); - assert.equal(model.getLineContent(5), ' return true;', '002'); + assert.strictEqual(model.getLineContent(5), ' return true;', '002'); }); }); @@ -3608,12 +3608,12 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 4, 4, 4)); - assert.equal(model.getLineContent(4), ' return true;', '001'); + assert.strictEqual(model.getLineContent(4), ' return true;', '001'); moveTo(editor, viewModel, 9, 4, false); viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(10, 5, 10, 5)); - assert.equal(model.getLineContent(10), ' return true;', '001'); + assert.strictEqual(model.getLineContent(10), ' return true;', '001'); }); }); @@ -3635,7 +3635,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 3, 4, 3)); - assert.equal(model.getLineContent(4), ' return true;', '001'); + assert.strictEqual(model.getLineContent(4), ' return true;', '001'); }); }); @@ -3657,7 +3657,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(3, 8, 2, 12)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(3), '\treturn x;'); + assert.strictEqual(model.getLineContent(3), '\treturn x;'); assertCursor(viewModel, new Position(3, 2)); }); }); @@ -3680,7 +3680,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(2, 12, 3, 8)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(3), '\treturn x;'); + assert.strictEqual(model.getLineContent(3), '\treturn x;'); assertCursor(viewModel, new Position(3, 2)); }); }); @@ -3701,9 +3701,9 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(5, 3, 5, 3)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getLineContent(6), '\t'); + assert.strictEqual(model.getLineContent(6), '\t'); assertCursor(viewModel, new Selection(6, 2, 6, 2)); - assert.equal(model.getLineContent(5), '\t}'); + assert.strictEqual(model.getLineContent(5), '\t}'); }); }); @@ -3721,7 +3721,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('\n', 'keyboard'); assertCursor(viewModel, new Selection(4, 2, 4, 2)); - assert.equal(model.getLineContent(4), '\t'); + assert.strictEqual(model.getLineContent(4), '\t'); }); }); @@ -3746,7 +3746,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 1, 4, 1)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(4), '\t\t'); + assert.strictEqual(model.getLineContent(4), '\t\t'); }); model.dispose(); @@ -3774,7 +3774,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 2, 4, 2)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(4), '\t\t\t'); + assert.strictEqual(model.getLineContent(4), '\t\t\t'); }); model.dispose(); @@ -3802,7 +3802,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 1, 4, 1)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(4), '\t\t\t'); + assert.strictEqual(model.getLineContent(4), '\t\t\t'); }); model.dispose(); @@ -3829,7 +3829,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 3, 4, 3)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(4), '\t\t\t\t'); + assert.strictEqual(model.getLineContent(4), '\t\t\t\t'); }); model.dispose(); @@ -3856,7 +3856,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 4, 4, 4)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(4), '\t\t\t\t\t'); + assert.strictEqual(model.getLineContent(4), '\t\t\t\t\t'); }); model.dispose(); @@ -3880,11 +3880,11 @@ suite('Editor Controller - Indentation Rules', () => { moveTo(editor, viewModel, 3, 1); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), ' if (a) {'); - assert.equal(model.getLineContent(2), ' '); - assert.equal(model.getLineContent(3), ' '); - assert.equal(model.getLineContent(4), ''); - assert.equal(model.getLineContent(5), ' }'); + assert.strictEqual(model.getLineContent(1), ' if (a) {'); + assert.strictEqual(model.getLineContent(2), ' '); + assert.strictEqual(model.getLineContent(3), ' '); + assert.strictEqual(model.getLineContent(4), ''); + assert.strictEqual(model.getLineContent(5), ' }'); }); model.dispose(); @@ -3911,7 +3911,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(4, 7, 4, 7)); viewModel.type('d', 'keyboard'); - assert.equal(model.getLineContent(4), ' end'); + assert.strictEqual(model.getLineContent(4), ' end'); }); rubyMode.dispose(); @@ -3934,7 +3934,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('e', 'keyboard'); assertCursor(viewModel, new Selection(5, 4, 5, 4)); - assert.equal(model.getLineContent(5), '\t}e', 'This line should not decrease indent'); + assert.strictEqual(model.getLineContent(5), '\t}e', 'This line should not decrease indent'); }); }); @@ -3955,7 +3955,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type(' ', 'keyboard'); assertCursor(viewModel, new Selection(2, 4, 2, 4)); - assert.equal(model.getLineContent(2), '\t ) {', 'This line should not decrease indent'); + assert.strictEqual(model.getLineContent(2), '\t ) {', 'This line should not decrease indent'); }); }); @@ -3974,7 +3974,7 @@ suite('Editor Controller - Indentation Rules', () => { viewModel.type('}', 'keyboard'); assertCursor(viewModel, new Selection(3, 2, 3, 2)); - assert.equal(model.getLineContent(3), '}'); + assert.strictEqual(model.getLineContent(3), '}'); }); }); @@ -4021,7 +4021,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(7, 6, 7, 6)); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(), + assert.strictEqual(model.getValue(), [ 'class ItemCtrl {', ' getPropertiesByItemId(id) {', @@ -4085,7 +4085,7 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(8, 1, 8, 1)); CoreEditingCommands.Tab.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), + assert.strictEqual(model.getValue(), [ 'int main() {', ' return 0;', @@ -4098,7 +4098,7 @@ suite('Editor Controller - Indentation Rules', () => { ')', ].join('\n') ); - assert.deepEqual(viewModel.getSelection(), new Selection(8, 3, 8, 3)); + assert.deepStrictEqual(viewModel.getSelection(), new Selection(8, 3, 8, 3)); }); model.dispose(); @@ -4175,26 +4175,26 @@ suite('Editor Controller - Indentation Rules', () => { assertCursor(viewModel, new Selection(3, 19, 3, 19)); viewModel.type('\n', 'keyboard'); - assert.deepEqual(model.getLineContent(4), ' '); + assert.deepStrictEqual(model.getLineContent(4), ' '); moveTo(editor, viewModel, 5, 18, false); assertCursor(viewModel, new Selection(5, 18, 5, 18)); viewModel.type('\n', 'keyboard'); - assert.deepEqual(model.getLineContent(6), ' '); + assert.deepStrictEqual(model.getLineContent(6), ' '); moveTo(editor, viewModel, 7, 15, false); assertCursor(viewModel, new Selection(7, 15, 7, 15)); viewModel.type('\n', 'keyboard'); - assert.deepEqual(model.getLineContent(8), ' '); - assert.deepEqual(model.getLineContent(9), ' ]'); + assert.deepStrictEqual(model.getLineContent(8), ' '); + assert.deepStrictEqual(model.getLineContent(9), ' ]'); moveTo(editor, viewModel, 10, 18, false); assertCursor(viewModel, new Selection(10, 18, 10, 18)); viewModel.type('\n', 'keyboard'); - assert.deepEqual(model.getLineContent(11), ' ]'); + assert.deepStrictEqual(model.getLineContent(11), ' ]'); }); model.dispose(); @@ -4209,7 +4209,7 @@ suite('Editor Controller - Indentation Rules', () => { new Selection(1, 14, 1, 14), ]); viewModel.type('\n', 'keyboard'); - assert.equal(model.getValue(), ' let a,\n\t b,\n\t c;'); + assert.strictEqual(model.getValue(), ' let a,\n\t b,\n\t c;'); }); }); }); @@ -4261,7 +4261,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 1); viewModel.type('*', 'keyboard'); - assert.deepEqual(model.getLineContent(2), '*'); + assert.deepStrictEqual(model.getLineContent(2), '*'); }); mode.dispose(); }); @@ -4277,7 +4277,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 1); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' }'); + assert.deepStrictEqual(model.getLineContent(2), ' }'); }); mode.dispose(); }); @@ -4293,7 +4293,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 5); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' }'); + assert.deepStrictEqual(model.getLineContent(2), ' }'); }); mode.dispose(); }); @@ -4311,7 +4311,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 4, 1); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(4), ' } '); + assert.deepStrictEqual(model.getLineContent(4), ' } '); }); mode.dispose(); }); @@ -4329,7 +4329,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 4, 6); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(4), ' } }'); + assert.deepStrictEqual(model.getLineContent(4), ' } }'); }); mode.dispose(); }); @@ -4345,7 +4345,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 1); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' }// hello'); + assert.deepStrictEqual(model.getLineContent(2), ' }// hello'); }); mode.dispose(); }); @@ -4361,7 +4361,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 3); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' }'); + assert.deepStrictEqual(model.getLineContent(2), ' }'); }); mode.dispose(); }); @@ -4377,7 +4377,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 2); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), 'a}'); + assert.deepStrictEqual(model.getLineContent(2), 'a}'); }); mode.dispose(); }); @@ -4394,7 +4394,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 13); viewModel.type('*', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' ( 1 + 2 ) *'); + assert.deepStrictEqual(model.getLineContent(2), ' ( 1 + 2 ) *'); }); mode.dispose(); }); @@ -4413,8 +4413,8 @@ suite('ElectricCharacter', () => { changeText = e.changes[0].text; }); viewModel.type(')', 'keyboard'); - assert.deepEqual(model.getLineContent(1), '(div)'); - assert.deepEqual(changeText, ')'); + assert.deepStrictEqual(model.getLineContent(1), '(div)'); + assert.deepStrictEqual(changeText, ')'); }); mode.dispose(); }); @@ -4431,7 +4431,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 3, 3); viewModel.type(')', 'keyboard'); - assert.deepEqual(model.getLineContent(3), '\t3)'); + assert.deepStrictEqual(model.getLineContent(3), '\t3)'); }); mode.dispose(); }); @@ -4447,7 +4447,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 3); viewModel.type('*', 'keyboard'); - assert.deepEqual(model.getLineContent(2), '/** */'); + assert.deepStrictEqual(model.getLineContent(2), '/** */'); }); mode.dispose(); }); @@ -4463,7 +4463,7 @@ suite('ElectricCharacter', () => { }, (editor, model, viewModel) => { moveTo(editor, viewModel, 2, 5); viewModel.type('*', 'keyboard'); - assert.deepEqual(model.getLineContent(2), ' /** */'); + assert.deepStrictEqual(model.getLineContent(2), ' /** */'); }); mode.dispose(); }); @@ -4480,7 +4480,7 @@ suite('ElectricCharacter', () => { moveTo(editor, viewModel, 2, 5); moveTo(editor, viewModel, 2, 1, true); viewModel.type('}', 'keyboard'); - assert.deepEqual(model.getLineContent(2), '}'); + assert.deepStrictEqual(model.getLineContent(2), '}'); }); mode.dispose(); }); @@ -4556,7 +4556,7 @@ suite('autoClosingPairs', () => { let expected = lineContent.substr(0, column - 1) + expectedInsert + lineContent.substr(column - 1); moveTo(editor, viewModel, lineNumber, column); viewModel.type(chr, 'keyboard'); - assert.deepEqual(model.getLineContent(lineNumber), expected, message); + assert.deepStrictEqual(model.getLineContent(lineNumber), expected, message); model.undo(); } @@ -4826,12 +4826,12 @@ suite('autoClosingPairs', () => { // type a ` viewModel.type('`', 'keyboard'); - assert.equal(model.getValue(), '`var` a = `asd`'); + assert.strictEqual(model.getValue(), '`var` a = `asd`'); // type a ( viewModel.type('(', 'keyboard'); - assert.equal(model.getValue(), '`(var)` a = `(asd)`'); + assert.strictEqual(model.getValue(), '`(var)` a = `(asd)`'); }); usingCursor({ @@ -4851,7 +4851,7 @@ suite('autoClosingPairs', () => { // type a ` viewModel.type('`', 'keyboard'); - assert.equal(model.getValue(), '` a = asd'); + assert.strictEqual(model.getValue(), '` a = asd'); }); usingCursor({ @@ -4870,11 +4870,11 @@ suite('autoClosingPairs', () => { // type a ` viewModel.type('`', 'keyboard'); - assert.equal(model.getValue(), '`var` a = asd'); + assert.strictEqual(model.getValue(), '`var` a = asd'); // type a ( viewModel.type('(', 'keyboard'); - assert.equal(model.getValue(), '`(` a = asd'); + assert.strictEqual(model.getValue(), '`(` a = asd'); }); usingCursor({ @@ -4893,11 +4893,11 @@ suite('autoClosingPairs', () => { // type a ( viewModel.type('(', 'keyboard'); - assert.equal(model.getValue(), '(var) a = asd'); + assert.strictEqual(model.getValue(), '(var) a = asd'); // type a ` viewModel.type('`', 'keyboard'); - assert.equal(model.getValue(), '(`) a = asd'); + assert.strictEqual(model.getValue(), '(`) a = asd'); }); mode.dispose(); }); @@ -5090,50 +5090,50 @@ suite('autoClosingPairs', () => { // First gif model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste1 = teste\' ok'); - assert.equal(model.getLineContent(1), 'teste1 = teste\' ok'); + assert.strictEqual(model.getLineContent(1), 'teste1 = teste\' ok'); viewModel.setSelections('test', [new Selection(1, 1000, 1, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste2 = teste \'ok'); - assert.equal(model.getLineContent(2), 'teste2 = teste \'ok\''); + assert.strictEqual(model.getLineContent(2), 'teste2 = teste \'ok\''); viewModel.setSelections('test', [new Selection(2, 1000, 2, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste3 = teste" ok'); - assert.equal(model.getLineContent(3), 'teste3 = teste" ok'); + assert.strictEqual(model.getLineContent(3), 'teste3 = teste" ok'); viewModel.setSelections('test', [new Selection(3, 1000, 3, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste4 = teste "ok'); - assert.equal(model.getLineContent(4), 'teste4 = teste "ok"'); + assert.strictEqual(model.getLineContent(4), 'teste4 = teste "ok"'); // Second gif viewModel.setSelections('test', [new Selection(4, 1000, 4, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste \''); - assert.equal(model.getLineContent(5), 'teste \'\''); + assert.strictEqual(model.getLineContent(5), 'teste \'\''); viewModel.setSelections('test', [new Selection(5, 1000, 5, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste "'); - assert.equal(model.getLineContent(6), 'teste ""'); + assert.strictEqual(model.getLineContent(6), 'teste ""'); viewModel.setSelections('test', [new Selection(6, 1000, 6, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste\''); - assert.equal(model.getLineContent(7), 'teste\''); + assert.strictEqual(model.getLineContent(7), 'teste\''); viewModel.setSelections('test', [new Selection(7, 1000, 7, 1000)]); typeCharacters(viewModel, '\n'); model.forceTokenization(model.getLineCount()); typeCharacters(viewModel, 'teste"'); - assert.equal(model.getLineContent(8), 'teste"'); + assert.strictEqual(model.getLineContent(8), 'teste"'); }); mode.dispose(); }); @@ -5380,7 +5380,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('è', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), 'è'); + assert.strictEqual(model.getValue(), 'è'); }); mode.dispose(); }); @@ -5402,7 +5402,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '\'test\''); + assert.strictEqual(model.getValue(), '\'test\''); }); mode.dispose(); }); @@ -5419,16 +5419,16 @@ suite('autoClosingPairs', () => { viewModel.setSelections('test', [new Selection(1, 13, 1, 13)]); viewModel.type('\'', 'keyboard'); - assert.equal(model.getValue(), 'console.log(\'\');'); + assert.strictEqual(model.getValue(), 'console.log(\'\');'); viewModel.type('it', 'keyboard'); - assert.equal(model.getValue(), 'console.log(\'it\');'); + assert.strictEqual(model.getValue(), 'console.log(\'it\');'); viewModel.type('\\', 'keyboard'); - assert.equal(model.getValue(), 'console.log(\'it\\\');'); + assert.strictEqual(model.getValue(), 'console.log(\'it\\\');'); viewModel.type('\'', 'keyboard'); - assert.equal(model.getValue(), 'console.log(\'it\\\'\');'); + assert.strictEqual(model.getValue(), 'console.log(\'it\\\'\');'); }); mode.dispose(); }); @@ -5445,19 +5445,19 @@ suite('autoClosingPairs', () => { viewModel.setSelections('test', [new Selection(1, 1, 1, 1)]); viewModel.type('\\', 'keyboard'); - assert.equal(model.getValue(), '\\'); + assert.strictEqual(model.getValue(), '\\'); viewModel.type('(', 'keyboard'); - assert.equal(model.getValue(), '\\()'); + assert.strictEqual(model.getValue(), '\\()'); viewModel.type('abc', 'keyboard'); - assert.equal(model.getValue(), '\\(abc)'); + assert.strictEqual(model.getValue(), '\\(abc)'); viewModel.type('\\', 'keyboard'); - assert.equal(model.getValue(), '\\(abc\\)'); + assert.strictEqual(model.getValue(), '\\(abc\\)'); viewModel.type(')', 'keyboard'); - assert.equal(model.getValue(), '\\(abc\\)'); + assert.strictEqual(model.getValue(), '\\(abc\\)'); }); mode.dispose(); }); @@ -5482,7 +5482,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('`', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '`hello\nworld'); + assert.strictEqual(model.getValue(), '`hello\nworld'); assertCursor(viewModel, new Selection(1, 2, 2, 2)); }); mode.dispose(); @@ -5505,14 +5505,14 @@ suite('autoClosingPairs', () => { viewModel.type('\'', 'keyboard'); viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '\'\''); + assert.strictEqual(model.getValue(), '\'\''); // Typing one more ' + space viewModel.startComposition(); viewModel.type('\'', 'keyboard'); viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '\'\''); + assert.strictEqual(model.getValue(), '\'\''); // Typing ' as a closing tag model.setValue('\'abc'); @@ -5522,7 +5522,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '\'abc\''); + assert.strictEqual(model.getValue(), '\'abc\''); // quotes before the newly added character are all paired. model.setValue('\'abc\'def '); @@ -5532,7 +5532,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '\'abc\'def \'\''); + assert.strictEqual(model.getValue(), '\'abc\'def \'\''); // No auto closing if there is non-whitespace character after the cursor model.setValue('abc'); @@ -5550,7 +5550,7 @@ suite('autoClosingPairs', () => { viewModel.replacePreviousChar('\'', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), 'abc\''); + assert.strictEqual(model.getValue(), 'abc\''); }); mode.dispose(); }); @@ -5570,7 +5570,7 @@ suite('autoClosingPairs', () => { viewModel.type('a', 'keyboard'); viewModel.replacePreviousChar('', 1, 'keyboard'); viewModel.endComposition('keyboard'); - assert.equal(model.getValue(), '{}'); + assert.strictEqual(model.getValue(), '{}'); }); mode.dispose(); }); @@ -5592,7 +5592,7 @@ suite('autoClosingPairs', () => { // type a ` viewModel.type('`', 'keyboard'); - assert.equal(model.getValue(), 'var a = `asd`'); + assert.strictEqual(model.getValue(), 'var a = `asd`'); }); mode.dispose(); }); @@ -5620,14 +5620,14 @@ suite('autoClosingPairs', () => { new Selection(1, 12, 1, 13) ]); viewModel.type('"', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), 'var x = "hi";', 'assert1'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'var x = "hi";', 'assert1'); editor.setSelections([ new Selection(1, 9, 1, 10), new Selection(1, 12, 1, 13) ]); viewModel.type('\'', 'keyboard'); - assert.equal(model.getValue(EndOfLinePreference.LF), 'var x = \'hi\';', 'assert2'); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'var x = \'hi\';', 'assert2'); }); model.dispose(); @@ -5653,7 +5653,7 @@ suite('autoClosingPairs', () => { // delete left CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), 'va a = )'); + assert.strictEqual(model.getValue(), 'va a = )'); }); model.dispose(); mode.dispose(); @@ -5700,20 +5700,20 @@ suite('Undo stops', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.setSelections('test', [new Selection(1, 3, 1, 3)]); viewModel.type('first', 'keyboard'); - assert.equal(model.getLineContent(1), 'A first line'); + assert.strictEqual(model.getLineContent(1), 'A first line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A fir line'); + assert.strictEqual(model.getLineContent(1), 'A fir line'); assertCursor(viewModel, new Selection(1, 6, 1, 6)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A first line'); + assert.strictEqual(model.getLineContent(1), 'A first line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A line'); + assert.strictEqual(model.getLineContent(1), 'A line'); assertCursor(viewModel, new Selection(1, 3, 1, 3)); }); }); @@ -5729,20 +5729,20 @@ suite('Undo stops', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.setSelections('test', [new Selection(1, 3, 1, 3)]); viewModel.type('first', 'keyboard'); - assert.equal(model.getLineContent(1), 'A first line'); + assert.strictEqual(model.getLineContent(1), 'A first line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A firstine'); + assert.strictEqual(model.getLineContent(1), 'A firstine'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A first line'); + assert.strictEqual(model.getLineContent(1), 'A first line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A line'); + assert.strictEqual(model.getLineContent(1), 'A line'); assertCursor(viewModel, new Selection(1, 3, 1, 3)); }); }); @@ -5764,19 +5764,19 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' line'); + assert.strictEqual(model.getLineContent(2), ' line'); assertCursor(viewModel, new Selection(2, 1, 2, 1)); viewModel.type('Second', 'keyboard'); - assert.equal(model.getLineContent(2), 'Second line'); + assert.strictEqual(model.getLineContent(2), 'Second line'); assertCursor(viewModel, new Selection(2, 7, 2, 7)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' line'); + assert.strictEqual(model.getLineContent(2), ' line'); assertCursor(viewModel, new Selection(2, 1, 2, 1)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another line'); + assert.strictEqual(model.getLineContent(2), 'Another line'); assertCursor(viewModel, new Selection(2, 8, 2, 8)); }); }); @@ -5798,7 +5798,7 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' line'); + assert.strictEqual(model.getLineContent(2), ' line'); assertCursor(viewModel, new Selection(2, 1, 2, 1)); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); @@ -5806,15 +5806,15 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ''); + assert.strictEqual(model.getLineContent(2), ''); assertCursor(viewModel, new Selection(2, 1, 2, 1)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), ' line'); + assert.strictEqual(model.getLineContent(2), ' line'); assertCursor(viewModel, new Selection(2, 1, 2, 1)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another line'); + assert.strictEqual(model.getLineContent(2), 'Another line'); assertCursor(viewModel, new Selection(2, 8, 2, 8)); }); }); @@ -5833,19 +5833,19 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another '); + assert.strictEqual(model.getLineContent(2), 'Another '); assertCursor(viewModel, new Selection(2, 9, 2, 9)); viewModel.type('text', 'keyboard'); - assert.equal(model.getLineContent(2), 'Another text'); + assert.strictEqual(model.getLineContent(2), 'Another text'); assertCursor(viewModel, new Selection(2, 13, 2, 13)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another '); + assert.strictEqual(model.getLineContent(2), 'Another '); assertCursor(viewModel, new Selection(2, 9, 2, 9)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another line'); + assert.strictEqual(model.getLineContent(2), 'Another line'); assertCursor(viewModel, new Selection(2, 9, 2, 9)); }); }); @@ -5864,7 +5864,7 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another '); + assert.strictEqual(model.getLineContent(2), 'Another '); assertCursor(viewModel, new Selection(2, 9, 2, 9)); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); @@ -5873,15 +5873,15 @@ suite('Undo stops', () => { CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'An'); + assert.strictEqual(model.getLineContent(2), 'An'); assertCursor(viewModel, new Selection(2, 3, 2, 3)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another '); + assert.strictEqual(model.getLineContent(2), 'Another '); assertCursor(viewModel, new Selection(2, 9, 2, 9)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(2), 'Another line'); + assert.strictEqual(model.getLineContent(2), 'Another line'); assertCursor(viewModel, new Selection(2, 9, 2, 9)); }); }); @@ -5897,19 +5897,19 @@ suite('Undo stops', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.setSelections('test', [new Selection(1, 3, 1, 3)]); viewModel.type('first and interesting', 'keyboard'); - assert.equal(model.getLineContent(1), 'A first and interesting line'); + assert.strictEqual(model.getLineContent(1), 'A first and interesting line'); assertCursor(viewModel, new Selection(1, 24, 1, 24)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A first and line'); + assert.strictEqual(model.getLineContent(1), 'A first and line'); assertCursor(viewModel, new Selection(1, 12, 1, 12)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A first line'); + assert.strictEqual(model.getLineContent(1), 'A first line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getLineContent(1), 'A line'); + assert.strictEqual(model.getLineContent(1), 'A line'); assertCursor(viewModel, new Selection(1, 3, 1, 3)); }); }); @@ -5925,15 +5925,15 @@ suite('Undo stops', () => { withTestCodeEditor(null, { model: model }, (editor, viewModel) => { viewModel.setSelections('test', [new Selection(1, 3, 1, 3)]); viewModel.type('first', 'keyboard'); - assert.equal(model.getValue(), 'A first line\nAnother line'); + assert.strictEqual(model.getValue(), 'A first line\nAnother line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); model.pushEOL(EndOfLineSequence.CRLF); - assert.equal(model.getValue(), 'A first line\r\nAnother line'); + assert.strictEqual(model.getValue(), 'A first line\r\nAnother line'); assertCursor(viewModel, new Selection(1, 8, 1, 8)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), 'A line\nAnother line'); + assert.strictEqual(model.getValue(), 'A line\nAnother line'); assertCursor(viewModel, new Selection(1, 3, 1, 3)); }); }); @@ -5952,10 +5952,10 @@ suite('Undo stops', () => { new Selection(1, 7, 1, 12), ]); viewModel.type('no', 'keyboard'); - assert.equal(model.getValue(), 'hello no\nhello no'); + assert.strictEqual(model.getValue(), 'hello no\nhello no'); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); - assert.equal(model.getValue(), 'hello world\nhello world'); + assert.strictEqual(model.getValue(), 'hello world\nhello world'); }); }); }); diff --git a/src/vs/editor/test/browser/controller/cursorMoveCommand.test.ts b/src/vs/editor/test/browser/controller/cursorMoveCommand.test.ts index 3c85cc22eb2..55abff9fa91 100644 --- a/src/vs/editor/test/browser/controller/cursorMoveCommand.test.ts +++ b/src/vs/editor/test/browser/controller/cursorMoveCommand.test.ts @@ -484,11 +484,11 @@ function cursorEqual(viewModel: ViewModel, posLineNumber: number, posColumn: num } function positionEqual(position: Position, lineNumber: number, column: number) { - assert.deepEqual(position, new Position(lineNumber, column), 'position equal'); + assert.deepStrictEqual(position, new Position(lineNumber, column), 'position equal'); } function selectionEqual(selection: Selection, posLineNumber: number, posColumn: number, selLineNumber: number, selColumn: number) { - assert.deepEqual({ + assert.deepStrictEqual({ selectionStartLineNumber: selection.selectionStartLineNumber, selectionStartColumn: selection.selectionStartColumn, positionLineNumber: selection.positionLineNumber, diff --git a/src/vs/editor/test/browser/controller/textAreaState.test.ts b/src/vs/editor/test/browser/controller/textAreaState.test.ts index 163e9de5422..4ae25e14a22 100644 --- a/src/vs/editor/test/browser/controller/textAreaState.test.ts +++ b/src/vs/editor/test/browser/controller/textAreaState.test.ts @@ -84,8 +84,8 @@ suite('TextAreaState', () => { let actual = TextAreaState.readFromTextArea(textArea); assertTextAreaState(actual, 'Hello world!', 1, 12); - assert.equal(actual.value, 'Hello world!'); - assert.equal(actual.selectionStart, 1); + assert.strictEqual(actual.value, 'Hello world!'); + assert.strictEqual(actual.selectionStart, 1); actual = actual.collapseSelection(); assertTextAreaState(actual, 'Hello world!', 12, 12); @@ -102,23 +102,23 @@ suite('TextAreaState', () => { let state = new TextAreaState('Hi world!', 2, 2, null, null); state.writeToTextArea('test', textArea, false); - assert.equal(textArea._value, 'Hi world!'); - assert.equal(textArea._selectionStart, 9); - assert.equal(textArea._selectionEnd, 9); + assert.strictEqual(textArea._value, 'Hi world!'); + assert.strictEqual(textArea._selectionStart, 9); + assert.strictEqual(textArea._selectionEnd, 9); state = new TextAreaState('Hi world!', 3, 3, null, null); state.writeToTextArea('test', textArea, false); - assert.equal(textArea._value, 'Hi world!'); - assert.equal(textArea._selectionStart, 9); - assert.equal(textArea._selectionEnd, 9); + assert.strictEqual(textArea._value, 'Hi world!'); + assert.strictEqual(textArea._selectionStart, 9); + assert.strictEqual(textArea._selectionEnd, 9); state = new TextAreaState('Hi world!', 0, 2, null, null); state.writeToTextArea('test', textArea, true); - assert.equal(textArea._value, 'Hi world!'); - assert.equal(textArea._selectionStart, 0); - assert.equal(textArea._selectionEnd, 2); + assert.strictEqual(textArea._value, 'Hi world!'); + assert.strictEqual(textArea._selectionStart, 0); + assert.strictEqual(textArea._selectionEnd, 2); textArea.dispose(); }); @@ -134,8 +134,8 @@ suite('TextAreaState', () => { let newState = TextAreaState.readFromTextArea(textArea); let actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput); - assert.equal(actual.text, expected); - assert.equal(actual.replaceCharCnt, expectedCharReplaceCnt); + assert.strictEqual(actual.text, expected); + assert.strictEqual(actual.replaceCharCnt, expectedCharReplaceCnt); textArea.dispose(); } diff --git a/src/vs/editor/test/browser/core/editorState.test.ts b/src/vs/editor/test/browser/core/editorState.test.ts index 1915af4f711..32534c2b7d2 100644 --- a/src/vs/editor/test/browser/core/editorState.test.ts +++ b/src/vs/editor/test/browser/core/editorState.test.ts @@ -29,7 +29,7 @@ suite('Editor Core - Editor State', () => { test('empty editor state should be valid', () => { let result = validate({}, {}); - assert.equal(result, true); + assert.strictEqual(result, true); }); test('different model URIs should be invalid', () => { @@ -38,7 +38,7 @@ suite('Editor Core - Editor State', () => { { model: { uri: URI.parse('http://test2') } } ); - assert.equal(result, false); + assert.strictEqual(result, false); }); test('different model versions should be invalid', () => { @@ -47,7 +47,7 @@ suite('Editor Core - Editor State', () => { { model: { version: 2 } } ); - assert.equal(result, false); + assert.strictEqual(result, false); }); test('different positions should be invalid', () => { @@ -56,7 +56,7 @@ suite('Editor Core - Editor State', () => { { position: new Position(2, 3) } ); - assert.equal(result, false); + assert.strictEqual(result, false); }); test('different selections should be invalid', () => { @@ -65,7 +65,7 @@ suite('Editor Core - Editor State', () => { { selection: new Selection(5, 2, 3, 4) } ); - assert.equal(result, false); + assert.strictEqual(result, false); }); test('different scroll positions should be invalid', () => { @@ -74,7 +74,7 @@ suite('Editor Core - Editor State', () => { { scroll: { left: 3, top: 2 } } ); - assert.equal(result, false); + assert.strictEqual(result, false); }); diff --git a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts index 9c8c6c6ed64..37055a85416 100644 --- a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts +++ b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts @@ -60,12 +60,12 @@ suite('Decoration Render Options', () => { test('register and resolve decoration type', () => { let s = new TestCodeEditorServiceImpl(themeServiceMock); s.registerDecorationType('example', options); - assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined); }); test('remove decoration type', () => { let s = new TestCodeEditorServiceImpl(themeServiceMock); s.registerDecorationType('example', options); - assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined); s.removeDecorationType('example'); assert.throws(() => s.resolveDecorationOptions('example', false)); }); @@ -95,16 +95,16 @@ suite('Decoration Render Options', () => { })); const s = new TestCodeEditorServiceImpl(themeService, styleSheet); s.registerDecorationType('example', options); - assert.equal(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ff0000;border-color:transparent;box-sizing: border-box;}'); + assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ff0000;border-color:transparent;box-sizing: border-box;}'); themeService.setTheme(new TestColorTheme({ editorBackground: '#EE0000', editorBorder: '#00FFFF' })); - assert.equal(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ee0000;border-color:#00ffff;box-sizing: border-box;}'); + assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ee0000;border-color:#00ffff;box-sizing: border-box;}'); s.removeDecorationType('example'); - assert.equal(readStyleSheet(styleSheet), ''); + assert.strictEqual(readStyleSheet(styleSheet), ''); }); test('theme overrides', () => { @@ -134,10 +134,10 @@ suite('Decoration Render Options', () => { '.vs.monaco-editor .ced-example-1 {color:#FF00FF !important;}', '.monaco-editor .ced-example-1 {color:#ff0000 !important;}' ].join('\n'); - assert.equal(readStyleSheet(styleSheet), expected); + assert.strictEqual(readStyleSheet(styleSheet), expected); s.removeDecorationType('example'); - assert.equal(readStyleSheet(styleSheet), ''); + assert.strictEqual(readStyleSheet(styleSheet), ''); }); test('css properties, gutterIconPaths', () => { diff --git a/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts b/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts index cde86790141..81aed990b4b 100644 --- a/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts +++ b/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts @@ -85,7 +85,7 @@ suite('MinimapCharRenderer', () => { actual[i] = imageData.data[i]; } - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ 0x2D, 0x2D, 0x2D, 0xFF, 0xAC, 0xAC, 0xAC, 0xFF, 0xC6, 0xC6, 0xC6, 0xFF, 0xC8, 0xC8, 0xC8, 0xFF, 0xC0, 0xC0, 0xC0, 0xFF, 0xCB, 0xCB, 0xCB, 0xFF, @@ -115,7 +115,7 @@ suite('MinimapCharRenderer', () => { actual[i] = imageData.data[i]; } - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ 0xCB, 0xCB, 0xCB, 0xFF, 0x81, 0x81, 0x81, 0xFF, ]); diff --git a/src/vs/editor/test/browser/view/viewLayer.test.ts b/src/vs/editor/test/browser/view/viewLayer.test.ts index bffb2f8b18b..eba81ff74ba 100644 --- a/src/vs/editor/test/browser/view/viewLayer.test.ts +++ b/src/vs/editor/test/browser/view/viewLayer.test.ts @@ -36,7 +36,7 @@ function assertState(col: RenderedLinesCollection, state: ILinesCollec actualState.lines.push(col.getLine(lineNumber).id); actualState.pinged.push(col.getLine(lineNumber)._pinged); } - assert.deepEqual(actualState, state); + assert.deepStrictEqual(actualState, state); } suite('RenderedLinesCollection onLinesDeleted', () => { @@ -54,7 +54,7 @@ suite('RenderedLinesCollection onLinesDeleted', () => { if (actualDeleted1) { actualDeleted = actualDeleted1.map(line => line.id); } - assert.deepEqual(actualDeleted, expectedDeleted); + assert.deepStrictEqual(actualDeleted, expectedDeleted); assertState(col, expectedState); } @@ -325,7 +325,7 @@ suite('RenderedLinesCollection onLineChanged', () => { new TestLine('old9') ]); let actualPinged = col.onLinesChanged(changedLineNumber, changedLineNumber); - assert.deepEqual(actualPinged, expectedPinged); + assert.deepStrictEqual(actualPinged, expectedPinged); assertState(col, expectedState); } @@ -410,7 +410,7 @@ suite('RenderedLinesCollection onLinesInserted', () => { if (actualDeleted1) { actualDeleted = actualDeleted1.map(line => line.id); } - assert.deepEqual(actualDeleted, expectedDeleted); + assert.deepStrictEqual(actualDeleted, expectedDeleted); assertState(col, expectedState); } @@ -682,7 +682,7 @@ suite('RenderedLinesCollection onTokensChanged', () => { new TestLine('old9') ]); let actualPinged = col.onTokensChanged([{ fromLineNumber: changedFromLineNumber, toLineNumber: changedToLineNumber }]); - assert.deepEqual(actualPinged, expectedPinged); + assert.deepStrictEqual(actualPinged, expectedPinged); assertState(col, expectedState); } diff --git a/src/vs/editor/test/common/config/commonEditorConfig.test.ts b/src/vs/editor/test/common/config/commonEditorConfig.test.ts index d0edc8f44c0..1faca7a1767 100644 --- a/src/vs/editor/test/common/config/commonEditorConfig.test.ts +++ b/src/vs/editor/test/common/config/commonEditorConfig.test.ts @@ -16,40 +16,40 @@ suite('Common Editor Config', () => { const zoom = EditorZoom; zoom.setZoomLevel(0); - assert.equal(zoom.getZoomLevel(), 0); + assert.strictEqual(zoom.getZoomLevel(), 0); zoom.setZoomLevel(-0); - assert.equal(zoom.getZoomLevel(), 0); + assert.strictEqual(zoom.getZoomLevel(), 0); zoom.setZoomLevel(5); - assert.equal(zoom.getZoomLevel(), 5); + assert.strictEqual(zoom.getZoomLevel(), 5); zoom.setZoomLevel(-1); - assert.equal(zoom.getZoomLevel(), -1); + assert.strictEqual(zoom.getZoomLevel(), -1); zoom.setZoomLevel(9); - assert.equal(zoom.getZoomLevel(), 9); + assert.strictEqual(zoom.getZoomLevel(), 9); zoom.setZoomLevel(-9); - assert.equal(zoom.getZoomLevel(), -5); + assert.strictEqual(zoom.getZoomLevel(), -5); zoom.setZoomLevel(20); - assert.equal(zoom.getZoomLevel(), 20); + assert.strictEqual(zoom.getZoomLevel(), 20); zoom.setZoomLevel(-10); - assert.equal(zoom.getZoomLevel(), -5); + assert.strictEqual(zoom.getZoomLevel(), -5); zoom.setZoomLevel(9.1); - assert.equal(zoom.getZoomLevel(), 9.1); + assert.strictEqual(zoom.getZoomLevel(), 9.1); zoom.setZoomLevel(-9.1); - assert.equal(zoom.getZoomLevel(), -5); + assert.strictEqual(zoom.getZoomLevel(), -5); zoom.setZoomLevel(Infinity); - assert.equal(zoom.getZoomLevel(), 20); + assert.strictEqual(zoom.getZoomLevel(), 20); zoom.setZoomLevel(Number.NEGATIVE_INFINITY); - assert.equal(zoom.getZoomLevel(), -5); + assert.strictEqual(zoom.getZoomLevel(), -5); }); class TestWrappingConfiguration extends TestConfiguration { @@ -69,8 +69,8 @@ suite('Common Editor Config', () => { function assertWrapping(config: TestConfiguration, isViewportWrapping: boolean, wrappingColumn: number): void { const options = config.options; const wrappingInfo = options.get(EditorOption.wrappingInfo); - assert.equal(wrappingInfo.isViewportWrapping, isViewportWrapping); - assert.equal(wrappingInfo.wrappingColumn, wrappingColumn); + assert.strictEqual(wrappingInfo.isViewportWrapping, isViewportWrapping); + assert.strictEqual(wrappingInfo.wrappingColumn, wrappingColumn); } test('wordWrap default', () => { @@ -186,26 +186,26 @@ suite('Common Editor Config', () => { }); let config = new TestConfiguration({ hover: hoverOptions }); - assert.equal(config.options.get(EditorOption.hover).enabled, true); + assert.strictEqual(config.options.get(EditorOption.hover).enabled, true); config.updateOptions({ hover: { enabled: false } }); - assert.equal(config.options.get(EditorOption.hover).enabled, false); + assert.strictEqual(config.options.get(EditorOption.hover).enabled, false); }); test('does not emit event when nothing changes', () => { const config = new TestConfiguration({ glyphMargin: true, roundedSelection: false }); let event: ConfigurationChangedEvent | null = null; config.onDidChange(e => event = e); - assert.equal(config.options.get(EditorOption.glyphMargin), true); + assert.strictEqual(config.options.get(EditorOption.glyphMargin), true); config.updateOptions({ glyphMargin: true }); config.updateOptions({ roundedSelection: false }); - assert.equal(event, null); + assert.strictEqual(event, null); }); test('issue #94931: Unable to open source file', () => { const config = new TestConfiguration({ quickSuggestions: null! }); const actual = >>config.options.get(EditorOption.quickSuggestions); - assert.deepEqual(actual, { + assert.deepStrictEqual(actual, { other: true, comments: false, strings: false @@ -216,7 +216,7 @@ suite('Common Editor Config', () => { const config = new TestConfiguration({ quickSuggestions: null! }); config.updateOptions({ quickSuggestions: { strings: true } }); const actual = >>config.options.get(EditorOption.quickSuggestions); - assert.deepEqual(actual, { + assert.deepStrictEqual(actual, { other: true, comments: false, strings: true diff --git a/src/vs/editor/test/common/controller/cursorMoveHelper.test.ts b/src/vs/editor/test/common/controller/cursorMoveHelper.test.ts index e7cd6b4b35e..e07042281eb 100644 --- a/src/vs/editor/test/common/controller/cursorMoveHelper.test.ts +++ b/src/vs/editor/test/common/controller/cursorMoveHelper.test.ts @@ -8,41 +8,41 @@ import { CursorColumns } from 'vs/editor/common/controller/cursorCommon'; suite('CursorMove', () => { test('nextRenderTabStop', () => { - assert.equal(CursorColumns.nextRenderTabStop(0, 4), 4); - assert.equal(CursorColumns.nextRenderTabStop(1, 4), 4); - assert.equal(CursorColumns.nextRenderTabStop(2, 4), 4); - assert.equal(CursorColumns.nextRenderTabStop(3, 4), 4); - assert.equal(CursorColumns.nextRenderTabStop(4, 4), 8); - assert.equal(CursorColumns.nextRenderTabStop(5, 4), 8); - assert.equal(CursorColumns.nextRenderTabStop(6, 4), 8); - assert.equal(CursorColumns.nextRenderTabStop(7, 4), 8); - assert.equal(CursorColumns.nextRenderTabStop(8, 4), 12); + assert.strictEqual(CursorColumns.nextRenderTabStop(0, 4), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(1, 4), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(2, 4), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(3, 4), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(4, 4), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(5, 4), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(6, 4), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(7, 4), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(8, 4), 12); - assert.equal(CursorColumns.nextRenderTabStop(0, 2), 2); - assert.equal(CursorColumns.nextRenderTabStop(1, 2), 2); - assert.equal(CursorColumns.nextRenderTabStop(2, 2), 4); - assert.equal(CursorColumns.nextRenderTabStop(3, 2), 4); - assert.equal(CursorColumns.nextRenderTabStop(4, 2), 6); - assert.equal(CursorColumns.nextRenderTabStop(5, 2), 6); - assert.equal(CursorColumns.nextRenderTabStop(6, 2), 8); - assert.equal(CursorColumns.nextRenderTabStop(7, 2), 8); - assert.equal(CursorColumns.nextRenderTabStop(8, 2), 10); + assert.strictEqual(CursorColumns.nextRenderTabStop(0, 2), 2); + assert.strictEqual(CursorColumns.nextRenderTabStop(1, 2), 2); + assert.strictEqual(CursorColumns.nextRenderTabStop(2, 2), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(3, 2), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(4, 2), 6); + assert.strictEqual(CursorColumns.nextRenderTabStop(5, 2), 6); + assert.strictEqual(CursorColumns.nextRenderTabStop(6, 2), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(7, 2), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(8, 2), 10); - assert.equal(CursorColumns.nextRenderTabStop(0, 1), 1); - assert.equal(CursorColumns.nextRenderTabStop(1, 1), 2); - assert.equal(CursorColumns.nextRenderTabStop(2, 1), 3); - assert.equal(CursorColumns.nextRenderTabStop(3, 1), 4); - assert.equal(CursorColumns.nextRenderTabStop(4, 1), 5); - assert.equal(CursorColumns.nextRenderTabStop(5, 1), 6); - assert.equal(CursorColumns.nextRenderTabStop(6, 1), 7); - assert.equal(CursorColumns.nextRenderTabStop(7, 1), 8); - assert.equal(CursorColumns.nextRenderTabStop(8, 1), 9); + assert.strictEqual(CursorColumns.nextRenderTabStop(0, 1), 1); + assert.strictEqual(CursorColumns.nextRenderTabStop(1, 1), 2); + assert.strictEqual(CursorColumns.nextRenderTabStop(2, 1), 3); + assert.strictEqual(CursorColumns.nextRenderTabStop(3, 1), 4); + assert.strictEqual(CursorColumns.nextRenderTabStop(4, 1), 5); + assert.strictEqual(CursorColumns.nextRenderTabStop(5, 1), 6); + assert.strictEqual(CursorColumns.nextRenderTabStop(6, 1), 7); + assert.strictEqual(CursorColumns.nextRenderTabStop(7, 1), 8); + assert.strictEqual(CursorColumns.nextRenderTabStop(8, 1), 9); }); test('visibleColumnFromColumn', () => { function testVisibleColumnFromColumn(text: string, tabSize: number, column: number, expected: number): void { - assert.equal(CursorColumns.visibleColumnFromColumn(text, column, tabSize), expected); + assert.strictEqual(CursorColumns.visibleColumnFromColumn(text, column, tabSize), expected); } testVisibleColumnFromColumn('\t\tvar x = 3;', 4, 1, 0); @@ -101,7 +101,7 @@ suite('CursorMove', () => { test('columnFromVisibleColumn', () => { function testColumnFromVisibleColumn(text: string, tabSize: number, visibleColumn: number, expected: number): void { - assert.equal(CursorColumns.columnFromVisibleColumn(text, visibleColumn, tabSize), expected); + assert.strictEqual(CursorColumns.columnFromVisibleColumn(text, visibleColumn, tabSize), expected); } // testColumnFromVisibleColumn('\t\tvar x = 3;', 4, 0, 1); @@ -177,7 +177,7 @@ suite('CursorMove', () => { test('toStatusbarColumn', () => { function t(text: string, tabSize: number, column: number, expected: number): void { - assert.equal(CursorColumns.toStatusbarColumn(text, column, tabSize), expected, `<>`); + assert.strictEqual(CursorColumns.toStatusbarColumn(text, column, tabSize), expected, `<>`); } t(' spaces', 4, 1, 1); diff --git a/src/vs/editor/test/common/core/characterClassifier.test.ts b/src/vs/editor/test/common/core/characterClassifier.test.ts index de9effc7444..9d3bf750cee 100644 --- a/src/vs/editor/test/common/core/characterClassifier.test.ts +++ b/src/vs/editor/test/common/core/characterClassifier.test.ts @@ -11,27 +11,27 @@ suite('CharacterClassifier', () => { test('works', () => { let classifier = new CharacterClassifier(0); - assert.equal(classifier.get(-1), 0); - assert.equal(classifier.get(0), 0); - assert.equal(classifier.get(CharCode.a), 0); - assert.equal(classifier.get(CharCode.b), 0); - assert.equal(classifier.get(CharCode.z), 0); - assert.equal(classifier.get(255), 0); - assert.equal(classifier.get(1000), 0); - assert.equal(classifier.get(2000), 0); + assert.strictEqual(classifier.get(-1), 0); + assert.strictEqual(classifier.get(0), 0); + assert.strictEqual(classifier.get(CharCode.a), 0); + assert.strictEqual(classifier.get(CharCode.b), 0); + assert.strictEqual(classifier.get(CharCode.z), 0); + assert.strictEqual(classifier.get(255), 0); + assert.strictEqual(classifier.get(1000), 0); + assert.strictEqual(classifier.get(2000), 0); classifier.set(CharCode.a, 1); classifier.set(CharCode.z, 2); classifier.set(1000, 3); - assert.equal(classifier.get(-1), 0); - assert.equal(classifier.get(0), 0); - assert.equal(classifier.get(CharCode.a), 1); - assert.equal(classifier.get(CharCode.b), 0); - assert.equal(classifier.get(CharCode.z), 2); - assert.equal(classifier.get(255), 0); - assert.equal(classifier.get(1000), 3); - assert.equal(classifier.get(2000), 0); + assert.strictEqual(classifier.get(-1), 0); + assert.strictEqual(classifier.get(0), 0); + assert.strictEqual(classifier.get(CharCode.a), 1); + assert.strictEqual(classifier.get(CharCode.b), 0); + assert.strictEqual(classifier.get(CharCode.z), 2); + assert.strictEqual(classifier.get(255), 0); + assert.strictEqual(classifier.get(1000), 3); + assert.strictEqual(classifier.get(2000), 0); }); -}); \ No newline at end of file +}); diff --git a/src/vs/editor/test/common/core/lineTokens.test.ts b/src/vs/editor/test/common/core/lineTokens.test.ts index d3a9924fb88..2ffff0c7ed6 100644 --- a/src/vs/editor/test/common/core/lineTokens.test.ts +++ b/src/vs/editor/test/common/core/lineTokens.test.ts @@ -45,64 +45,64 @@ suite('LineTokens', () => { test('basics', () => { const lineTokens = createTestLineTokens(); - assert.equal(lineTokens.getLineContent(), 'Hello world, this is a lovely day'); - assert.equal(lineTokens.getLineContent().length, 33); - assert.equal(lineTokens.getCount(), 7); + assert.strictEqual(lineTokens.getLineContent(), 'Hello world, this is a lovely day'); + assert.strictEqual(lineTokens.getLineContent().length, 33); + assert.strictEqual(lineTokens.getCount(), 7); - assert.equal(lineTokens.getStartOffset(0), 0); - assert.equal(lineTokens.getEndOffset(0), 6); - assert.equal(lineTokens.getStartOffset(1), 6); - assert.equal(lineTokens.getEndOffset(1), 13); - assert.equal(lineTokens.getStartOffset(2), 13); - assert.equal(lineTokens.getEndOffset(2), 18); - assert.equal(lineTokens.getStartOffset(3), 18); - assert.equal(lineTokens.getEndOffset(3), 21); - assert.equal(lineTokens.getStartOffset(4), 21); - assert.equal(lineTokens.getEndOffset(4), 23); - assert.equal(lineTokens.getStartOffset(5), 23); - assert.equal(lineTokens.getEndOffset(5), 30); - assert.equal(lineTokens.getStartOffset(6), 30); - assert.equal(lineTokens.getEndOffset(6), 33); + assert.strictEqual(lineTokens.getStartOffset(0), 0); + assert.strictEqual(lineTokens.getEndOffset(0), 6); + assert.strictEqual(lineTokens.getStartOffset(1), 6); + assert.strictEqual(lineTokens.getEndOffset(1), 13); + assert.strictEqual(lineTokens.getStartOffset(2), 13); + assert.strictEqual(lineTokens.getEndOffset(2), 18); + assert.strictEqual(lineTokens.getStartOffset(3), 18); + assert.strictEqual(lineTokens.getEndOffset(3), 21); + assert.strictEqual(lineTokens.getStartOffset(4), 21); + assert.strictEqual(lineTokens.getEndOffset(4), 23); + assert.strictEqual(lineTokens.getStartOffset(5), 23); + assert.strictEqual(lineTokens.getEndOffset(5), 30); + assert.strictEqual(lineTokens.getStartOffset(6), 30); + assert.strictEqual(lineTokens.getEndOffset(6), 33); }); test('findToken', () => { const lineTokens = createTestLineTokens(); - assert.equal(lineTokens.findTokenIndexAtOffset(0), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(1), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(2), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(3), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(4), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(5), 0); - assert.equal(lineTokens.findTokenIndexAtOffset(6), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(7), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(8), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(9), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(10), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(11), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(12), 1); - assert.equal(lineTokens.findTokenIndexAtOffset(13), 2); - assert.equal(lineTokens.findTokenIndexAtOffset(14), 2); - assert.equal(lineTokens.findTokenIndexAtOffset(15), 2); - assert.equal(lineTokens.findTokenIndexAtOffset(16), 2); - assert.equal(lineTokens.findTokenIndexAtOffset(17), 2); - assert.equal(lineTokens.findTokenIndexAtOffset(18), 3); - assert.equal(lineTokens.findTokenIndexAtOffset(19), 3); - assert.equal(lineTokens.findTokenIndexAtOffset(20), 3); - assert.equal(lineTokens.findTokenIndexAtOffset(21), 4); - assert.equal(lineTokens.findTokenIndexAtOffset(22), 4); - assert.equal(lineTokens.findTokenIndexAtOffset(23), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(24), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(25), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(26), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(27), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(28), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(29), 5); - assert.equal(lineTokens.findTokenIndexAtOffset(30), 6); - assert.equal(lineTokens.findTokenIndexAtOffset(31), 6); - assert.equal(lineTokens.findTokenIndexAtOffset(32), 6); - assert.equal(lineTokens.findTokenIndexAtOffset(33), 6); - assert.equal(lineTokens.findTokenIndexAtOffset(34), 6); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(0), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(1), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(2), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(3), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(4), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(5), 0); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(6), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(7), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(8), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(9), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(10), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(11), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(12), 1); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(13), 2); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(14), 2); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(15), 2); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(16), 2); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(17), 2); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(18), 3); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(19), 3); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(20), 3); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(21), 4); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(22), 4); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(23), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(24), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(25), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(26), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(27), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(28), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(29), 5); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(30), 6); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(31), 6); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(32), 6); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(33), 6); + assert.strictEqual(lineTokens.findTokenIndexAtOffset(34), 6); }); interface ITestViewLineToken { @@ -118,7 +118,7 @@ suite('LineTokens', () => { foreground: _actual.getForeground(i) }; } - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('inflate', () => { diff --git a/src/vs/editor/test/common/core/range.test.ts b/src/vs/editor/test/common/core/range.test.ts index 5420ae45223..26415e8c684 100644 --- a/src/vs/editor/test/common/core/range.test.ts +++ b/src/vs/editor/test/common/core/range.test.ts @@ -9,47 +9,47 @@ import { Range } from 'vs/editor/common/core/range'; suite('Editor Core - Range', () => { test('empty range', () => { let s = new Range(1, 1, 1, 1); - assert.equal(s.startLineNumber, 1); - assert.equal(s.startColumn, 1); - assert.equal(s.endLineNumber, 1); - assert.equal(s.endColumn, 1); - assert.equal(s.isEmpty(), true); + assert.strictEqual(s.startLineNumber, 1); + assert.strictEqual(s.startColumn, 1); + assert.strictEqual(s.endLineNumber, 1); + assert.strictEqual(s.endColumn, 1); + assert.strictEqual(s.isEmpty(), true); }); test('swap start and stop same line', () => { let s = new Range(1, 2, 1, 1); - assert.equal(s.startLineNumber, 1); - assert.equal(s.startColumn, 1); - assert.equal(s.endLineNumber, 1); - assert.equal(s.endColumn, 2); - assert.equal(s.isEmpty(), false); + assert.strictEqual(s.startLineNumber, 1); + assert.strictEqual(s.startColumn, 1); + assert.strictEqual(s.endLineNumber, 1); + assert.strictEqual(s.endColumn, 2); + assert.strictEqual(s.isEmpty(), false); }); test('swap start and stop', () => { let s = new Range(2, 1, 1, 2); - assert.equal(s.startLineNumber, 1); - assert.equal(s.startColumn, 2); - assert.equal(s.endLineNumber, 2); - assert.equal(s.endColumn, 1); - assert.equal(s.isEmpty(), false); + assert.strictEqual(s.startLineNumber, 1); + assert.strictEqual(s.startColumn, 2); + assert.strictEqual(s.endLineNumber, 2); + assert.strictEqual(s.endColumn, 1); + assert.strictEqual(s.isEmpty(), false); }); test('no swap same line', () => { let s = new Range(1, 1, 1, 2); - assert.equal(s.startLineNumber, 1); - assert.equal(s.startColumn, 1); - assert.equal(s.endLineNumber, 1); - assert.equal(s.endColumn, 2); - assert.equal(s.isEmpty(), false); + assert.strictEqual(s.startLineNumber, 1); + assert.strictEqual(s.startColumn, 1); + assert.strictEqual(s.endLineNumber, 1); + assert.strictEqual(s.endColumn, 2); + assert.strictEqual(s.isEmpty(), false); }); test('no swap', () => { let s = new Range(1, 1, 2, 1); - assert.equal(s.startLineNumber, 1); - assert.equal(s.startColumn, 1); - assert.equal(s.endLineNumber, 2); - assert.equal(s.endColumn, 1); - assert.equal(s.isEmpty(), false); + assert.strictEqual(s.startLineNumber, 1); + assert.strictEqual(s.startColumn, 1); + assert.strictEqual(s.endLineNumber, 2); + assert.strictEqual(s.endColumn, 1); + assert.strictEqual(s.isEmpty(), false); }); test('compareRangesUsingEnds', () => { @@ -93,36 +93,36 @@ suite('Editor Core - Range', () => { }); test('containsPosition', () => { - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(1, 3)), false); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(2, 1)), false); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(2, 2)), true); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(2, 3)), true); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(3, 1)), true); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(5, 9)), true); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(5, 10)), true); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(5, 11)), false); - assert.equal(new Range(2, 2, 5, 10).containsPosition(new Position(6, 1)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(1, 3)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(2, 1)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(2, 2)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(2, 3)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(3, 1)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(5, 9)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(5, 10)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(5, 11)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsPosition(new Position(6, 1)), false); }); test('containsRange', () => { - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(1, 3, 2, 2)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(2, 1, 2, 2)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 5, 11)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 6, 1)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(5, 9, 6, 1)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(5, 10, 6, 1)), false); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 5, 10)), true); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(2, 3, 5, 9)), true); - assert.equal(new Range(2, 2, 5, 10).containsRange(new Range(3, 100, 4, 100)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(1, 3, 2, 2)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(2, 1, 2, 2)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 5, 11)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 6, 1)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(5, 9, 6, 1)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(5, 10, 6, 1)), false); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(2, 2, 5, 10)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(2, 3, 5, 9)), true); + assert.strictEqual(new Range(2, 2, 5, 10).containsRange(new Range(3, 100, 4, 100)), true); }); test('areIntersecting', () => { - assert.equal(Range.areIntersecting(new Range(2, 2, 3, 2), new Range(4, 2, 5, 2)), false); - assert.equal(Range.areIntersecting(new Range(4, 2, 5, 2), new Range(2, 2, 3, 2)), false); - assert.equal(Range.areIntersecting(new Range(4, 2, 5, 2), new Range(5, 2, 6, 2)), false); - assert.equal(Range.areIntersecting(new Range(5, 2, 6, 2), new Range(4, 2, 5, 2)), false); - assert.equal(Range.areIntersecting(new Range(2, 2, 2, 7), new Range(2, 4, 2, 6)), true); - assert.equal(Range.areIntersecting(new Range(2, 2, 2, 7), new Range(2, 4, 2, 9)), true); - assert.equal(Range.areIntersecting(new Range(2, 4, 2, 9), new Range(2, 2, 2, 7)), true); + assert.strictEqual(Range.areIntersecting(new Range(2, 2, 3, 2), new Range(4, 2, 5, 2)), false); + assert.strictEqual(Range.areIntersecting(new Range(4, 2, 5, 2), new Range(2, 2, 3, 2)), false); + assert.strictEqual(Range.areIntersecting(new Range(4, 2, 5, 2), new Range(5, 2, 6, 2)), false); + assert.strictEqual(Range.areIntersecting(new Range(5, 2, 6, 2), new Range(4, 2, 5, 2)), false); + assert.strictEqual(Range.areIntersecting(new Range(2, 2, 2, 7), new Range(2, 4, 2, 6)), true); + assert.strictEqual(Range.areIntersecting(new Range(2, 2, 2, 7), new Range(2, 4, 2, 9)), true); + assert.strictEqual(Range.areIntersecting(new Range(2, 4, 2, 9), new Range(2, 2, 2, 7)), true); }); }); diff --git a/src/vs/editor/test/common/diff/diffComputer.test.ts b/src/vs/editor/test/common/diff/diffComputer.test.ts index eabd6fdc396..32dd4bce0be 100644 --- a/src/vs/editor/test/common/diff/diffComputer.test.ts +++ b/src/vs/editor/test/common/diff/diffComputer.test.ts @@ -64,7 +64,7 @@ function assertDiff(originalLines: string[], modifiedLines: string[], expectedCh for (let i = 0; i < changes.length; i++) { extracted.push(extractLineChangeRepresentation(changes[i], (i < expectedChanges.length ? expectedChanges[i] : null))); } - assert.deepEqual(extracted, expectedChanges); + assert.deepStrictEqual(extracted, expectedChanges); } function createLineDeletion(startLineNumber: number, endLineNumber: number, modifiedLineNumber: number): ILineChange { diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 67c8a119e30..c0e4be805b4 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -22,10 +22,10 @@ suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () = let model = createEditableTextModelFromString(original.join('\n')); model.setEOL(EndOfLineSequence.LF); - assert.equal(model.mightContainRTL(), before); + assert.strictEqual(model.mightContainRTL(), before); model.applyEdits(edits); - assert.equal(model.mightContainRTL(), after); + assert.strictEqual(model.mightContainRTL(), after); model.dispose(); } @@ -68,10 +68,10 @@ suite('EditorModel - EditableTextModel.applyEdits updates mightContainNonBasicAS let model = createEditableTextModelFromString(original.join('\n')); model.setEOL(EndOfLineSequence.LF); - assert.equal(model.mightContainNonBasicASCII(), before); + assert.strictEqual(model.mightContainNonBasicASCII(), before); model.applyEdits(edits); - assert.equal(model.mightContainNonBasicASCII(), after); + assert.strictEqual(model.mightContainNonBasicASCII(), after); model.dispose(); } @@ -1043,7 +1043,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { test('issue #1580: Changes in line endings are not correctly reflected in the extension host, leading to invalid offsets sent to external refactoring tools', () => { let model = createEditableTextModelFromString('Hello\nWorld!'); - assert.equal(model.getEOL(), '\n'); + assert.strictEqual(model.getEOL(), '\n'); let mirrorModel2 = new MirrorTextModel(null!, model.getLinesContent(), model.getEOL(), model.getVersionId()); let mirrorModel2PrevVersionId = model.getVersionId(); @@ -1058,8 +1058,8 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }); let assertMirrorModels = () => { - assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK'); - assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK'); + assert.strictEqual(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK'); + assert.strictEqual(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK'); }; model.setEOL(EndOfLineSequence.CRLF); @@ -1077,16 +1077,16 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { { range: new Range(1, 2, 1, 2), text: '"' }, ]); - assert.equal(model.getValue(EndOfLinePreference.LF), '"\'"👁\''); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '"\'"👁\''); - assert.deepEqual(model.validateRange(new Range(1, 3, 1, 4)), new Range(1, 3, 1, 4)); + assert.deepStrictEqual(model.validateRange(new Range(1, 3, 1, 4)), new Range(1, 3, 1, 4)); model.applyEdits([ { range: new Range(1, 1, 1, 2), text: null }, { range: new Range(1, 3, 1, 4), text: null }, ]); - assert.equal(model.getValue(EndOfLinePreference.LF), '\'👁\''); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), '\'👁\''); model.dispose(); }); @@ -1108,7 +1108,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { model.applyEdits(undoEdits); - assert.deepEqual(model.getValue(), 'line1\nline2\nline3\n'); + assert.deepStrictEqual(model.getValue(), 'line1\nline2\nline3\n'); model.dispose(); }); diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index be89c016088..58e534c092d 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -111,7 +111,7 @@ suite('IntervalTree', () => { let actualNodes = this._tree.intervalSearch(op.begin, op.end, 0, false, 0); let actual = actualNodes.map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); let expected = this._oracle.search(new Interval(op.begin, op.end)); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); return; } @@ -123,7 +123,7 @@ suite('IntervalTree', () => { let actual = this._tree.getAllInOrder().map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); let expected = this._oracle.intervals; - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } public getExistingNodeId(index: number): number { @@ -500,7 +500,7 @@ suite('IntervalTree', () => { function assertIntervalSearch(start: number, end: number, expected: [number, number][]): void { let actualNodes = T.intervalSearch(start, end, 0, false, 0); let actual = actualNodes.map((n) => <[number, number]>[n.cachedAbsoluteStart, n.cachedAbsoluteEnd]); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('cormen 1->2', () => { @@ -559,7 +559,7 @@ suite('IntervalTree', () => { let node = new IntervalNode('', nodeStart, nodeEnd); setNodeStickiness(node, nodeStickiness); nodeAcceptEdit(node, start, end, textLength, forceMoveMarkers); - assert.deepEqual([node.start, node.end], [expectedNodeStart, expectedNodeEnd], msg); + assert.deepStrictEqual([node.start, node.end], [expectedNodeStart, expectedNodeEnd], msg); } test('nodeAcceptEdit', () => { diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts index 7b1491b3e72..f385fdda90d 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts @@ -33,7 +33,7 @@ suite('PieceTreeTextBuffer._getInverseEdits', () => { function assertInverseEdits(ops: IValidatedEditOperation[], expected: Range[]): void { let actual = PieceTreeTextBuffer._getInverseEditRanges(ops); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('single insert', () => { @@ -285,7 +285,7 @@ suite('PieceTreeTextBuffer._toSingleEditOperation', () => { const textBuffer = createTextBufferFactory(original.join('\n')).create(DefaultEndOfLine.LF).textBuffer; const actual = textBuffer._toSingleEditOperation(edits); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('one edit op is unchanged', () => { diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts index 4edebdf68d2..83b4a90d9b5 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts @@ -12,9 +12,9 @@ import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; export function testTextBufferFactory(text: string, eol: string, mightContainNonBasicASCII: boolean, mightContainRTL: boolean): void { const textBuffer = createTextBufferFactory(text).create(DefaultEndOfLine.LF).textBuffer; - assert.equal(textBuffer.mightContainNonBasicASCII(), mightContainNonBasicASCII); - assert.equal(textBuffer.mightContainRTL(), mightContainRTL); - assert.equal(textBuffer.getEOL(), eol); + assert.strictEqual(textBuffer.mightContainNonBasicASCII(), mightContainNonBasicASCII); + assert.strictEqual(textBuffer.mightContainRTL(), mightContainRTL); + assert.strictEqual(textBuffer.getEOL(), eol); } suite('ModelBuilder', () => { diff --git a/src/vs/editor/test/common/model/model.line.test.ts b/src/vs/editor/test/common/model/model.line.test.ts index 139b169bf1d..b07f2481009 100644 --- a/src/vs/editor/test/common/model/model.line.test.ts +++ b/src/vs/editor/test/common/model/model.line.test.ts @@ -39,13 +39,13 @@ function assertLineTokens(__actual: LineTokens, _expected: TestToken[]): void { type: token.getType() }; }; - assert.deepEqual(actual, expected.map(decode)); + assert.deepStrictEqual(actual, expected.map(decode)); } suite('ModelLine - getIndentLevel', () => { function assertIndentLevel(text: string, expected: number, tabSize: number = 4): void { let actual = TextModel.computeIndentLevel(text, tabSize); - assert.equal(actual, expected, text); + assert.strictEqual(actual, expected, text); } test('getIndentLevel', () => { @@ -126,7 +126,7 @@ suite('ModelLinesTokens', () => { for (let lineIndex = 0; lineIndex < expected.length; lineIndex++) { const actualLine = model.getLineContent(lineIndex + 1); const actualTokens = model.getLineTokens(lineIndex + 1); - assert.equal(actualLine, expected[lineIndex].text); + assert.strictEqual(actualLine, expected[lineIndex].text); assertLineTokens(actualTokens, expected[lineIndex].tokens); } } diff --git a/src/vs/editor/test/common/model/model.modes.test.ts b/src/vs/editor/test/common/model/model.modes.test.ts index 3cc4db5b97c..1d255659eca 100644 --- a/src/vs/editor/test/common/model/model.modes.test.ts +++ b/src/vs/editor/test/common/model/model.modes.test.ts @@ -21,7 +21,7 @@ suite('Editor Model - Model Modes 1', () => { let calledFor: string[] = []; function checkAndClear(arr: string[]) { - assert.deepEqual(calledFor, arr); + assert.deepStrictEqual(calledFor, arr); calledFor = []; } @@ -106,7 +106,7 @@ suite('Editor Model - Model Modes 1', () => { checkAndClear(['1', '2', '3', '4', '5']); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), '0\n-\n+')]); - assert.equal(thisModel.getLineCount(), 7); + assert.strictEqual(thisModel.getLineCount(), 7); thisModel.forceTokenization(7); checkAndClear(['0', '-', '+']); @@ -174,7 +174,7 @@ suite('Editor Model - Model Modes 2', () => { let calledFor: string[] = []; function checkAndClear(arr: string[]): void { - assert.deepEqual(calledFor, arr); + assert.deepStrictEqual(calledFor, arr); calledFor = []; } diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index 59693e952ef..bfdcfc9464c 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -46,50 +46,50 @@ suite('Editor Model - Model', () => { // --------- insert text test('model getValue', () => { - assert.equal(thisModel.getValue(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1'); + assert.strictEqual(thisModel.getValue(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1'); }); test('model insert empty text', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 1), '')]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'My First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'My First Line'); }); test('model insert text without newline 1', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'foo ')]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'foo My First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'foo My First Line'); }); test('model insert text without newline 2', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 3), ' foo')]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'My foo First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'My foo First Line'); }); test('model insert text with one newline', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 3), ' new line\nNo longer')]); - assert.equal(thisModel.getLineCount(), 6); - assert.equal(thisModel.getLineContent(1), 'My new line'); - assert.equal(thisModel.getLineContent(2), 'No longer First Line'); + assert.strictEqual(thisModel.getLineCount(), 6); + assert.strictEqual(thisModel.getLineContent(1), 'My new line'); + assert.strictEqual(thisModel.getLineContent(2), 'No longer First Line'); }); test('model insert text with two newlines', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 3), ' new line\nOne more line in the middle\nNo longer')]); - assert.equal(thisModel.getLineCount(), 7); - assert.equal(thisModel.getLineContent(1), 'My new line'); - assert.equal(thisModel.getLineContent(2), 'One more line in the middle'); - assert.equal(thisModel.getLineContent(3), 'No longer First Line'); + assert.strictEqual(thisModel.getLineCount(), 7); + assert.strictEqual(thisModel.getLineContent(1), 'My new line'); + assert.strictEqual(thisModel.getLineContent(2), 'One more line in the middle'); + assert.strictEqual(thisModel.getLineContent(3), 'No longer First Line'); }); test('model insert text with many newlines', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 3), '\n\n\n\n')]); - assert.equal(thisModel.getLineCount(), 9); - assert.equal(thisModel.getLineContent(1), 'My'); - assert.equal(thisModel.getLineContent(2), ''); - assert.equal(thisModel.getLineContent(3), ''); - assert.equal(thisModel.getLineContent(4), ''); - assert.equal(thisModel.getLineContent(5), ' First Line'); + assert.strictEqual(thisModel.getLineCount(), 9); + assert.strictEqual(thisModel.getLineContent(1), 'My'); + assert.strictEqual(thisModel.getLineContent(2), ''); + assert.strictEqual(thisModel.getLineContent(3), ''); + assert.strictEqual(thisModel.getLineContent(4), ''); + assert.strictEqual(thisModel.getLineContent(5), ' First Line'); }); @@ -111,7 +111,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'foo ')]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, 'foo My First Line') ], @@ -130,7 +130,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.insert(new Position(1, 3), ' new line\nNo longer')]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, 'My new line'), new ModelRawLinesInserted(2, 2, ['No longer First Line']), @@ -146,47 +146,47 @@ suite('Editor Model - Model', () => { test('model delete empty text', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 1))]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'My First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'My First Line'); }); test('model delete text from one line', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 2))]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'y First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'y First Line'); }); test('model delete text from one line 2', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'a')]); - assert.equal(thisModel.getLineContent(1), 'aMy First Line'); + assert.strictEqual(thisModel.getLineContent(1), 'aMy First Line'); thisModel.applyEdits([EditOperation.delete(new Range(1, 2, 1, 4))]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), 'a First Line'); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), 'a First Line'); }); test('model delete all text from a line', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 14))]); - assert.equal(thisModel.getLineCount(), 5); - assert.equal(thisModel.getLineContent(1), ''); + assert.strictEqual(thisModel.getLineCount(), 5); + assert.strictEqual(thisModel.getLineContent(1), ''); }); test('model delete text from two lines', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 2, 6))]); - assert.equal(thisModel.getLineCount(), 4); - assert.equal(thisModel.getLineContent(1), 'My Second Line'); + assert.strictEqual(thisModel.getLineCount(), 4); + assert.strictEqual(thisModel.getLineContent(1), 'My Second Line'); }); test('model delete text from many lines', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 3, 5))]); - assert.equal(thisModel.getLineCount(), 3); - assert.equal(thisModel.getLineContent(1), 'My Third Line'); + assert.strictEqual(thisModel.getLineCount(), 3); + assert.strictEqual(thisModel.getLineContent(1), 'My Third Line'); }); test('model delete everything', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 5, 2))]); - assert.equal(thisModel.getLineCount(), 1); - assert.equal(thisModel.getLineContent(1), ''); + assert.strictEqual(thisModel.getLineCount(), 1); + assert.strictEqual(thisModel.getLineContent(1), ''); }); // --------- delete text eventing @@ -207,7 +207,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 2))]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, 'y First Line'), ], @@ -226,7 +226,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 14))]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, ''), ], @@ -245,7 +245,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 2, 6))]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, 'My Second Line'), new ModelRawLinesDeleted(2, 2), @@ -265,7 +265,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 3, 5))]); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawLineChanged(1, 'My Third Line'), new ModelRawLinesDeleted(2, 3), @@ -279,31 +279,31 @@ suite('Editor Model - Model', () => { // --------- getValueInRange test('getValueInRange', () => { - assert.equal(thisModel.getValueInRange(new Range(1, 1, 1, 1)), ''); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 1, 2)), 'M'); - assert.equal(thisModel.getValueInRange(new Range(1, 2, 1, 3)), 'y'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 1, 14)), 'My First Line'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 2, 1)), 'My First Line\n'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 2, 2)), 'My First Line\n\t'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 2, 3)), 'My First Line\n\t\t'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 2, 17)), 'My First Line\n\t\tMy Second Line'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 3, 1)), 'My First Line\n\t\tMy Second Line\n'); - assert.equal(thisModel.getValueInRange(new Range(1, 1, 4, 1)), 'My First Line\n\t\tMy Second Line\n Third Line\n'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 1, 1)), ''); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 1, 2)), 'M'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 2, 1, 3)), 'y'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 1, 14)), 'My First Line'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 2, 1)), 'My First Line\n'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 2, 2)), 'My First Line\n\t'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 2, 3)), 'My First Line\n\t\t'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 2, 17)), 'My First Line\n\t\tMy Second Line'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 3, 1)), 'My First Line\n\t\tMy Second Line\n'); + assert.strictEqual(thisModel.getValueInRange(new Range(1, 1, 4, 1)), 'My First Line\n\t\tMy Second Line\n Third Line\n'); }); // --------- getValueLengthInRange test('getValueLengthInRange', () => { - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\n'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 2, 2)), 'My First Line\n\t'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 2, 3)), 'My First Line\n\t\t'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 2, 17)), 'My First Line\n\t\tMy Second Line'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 3, 1)), 'My First Line\n\t\tMy Second Line\n'.length); - assert.equal(thisModel.getValueLengthInRange(new Range(1, 1, 4, 1)), 'My First Line\n\t\tMy Second Line\n Third Line\n'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\n'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 2, 2)), 'My First Line\n\t'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 2, 3)), 'My First Line\n\t\t'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 2, 17)), 'My First Line\n\t\tMy Second Line'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 3, 1)), 'My First Line\n\t\tMy Second Line\n'.length); + assert.strictEqual(thisModel.getValueLengthInRange(new Range(1, 1, 4, 1)), 'My First Line\n\t\tMy Second Line\n Third Line\n'.length); }); // --------- setValue @@ -316,7 +316,7 @@ suite('Editor Model - Model', () => { e = _e; }); thisModel.setValue('new value'); - assert.deepEqual(e, new ModelRawContentChangedEvent( + assert.deepStrictEqual(e, new ModelRawContentChangedEvent( [ new ModelRawFlush() ], @@ -332,8 +332,8 @@ suite('Editor Model - Model', () => { { range: new Range(1, 1, 1, 1), text: 'b' }, ], true); - assert.deepEqual(res[0].range, new Range(2, 1, 2, 2)); - assert.deepEqual(res[1].range, new Range(1, 1, 1, 2)); + assert.deepStrictEqual(res[0].range, new Range(2, 1, 2, 2)); + assert.deepStrictEqual(res[1].range, new Range(1, 1, 1, 2)); }); }); @@ -358,17 +358,17 @@ suite('Editor Model - Model Line Separators', () => { }); test('model getValue', () => { - assert.equal(thisModel.getValue(), 'My First Line\u2028\t\tMy Second Line\n Third Line\u2028\n1'); + assert.strictEqual(thisModel.getValue(), 'My First Line\u2028\t\tMy Second Line\n Third Line\u2028\n1'); }); test('model lines', () => { - assert.equal(thisModel.getLineCount(), 3); + assert.strictEqual(thisModel.getLineCount(), 3); }); test('Bug 13333:Model should line break on lonely CR too', () => { let model = createTextModel('Hello\rWorld!\r\nAnother line'); - assert.equal(model.getLineCount(), 3); - assert.equal(model.getValue(), 'Hello\r\nWorld!\r\nAnother line'); + assert.strictEqual(model.getLineCount(), 3); + assert.strictEqual(model.getValue(), 'Hello\r\nWorld!\r\nAnother line'); model.dispose(); }); }); @@ -434,17 +434,17 @@ suite('Editor Model - Words', () => { const thisModel = createTextModel(text.join('\n')); disposables.push(thisModel); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: 'This', startColumn: 1, endColumn: 5 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 2)), { word: 'This', startColumn: 1, endColumn: 5 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 4)), { word: 'This', startColumn: 1, endColumn: 5 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 5)), { word: 'This', startColumn: 1, endColumn: 5 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 6)), { word: 'text', startColumn: 6, endColumn: 10 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 19)), { word: 'some', startColumn: 15, endColumn: 19 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 20)), null); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 21)), { word: 'words', startColumn: 21, endColumn: 26 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 26)), { word: 'words', startColumn: 21, endColumn: 26 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 27)), null); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 28)), null); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: 'This', startColumn: 1, endColumn: 5 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 2)), { word: 'This', startColumn: 1, endColumn: 5 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 4)), { word: 'This', startColumn: 1, endColumn: 5 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 5)), { word: 'This', startColumn: 1, endColumn: 5 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 6)), { word: 'text', startColumn: 6, endColumn: 10 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 19)), { word: 'some', startColumn: 15, endColumn: 19 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 20)), null); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 21)), { word: 'words', startColumn: 21, endColumn: 26 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 26)), { word: 'words', startColumn: 21, endColumn: 26 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 27)), null); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 28)), null); }); test('getWordAtPosition at embedded language boundaries', () => { @@ -455,13 +455,13 @@ suite('Editor Model - Words', () => { const model = createTextModel('abab', undefined, outerMode.getLanguageIdentifier()); disposables.push(model); - assert.deepEqual(model.getWordAtPosition(new Position(1, 1)), { word: 'ab', startColumn: 1, endColumn: 3 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 2)), { word: 'ab', startColumn: 1, endColumn: 3 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 3)), { word: 'ab', startColumn: 1, endColumn: 3 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 4)), { word: 'xx', startColumn: 4, endColumn: 6 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 5)), { word: 'xx', startColumn: 4, endColumn: 6 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 6)), { word: 'xx', startColumn: 4, endColumn: 6 }); - assert.deepEqual(model.getWordAtPosition(new Position(1, 7)), { word: 'ab', startColumn: 7, endColumn: 9 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 1)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 2)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 3)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 4)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 5)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 6)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepStrictEqual(model.getWordAtPosition(new Position(1, 7)), { word: 'ab', startColumn: 7, endColumn: 9 }); }); test('issue #61296: VS code freezes when editing CSS file with emoji', () => { @@ -480,13 +480,13 @@ suite('Editor Model - Words', () => { const thisModel = createTextModel('.🐷-a-b', undefined, MODE_ID); disposables.push(thisModel); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: '.', startColumn: 1, endColumn: 2 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 2)), { word: '.', startColumn: 1, endColumn: 2 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 3)), null); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 4)), { word: '-a-b', startColumn: 4, endColumn: 8 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 5)), { word: '-a-b', startColumn: 4, endColumn: 8 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 6)), { word: '-a-b', startColumn: 4, endColumn: 8 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 7)), { word: '-a-b', startColumn: 4, endColumn: 8 }); - assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 8)), { word: '-a-b', startColumn: 4, endColumn: 8 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: '.', startColumn: 1, endColumn: 2 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 2)), { word: '.', startColumn: 1, endColumn: 2 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 3)), null); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 4)), { word: '-a-b', startColumn: 4, endColumn: 8 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 5)), { word: '-a-b', startColumn: 4, endColumn: 8 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 6)), { word: '-a-b', startColumn: 4, endColumn: 8 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 7)), { word: '-a-b', startColumn: 4, endColumn: 8 }); + assert.deepStrictEqual(thisModel.getWordAtPosition(new Position(1, 8)), { word: '-a-b', startColumn: 4, endColumn: 8 }); }); }); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 4f7690f1111..da7b0093910 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -28,7 +28,7 @@ function modelHasDecorations(model: TextModel, decorations: ILightWeightDecorati }); } modelDecorations.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); - assert.deepEqual(modelDecorations, decorations); + assert.deepStrictEqual(modelDecorations, decorations); } function modelHasDecoration(model: TextModel, startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, className: string) { @@ -39,7 +39,7 @@ function modelHasDecoration(model: TextModel, startLineNumber: number, startColu } function modelHasNoDecorations(model: TextModel) { - assert.equal(model.getAllDecorations().length, 0, 'Model has no decoration'); + assert.strictEqual(model.getAllDecorations().length, 0, 'Model has no decoration'); } function addDecoration(model: TextModel, startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, className: string): string { @@ -60,7 +60,7 @@ function lineHasDecorations(model: TextModel, lineNumber: number, decorations: { className: decs[i].options.className }); } - assert.deepEqual(lineDecorations, decorations, 'Line decorations'); + assert.deepStrictEqual(lineDecorations, decorations, 'Line decorations'); } function lineHasNoDecorations(model: TextModel, lineNumber: number) { @@ -122,12 +122,12 @@ suite('Editor Model - Model Decorations', () => { addDecoration(thisModel, 1, 1, 2, 1, 'myType'); let line1Decorations = thisModel.getLineDecorations(1); - assert.equal(line1Decorations.length, 1); - assert.equal(line1Decorations[0].options.className, 'myType'); + assert.strictEqual(line1Decorations.length, 1); + assert.strictEqual(line1Decorations[0].options.className, 'myType'); let line2Decorations = thisModel.getLineDecorations(1); - assert.equal(line2Decorations.length, 1); - assert.equal(line2Decorations[0].options.className, 'myType'); + assert.strictEqual(line2Decorations.length, 1); + assert.strictEqual(line2Decorations[0].options.className, 'myType'); lineHasNoDecorations(thisModel, 3); lineHasNoDecorations(thisModel, 4); @@ -138,16 +138,16 @@ suite('Editor Model - Model Decorations', () => { addDecoration(thisModel, 1, 2, 3, 2, 'myType'); let line1Decorations = thisModel.getLineDecorations(1); - assert.equal(line1Decorations.length, 1); - assert.equal(line1Decorations[0].options.className, 'myType'); + assert.strictEqual(line1Decorations.length, 1); + assert.strictEqual(line1Decorations[0].options.className, 'myType'); let line2Decorations = thisModel.getLineDecorations(1); - assert.equal(line2Decorations.length, 1); - assert.equal(line2Decorations[0].options.className, 'myType'); + assert.strictEqual(line2Decorations.length, 1); + assert.strictEqual(line2Decorations[0].options.className, 'myType'); let line3Decorations = thisModel.getLineDecorations(1); - assert.equal(line3Decorations.length, 1); - assert.equal(line3Decorations[0].options.className, 'myType'); + assert.strictEqual(line3Decorations.length, 1); + assert.strictEqual(line3Decorations[0].options.className, 'myType'); lineHasNoDecorations(thisModel, 4); lineHasNoDecorations(thisModel, 5); @@ -209,7 +209,7 @@ suite('Editor Model - Model Decorations', () => { listenerCalled++; }); addDecoration(thisModel, 1, 2, 3, 2, 'myType'); - assert.equal(listenerCalled, 1, 'listener called'); + assert.strictEqual(listenerCalled, 1, 'listener called'); }); test('decorations emit event on change', () => { @@ -221,7 +221,7 @@ suite('Editor Model - Model Decorations', () => { thisModel.changeDecorations((changeAccessor) => { changeAccessor.changeDecoration(decId, new Range(1, 1, 1, 2)); }); - assert.equal(listenerCalled, 1, 'listener called'); + assert.strictEqual(listenerCalled, 1, 'listener called'); }); test('decorations emit event on remove', () => { @@ -233,7 +233,7 @@ suite('Editor Model - Model Decorations', () => { thisModel.changeDecorations((changeAccessor) => { changeAccessor.removeDecoration(decId); }); - assert.equal(listenerCalled, 1, 'listener called'); + assert.strictEqual(listenerCalled, 1, 'listener called'); }); test('decorations emit event when inserting one line text before it', () => { @@ -245,7 +245,7 @@ suite('Editor Model - Model Decorations', () => { }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'Hallo ')]); - assert.equal(listenerCalled, 1, 'listener called'); + assert.strictEqual(listenerCalled, 1, 'listener called'); }); test('decorations do not emit event on no-op deltaDecorations', () => { @@ -260,7 +260,7 @@ suite('Editor Model - Model Decorations', () => { accessor.deltaDecorations([], []); }); - assert.equal(listenerCalled, 0, 'listener not called'); + assert.strictEqual(listenerCalled, 0, 'listener not called'); }); // --------- editing text & effects on decorations @@ -429,7 +429,7 @@ suite('Decorations and editing', () => { forceMoveMarkers: editForceMoveMarkers }]); const actual = model.getDecorationRange(id); - assert.deepEqual(actual, expectedDecRange, msg); + assert.deepStrictEqual(actual, expectedDecRange, msg); model.dispose(); } @@ -1155,20 +1155,20 @@ suite('deltaDecorations', () => { let initialIds = model.deltaDecorations([], decorations.map(toModelDeltaDecoration)); let actualDecorations = readModelDecorations(model, initialIds); - assert.equal(initialIds.length, decorations.length, 'returns expected cnt of ids'); - assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); + assert.strictEqual(initialIds.length, decorations.length, 'returns expected cnt of ids'); + assert.strictEqual(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); actualDecorations.sort((a, b) => strcmp(a.id, b.id)); decorations.sort((a, b) => strcmp(a.id, b.id)); - assert.deepEqual(actualDecorations, decorations); + assert.deepStrictEqual(actualDecorations, decorations); let newIds = model.deltaDecorations(initialIds, newDecorations.map(toModelDeltaDecoration)); let actualNewDecorations = readModelDecorations(model, newIds); - assert.equal(newIds.length, newDecorations.length, 'returns expected cnt of ids'); - assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); + assert.strictEqual(newIds.length, newDecorations.length, 'returns expected cnt of ids'); + assert.strictEqual(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); actualNewDecorations.sort((a, b) => strcmp(a.id, b.id)); newDecorations.sort((a, b) => strcmp(a.id, b.id)); - assert.deepEqual(actualDecorations, decorations); + assert.deepStrictEqual(actualDecorations, decorations); model.dispose(); } @@ -1188,8 +1188,8 @@ suite('deltaDecorations', () => { toModelDeltaDecoration(decoration('b', 2, 1, 2, 13)) ]); - assert.deepEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); - assert.deepEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); + assert.deepStrictEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); + assert.deepStrictEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); model.dispose(); }); @@ -1294,7 +1294,7 @@ suite('deltaDecorations', () => { let actualDecoration = model.getDecorationOptions(ids[0]); - assert.deepEqual(actualDecoration!.hoverMessage, { value: 'hello2' }); + assert.deepStrictEqual(actualDecoration!.hoverMessage, { value: 'hello2' }); model.dispose(); }); @@ -1326,16 +1326,16 @@ suite('deltaDecorations', () => { toModelDeltaDecoration(decoration('b', 2, 1, 2, 13)) ]); - assert.deepEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); - assert.deepEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); + assert.deepStrictEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); + assert.deepStrictEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); ids = model.deltaDecorations(ids, [ toModelDeltaDecoration(decoration('a', 1, 1, 1, 12)), toModelDeltaDecoration(decoration('b', 2, 1, 2, 13)) ]); - assert.deepEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); - assert.deepEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); + assert.deepStrictEqual(model.getDecorationRange(ids[0]), range(1, 1, 1, 12)); + assert.deepStrictEqual(model.getDecorationRange(ids[1]), range(2, 1, 2, 13)); model.dispose(); }); @@ -1365,7 +1365,7 @@ suite('deltaDecorations', () => { let inRangeClassNames = inRange.map(d => d.options.className); inRangeClassNames.sort(); - assert.deepEqual(inRangeClassNames, ['x1', 'x2', 'x3', 'x4']); + assert.deepStrictEqual(inRangeClassNames, ['x1', 'x2', 'x3', 'x4']); model.dispose(); }); @@ -1383,7 +1383,7 @@ suite('deltaDecorations', () => { forceMoveMarkers: false }]); const actual = model.getDecorationRange(id); - assert.deepEqual(actual, new Range(1, 1, 1, 1)); + assert.deepStrictEqual(actual, new Range(1, 1, 1, 1)); model.dispose(); }); diff --git a/src/vs/editor/test/common/model/modelEditOperation.test.ts b/src/vs/editor/test/common/model/modelEditOperation.test.ts index 058c5d3d56a..d6c2af9b987 100644 --- a/src/vs/editor/test/common/model/modelEditOperation.test.ts +++ b/src/vs/editor/test/common/model/modelEditOperation.test.ts @@ -52,19 +52,19 @@ suite('Editor Model - Model Edit Operation', () => { let inverseEditOp = model.applyEdits(editOp, true); - assert.equal(model.getLineCount(), editedLines.length); + assert.strictEqual(model.getLineCount(), editedLines.length); for (let i = 0; i < editedLines.length; i++) { - assert.equal(model.getLineContent(i + 1), editedLines[i]); + assert.strictEqual(model.getLineContent(i + 1), editedLines[i]); } let originalOp = model.applyEdits(inverseEditOp, true); - assert.equal(model.getLineCount(), 5); - assert.equal(model.getLineContent(1), LINE1); - assert.equal(model.getLineContent(2), LINE2); - assert.equal(model.getLineContent(3), LINE3); - assert.equal(model.getLineContent(4), LINE4); - assert.equal(model.getLineContent(5), LINE5); + assert.strictEqual(model.getLineCount(), 5); + assert.strictEqual(model.getLineContent(1), LINE1); + assert.strictEqual(model.getLineContent(2), LINE2); + assert.strictEqual(model.getLineContent(3), LINE3); + assert.strictEqual(model.getLineContent(4), LINE4); + assert.strictEqual(model.getLineContent(5), LINE5); const simplifyEdit = (edit: IIdentifiedSingleEditOperation) => { return { @@ -75,7 +75,7 @@ suite('Editor Model - Model Edit Operation', () => { isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit || false }; }; - assert.deepEqual(originalOp.map(simplifyEdit), editOp.map(simplifyEdit)); + assert.deepStrictEqual(originalOp.map(simplifyEdit), editOp.map(simplifyEdit)); } test('Insert inline', () => { diff --git a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts index a8b46bbe6da..04fc6d743c7 100644 --- a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts @@ -77,11 +77,11 @@ function trimLineFeed(text: string): string { function testLinesContent(str: string, pieceTable: PieceTreeBase) { let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLinesRawContent(), str); for (let i = 0; i < lines.length; i++) { - assert.equal(pieceTable.getLineContent(i + 1), lines[i]); - assert.equal( + assert.strictEqual(pieceTable.getLineContent(i + 1), lines[i]); + assert.strictEqual( trimLineFeed( pieceTable.getValueInRange( new Range( @@ -136,16 +136,16 @@ function testLineStarts(str: string, pieceTable: PieceTreeBase) { } while (m); for (let i = 0; i < lineStarts.length; i++) { - assert.deepEqual( + assert.deepStrictEqual( pieceTable.getPositionAt(lineStarts[i]), new Position(i + 1, 1) ); - assert.equal(pieceTable.getOffsetAt(i + 1, 1), lineStarts[i]); + assert.strictEqual(pieceTable.getOffsetAt(i + 1, 1), lineStarts[i]); } for (let i = 1; i < lineStarts.length; i++) { let pos = pieceTable.getPositionAt(lineStarts[i] - 1); - assert.equal( + assert.strictEqual( pieceTable.getOffsetAt(pos.lineNumber, pos.column), lineStarts[i] - 1 ); @@ -219,12 +219,12 @@ suite('inserts and deletes', () => { ]); pieceTable.insert(34, 'This is some more text to insert at offset 34.'); - assert.equal( + assert.strictEqual( pieceTable.getLinesRawContent(), 'This is a document with some text.This is some more text to insert at offset 34.' ); pieceTable.delete(42, 5); - assert.equal( + assert.strictEqual( pieceTable.getLinesRawContent(), 'This is a document with some text.This is more text to insert at offset 34.' ); @@ -235,28 +235,28 @@ suite('inserts and deletes', () => { let pt = createTextBuffer(['']); pt.insert(0, 'AAA'); - assert.equal(pt.getLinesRawContent(), 'AAA'); + assert.strictEqual(pt.getLinesRawContent(), 'AAA'); pt.insert(0, 'BBB'); - assert.equal(pt.getLinesRawContent(), 'BBBAAA'); + assert.strictEqual(pt.getLinesRawContent(), 'BBBAAA'); pt.insert(6, 'CCC'); - assert.equal(pt.getLinesRawContent(), 'BBBAAACCC'); + assert.strictEqual(pt.getLinesRawContent(), 'BBBAAACCC'); pt.insert(5, 'DDD'); - assert.equal(pt.getLinesRawContent(), 'BBBAADDDACCC'); + assert.strictEqual(pt.getLinesRawContent(), 'BBBAADDDACCC'); assertTreeInvariants(pt); }); test('more deletes', () => { let pt = createTextBuffer(['012345678']); pt.delete(8, 1); - assert.equal(pt.getLinesRawContent(), '01234567'); + assert.strictEqual(pt.getLinesRawContent(), '01234567'); pt.delete(0, 1); - assert.equal(pt.getLinesRawContent(), '1234567'); + assert.strictEqual(pt.getLinesRawContent(), '1234567'); pt.delete(5, 1); - assert.equal(pt.getLinesRawContent(), '123457'); + assert.strictEqual(pt.getLinesRawContent(), '123457'); pt.delete(5, 1); - assert.equal(pt.getLinesRawContent(), '12345'); + assert.strictEqual(pt.getLinesRawContent(), '12345'); pt.delete(0, 5); - assert.equal(pt.getLinesRawContent(), ''); + assert.strictEqual(pt.getLinesRawContent(), ''); assertTreeInvariants(pt); }); @@ -265,17 +265,17 @@ suite('inserts and deletes', () => { let pieceTable = createTextBuffer(['']); pieceTable.insert(0, 'ceLPHmFzvCtFeHkCBej '); str = str.substring(0, 0) + 'ceLPHmFzvCtFeHkCBej ' + str.substring(0); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.insert(8, 'gDCEfNYiBUNkSwtvB K '); str = str.substring(0, 8) + 'gDCEfNYiBUNkSwtvB K ' + str.substring(8); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.insert(38, 'cyNcHxjNPPoehBJldLS '); str = str.substring(0, 38) + 'cyNcHxjNPPoehBJldLS ' + str.substring(38); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.insert(59, 'ejMx\nOTgWlbpeDExjOk '); str = str.substring(0, 59) + 'ejMx\nOTgWlbpeDExjOk ' + str.substring(59); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -293,7 +293,7 @@ suite('inserts and deletes', () => { pieceTable.insert(10, 'Gbtp '); str = str.substring(0, 10) + 'Gbtp ' + str.substring(10); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -310,7 +310,7 @@ suite('inserts and deletes', () => { str = str.substring(0, 2) + 'GGZB' + str.substring(2); pieceTable.insert(12, 'wXpq'); str = str.substring(0, 12) + 'wXpq' + str.substring(12); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); }); test('random delete 1', () => { @@ -319,30 +319,30 @@ suite('inserts and deletes', () => { pieceTable.insert(0, 'vfb'); str = str.substring(0, 0) + 'vfb' + str.substring(0); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.insert(0, 'zRq'); str = str.substring(0, 0) + 'zRq' + str.substring(0); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.delete(5, 1); str = str.substring(0, 5) + str.substring(5 + 1); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.insert(1, 'UNw'); str = str.substring(0, 1) + 'UNw' + str.substring(1); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.delete(4, 3); str = str.substring(0, 4) + str.substring(4 + 3); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.delete(1, 4); str = str.substring(0, 1) + str.substring(1 + 4); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.delete(0, 1); str = str.substring(0, 0) + str.substring(0 + 1); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -368,7 +368,7 @@ suite('inserts and deletes', () => { str = str.substring(0, 6) + str.substring(6 + 7); pieceTable.delete(3, 5); str = str.substring(0, 3) + str.substring(3 + 5); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -401,7 +401,7 @@ suite('inserts and deletes', () => { str = str.substring(0, 5) + str.substring(5 + 8); pieceTable.delete(3, 4); str = str.substring(0, 3) + str.substring(3 + 4); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -427,7 +427,7 @@ suite('inserts and deletes', () => { pieceTable.insert(5, '\n\na\r'); str = str.substring(0, 5) + '\n\na\r' + str.substring(5); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -455,7 +455,7 @@ suite('inserts and deletes', () => { pieceTable.insert(2, 'a\ra\n'); str = str.substring(0, 2) + 'a\ra\n' + str.substring(2); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -480,11 +480,11 @@ suite('inserts and deletes', () => { str = str.substring(0, 5) + '\n\na\r' + str.substring(5); pieceTable.insert(10, '\r\r\n\r'); str = str.substring(0, 10) + '\r\r\n\r' + str.substring(10); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); pieceTable.delete(21, 3); str = str.substring(0, 21) + str.substring(21 + 3); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); @@ -512,7 +512,7 @@ suite('inserts and deletes', () => { pieceTable.insert(3, 'a\naa'); str = str.substring(0, 3) + 'a\naa' + str.substring(3); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); test('random insert/delete \\r bug 5', () => { @@ -539,7 +539,7 @@ suite('inserts and deletes', () => { pieceTable.insert(15, '\n\r\r\r'); str = str.substring(0, 15) + '\n\r\r\r' + str.substring(15); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); assertTreeInvariants(pieceTable); }); }); @@ -548,22 +548,22 @@ suite('prefix sum for line feed', () => { test('basic', () => { let pieceTable = createTextBuffer(['1\n2\n3\n4']); - assert.equal(pieceTable.getLineCount(), 4); - assert.deepEqual(pieceTable.getPositionAt(0), new Position(1, 1)); - assert.deepEqual(pieceTable.getPositionAt(1), new Position(1, 2)); - assert.deepEqual(pieceTable.getPositionAt(2), new Position(2, 1)); - assert.deepEqual(pieceTable.getPositionAt(3), new Position(2, 2)); - assert.deepEqual(pieceTable.getPositionAt(4), new Position(3, 1)); - assert.deepEqual(pieceTable.getPositionAt(5), new Position(3, 2)); - assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.strictEqual(pieceTable.getLineCount(), 4); + assert.deepStrictEqual(pieceTable.getPositionAt(0), new Position(1, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(1), new Position(1, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(2), new Position(2, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(3), new Position(2, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(4), new Position(3, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(5), new Position(3, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1)); - assert.equal(pieceTable.getOffsetAt(1, 1), 0); - assert.equal(pieceTable.getOffsetAt(1, 2), 1); - assert.equal(pieceTable.getOffsetAt(2, 1), 2); - assert.equal(pieceTable.getOffsetAt(2, 2), 3); - assert.equal(pieceTable.getOffsetAt(3, 1), 4); - assert.equal(pieceTable.getOffsetAt(3, 2), 5); - assert.equal(pieceTable.getOffsetAt(4, 1), 6); + assert.strictEqual(pieceTable.getOffsetAt(1, 1), 0); + assert.strictEqual(pieceTable.getOffsetAt(1, 2), 1); + assert.strictEqual(pieceTable.getOffsetAt(2, 1), 2); + assert.strictEqual(pieceTable.getOffsetAt(2, 2), 3); + assert.strictEqual(pieceTable.getOffsetAt(3, 1), 4); + assert.strictEqual(pieceTable.getOffsetAt(3, 2), 5); + assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6); assertTreeInvariants(pieceTable); }); @@ -571,9 +571,9 @@ suite('prefix sum for line feed', () => { let pieceTable = createTextBuffer(['a\nb\nc\nde']); pieceTable.insert(8, 'fh\ni\njk'); - assert.equal(pieceTable.getLineCount(), 6); - assert.deepEqual(pieceTable.getPositionAt(9), new Position(4, 4)); - assert.equal(pieceTable.getOffsetAt(1, 1), 0); + assert.strictEqual(pieceTable.getLineCount(), 6); + assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(4, 4)); + assert.strictEqual(pieceTable.getOffsetAt(1, 1), 0); assertTreeInvariants(pieceTable); }); @@ -581,22 +581,22 @@ suite('prefix sum for line feed', () => { let pieceTable = createTextBuffer(['a\nb\nc\nde']); pieceTable.insert(7, 'fh\ni\njk'); - assert.equal(pieceTable.getLineCount(), 6); - assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); - assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); - assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); - assert.deepEqual(pieceTable.getPositionAt(9), new Position(4, 4)); - assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 1)); - assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 2)); - assert.deepEqual(pieceTable.getPositionAt(14), new Position(6, 3)); + assert.strictEqual(pieceTable.getLineCount(), 6); + assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(4, 4)); + assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(14), new Position(6, 3)); - assert.equal(pieceTable.getOffsetAt(4, 1), 6); - assert.equal(pieceTable.getOffsetAt(4, 2), 7); - assert.equal(pieceTable.getOffsetAt(4, 3), 8); - assert.equal(pieceTable.getOffsetAt(4, 4), 9); - assert.equal(pieceTable.getOffsetAt(6, 1), 12); - assert.equal(pieceTable.getOffsetAt(6, 2), 13); - assert.equal(pieceTable.getOffsetAt(6, 3), 14); + assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6); + assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7); + assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8); + assert.strictEqual(pieceTable.getOffsetAt(4, 4), 9); + assert.strictEqual(pieceTable.getOffsetAt(6, 1), 12); + assert.strictEqual(pieceTable.getOffsetAt(6, 2), 13); + assert.strictEqual(pieceTable.getOffsetAt(6, 3), 14); assertTreeInvariants(pieceTable); }); @@ -604,23 +604,23 @@ suite('prefix sum for line feed', () => { let pieceTable = createTextBuffer(['a\nb\nc\ndefh\ni\njk']); pieceTable.delete(7, 2); - assert.equal(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); - assert.equal(pieceTable.getLineCount(), 6); - assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); - assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); - assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); - assert.deepEqual(pieceTable.getPositionAt(9), new Position(5, 1)); - assert.deepEqual(pieceTable.getPositionAt(11), new Position(6, 1)); - assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 2)); - assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 3)); + assert.strictEqual(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); + assert.strictEqual(pieceTable.getLineCount(), 6); + assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(5, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(11), new Position(6, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 3)); - assert.equal(pieceTable.getOffsetAt(4, 1), 6); - assert.equal(pieceTable.getOffsetAt(4, 2), 7); - assert.equal(pieceTable.getOffsetAt(4, 3), 8); - assert.equal(pieceTable.getOffsetAt(5, 1), 9); - assert.equal(pieceTable.getOffsetAt(6, 1), 11); - assert.equal(pieceTable.getOffsetAt(6, 2), 12); - assert.equal(pieceTable.getOffsetAt(6, 3), 13); + assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6); + assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7); + assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8); + assert.strictEqual(pieceTable.getOffsetAt(5, 1), 9); + assert.strictEqual(pieceTable.getOffsetAt(6, 1), 11); + assert.strictEqual(pieceTable.getOffsetAt(6, 2), 12); + assert.strictEqual(pieceTable.getOffsetAt(6, 3), 13); assertTreeInvariants(pieceTable); }); @@ -629,23 +629,23 @@ suite('prefix sum for line feed', () => { pieceTable.insert(8, 'fh\ni\njk'); pieceTable.delete(7, 2); - assert.equal(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); - assert.equal(pieceTable.getLineCount(), 6); - assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); - assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); - assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); - assert.deepEqual(pieceTable.getPositionAt(9), new Position(5, 1)); - assert.deepEqual(pieceTable.getPositionAt(11), new Position(6, 1)); - assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 2)); - assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 3)); + assert.strictEqual(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); + assert.strictEqual(pieceTable.getLineCount(), 6); + assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(5, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(11), new Position(6, 1)); + assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 2)); + assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 3)); - assert.equal(pieceTable.getOffsetAt(4, 1), 6); - assert.equal(pieceTable.getOffsetAt(4, 2), 7); - assert.equal(pieceTable.getOffsetAt(4, 3), 8); - assert.equal(pieceTable.getOffsetAt(5, 1), 9); - assert.equal(pieceTable.getOffsetAt(6, 1), 11); - assert.equal(pieceTable.getOffsetAt(6, 2), 12); - assert.equal(pieceTable.getOffsetAt(6, 3), 13); + assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6); + assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7); + assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8); + assert.strictEqual(pieceTable.getOffsetAt(5, 1), 9); + assert.strictEqual(pieceTable.getOffsetAt(6, 1), 11); + assert.strictEqual(pieceTable.getOffsetAt(6, 2), 12); + assert.strictEqual(pieceTable.getOffsetAt(6, 3), 13); assertTreeInvariants(pieceTable); }); @@ -661,7 +661,7 @@ suite('prefix sum for line feed', () => { str = str.substring(0, 14) + 'X ZZ\nYZZYZXXY Y XY\n ' + str.substring(14); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -675,7 +675,7 @@ suite('prefix sum for line feed', () => { pieceTable.insert(3, 'XXY \n\nY Y YYY ZYXY '); str = str.substring(0, 3) + 'XXY \n\nY Y YYY ZYXY ' + str.substring(3); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -803,12 +803,12 @@ suite('get text in range', () => { pieceTable.delete(7, 2); // 'a\nb\nc\ndh\ni\njk' - assert.equal(pieceTable.getValueInRange(new Range(1, 1, 1, 3)), 'a\n'); - assert.equal(pieceTable.getValueInRange(new Range(2, 1, 2, 3)), 'b\n'); - assert.equal(pieceTable.getValueInRange(new Range(3, 1, 3, 3)), 'c\n'); - assert.equal(pieceTable.getValueInRange(new Range(4, 1, 4, 4)), 'dh\n'); - assert.equal(pieceTable.getValueInRange(new Range(5, 1, 5, 3)), 'i\n'); - assert.equal(pieceTable.getValueInRange(new Range(6, 1, 6, 3)), 'jk'); + assert.strictEqual(pieceTable.getValueInRange(new Range(1, 1, 1, 3)), 'a\n'); + assert.strictEqual(pieceTable.getValueInRange(new Range(2, 1, 2, 3)), 'b\n'); + assert.strictEqual(pieceTable.getValueInRange(new Range(3, 1, 3, 3)), 'c\n'); + assert.strictEqual(pieceTable.getValueInRange(new Range(4, 1, 4, 4)), 'dh\n'); + assert.strictEqual(pieceTable.getValueInRange(new Range(5, 1, 5, 3)), 'i\n'); + assert.strictEqual(pieceTable.getValueInRange(new Range(6, 1, 6, 3)), 'jk'); assertTreeInvariants(pieceTable); }); @@ -902,18 +902,18 @@ suite('get text in range', () => { test('get line content', () => { let pieceTable = createTextBuffer(['1']); - assert.equal(pieceTable.getLineRawContent(1), '1'); + assert.strictEqual(pieceTable.getLineRawContent(1), '1'); pieceTable.insert(1, '2'); - assert.equal(pieceTable.getLineRawContent(1), '12'); + assert.strictEqual(pieceTable.getLineRawContent(1), '12'); assertTreeInvariants(pieceTable); }); test('get line content basic', () => { let pieceTable = createTextBuffer(['1\n2\n3\n4']); - assert.equal(pieceTable.getLineRawContent(1), '1\n'); - assert.equal(pieceTable.getLineRawContent(2), '2\n'); - assert.equal(pieceTable.getLineRawContent(3), '3\n'); - assert.equal(pieceTable.getLineRawContent(4), '4'); + assert.strictEqual(pieceTable.getLineRawContent(1), '1\n'); + assert.strictEqual(pieceTable.getLineRawContent(2), '2\n'); + assert.strictEqual(pieceTable.getLineRawContent(3), '3\n'); + assert.strictEqual(pieceTable.getLineRawContent(4), '4'); assertTreeInvariants(pieceTable); }); @@ -923,12 +923,12 @@ suite('get text in range', () => { pieceTable.delete(7, 2); // 'a\nb\nc\ndh\ni\njk' - assert.equal(pieceTable.getLineRawContent(1), 'a\n'); - assert.equal(pieceTable.getLineRawContent(2), 'b\n'); - assert.equal(pieceTable.getLineRawContent(3), 'c\n'); - assert.equal(pieceTable.getLineRawContent(4), 'dh\n'); - assert.equal(pieceTable.getLineRawContent(5), 'i\n'); - assert.equal(pieceTable.getLineRawContent(6), 'jk'); + assert.strictEqual(pieceTable.getLineRawContent(1), 'a\n'); + assert.strictEqual(pieceTable.getLineRawContent(2), 'b\n'); + assert.strictEqual(pieceTable.getLineRawContent(3), 'c\n'); + assert.strictEqual(pieceTable.getLineRawContent(4), 'dh\n'); + assert.strictEqual(pieceTable.getLineRawContent(5), 'i\n'); + assert.strictEqual(pieceTable.getLineRawContent(6), 'jk'); assertTreeInvariants(pieceTable); }); @@ -973,7 +973,7 @@ suite('CRLF', () => { pieceTable.insert(0, 'a\r\nb'); pieceTable.delete(0, 2); - assert.equal(pieceTable.getLineCount(), 2); + assert.strictEqual(pieceTable.getLineCount(), 2); assertTreeInvariants(pieceTable); }); @@ -982,7 +982,7 @@ suite('CRLF', () => { pieceTable.insert(0, 'a\r\nb'); pieceTable.delete(2, 2); - assert.equal(pieceTable.getLineCount(), 2); + assert.strictEqual(pieceTable.getLineCount(), 2); assertTreeInvariants(pieceTable); }); @@ -999,7 +999,7 @@ suite('CRLF', () => { str = str.substring(0, 2) + str.substring(2 + 3); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); test('random bug 2', () => { @@ -1014,7 +1014,7 @@ suite('CRLF', () => { str = str.substring(0, 4) + str.substring(4 + 1); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); test('random bug 3', () => { @@ -1035,7 +1035,7 @@ suite('CRLF', () => { str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); test('random bug 4', () => { @@ -1185,14 +1185,14 @@ suite('centralized lineStarts with CRLF', () => { test('delete CR in CRLF 1', () => { let pieceTable = createTextBuffer(['a\r\nb'], false); pieceTable.delete(2, 2); - assert.equal(pieceTable.getLineCount(), 2); + assert.strictEqual(pieceTable.getLineCount(), 2); assertTreeInvariants(pieceTable); }); test('delete CR in CRLF 2', () => { let pieceTable = createTextBuffer(['a\r\nb']); pieceTable.delete(0, 2); - assert.equal(pieceTable.getLineCount(), 2); + assert.strictEqual(pieceTable.getLineCount(), 2); assertTreeInvariants(pieceTable); }); @@ -1207,7 +1207,7 @@ suite('centralized lineStarts with CRLF', () => { str = str.substring(0, 2) + str.substring(2 + 3); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); test('random bug 2', () => { @@ -1220,7 +1220,7 @@ suite('centralized lineStarts with CRLF', () => { str = str.substring(0, 4) + str.substring(4 + 1); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); @@ -1240,7 +1240,7 @@ suite('centralized lineStarts with CRLF', () => { str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3); let lines = splitLines(str); - assert.equal(pieceTable.getLineCount(), lines.length); + assert.strictEqual(pieceTable.getLineCount(), lines.length); assertTreeInvariants(pieceTable); }); @@ -1386,7 +1386,7 @@ suite('centralized lineStarts with CRLF', () => { pieceTable.insert(7, '\r\r\r\r'); str = str.substring(0, 7) + '\r\r\r\r' + str.substring(7); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -1407,7 +1407,7 @@ suite('centralized lineStarts with CRLF', () => { pieceTable.delete(11, 2); str = str.substring(0, 11) + str.substring(11 + 2); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -1424,7 +1424,7 @@ suite('centralized lineStarts with CRLF', () => { pieceTable.delete(1, 2); str = str.substring(0, 1) + str.substring(1 + 2); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -1437,7 +1437,7 @@ suite('centralized lineStarts with CRLF', () => { pieceTable.insert(3, '\r\n\n\n'); str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); assertTreeInvariants(pieceTable); }); @@ -1469,7 +1469,7 @@ suite('random is unsupervised', () => { pieceTable.insert(0, 'VZXXZYZX\r'); str = str.substring(0, 0) + 'VZXXZYZX\r' + str.substring(0); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); testLinesContent(str, pieceTable); @@ -1507,7 +1507,7 @@ suite('random is unsupervised', () => { } // console.log(output); - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); testLinesContent(str, pieceTable); @@ -1543,7 +1543,7 @@ suite('random is unsupervised', () => { } } - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); testLinesContent(str, pieceTable); assertTreeInvariants(pieceTable); @@ -1577,7 +1577,7 @@ suite('random is unsupervised', () => { testLinesContent(str, pieceTable); } - assert.equal(pieceTable.getLinesRawContent(), str); + assert.strictEqual(pieceTable.getLinesRawContent(), str); testLineStarts(str, pieceTable); testLinesContent(str, pieceTable); assertTreeInvariants(pieceTable); @@ -1612,33 +1612,33 @@ suite('buffer api', () => { test('getLineCharCode - issue #45735', () => { let pieceTable = createTextBuffer(['LINE1\nline2']); - assert.equal(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); - assert.equal(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); - assert.equal(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); - assert.equal(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); - assert.equal(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); - assert.equal(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); - assert.equal(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); - assert.equal(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); - assert.equal(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); - assert.equal(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); - assert.equal(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); + assert.strictEqual(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); + assert.strictEqual(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); + assert.strictEqual(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); + assert.strictEqual(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); + assert.strictEqual(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); + assert.strictEqual(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); + assert.strictEqual(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); + assert.strictEqual(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); + assert.strictEqual(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); + assert.strictEqual(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); + assert.strictEqual(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); }); test('getLineCharCode - issue #47733', () => { let pieceTable = createTextBuffer(['', 'LINE1\n', 'line2']); - assert.equal(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); - assert.equal(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); - assert.equal(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); - assert.equal(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); - assert.equal(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); - assert.equal(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); - assert.equal(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); - assert.equal(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); - assert.equal(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); - assert.equal(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); - assert.equal(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); + assert.strictEqual(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); + assert.strictEqual(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); + assert.strictEqual(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); + assert.strictEqual(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); + assert.strictEqual(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); + assert.strictEqual(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); + assert.strictEqual(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); + assert.strictEqual(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); + assert.strictEqual(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); + assert.strictEqual(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); + assert.strictEqual(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); }); }); @@ -1771,7 +1771,7 @@ suite('snapshot', () => { ]); const snapshot = model.createSnapshot(); const snapshot1 = model.createSnapshot(); - assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); model.applyEdits([ { @@ -1786,7 +1786,7 @@ suite('snapshot', () => { } ]); - assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot1)); + assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot1)); }); test('immutable snapshot 1', () => { @@ -1806,7 +1806,7 @@ suite('snapshot', () => { } ]); - assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); }); test('immutable snapshot 2', () => { @@ -1826,7 +1826,7 @@ suite('snapshot', () => { } ]); - assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); }); test('immutable snapshot 3', () => { @@ -1845,7 +1845,7 @@ suite('snapshot', () => { } ]); - assert.notEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + assert.notStrictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); }); }); @@ -1854,7 +1854,7 @@ suite('chunk based search', () => { let pieceTree = createTextBuffer(['']); pieceTree.delete(0, 1); let ret = pieceTree.findMatchesLineByLine(new Range(1, 1, 1, 1), new SearchData(/abc/, new WordCharacterClassifier(',./'), 'abc'), true, 1000); - assert.equal(ret.length, 0); + assert.strictEqual(ret.length, 0); }); test('#45770. FindInNode should not cross node boundary.', () => { @@ -1873,11 +1873,11 @@ suite('chunk based search', () => { pieceTree.insert(16, ' '); let ret = pieceTree.findMatchesLineByLine(new Range(1, 1, 4, 13), new SearchData(/\[/gi, new WordCharacterClassifier(',./'), '['), true, 1000); - assert.equal(ret.length, 3); + assert.strictEqual(ret.length, 3); - assert.deepEqual(ret[0].range, new Range(2, 3, 2, 4)); - assert.deepEqual(ret[1].range, new Range(3, 3, 3, 4)); - assert.deepEqual(ret[2].range, new Range(4, 3, 4, 4)); + assert.deepStrictEqual(ret[0].range, new Range(2, 3, 2, 4)); + assert.deepStrictEqual(ret[1].range, new Range(3, 3, 3, 4)); + assert.deepStrictEqual(ret[2].range, new Range(4, 3, 4, 4)); }); test('search searching from the middle', () => { @@ -1889,12 +1889,12 @@ suite('chunk based search', () => { ]); pieceTree.delete(4, 1); let ret = pieceTree.findMatchesLineByLine(new Range(2, 3, 2, 6), new SearchData(/a/gi, null, 'a'), true, 1000); - assert.equal(ret.length, 1); - assert.deepEqual(ret[0].range, new Range(2, 3, 2, 4)); + assert.strictEqual(ret.length, 1); + assert.deepStrictEqual(ret[0].range, new Range(2, 3, 2, 4)); pieceTree.delete(4, 1); ret = pieceTree.findMatchesLineByLine(new Range(2, 2, 2, 5), new SearchData(/a/gi, null, 'a'), true, 1000); - assert.equal(ret.length, 1); - assert.deepEqual(ret[0].range, new Range(2, 2, 2, 3)); + assert.strictEqual(ret.length, 1); + assert.deepStrictEqual(ret[0].range, new Range(2, 2, 2, 3)); }); }); diff --git a/src/vs/editor/test/common/model/textChange.test.ts b/src/vs/editor/test/common/model/textChange.test.ts index d6d42dfc683..bbc29ea577e 100644 --- a/src/vs/editor/test/common/model/textChange.test.ts +++ b/src/vs/editor/test/common/model/textChange.test.ts @@ -75,7 +75,7 @@ suite('TextChangeCompressor', () => { }; }); let actualDoResult = getResultingContent(initialText, compressedDoTextEdits); - assert.equal(actualDoResult, finalText); + assert.strictEqual(actualDoResult, finalText); let compressedUndoTextEdits: IGeneratedEdit[] = compressedTextChanges.map((change) => { return { @@ -85,7 +85,7 @@ suite('TextChangeCompressor', () => { }; }); let actualUndoResult = getResultingContent(finalText, compressedUndoTextEdits); - assert.equal(actualUndoResult, initialText); + assert.strictEqual(actualUndoResult, initialText); } test('simple 1', () => { diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 031a5f36efb..2d8e6bbde8c 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -22,8 +22,8 @@ function testGuessIndentation(defaultInsertSpaces: boolean, defaultTabSize: numb let r = m.getOptions(); m.dispose(); - assert.equal(r.insertSpaces, expectedInsertSpaces, msg); - assert.equal(r.tabSize, expectedTabSize, msg); + assert.strictEqual(r.insertSpaces, expectedInsertSpaces, msg); + assert.strictEqual(r.tabSize, expectedTabSize, msg); } function assertGuess(expectedInsertSpaces: boolean | undefined, expectedTabSize: number | undefined | [number], text: string[], msg?: string): void { @@ -82,7 +82,7 @@ suite('TextModelData.fromString', () => { containsRTL: textBuffer.mightContainRTL(), isBasicASCII: !textBuffer.mightContainNonBasicASCII() }; - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('one line text', () => { @@ -164,30 +164,30 @@ suite('Editor Model - TextModel', () => { test('getValueLengthInRange', () => { let m = createTextModel('My First Line\r\nMy Second Line\r\nMy Third Line'); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\r\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 1)), 'y First Line\r\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 2)), 'y First Line\r\nM'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 1000)), 'y First Line\r\nMy Second Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1)), 'y First Line\r\nMy Second Line\r\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\r\nMy Second Line\r\nMy Third Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\r\nMy Second Line\r\nMy Third Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\r\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 1)), 'y First Line\r\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 2)), 'y First Line\r\nM'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 1000)), 'y First Line\r\nMy Second Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 3, 1)), 'y First Line\r\nMy Second Line\r\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\r\nMy Second Line\r\nMy Third Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\r\nMy Second Line\r\nMy Third Line'.length); m = createTextModel('My First Line\nMy Second Line\nMy Third Line'); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 1)), 'y First Line\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 2)), 'y First Line\nM'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 2, 1000)), 'y First Line\nMy Second Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1)), 'y First Line\nMy Second Line\n'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\nMy Second Line\nMy Third Line'.length); - assert.equal(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\nMy Second Line\nMy Third Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1, 14)), 'My First Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 2, 1)), 'My First Line\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 1)), 'y First Line\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 2)), 'y First Line\nM'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 2, 1000)), 'y First Line\nMy Second Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 3, 1)), 'y First Line\nMy Second Line\n'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\nMy Second Line\nMy Third Line'.length); + assert.strictEqual(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\nMy Second Line\nMy Third Line'.length); }); test('guess indentation 1', () => { @@ -664,69 +664,69 @@ suite('Editor Model - TextModel', () => { let m = createTextModel('line one\nline two'); - assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); - assert.deepEqual(m.validatePosition(new Position(1, 30)), new Position(1, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 30)), new Position(1, 9)); - assert.deepEqual(m.validatePosition(new Position(2, 0)), new Position(2, 1)); - assert.deepEqual(m.validatePosition(new Position(2, 1)), new Position(2, 1)); - assert.deepEqual(m.validatePosition(new Position(2, 2)), new Position(2, 2)); - assert.deepEqual(m.validatePosition(new Position(2, 30)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 0)), new Position(2, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 1)), new Position(2, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 2)), new Position(2, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 30)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(3, 0)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(3, 1)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(3, 30)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(3, 0)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(3, 1)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(3, 30)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(30, 30)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(30, 30)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(-123.123, -0.5)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(Number.MIN_VALUE, Number.MIN_VALUE)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(-123.123, -0.5)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(Number.MIN_VALUE, Number.MIN_VALUE)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(Number.MAX_VALUE, Number.MAX_VALUE)), new Position(2, 9)); - assert.deepEqual(m.validatePosition(new Position(123.23, 47.5)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(Number.MAX_VALUE, Number.MAX_VALUE)), new Position(2, 9)); + assert.deepStrictEqual(m.validatePosition(new Position(123.23, 47.5)), new Position(2, 9)); }); test('validatePosition around high-low surrogate pairs 1', () => { let m = createTextModel('a📚b'); - assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(0, 7)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(0, 7)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); - assert.deepEqual(m.validatePosition(new Position(1, 3)), new Position(1, 2)); - assert.deepEqual(m.validatePosition(new Position(1, 4)), new Position(1, 4)); - assert.deepEqual(m.validatePosition(new Position(1, 5)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(1, 30)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 3)), new Position(1, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 4)), new Position(1, 4)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 5)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 30)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(2, 0)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(2, 1)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(2, 2)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(2, 30)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 0)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 1)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 2)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(2, 30)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(-123.123, -0.5)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(Number.MIN_VALUE, Number.MIN_VALUE)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(-123.123, -0.5)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(Number.MIN_VALUE, Number.MIN_VALUE)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(Number.MAX_VALUE, Number.MAX_VALUE)), new Position(1, 5)); - assert.deepEqual(m.validatePosition(new Position(123.23, 47.5)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(Number.MAX_VALUE, Number.MAX_VALUE)), new Position(1, 5)); + assert.deepStrictEqual(m.validatePosition(new Position(123.23, 47.5)), new Position(1, 5)); }); test('validatePosition around high-low surrogate pairs 2', () => { let m = createTextModel('a📚📚b'); - assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); - assert.deepEqual(m.validatePosition(new Position(1, 3)), new Position(1, 2)); - assert.deepEqual(m.validatePosition(new Position(1, 4)), new Position(1, 4)); - assert.deepEqual(m.validatePosition(new Position(1, 5)), new Position(1, 4)); - assert.deepEqual(m.validatePosition(new Position(1, 6)), new Position(1, 6)); - assert.deepEqual(m.validatePosition(new Position(1, 7)), new Position(1, 7)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 3)), new Position(1, 2)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 4)), new Position(1, 4)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 5)), new Position(1, 4)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 6)), new Position(1, 6)); + assert.deepStrictEqual(m.validatePosition(new Position(1, 7)), new Position(1, 7)); }); @@ -734,133 +734,133 @@ suite('Editor Model - TextModel', () => { let m = createTextModel('line one\nline two'); - assert.deepEqual(m.validatePosition(new Position(NaN, 1)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(1, NaN)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(NaN, 1)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(1, NaN)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(NaN, NaN)), new Position(1, 1)); - assert.deepEqual(m.validatePosition(new Position(2, NaN)), new Position(2, 1)); - assert.deepEqual(m.validatePosition(new Position(NaN, 3)), new Position(1, 3)); + assert.deepStrictEqual(m.validatePosition(new Position(NaN, NaN)), new Position(1, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(2, NaN)), new Position(2, 1)); + assert.deepStrictEqual(m.validatePosition(new Position(NaN, 3)), new Position(1, 3)); }); test('issue #71480: validatePosition handle floats', () => { let m = createTextModel('line one\nline two'); - assert.deepEqual(m.validatePosition(new Position(0.2, 1)), new Position(1, 1), 'a'); - assert.deepEqual(m.validatePosition(new Position(1.2, 1)), new Position(1, 1), 'b'); - assert.deepEqual(m.validatePosition(new Position(1.5, 2)), new Position(1, 2), 'c'); - assert.deepEqual(m.validatePosition(new Position(1.8, 3)), new Position(1, 3), 'd'); - assert.deepEqual(m.validatePosition(new Position(1, 0.3)), new Position(1, 1), 'e'); - assert.deepEqual(m.validatePosition(new Position(2, 0.8)), new Position(2, 1), 'f'); - assert.deepEqual(m.validatePosition(new Position(1, 1.2)), new Position(1, 1), 'g'); - assert.deepEqual(m.validatePosition(new Position(2, 1.5)), new Position(2, 1), 'h'); + assert.deepStrictEqual(m.validatePosition(new Position(0.2, 1)), new Position(1, 1), 'a'); + assert.deepStrictEqual(m.validatePosition(new Position(1.2, 1)), new Position(1, 1), 'b'); + assert.deepStrictEqual(m.validatePosition(new Position(1.5, 2)), new Position(1, 2), 'c'); + assert.deepStrictEqual(m.validatePosition(new Position(1.8, 3)), new Position(1, 3), 'd'); + assert.deepStrictEqual(m.validatePosition(new Position(1, 0.3)), new Position(1, 1), 'e'); + assert.deepStrictEqual(m.validatePosition(new Position(2, 0.8)), new Position(2, 1), 'f'); + assert.deepStrictEqual(m.validatePosition(new Position(1, 1.2)), new Position(1, 1), 'g'); + assert.deepStrictEqual(m.validatePosition(new Position(2, 1.5)), new Position(2, 1), 'h'); }); test('issue #71480: validateRange handle floats', () => { let m = createTextModel('line one\nline two'); - assert.deepEqual(m.validateRange(new Range(0.2, 1.5, 0.8, 2.5)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(1.2, 1.7, 1.8, 2.2)), new Range(1, 1, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(0.2, 1.5, 0.8, 2.5)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(1.2, 1.7, 1.8, 2.2)), new Range(1, 1, 1, 2)); }); test('validateRange around high-low surrogate pairs 1', () => { let m = createTextModel('a📚b'); - assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 1)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 2)), new Range(1, 1, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 3)), new Range(1, 1, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 4)), new Range(1, 1, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 5)), new Range(1, 1, 1, 5)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 1)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 2)), new Range(1, 1, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 3)), new Range(1, 1, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 4)), new Range(1, 1, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 5)), new Range(1, 1, 1, 5)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 2)), new Range(1, 2, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 3)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 4)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 5)), new Range(1, 2, 1, 5)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 2)), new Range(1, 2, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 3)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 4)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 5)), new Range(1, 2, 1, 5)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 3)), new Range(1, 2, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 4)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 5)), new Range(1, 2, 1, 5)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 3)), new Range(1, 2, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 4)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 5)), new Range(1, 2, 1, 5)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 4)), new Range(1, 4, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 5)), new Range(1, 4, 1, 5)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 4)), new Range(1, 4, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 5)), new Range(1, 4, 1, 5)); - assert.deepEqual(m.validateRange(new Range(1, 5, 1, 5)), new Range(1, 5, 1, 5)); + assert.deepStrictEqual(m.validateRange(new Range(1, 5, 1, 5)), new Range(1, 5, 1, 5)); }); test('validateRange around high-low surrogate pairs 2', () => { let m = createTextModel('a📚📚b'); - assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 1)), new Range(1, 1, 1, 1)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 2)), new Range(1, 1, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 3)), new Range(1, 1, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 4)), new Range(1, 1, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 5)), new Range(1, 1, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 6)), new Range(1, 1, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 1, 1, 7)), new Range(1, 1, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 1)), new Range(1, 1, 1, 1)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 2)), new Range(1, 1, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 3)), new Range(1, 1, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 4)), new Range(1, 1, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 5)), new Range(1, 1, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 6)), new Range(1, 1, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 1, 1, 7)), new Range(1, 1, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 2)), new Range(1, 2, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 3)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 4)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 5)), new Range(1, 2, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 6)), new Range(1, 2, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 2, 1, 7)), new Range(1, 2, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 2)), new Range(1, 2, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 3)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 4)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 5)), new Range(1, 2, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 6)), new Range(1, 2, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 2, 1, 7)), new Range(1, 2, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 3)), new Range(1, 2, 1, 2)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 4)), new Range(1, 2, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 5)), new Range(1, 2, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 6)), new Range(1, 2, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 3, 1, 7)), new Range(1, 2, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 3)), new Range(1, 2, 1, 2)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 4)), new Range(1, 2, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 5)), new Range(1, 2, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 6)), new Range(1, 2, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 3, 1, 7)), new Range(1, 2, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 4)), new Range(1, 4, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 5)), new Range(1, 4, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 6)), new Range(1, 4, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 4, 1, 7)), new Range(1, 4, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 4)), new Range(1, 4, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 5)), new Range(1, 4, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 6)), new Range(1, 4, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 4, 1, 7)), new Range(1, 4, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 5, 1, 5)), new Range(1, 4, 1, 4)); - assert.deepEqual(m.validateRange(new Range(1, 5, 1, 6)), new Range(1, 4, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 5, 1, 7)), new Range(1, 4, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 5, 1, 5)), new Range(1, 4, 1, 4)); + assert.deepStrictEqual(m.validateRange(new Range(1, 5, 1, 6)), new Range(1, 4, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 5, 1, 7)), new Range(1, 4, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 6, 1, 6)), new Range(1, 6, 1, 6)); - assert.deepEqual(m.validateRange(new Range(1, 6, 1, 7)), new Range(1, 6, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 6, 1, 6)), new Range(1, 6, 1, 6)); + assert.deepStrictEqual(m.validateRange(new Range(1, 6, 1, 7)), new Range(1, 6, 1, 7)); - assert.deepEqual(m.validateRange(new Range(1, 7, 1, 7)), new Range(1, 7, 1, 7)); + assert.deepStrictEqual(m.validateRange(new Range(1, 7, 1, 7)), new Range(1, 7, 1, 7)); }); test('modifyPosition', () => { let m = createTextModel('line one\nline two'); - assert.deepEqual(m.modifyPosition(new Position(1, 1), 0), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(0, 0), 0), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 1), 0), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(0, 0), 0), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(1, 1), 17), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(1, 1), 1), new Position(1, 2)); - assert.deepEqual(m.modifyPosition(new Position(1, 1), 3), new Position(1, 4)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), 10), new Position(2, 3)); - assert.deepEqual(m.modifyPosition(new Position(1, 5), 13), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), 16), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 1), 17), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 1), 1), new Position(1, 2)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 1), 3), new Position(1, 4)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), 10), new Position(2, 3)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 5), 13), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), 16), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(2, 9), -17), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), -1), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(1, 4), -3), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(2, 3), -10), new Position(1, 2)); - assert.deepEqual(m.modifyPosition(new Position(2, 9), -13), new Position(1, 5)); - assert.deepEqual(m.modifyPosition(new Position(2, 9), -16), new Position(1, 2)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 9), -17), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), -1), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 4), -3), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 3), -10), new Position(1, 2)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 9), -13), new Position(1, 5)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 9), -16), new Position(1, 2)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), 17), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), 100), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), 17), new Position(2, 9)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), 100), new Position(2, 9)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), -2), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(1, 2), -100), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(2, 2), -100), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(2, 9), -18), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), -2), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(1, 2), -100), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 2), -100), new Position(1, 1)); + assert.deepStrictEqual(m.modifyPosition(new Position(2, 9), -18), new Position(1, 1)); }); test('normalizeIndentation 1', () => { @@ -870,27 +870,27 @@ suite('Editor Model - TextModel', () => { } ); - assert.equal(model.normalizeIndentation('\t'), '\t'); - assert.equal(model.normalizeIndentation(' '), '\t'); - assert.equal(model.normalizeIndentation(' '), ' '); - assert.equal(model.normalizeIndentation(' '), ' '); - assert.equal(model.normalizeIndentation(' '), ' '); - assert.equal(model.normalizeIndentation(''), ''); - assert.equal(model.normalizeIndentation(' \t '), '\t\t'); - assert.equal(model.normalizeIndentation(' \t '), '\t '); - assert.equal(model.normalizeIndentation(' \t '), '\t '); - assert.equal(model.normalizeIndentation(' \t'), '\t '); + assert.strictEqual(model.normalizeIndentation('\t'), '\t'); + assert.strictEqual(model.normalizeIndentation(' '), '\t'); + assert.strictEqual(model.normalizeIndentation(' '), ' '); + assert.strictEqual(model.normalizeIndentation(' '), ' '); + assert.strictEqual(model.normalizeIndentation(' '), ' '); + assert.strictEqual(model.normalizeIndentation(''), ''); + assert.strictEqual(model.normalizeIndentation(' \t '), '\t\t'); + assert.strictEqual(model.normalizeIndentation(' \t '), '\t '); + assert.strictEqual(model.normalizeIndentation(' \t '), '\t '); + assert.strictEqual(model.normalizeIndentation(' \t'), '\t '); - assert.equal(model.normalizeIndentation('\ta'), '\ta'); - assert.equal(model.normalizeIndentation(' a'), '\ta'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation('a'), 'a'); - assert.equal(model.normalizeIndentation(' \t a'), '\t\ta'); - assert.equal(model.normalizeIndentation(' \t a'), '\t a'); - assert.equal(model.normalizeIndentation(' \t a'), '\t a'); - assert.equal(model.normalizeIndentation(' \ta'), '\t a'); + assert.strictEqual(model.normalizeIndentation('\ta'), '\ta'); + assert.strictEqual(model.normalizeIndentation(' a'), '\ta'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation('a'), 'a'); + assert.strictEqual(model.normalizeIndentation(' \t a'), '\t\ta'); + assert.strictEqual(model.normalizeIndentation(' \t a'), '\t a'); + assert.strictEqual(model.normalizeIndentation(' \t a'), '\t a'); + assert.strictEqual(model.normalizeIndentation(' \ta'), '\t a'); model.dispose(); }); @@ -898,16 +898,16 @@ suite('Editor Model - TextModel', () => { test('normalizeIndentation 2', () => { let model = createTextModel(''); - assert.equal(model.normalizeIndentation('\ta'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation(' a'), ' a'); - assert.equal(model.normalizeIndentation('a'), 'a'); - assert.equal(model.normalizeIndentation(' \t a'), ' a'); - assert.equal(model.normalizeIndentation(' \t a'), ' a'); - assert.equal(model.normalizeIndentation(' \t a'), ' a'); - assert.equal(model.normalizeIndentation(' \ta'), ' a'); + assert.strictEqual(model.normalizeIndentation('\ta'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' a'), ' a'); + assert.strictEqual(model.normalizeIndentation('a'), 'a'); + assert.strictEqual(model.normalizeIndentation(' \t a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' \t a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' \t a'), ' a'); + assert.strictEqual(model.normalizeIndentation(' \ta'), ' a'); model.dispose(); }); @@ -928,18 +928,18 @@ suite('Editor Model - TextModel', () => { '' ].join('\n')); - assert.equal(model.getLineFirstNonWhitespaceColumn(1), 1, '1'); - assert.equal(model.getLineFirstNonWhitespaceColumn(2), 2, '2'); - assert.equal(model.getLineFirstNonWhitespaceColumn(3), 2, '3'); - assert.equal(model.getLineFirstNonWhitespaceColumn(4), 3, '4'); - assert.equal(model.getLineFirstNonWhitespaceColumn(5), 3, '5'); - assert.equal(model.getLineFirstNonWhitespaceColumn(6), 0, '6'); - assert.equal(model.getLineFirstNonWhitespaceColumn(7), 0, '7'); - assert.equal(model.getLineFirstNonWhitespaceColumn(8), 0, '8'); - assert.equal(model.getLineFirstNonWhitespaceColumn(9), 0, '9'); - assert.equal(model.getLineFirstNonWhitespaceColumn(10), 4, '10'); - assert.equal(model.getLineFirstNonWhitespaceColumn(11), 0, '11'); - assert.equal(model.getLineFirstNonWhitespaceColumn(12), 0, '12'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(1), 1, '1'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(2), 2, '2'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(3), 2, '3'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(4), 3, '4'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(5), 3, '5'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(6), 0, '6'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(7), 0, '7'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(8), 0, '8'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(9), 0, '9'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(10), 4, '10'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(11), 0, '11'); + assert.strictEqual(model.getLineFirstNonWhitespaceColumn(12), 0, '12'); }); test('getLineLastNonWhitespaceColumn', () => { @@ -958,24 +958,24 @@ suite('Editor Model - TextModel', () => { '' ].join('\n')); - assert.equal(model.getLineLastNonWhitespaceColumn(1), 4, '1'); - assert.equal(model.getLineLastNonWhitespaceColumn(2), 4, '2'); - assert.equal(model.getLineLastNonWhitespaceColumn(3), 4, '3'); - assert.equal(model.getLineLastNonWhitespaceColumn(4), 4, '4'); - assert.equal(model.getLineLastNonWhitespaceColumn(5), 4, '5'); - assert.equal(model.getLineLastNonWhitespaceColumn(6), 0, '6'); - assert.equal(model.getLineLastNonWhitespaceColumn(7), 0, '7'); - assert.equal(model.getLineLastNonWhitespaceColumn(8), 0, '8'); - assert.equal(model.getLineLastNonWhitespaceColumn(9), 0, '9'); - assert.equal(model.getLineLastNonWhitespaceColumn(10), 4, '10'); - assert.equal(model.getLineLastNonWhitespaceColumn(11), 0, '11'); - assert.equal(model.getLineLastNonWhitespaceColumn(12), 0, '12'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(1), 4, '1'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(2), 4, '2'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(3), 4, '3'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(4), 4, '4'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(5), 4, '5'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(6), 0, '6'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(7), 0, '7'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(8), 0, '8'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(9), 0, '9'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(10), 4, '10'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(11), 0, '11'); + assert.strictEqual(model.getLineLastNonWhitespaceColumn(12), 0, '12'); }); test('#50471. getValueInRange with invalid range', () => { let m = createTextModel('My First Line\r\nMy Second Line\r\nMy Third Line'); - assert.equal(m.getValueInRange(new Range(1, NaN, 1, 3)), 'My'); - assert.equal(m.getValueInRange(new Range(NaN, NaN, NaN, NaN)), ''); + assert.strictEqual(m.getValueInRange(new Range(1, NaN, 1, 3)), 'My'); + assert.strictEqual(m.getValueInRange(new Range(NaN, NaN, NaN, NaN)), ''); }); }); @@ -983,26 +983,26 @@ suite('TextModel.mightContainRTL', () => { test('nope', () => { let model = createTextModel('hello world!'); - assert.equal(model.mightContainRTL(), false); + assert.strictEqual(model.mightContainRTL(), false); }); test('yes', () => { let model = createTextModel('Hello,\nזוהי עובדה מבוססת שדעתו'); - assert.equal(model.mightContainRTL(), true); + assert.strictEqual(model.mightContainRTL(), true); }); test('setValue resets 1', () => { let model = createTextModel('hello world!'); - assert.equal(model.mightContainRTL(), false); + assert.strictEqual(model.mightContainRTL(), false); model.setValue('Hello,\nזוהי עובדה מבוססת שדעתו'); - assert.equal(model.mightContainRTL(), true); + assert.strictEqual(model.mightContainRTL(), true); }); test('setValue resets 2', () => { let model = createTextModel('Hello,\nهناك حقيقة مثبتة منذ زمن طويل'); - assert.equal(model.mightContainRTL(), true); + assert.strictEqual(model.mightContainRTL(), true); model.setValue('hello world!'); - assert.equal(model.mightContainRTL(), false); + assert.strictEqual(model.mightContainRTL(), false); }); }); @@ -1012,24 +1012,24 @@ suite('TextModel.createSnapshot', () => { test('empty file', () => { let model = createTextModel(''); let snapshot = model.createSnapshot(); - assert.equal(snapshot.read(), null); + assert.strictEqual(snapshot.read(), null); model.dispose(); }); test('file with BOM', () => { let model = createTextModel(UTF8_BOM_CHARACTER + 'Hello'); - assert.equal(model.getLineContent(1), 'Hello'); + assert.strictEqual(model.getLineContent(1), 'Hello'); let snapshot = model.createSnapshot(true); - assert.equal(snapshot.read(), UTF8_BOM_CHARACTER + 'Hello'); - assert.equal(snapshot.read(), null); + assert.strictEqual(snapshot.read(), UTF8_BOM_CHARACTER + 'Hello'); + assert.strictEqual(snapshot.read(), null); model.dispose(); }); test('regular file', () => { let model = createTextModel('My First Line\n\t\tMy Second Line\n Third Line\n\n1'); let snapshot = model.createSnapshot(); - assert.equal(snapshot.read(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1'); - assert.equal(snapshot.read(), null); + assert.strictEqual(snapshot.read(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1'); + assert.strictEqual(snapshot.read(), null); model.dispose(); }); @@ -1054,10 +1054,10 @@ suite('TextModel.createSnapshot', () => { // all good } else { actual += tmp2; - assert.equal(snapshot.read(), null); + assert.strictEqual(snapshot.read(), null); } - assert.equal(actual, text); + assert.strictEqual(actual, text); model.dispose(); }); diff --git a/src/vs/editor/test/common/model/textModelSearch.test.ts b/src/vs/editor/test/common/model/textModelSearch.test.ts index 715cd3032b5..5586647468d 100644 --- a/src/vs/editor/test/common/model/textModelSearch.test.ts +++ b/src/vs/editor/test/common/model/textModelSearch.test.ts @@ -19,31 +19,31 @@ suite('TextModelSearch', () => { const usualWordSeparators = getMapForWordSeparators(USUAL_WORD_SEPARATORS); function assertFindMatch(actual: FindMatch | null, expectedRange: Range, expectedMatches: string[] | null = null): void { - assert.deepEqual(actual, new FindMatch(expectedRange, expectedMatches)); + assert.deepStrictEqual(actual, new FindMatch(expectedRange, expectedMatches)); } function _assertFindMatches(model: TextModel, searchParams: SearchParams, expectedMatches: FindMatch[]): void { let actual = TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), false, 1000); - assert.deepEqual(actual, expectedMatches, 'findMatches OK'); + assert.deepStrictEqual(actual, expectedMatches, 'findMatches OK'); // test `findNextMatch` let startPos = new Position(1, 1); let match = TextModelSearch.findNextMatch(model, searchParams, startPos, false); - assert.deepEqual(match, expectedMatches[0], `findNextMatch ${startPos}`); + assert.deepStrictEqual(match, expectedMatches[0], `findNextMatch ${startPos}`); for (const expectedMatch of expectedMatches) { startPos = expectedMatch.range.getStartPosition(); match = TextModelSearch.findNextMatch(model, searchParams, startPos, false); - assert.deepEqual(match, expectedMatch, `findNextMatch ${startPos}`); + assert.deepStrictEqual(match, expectedMatch, `findNextMatch ${startPos}`); } // test `findPrevMatch` startPos = new Position(model.getLineCount(), model.getLineMaxColumn(model.getLineCount())); match = TextModelSearch.findPreviousMatch(model, searchParams, startPos, false); - assert.deepEqual(match, expectedMatches[expectedMatches.length - 1], `findPrevMatch ${startPos}`); + assert.deepStrictEqual(match, expectedMatches[expectedMatches.length - 1], `findPrevMatch ${startPos}`); for (const expectedMatch of expectedMatches) { startPos = expectedMatch.range.getEndPosition(); match = TextModelSearch.findPreviousMatch(model, searchParams, startPos, false); - assert.deepEqual(match, expectedMatch, `findPrevMatch ${startPos}`); + assert.deepStrictEqual(match, expectedMatch, `findPrevMatch ${startPos}`); } } @@ -486,7 +486,7 @@ suite('TextModelSearch', () => { let searchParams = new SearchParams('(l(in)e)', true, false, null); let actual = TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), true, 100); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ new FindMatch(new Range(1, 5, 1, 9), ['line', 'line', 'in']), new FindMatch(new Range(1, 10, 1, 14), ['line', 'line', 'in']), new FindMatch(new Range(2, 5, 2, 9), ['line', 'line', 'in']), @@ -501,7 +501,7 @@ suite('TextModelSearch', () => { let searchParams = new SearchParams('(l(in)e)\\n', true, false, null); let actual = TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), true, 100); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ new FindMatch(new Range(1, 10, 2, 1), ['line\n', 'line', 'in']), new FindMatch(new Range(2, 5, 3, 1), ['line\n', 'line', 'in']), ]); @@ -556,7 +556,7 @@ suite('TextModelSearch', () => { test('\\n matches \\r\\n', () => { let model = createTextModel('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni'); - assert.equal(model.getEOL(), '\r\n'); + assert.strictEqual(model.getEOL(), '\r\n'); let searchParams = new SearchParams('h\\n', true, false, null); let actual = TextModelSearch.findNextMatch(model, searchParams, new Position(1, 1), true); @@ -579,12 +579,12 @@ suite('TextModelSearch', () => { test('\\r can never be found', () => { let model = createTextModel('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni'); - assert.equal(model.getEOL(), '\r\n'); + assert.strictEqual(model.getEOL(), '\r\n'); let searchParams = new SearchParams('\\r\\n', true, false, null); let actual = TextModelSearch.findNextMatch(model, searchParams, new Position(1, 1), true); - assert.equal(actual, null); - assert.deepEqual(TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), true, 1000), []); + assert.strictEqual(actual, null); + assert.deepStrictEqual(TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), true, 1000), []); model.dispose(); }); @@ -596,8 +596,8 @@ suite('TextModelSearch', () => { if (expected === null) { assert.ok(actual === null); } else { - assert.deepEqual(actual!.regex, expected.regex); - assert.deepEqual(actual!.simpleSearch, expected.simpleSearch); + assert.deepStrictEqual(actual!.regex, expected.regex); + assert.deepStrictEqual(actual!.simpleSearch, expected.simpleSearch); if (wordSeparators) { assert.ok(actual!.wordSeparators !== null); } else { @@ -769,7 +769,7 @@ suite('TextModelSearch', () => { let searchParams = new SearchParams('\\d*', true, false, null); let actual = TextModelSearch.findMatches(model, searchParams, model.getFullModelRange(), true, 100); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ new FindMatch(new Range(1, 1, 1, 3), ['10']), new FindMatch(new Range(1, 3, 1, 3), ['']), new FindMatch(new Range(1, 4, 1, 7), ['243']), diff --git a/src/vs/editor/test/common/model/textModelWithTokens.test.ts b/src/vs/editor/test/common/model/textModelWithTokens.test.ts index 22f67dd0801..e4560fd8233 100644 --- a/src/vs/editor/test/common/model/textModelWithTokens.test.ts +++ b/src/vs/editor/test/common/model/textModelWithTokens.test.ts @@ -100,7 +100,7 @@ suite('TextModelWithTokens', () => { column: column }); - assert.deepEqual(toRelaxedFoundBracket(actual), toRelaxedFoundBracket(currentExpectedBracket), 'findPrevBracket of ' + lineNumber + ', ' + column); + assert.deepStrictEqual(toRelaxedFoundBracket(actual), toRelaxedFoundBracket(currentExpectedBracket), 'findPrevBracket of ' + lineNumber + ', ' + column); } } } @@ -126,7 +126,7 @@ suite('TextModelWithTokens', () => { column: column }); - assert.deepEqual(toRelaxedFoundBracket(actual), toRelaxedFoundBracket(currentExpectedBracket), 'findNextBracket of ' + lineNumber + ', ' + column); + assert.deepStrictEqual(toRelaxedFoundBracket(actual), toRelaxedFoundBracket(currentExpectedBracket), 'findNextBracket of ' + lineNumber + ', ' + column); } } } @@ -148,12 +148,12 @@ suite('TextModelWithTokens', () => { function assertIsNotBracket(model: TextModel, lineNumber: number, column: number) { const match = model.matchBracket(new Position(lineNumber, column)); - assert.equal(match, null, 'is not matching brackets at ' + lineNumber + ', ' + column); + assert.strictEqual(match, null, 'is not matching brackets at ' + lineNumber + ', ' + column); } function assertIsBracket(model: TextModel, testPosition: Position, expected: [Range, Range]): void { const actual = model.matchBracket(testPosition); - assert.deepEqual(actual, expected, 'matches brackets at ' + testPosition); + assert.deepStrictEqual(actual, expected, 'matches brackets at ' + testPosition); } suite('TextModelWithTokens - bracket matching', () => { @@ -399,8 +399,8 @@ suite('TextModelWithTokens', () => { model.forceTokenization(2); model.forceTokenization(3); - assert.deepEqual(model.matchBracket(new Position(2, 23)), null); - assert.deepEqual(model.matchBracket(new Position(2, 20)), null); + assert.deepStrictEqual(model.matchBracket(new Position(2, 23)), null); + assert.deepStrictEqual(model.matchBracket(new Position(2, 20)), null); model.dispose(); registration1.dispose(); @@ -434,7 +434,7 @@ suite('TextModelWithTokens regression tests', () => { foreground: token.getForeground() }; }; - assert.deepEqual(actual, expected.map(decode)); + assert.deepStrictEqual(actual, expected.map(decode)); } let _tokenId = 10; @@ -512,7 +512,7 @@ suite('TextModelWithTokens regression tests', () => { ].join('\n'), undefined, languageIdentifier); let actual = model.matchBracket(new Position(4, 1)); - assert.deepEqual(actual, [new Range(4, 1, 4, 7), new Range(9, 1, 9, 11)]); + assert.deepStrictEqual(actual, [new Range(4, 1, 4, 7), new Range(9, 1, 9, 11)]); model.dispose(); registration.dispose(); @@ -537,7 +537,7 @@ suite('TextModelWithTokens regression tests', () => { ].join('\n'), undefined, languageIdentifier); let actual = model.matchBracket(new Position(3, 9)); - assert.deepEqual(actual, [new Range(3, 6, 3, 17), new Range(2, 6, 2, 14)]); + assert.deepStrictEqual(actual, [new Range(3, 6, 3, 17), new Range(2, 6, 2, 14)]); model.dispose(); registration.dispose(); @@ -565,7 +565,7 @@ suite('TextModelWithTokens regression tests', () => { let model = createTextModel('A model with one line', undefined, outerMode); model.forceTokenization(1); - assert.equal(model.getLanguageIdAtPosition(1, 1), innerMode.id); + assert.strictEqual(model.getLanguageIdAtPosition(1, 1), innerMode.id); model.dispose(); registration.dispose(); @@ -586,7 +586,7 @@ suite('TextModel.getLineIndentGuide', () => { actual[line - 1] = [actualIndents[line - 1], activeIndentGuide.startLineNumber, activeIndentGuide.endLineNumber, activeIndentGuide.indent, model.getLineContent(line)]; } - assert.deepEqual(actual, lines); + assert.deepStrictEqual(actual, lines); model.dispose(); } @@ -764,7 +764,7 @@ suite('TextModel.getLineIndentGuide', () => { ].join('\n')); const actual = model.getActiveIndentGuide(2, 4, 9); - assert.deepEqual(actual, { startLineNumber: 2, endLineNumber: 9, indent: 1 }); + assert.deepStrictEqual(actual, { startLineNumber: 2, endLineNumber: 9, indent: 1 }); model.dispose(); }); diff --git a/src/vs/editor/test/common/model/tokensStore.test.ts b/src/vs/editor/test/common/model/tokensStore.test.ts index ee8b438b43a..e883d551ea8 100644 --- a/src/vs/editor/test/common/model/tokensStore.test.ts +++ b/src/vs/editor/test/common/model/tokensStore.test.ts @@ -104,7 +104,7 @@ suite('TokensStore', () => { model.applyEdits(edits); const actualState = extractState(model); - assert.deepEqual(actualState, rawFinalState); + assert.deepStrictEqual(actualState, rawFinalState); model.dispose(); } @@ -191,7 +191,7 @@ suite('TokensStore', () => { decodedTokens.push(lineTokens.getEndOffset(i), lineTokens.getMetadata(i)); } - assert.deepEqual(decodedTokens, [ + assert.deepStrictEqual(decodedTokens, [ 20, 16793600, 24, 17022976, 25, 16793600, @@ -252,7 +252,7 @@ suite('TokensStore', () => { ]); const lineTokens = store.addSemanticTokens(10, new LineTokens(new Uint32Array([12, 1]), `enum Enum1 {`)); - assert.equal(lineTokens.getCount(), 3); + assert.strictEqual(lineTokens.getCount(), 3); }); test('partial tokens 2', () => { @@ -293,7 +293,7 @@ suite('TokensStore', () => { ]); const lineTokens = store.addSemanticTokens(20, new LineTokens(new Uint32Array([12, 1]), `enum Enum1 {`)); - assert.equal(lineTokens.getCount(), 3); + assert.strictEqual(lineTokens.getCount(), 3); }); test('partial tokens 3', () => { @@ -320,7 +320,7 @@ suite('TokensStore', () => { ]); const lineTokens = store.addSemanticTokens(5, new LineTokens(new Uint32Array([12, 1]), `enum Enum1 {`)); - assert.equal(lineTokens.getCount(), 3); + assert.strictEqual(lineTokens.getCount(), 3); }); test('issue #94133: Semantic colors stick around when using (only) range provider', () => { @@ -337,7 +337,7 @@ suite('TokensStore', () => { store.setPartial(new Range(1, 1, 1, 20), []); const lineTokens = store.addSemanticTokens(1, new LineTokens(new Uint32Array([12, 1]), `enum Enum1 {`)); - assert.equal(lineTokens.getCount(), 1); + assert.strictEqual(lineTokens.getCount(), 1); }); test('bug', () => { @@ -385,7 +385,7 @@ suite('TokensStore', () => { ); const lineTokens = store.addSemanticTokens(36451, new LineTokens(new Uint32Array([60, 1]), ` if (flags & ModifierFlags.Ambient) {`)); - assert.equal(lineTokens.getCount(), 7); + assert.strictEqual(lineTokens.getCount(), 7); }); @@ -424,7 +424,7 @@ suite('TokensStore', () => { ]), `const hello = 123;`)); const actual = toArr(lineTokens); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ 5, createTMMetadata(5, FontStyle.Bold, 53), 6, createTMMetadata(1, FontStyle.None, 53), 11, createTMMetadata(1, FontStyle.None, 53), diff --git a/src/vs/editor/test/common/modes/languageConfiguration.test.ts b/src/vs/editor/test/common/modes/languageConfiguration.test.ts index e898568a727..3acba6ddf3e 100644 --- a/src/vs/editor/test/common/modes/languageConfiguration.test.ts +++ b/src/vs/editor/test/common/modes/languageConfiguration.test.ts @@ -11,81 +11,81 @@ suite('StandardAutoClosingPairConditional', () => { test('Missing notIn', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}' }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('Empty notIn', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: [] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('Invalid notIn', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['bla'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('notIn in strings', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['string'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), false); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), false); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('notIn in comments', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['comment'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), false); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), false); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('notIn in regex', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['regex'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), false); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), false); }); test('notIn in strings nor comments', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['string', 'comment'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), false); - assert.equal(v.isOK(StandardTokenType.String), false); - assert.equal(v.isOK(StandardTokenType.RegEx), true); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), false); + assert.strictEqual(v.isOK(StandardTokenType.String), false); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), true); }); test('notIn in strings nor regex', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['string', 'regex'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), true); - assert.equal(v.isOK(StandardTokenType.String), false); - assert.equal(v.isOK(StandardTokenType.RegEx), false); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), true); + assert.strictEqual(v.isOK(StandardTokenType.String), false); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), false); }); test('notIn in comments nor regex', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['comment', 'regex'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), false); - assert.equal(v.isOK(StandardTokenType.String), true); - assert.equal(v.isOK(StandardTokenType.RegEx), false); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), false); + assert.strictEqual(v.isOK(StandardTokenType.String), true); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), false); }); test('notIn in strings, comments nor regex', () => { let v = new StandardAutoClosingPairConditional({ open: '{', close: '}', notIn: ['string', 'comment', 'regex'] }); - assert.equal(v.isOK(StandardTokenType.Other), true); - assert.equal(v.isOK(StandardTokenType.Comment), false); - assert.equal(v.isOK(StandardTokenType.String), false); - assert.equal(v.isOK(StandardTokenType.RegEx), false); + assert.strictEqual(v.isOK(StandardTokenType.Other), true); + assert.strictEqual(v.isOK(StandardTokenType.Comment), false); + assert.strictEqual(v.isOK(StandardTokenType.String), false); + assert.strictEqual(v.isOK(StandardTokenType.RegEx), false); }); }); diff --git a/src/vs/editor/test/common/modes/languageSelector.test.ts b/src/vs/editor/test/common/modes/languageSelector.test.ts index 0886c65bbee..dc06141f65c 100644 --- a/src/vs/editor/test/common/modes/languageSelector.test.ts +++ b/src/vs/editor/test/common/modes/languageSelector.test.ts @@ -15,18 +15,18 @@ suite('LanguageSelector', function () { }; test('score, invalid selector', function () { - assert.equal(score({}, model.uri, model.language, true), 0); - assert.equal(score(undefined!, model.uri, model.language, true), 0); - assert.equal(score(null!, model.uri, model.language, true), 0); - assert.equal(score('', model.uri, model.language, true), 0); + assert.strictEqual(score({}, model.uri, model.language, true), 0); + assert.strictEqual(score(undefined!, model.uri, model.language, true), 0); + assert.strictEqual(score(null!, model.uri, model.language, true), 0); + assert.strictEqual(score('', model.uri, model.language, true), 0); }); test('score, any language', function () { - assert.equal(score({ language: '*' }, model.uri, model.language, true), 5); - assert.equal(score('*', model.uri, model.language, true), 5); + assert.strictEqual(score({ language: '*' }, model.uri, model.language, true), 5); + assert.strictEqual(score('*', model.uri, model.language, true), 5); - assert.equal(score('*', URI.parse('foo:bar'), model.language, true), 5); - assert.equal(score('farboo', URI.parse('foo:bar'), model.language, true), 10); + assert.strictEqual(score('*', URI.parse('foo:bar'), model.language, true), 5); + assert.strictEqual(score('farboo', URI.parse('foo:bar'), model.language, true), 10); }); test('score, default schemes', function () { @@ -34,50 +34,50 @@ suite('LanguageSelector', function () { const uri = URI.parse('git:foo/file.txt'); const language = 'farboo'; - assert.equal(score('*', uri, language, true), 5); - assert.equal(score('farboo', uri, language, true), 10); - assert.equal(score({ language: 'farboo', scheme: '' }, uri, language, true), 10); - assert.equal(score({ language: 'farboo', scheme: 'git' }, uri, language, true), 10); - assert.equal(score({ language: 'farboo', scheme: '*' }, uri, language, true), 10); - assert.equal(score({ language: 'farboo' }, uri, language, true), 10); - assert.equal(score({ language: '*' }, uri, language, true), 5); + assert.strictEqual(score('*', uri, language, true), 5); + assert.strictEqual(score('farboo', uri, language, true), 10); + assert.strictEqual(score({ language: 'farboo', scheme: '' }, uri, language, true), 10); + assert.strictEqual(score({ language: 'farboo', scheme: 'git' }, uri, language, true), 10); + assert.strictEqual(score({ language: 'farboo', scheme: '*' }, uri, language, true), 10); + assert.strictEqual(score({ language: 'farboo' }, uri, language, true), 10); + assert.strictEqual(score({ language: '*' }, uri, language, true), 5); - assert.equal(score({ scheme: '*' }, uri, language, true), 5); - assert.equal(score({ scheme: 'git' }, uri, language, true), 10); + assert.strictEqual(score({ scheme: '*' }, uri, language, true), 5); + assert.strictEqual(score({ scheme: 'git' }, uri, language, true), 10); }); test('score, filter', function () { - assert.equal(score('farboo', model.uri, model.language, true), 10); - assert.equal(score({ language: 'farboo' }, model.uri, model.language, true), 10); - assert.equal(score({ language: 'farboo', scheme: 'file' }, model.uri, model.language, true), 10); - assert.equal(score({ language: 'farboo', scheme: 'http' }, model.uri, model.language, true), 0); + assert.strictEqual(score('farboo', model.uri, model.language, true), 10); + assert.strictEqual(score({ language: 'farboo' }, model.uri, model.language, true), 10); + assert.strictEqual(score({ language: 'farboo', scheme: 'file' }, model.uri, model.language, true), 10); + assert.strictEqual(score({ language: 'farboo', scheme: 'http' }, model.uri, model.language, true), 0); - assert.equal(score({ pattern: '**/*.fb' }, model.uri, model.language, true), 10); - assert.equal(score({ pattern: '**/*.fb', scheme: 'file' }, model.uri, model.language, true), 10); - assert.equal(score({ pattern: '**/*.fb' }, URI.parse('foo:bar'), model.language, true), 0); - assert.equal(score({ pattern: '**/*.fb', scheme: 'foo' }, URI.parse('foo:bar'), model.language, true), 0); + assert.strictEqual(score({ pattern: '**/*.fb' }, model.uri, model.language, true), 10); + assert.strictEqual(score({ pattern: '**/*.fb', scheme: 'file' }, model.uri, model.language, true), 10); + assert.strictEqual(score({ pattern: '**/*.fb' }, URI.parse('foo:bar'), model.language, true), 0); + assert.strictEqual(score({ pattern: '**/*.fb', scheme: 'foo' }, URI.parse('foo:bar'), model.language, true), 0); let doc = { uri: URI.parse('git:/my/file.js'), langId: 'javascript' }; - assert.equal(score('javascript', doc.uri, doc.langId, true), 10); // 0; - assert.equal(score({ language: 'javascript', scheme: 'git' }, doc.uri, doc.langId, true), 10); // 10; - assert.equal(score('*', doc.uri, doc.langId, true), 5); // 5 - assert.equal(score('fooLang', doc.uri, doc.langId, true), 0); // 0 - assert.equal(score(['fooLang', '*'], doc.uri, doc.langId, true), 5); // 5 + assert.strictEqual(score('javascript', doc.uri, doc.langId, true), 10); // 0; + assert.strictEqual(score({ language: 'javascript', scheme: 'git' }, doc.uri, doc.langId, true), 10); // 10; + assert.strictEqual(score('*', doc.uri, doc.langId, true), 5); // 5 + assert.strictEqual(score('fooLang', doc.uri, doc.langId, true), 0); // 0 + assert.strictEqual(score(['fooLang', '*'], doc.uri, doc.langId, true), 5); // 5 }); test('score, max(filters)', function () { let match = { language: 'farboo', scheme: 'file' }; let fail = { language: 'farboo', scheme: 'http' }; - assert.equal(score(match, model.uri, model.language, true), 10); - assert.equal(score(fail, model.uri, model.language, true), 0); - assert.equal(score([match, fail], model.uri, model.language, true), 10); - assert.equal(score([fail, fail], model.uri, model.language, true), 0); - assert.equal(score(['farboo', '*'], model.uri, model.language, true), 10); - assert.equal(score(['*', 'farboo'], model.uri, model.language, true), 10); + assert.strictEqual(score(match, model.uri, model.language, true), 10); + assert.strictEqual(score(fail, model.uri, model.language, true), 0); + assert.strictEqual(score([match, fail], model.uri, model.language, true), 10); + assert.strictEqual(score([fail, fail], model.uri, model.language, true), 0); + assert.strictEqual(score(['farboo', '*'], model.uri, model.language, true), 10); + assert.strictEqual(score(['*', 'farboo'], model.uri, model.language, true), 10); }); test('score hasAccessToAllModels', function () { @@ -85,14 +85,14 @@ suite('LanguageSelector', function () { uri: URI.parse('file:/my/file.js'), langId: 'javascript' }; - assert.equal(score('javascript', doc.uri, doc.langId, false), 0); - assert.equal(score({ language: 'javascript', scheme: 'file' }, doc.uri, doc.langId, false), 0); - assert.equal(score('*', doc.uri, doc.langId, false), 0); - assert.equal(score('fooLang', doc.uri, doc.langId, false), 0); - assert.equal(score(['fooLang', '*'], doc.uri, doc.langId, false), 0); + assert.strictEqual(score('javascript', doc.uri, doc.langId, false), 0); + assert.strictEqual(score({ language: 'javascript', scheme: 'file' }, doc.uri, doc.langId, false), 0); + assert.strictEqual(score('*', doc.uri, doc.langId, false), 0); + assert.strictEqual(score('fooLang', doc.uri, doc.langId, false), 0); + assert.strictEqual(score(['fooLang', '*'], doc.uri, doc.langId, false), 0); - assert.equal(score({ language: 'javascript', scheme: 'file', hasAccessToAllModels: true }, doc.uri, doc.langId, false), 10); - assert.equal(score(['fooLang', '*', { language: '*', hasAccessToAllModels: true }], doc.uri, doc.langId, false), 5); + assert.strictEqual(score({ language: 'javascript', scheme: 'file', hasAccessToAllModels: true }, doc.uri, doc.langId, false), 10); + assert.strictEqual(score(['fooLang', '*', { language: '*', hasAccessToAllModels: true }], doc.uri, doc.langId, false), 5); }); test('Document selector match - unexpected result value #60232', function () { @@ -102,7 +102,7 @@ suite('LanguageSelector', function () { pattern: '**/*.interface.json' }; let value = score(selector, URI.parse('file:///C:/Users/zlhe/Desktop/test.interface.json'), 'json', true); - assert.equal(value, 10); + assert.strictEqual(value, 10); }); test('Document selector match - platform paths #99938', function () { @@ -113,6 +113,6 @@ suite('LanguageSelector', function () { } }; let value = score(selector, URI.file('/home/user/Desktop/test.json'), 'json', true); - assert.equal(value, 10); + assert.strictEqual(value, 10); }); }); diff --git a/src/vs/editor/test/common/modes/linkComputer.test.ts b/src/vs/editor/test/common/modes/linkComputer.test.ts index 9cf9ca77c2f..5bb34c91121 100644 --- a/src/vs/editor/test/common/modes/linkComputer.test.ts +++ b/src/vs/editor/test/common/modes/linkComputer.test.ts @@ -49,7 +49,7 @@ function assertLink(text: string, extractedLink: string): void { } let r = myComputeLinks([text]); - assert.deepEqual(r, [{ + assert.deepStrictEqual(r, [{ range: { startLineNumber: 1, startColumn: startColumn, @@ -64,7 +64,7 @@ suite('Editor Modes - Link Computer', () => { test('Null model', () => { let r = computeLinks(null); - assert.deepEqual(r, []); + assert.deepStrictEqual(r, []); }); test('Parsing', () => { diff --git a/src/vs/editor/test/common/modes/supports/characterPair.test.ts b/src/vs/editor/test/common/modes/supports/characterPair.test.ts index e244d6b47f9..ce1c31ee92d 100644 --- a/src/vs/editor/test/common/modes/supports/characterPair.test.ts +++ b/src/vs/editor/test/common/modes/supports/characterPair.test.ts @@ -13,44 +13,44 @@ suite('CharacterPairSupport', () => { test('only autoClosingPairs', () => { let characaterPairSupport = new CharacterPairSupport({ autoClosingPairs: [{ open: 'a', close: 'b' }] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), [{ open: 'a', close: 'b', _standardTokenMask: 0 }]); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), [{ open: 'a', close: 'b', _standardTokenMask: 0 }]); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), [new StandardAutoClosingPairConditional({ open: 'a', close: 'b' })]); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), [new StandardAutoClosingPairConditional({ open: 'a', close: 'b' })]); }); test('only empty autoClosingPairs', () => { let characaterPairSupport = new CharacterPairSupport({ autoClosingPairs: [] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), []); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), []); }); test('only brackets', () => { let characaterPairSupport = new CharacterPairSupport({ brackets: [['a', 'b']] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), [{ open: 'a', close: 'b', _standardTokenMask: 0 }]); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), [{ open: 'a', close: 'b', _standardTokenMask: 0 }]); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), [new StandardAutoClosingPairConditional({ open: 'a', close: 'b' })]); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), [new StandardAutoClosingPairConditional({ open: 'a', close: 'b' })]); }); test('only empty brackets', () => { let characaterPairSupport = new CharacterPairSupport({ brackets: [] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), []); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), []); }); test('only surroundingPairs', () => { let characaterPairSupport = new CharacterPairSupport({ surroundingPairs: [{ open: 'a', close: 'b' }] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), []); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), [{ open: 'a', close: 'b' }]); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), [{ open: 'a', close: 'b' }]); }); test('only empty surroundingPairs', () => { let characaterPairSupport = new CharacterPairSupport({ surroundingPairs: [] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), []); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), []); }); test('brackets is ignored when having autoClosingPairs', () => { let characaterPairSupport = new CharacterPairSupport({ autoClosingPairs: [], brackets: [['a', 'b']] }); - assert.deepEqual(characaterPairSupport.getAutoClosingPairs(), []); - assert.deepEqual(characaterPairSupport.getSurroundingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getAutoClosingPairs(), []); + assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), []); }); function findAutoClosingPair(characterPairSupport: CharacterPairSupport, character: string): StandardAutoClosingPairConditional | undefined { @@ -67,64 +67,64 @@ suite('CharacterPairSupport', () => { test('shouldAutoClosePair in empty line', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] }); - assert.equal(testShouldAutoClose(sup, [], 'a', 1), false); - assert.equal(testShouldAutoClose(sup, [], '{', 1), true); + assert.strictEqual(testShouldAutoClose(sup, [], 'a', 1), false); + assert.strictEqual(testShouldAutoClose(sup, [], '{', 1), true); }); test('shouldAutoClosePair in not interesting line 1', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] }); - assert.equal(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], '{', 3), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], 'a', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], '{', 3), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], 'a', 3), false); }); test('shouldAutoClosePair in not interesting line 2', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}' }] }); - assert.equal(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], '{', 3), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], 'a', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], '{', 3), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], 'a', 3), false); }); test('shouldAutoClosePair in interesting line 1', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] }); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 1), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 1), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 2), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 2), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 3), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 3), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 4), false); - assert.equal(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 1), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 1), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 2), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 2), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 4), false); }); test('shouldAutoClosePair in interesting line 2', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] }); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 1), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 1), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 2), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 2), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 3), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 3), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 4), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 4), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 5), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 5), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 6), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 6), false); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 7), true); - assert.equal(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 7), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 1), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 1), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 2), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 2), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 3), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 5), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 5), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 6), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 6), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 7), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 7), false); }); test('shouldAutoClosePair in interesting line 3', () => { let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] }); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 1), true); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 1), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 2), true); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 2), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 3), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 3), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 4), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 4), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 5), false); - assert.equal(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 5), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 1), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 1), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 2), true); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 2), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 3), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 4), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 5), false); + assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 5), false); }); }); diff --git a/src/vs/editor/test/common/modes/supports/electricCharacter.test.ts b/src/vs/editor/test/common/modes/supports/electricCharacter.test.ts index 22b818c6b67..ba609bdb459 100644 --- a/src/vs/editor/test/common/modes/supports/electricCharacter.test.ts +++ b/src/vs/editor/test/common/modes/supports/electricCharacter.test.ts @@ -18,12 +18,12 @@ suite('Editor Modes - Auto Indentation', () => { function testDoesNothing(electricCharacterSupport: BracketElectricCharacterSupport, line: TokenText[], character: string, offset: number): void { let actual = _testOnElectricCharacter(electricCharacterSupport, line, character, offset); - assert.deepEqual(actual, null); + assert.deepStrictEqual(actual, null); } function testMatchBracket(electricCharacterSupport: BracketElectricCharacterSupport, line: TokenText[], character: string, offset: number, matchOpenBracket: string): void { let actual = _testOnElectricCharacter(electricCharacterSupport, line, character, offset); - assert.deepEqual(actual, { matchOpenBracket: matchOpenBracket }); + assert.deepStrictEqual(actual, { matchOpenBracket: matchOpenBracket }); } test('getElectricCharacters uses all sources and dedups', () => { @@ -34,7 +34,7 @@ suite('Editor Modes - Auto Indentation', () => { ]) ); - assert.deepEqual(sup.getElectricCharacters(), ['}', ')']); + assert.deepStrictEqual(sup.getElectricCharacters(), ['}', ')']); }); test('matchOpenBracket', () => { diff --git a/src/vs/editor/test/common/modes/supports/onEnter.test.ts b/src/vs/editor/test/common/modes/supports/onEnter.test.ts index f799c66e76e..5e9794fc358 100644 --- a/src/vs/editor/test/common/modes/supports/onEnter.test.ts +++ b/src/vs/editor/test/common/modes/supports/onEnter.test.ts @@ -21,9 +21,9 @@ suite('OnEnter', () => { let testIndentAction = (beforeText: string, afterText: string, expected: IndentAction) => { let actual = support.onEnter(EditorAutoIndentStrategy.Advanced, '', beforeText, afterText); if (expected === IndentAction.None) { - assert.equal(actual, null); + assert.strictEqual(actual, null); } else { - assert.equal(actual!.indentAction, expected); + assert.strictEqual(actual!.indentAction, expected); } }; @@ -54,15 +54,15 @@ suite('OnEnter', () => { let testIndentAction = (oneLineAboveText: string, beforeText: string, afterText: string, expectedIndentAction: IndentAction | null, expectedAppendText: string | null, removeText: number = 0) => { let actual = support.onEnter(EditorAutoIndentStrategy.Advanced, oneLineAboveText, beforeText, afterText); if (expectedIndentAction === null) { - assert.equal(actual, null, 'isNull:' + beforeText); + assert.strictEqual(actual, null, 'isNull:' + beforeText); } else { - assert.equal(actual !== null, true, 'isNotNull:' + beforeText); - assert.equal(actual!.indentAction, expectedIndentAction, 'indentAction:' + beforeText); + assert.strictEqual(actual !== null, true, 'isNotNull:' + beforeText); + assert.strictEqual(actual!.indentAction, expectedIndentAction, 'indentAction:' + beforeText); if (expectedAppendText !== null) { - assert.equal(actual!.appendText, expectedAppendText, 'appendText:' + beforeText); + assert.strictEqual(actual!.appendText, expectedAppendText, 'appendText:' + beforeText); } if (removeText !== 0) { - assert.equal(actual!.removeText, removeText, 'removeText:' + beforeText); + assert.strictEqual(actual!.removeText, removeText, 'removeText:' + beforeText); } } }; diff --git a/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts b/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts index 40ae7e628b0..cf6bb99970b 100644 --- a/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts +++ b/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts @@ -19,61 +19,61 @@ suite('richEditBrackets', () => { test('findPrevBracketInToken one char 1', () => { let result = findPrevBracketInRange(/(\{)|(\})/i, '{', 0, 1); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 2); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 2); }); test('findPrevBracketInToken one char 2', () => { let result = findPrevBracketInRange(/(\{)|(\})/i, '{{', 0, 1); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 2); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 2); }); test('findPrevBracketInToken one char 3', () => { let result = findPrevBracketInRange(/(\{)|(\})/i, '{hello world!', 0, 13); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 2); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 2); }); test('findPrevBracketInToken more chars 1', () => { let result = findPrevBracketInRange(/(olleh)/i, 'hello world!', 0, 12); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 6); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 6); }); test('findPrevBracketInToken more chars 2', () => { let result = findPrevBracketInRange(/(olleh)/i, 'hello world!', 0, 5); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 6); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 6); }); test('findPrevBracketInToken more chars 3', () => { let result = findPrevBracketInRange(/(olleh)/i, ' hello world!', 0, 6); - assert.equal(result!.startColumn, 2); - assert.equal(result!.endColumn, 7); + assert.strictEqual(result!.startColumn, 2); + assert.strictEqual(result!.endColumn, 7); }); test('findNextBracketInToken one char', () => { let result = findNextBracketInRange(/(\{)|(\})/i, '{', 0, 1); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 2); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 2); }); test('findNextBracketInToken more chars', () => { let result = findNextBracketInRange(/(world)/i, 'hello world!', 0, 12); - assert.equal(result!.startColumn, 7); - assert.equal(result!.endColumn, 12); + assert.strictEqual(result!.startColumn, 7); + assert.strictEqual(result!.endColumn, 12); }); test('findNextBracketInToken with emoty result', () => { let result = findNextBracketInRange(/(\{)|(\})/i, '', 0, 0); - assert.equal(result, null); + assert.strictEqual(result, null); }); test('issue #3894: [Handlebars] Curly braces edit issues', () => { let result = findPrevBracketInRange(/(\-\-!<)|(>\-\-)|(\{\{)|(\}\})/i, '{{asd}}', 0, 2); - assert.equal(result!.startColumn, 1); - assert.equal(result!.endColumn, 3); + assert.strictEqual(result!.startColumn, 1); + assert.strictEqual(result!.endColumn, 3); }); }); diff --git a/src/vs/editor/test/common/modes/supports/tokenization.test.ts b/src/vs/editor/test/common/modes/supports/tokenization.test.ts index 9f2bd1b99b3..a8f90408560 100644 --- a/src/vs/editor/test/common/modes/supports/tokenization.test.ts +++ b/src/vs/editor/test/common/modes/supports/tokenization.test.ts @@ -24,7 +24,7 @@ suite('Token theme matching', () => { let actual = theme._match('punctuation.definition.string.begin.html'); - assert.deepEqual(actual, new ThemeTrieElementRule(FontStyle.None, _D, _B)); + assert.deepStrictEqual(actual, new ThemeTrieElementRule(FontStyle.None, _D, _B)); }); test('can match', () => { @@ -55,7 +55,7 @@ suite('Token theme matching', () => { function assertMatch(scopeName: string, expected: ThemeTrieElementRule): void { let actual = theme._match(scopeName); - assert.deepEqual(actual, expected, 'when matching <<' + scopeName + '>>'); + assert.deepStrictEqual(actual, expected, 'when matching <<' + scopeName + '>>'); } function assertSimpleMatch(scopeName: string, fontStyle: FontStyle, foreground: number, background: number): void { @@ -152,7 +152,7 @@ suite('Token theme parsing', () => { new ParsedTokenThemeRule('constant.numeric.dec', 10, FontStyle.None, '0000ff', null), ]; - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); }); @@ -162,7 +162,7 @@ suite('Token theme resolving', () => { let actual = ['bar', 'z', 'zu', 'a', 'ab', ''].sort(strcmp); let expected = ['', 'a', 'ab', 'bar', 'z', 'zu']; - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); test('always has defaults', () => { @@ -170,8 +170,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('000000'); const _B = colorMap.getId('ffffff'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); }); test('respects incoming defaults 1', () => { @@ -181,8 +181,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('000000'); const _B = colorMap.getId('ffffff'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); }); test('respects incoming defaults 2', () => { @@ -192,8 +192,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('000000'); const _B = colorMap.getId('ffffff'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); }); test('respects incoming defaults 3', () => { @@ -203,8 +203,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('000000'); const _B = colorMap.getId('ffffff'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _A, _B))); }); test('respects incoming defaults 4', () => { @@ -214,8 +214,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('ff0000'); const _B = colorMap.getId('ffffff'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); }); test('respects incoming defaults 5', () => { @@ -225,8 +225,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('000000'); const _B = colorMap.getId('ff0000'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B))); }); test('can merge incoming defaults', () => { @@ -238,8 +238,8 @@ suite('Token theme resolving', () => { let colorMap = new ColorMap(); const _A = colorMap.getId('00ff00'); const _B = colorMap.getId('ff0000'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); - assert.deepEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _A, _B))); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getThemeTrieElement(), new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _A, _B))); }); test('defaults are inherited', () => { @@ -251,7 +251,7 @@ suite('Token theme resolving', () => { const _A = colorMap.getId('F8F8F2'); const _B = colorMap.getId('272822'); const _C = colorMap.getId('ff0000'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), { 'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _C, _B)) }); @@ -268,7 +268,7 @@ suite('Token theme resolving', () => { const _A = colorMap.getId('F8F8F2'); const _B = colorMap.getId('272822'); const _C = colorMap.getId('ff0000'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), { 'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B)) }); @@ -286,7 +286,7 @@ suite('Token theme resolving', () => { const _B = colorMap.getId('272822'); const _C = colorMap.getId('ff0000'); const _D = colorMap.getId('00ff00'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), { 'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B), { 'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _D, _B)) @@ -314,7 +314,7 @@ suite('Token theme resolving', () => { const _E = colorMap.getId('300000'); const _F = colorMap.getId('ff0000'); const _G = colorMap.getId('00ff00'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), { 'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _F, _B), { 'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _G, _B)) @@ -341,6 +341,6 @@ suite('Token theme resolving', () => { colorMap.getId('FFFFFF'); colorMap.getId('0F0F0F'); colorMap.getId('F8F8F2'); - assert.deepEqual(actual.getColorMap(), colorMap.getColorMap()); + assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap()); }); }); diff --git a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts index 3e4c453e8cb..aaa8f060fd0 100644 --- a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts +++ b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts @@ -31,7 +31,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ]; let expectedStr = `
    ${toStr(expected)}
    `; - assert.equal(actual, expectedStr); + assert.strictEqual(actual, expectedStr); mode.dispose(); }); @@ -61,7 +61,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { let expectedStr2 = toStr(expected2); let expectedStr = `
    ${expectedStr1}
    ${expectedStr2}
    `; - assert.equal(actual, expectedStr); + assert.strictEqual(actual, expectedStr); mode.dispose(); }); @@ -104,7 +104,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ]); const colorMap = [null!, '#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff']; - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4, true), [ '
    ', @@ -117,7 +117,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 12, 4, true), [ '
    ', @@ -130,7 +130,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 11, 4, true), [ '
    ', @@ -142,7 +142,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 1, 11, 4, true), [ '
    ', @@ -154,7 +154,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 4, 11, 4, true), [ '
    ', @@ -165,7 +165,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 5, 11, 4, true), [ '
    ', @@ -175,7 +175,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 5, 10, 4, true), [ '
    ', @@ -184,7 +184,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 6, 9, 4, true), [ '
    ', @@ -237,7 +237,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ]); const colorMap = [null!, '#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff']; - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 21, 4, true), [ '
    ', @@ -251,7 +251,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4, true), [ '
    ', @@ -265,7 +265,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ].join('') ); - assert.equal( + assert.strictEqual( tokenizeLineToHTML(text, lineTokens, colorMap, 0, 3, 4, true), [ '
    ', diff --git a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts index 6a7656347ab..bcfafe9d097 100644 --- a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts +++ b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts @@ -43,13 +43,13 @@ suite('EditorSimpleWorker', () => { function assertPositionAt(offset: number, line: number, column: number) { let position = model.positionAt(offset); - assert.equal(position.lineNumber, line); - assert.equal(position.column, column); + assert.strictEqual(position.lineNumber, line); + assert.strictEqual(position.column, column); } function assertOffsetAt(lineNumber: number, column: number, offset: number) { let actual = model.offsetAt({ lineNumber, column }); - assert.equal(actual, offset); + assert.strictEqual(actual, offset); } test('ICommonModel#offsetAt', () => { @@ -83,16 +83,16 @@ suite('EditorSimpleWorker', () => { test('ICommonModel#validatePosition, issue #15882', function () { let model = worker.addModel(['{"id": "0001","type": "donut","name": "Cake","image":{"url": "images/0001.jpg","width": 200,"height": 200},"thumbnail":{"url": "images/thumbnails/0001.jpg","width": 32,"height": 32}}']); - assert.equal(model.offsetAt({ lineNumber: 1, column: 2 }), 1); + assert.strictEqual(model.offsetAt({ lineNumber: 1, column: 2 }), 1); }); test('MoreMinimal', () => { return worker.computeMoreMinimalEdits(model.uri.toString(), [{ text: 'This is line One', range: new Range(1, 1, 1, 17) }]).then(edits => { - assert.equal(edits.length, 1); + assert.strictEqual(edits.length, 1); const [first] = edits; - assert.equal(first.text, 'O'); - assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 14, endLineNumber: 1, endColumn: 15 }); + assert.strictEqual(first.text, 'O'); + assert.deepStrictEqual(first.range, { startLineNumber: 1, startColumn: 14, endLineNumber: 1, endColumn: 15 }); }); }); @@ -105,7 +105,7 @@ suite('EditorSimpleWorker', () => { ], '\n'); return worker.computeMoreMinimalEdits(model.uri.toString(), [{ text: '{\r\n\t"a":1\r\n}', range: new Range(1, 1, 3, 2) }]).then(edits => { - assert.equal(edits.length, 0); + assert.strictEqual(edits.length, 0); }); }); @@ -118,10 +118,10 @@ suite('EditorSimpleWorker', () => { ], '\n'); return worker.computeMoreMinimalEdits(model.uri.toString(), [{ text: '{\r\n\t"b":1\r\n}', range: new Range(1, 1, 3, 2) }]).then(edits => { - assert.equal(edits.length, 1); + assert.strictEqual(edits.length, 1); const [first] = edits; - assert.equal(first.text, 'b'); - assert.deepEqual(first.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 2, endColumn: 4 }); + assert.strictEqual(first.text, 'b'); + assert.deepStrictEqual(first.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 2, endColumn: 4 }); }); }); @@ -134,10 +134,10 @@ suite('EditorSimpleWorker', () => { ]); return worker.computeMoreMinimalEdits(model.uri.toString(), [{ text: '\n', range: new Range(3, 2, 4, 1000) }]).then(edits => { - assert.equal(edits.length, 1); + assert.strictEqual(edits.length, 1); const [first] = edits; - assert.equal(first.text, '\n'); - assert.deepEqual(first.range, { startLineNumber: 3, startColumn: 2, endLineNumber: 3, endColumn: 2 }); + assert.strictEqual(first.text, '\n'); + assert.deepStrictEqual(first.range, { startLineNumber: 3, startColumn: 2, endLineNumber: 3, endColumn: 2 }); }); }); @@ -151,7 +151,7 @@ suite('EditorSimpleWorker', () => { ]); const value = model.getValueInRange({ startLineNumber: 3, startColumn: 1, endLineNumber: 4, endColumn: 1 }); - assert.equal(value, '}'); + assert.strictEqual(value, '}'); }); @@ -166,9 +166,9 @@ suite('EditorSimpleWorker', () => { if (!result) { assert.ok(false); } - assert.equal(result.words.length, 1); - assert.equal(typeof result.duration, 'number'); - assert.equal(result.words[0], 'foobar'); + assert.strictEqual(result.words.length, 1); + assert.strictEqual(typeof result.duration, 'number'); + assert.strictEqual(result.words[0], 'foobar'); }); }); @@ -186,6 +186,6 @@ suite('EditorSimpleWorker', () => { let words: string[] = [...model.words(/[a-z]+/img)]; - assert.deepEqual(words, ['one', 'line', 'two', 'line', 'past', 'empty', 'single', 'and', 'now', 'we', 'are', 'done']); + assert.deepStrictEqual(words, ['one', 'line', 'two', 'line', 'past', 'empty', 'single', 'and', 'now', 'we', 'are', 'done']); }); }); diff --git a/src/vs/editor/test/common/services/languagesRegistry.test.ts b/src/vs/editor/test/common/services/languagesRegistry.test.ts index 09ef74cd000..d0eac05b517 100644 --- a/src/vs/editor/test/common/services/languagesRegistry.test.ts +++ b/src/vs/editor/test/common/services/languagesRegistry.test.ts @@ -19,7 +19,7 @@ suite('LanguagesRegistry', () => { mimetypes: ['outputModeMimeType'], }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), []); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), []); }); test('mode with alias does have a name', () => { @@ -32,8 +32,8 @@ suite('LanguagesRegistry', () => { mimetypes: ['bla'], }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['ModeName']); - assert.deepEqual(registry.getLanguageName('modeId'), 'ModeName'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['ModeName']); + assert.deepStrictEqual(registry.getLanguageName('modeId'), 'ModeName'); }); test('mode without alias gets a name', () => { @@ -45,8 +45,8 @@ suite('LanguagesRegistry', () => { mimetypes: ['bla'], }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['modeId']); - assert.deepEqual(registry.getLanguageName('modeId'), 'modeId'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['modeId']); + assert.deepStrictEqual(registry.getLanguageName('modeId'), 'modeId'); }); test('bug #4360: f# not shown in status bar', () => { @@ -66,8 +66,8 @@ suite('LanguagesRegistry', () => { mimetypes: ['bla'], }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['ModeName']); - assert.deepEqual(registry.getLanguageName('modeId'), 'ModeName'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['ModeName']); + assert.deepStrictEqual(registry.getLanguageName('modeId'), 'ModeName'); }); test('issue #5278: Extension cannot override language name anymore', () => { @@ -87,8 +87,8 @@ suite('LanguagesRegistry', () => { mimetypes: ['bla'], }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['BetterModeName']); - assert.deepEqual(registry.getLanguageName('modeId'), 'BetterModeName'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['BetterModeName']); + assert.deepStrictEqual(registry.getLanguageName('modeId'), 'BetterModeName'); }); test('mimetypes are generated if necessary', () => { @@ -98,7 +98,7 @@ suite('LanguagesRegistry', () => { id: 'modeId' }]); - assert.deepEqual(registry.getMimeForMode('modeId'), 'text/x-modeId'); + assert.deepStrictEqual(registry.getMimeForMode('modeId'), 'text/x-modeId'); }); test('first mimetype wins', () => { @@ -109,7 +109,7 @@ suite('LanguagesRegistry', () => { mimetypes: ['text/modeId', 'text/modeId2'] }]); - assert.deepEqual(registry.getMimeForMode('modeId'), 'text/modeId'); + assert.deepStrictEqual(registry.getMimeForMode('modeId'), 'text/modeId'); }); test('first mimetype wins 2', () => { @@ -124,7 +124,7 @@ suite('LanguagesRegistry', () => { mimetypes: ['text/modeId'] }]); - assert.deepEqual(registry.getMimeForMode('modeId'), 'text/x-modeId'); + assert.deepStrictEqual(registry.getMimeForMode('modeId'), 'text/x-modeId'); }); test('aliases', () => { @@ -134,42 +134,42 @@ suite('LanguagesRegistry', () => { id: 'a' }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('a'), ['a']); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); - assert.deepEqual(registry.getLanguageName('a'), 'a'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('a'), ['a']); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); + assert.deepStrictEqual(registry.getLanguageName('a'), 'a'); registry._registerLanguages([{ id: 'a', aliases: ['A1', 'A2'] }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['A1']); - assert.deepEqual(registry.getModeIdsFromLanguageName('a'), []); - assert.deepEqual(registry.getModeIdsFromLanguageName('A1'), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('A2'), []); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a1'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a2'), 'a'); - assert.deepEqual(registry.getLanguageName('a'), 'A1'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['A1']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('a'), []); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A1'), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A2'), []); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a1'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a2'), 'a'); + assert.deepStrictEqual(registry.getLanguageName('a'), 'A1'); registry._registerLanguages([{ id: 'a', aliases: ['A3', 'A4'] }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['A3']); - assert.deepEqual(registry.getModeIdsFromLanguageName('a'), []); - assert.deepEqual(registry.getModeIdsFromLanguageName('A1'), []); - assert.deepEqual(registry.getModeIdsFromLanguageName('A2'), []); - assert.deepEqual(registry.getModeIdsFromLanguageName('A3'), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('A4'), []); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a1'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a2'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a3'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a4'), 'a'); - assert.deepEqual(registry.getLanguageName('a'), 'A3'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['A3']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('a'), []); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A1'), []); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A2'), []); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A3'), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('A4'), []); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a1'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a2'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a3'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a4'), 'a'); + assert.deepStrictEqual(registry.getLanguageName('a'), 'A3'); }); test('empty aliases array means no alias', () => { @@ -179,23 +179,23 @@ suite('LanguagesRegistry', () => { id: 'a' }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('a'), ['a']); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); - assert.deepEqual(registry.getLanguageName('a'), 'a'); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('a'), ['a']); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); + assert.deepStrictEqual(registry.getLanguageName('a'), 'a'); registry._registerLanguages([{ id: 'b', aliases: [] }]); - assert.deepEqual(registry.getRegisteredLanguageNames(), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('a'), ['a']); - assert.deepEqual(registry.getModeIdsFromLanguageName('b'), []); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); - assert.deepEqual(registry.getModeIdForLanguageNameLowercase('b'), 'b'); - assert.deepEqual(registry.getLanguageName('a'), 'a'); - assert.deepEqual(registry.getLanguageName('b'), null); + assert.deepStrictEqual(registry.getRegisteredLanguageNames(), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('a'), ['a']); + assert.deepStrictEqual(registry.getModeIdsFromLanguageName('b'), []); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('a'), 'a'); + assert.deepStrictEqual(registry.getModeIdForLanguageNameLowercase('b'), 'b'); + assert.deepStrictEqual(registry.getLanguageName('a'), 'a'); + assert.deepStrictEqual(registry.getLanguageName('b'), null); }); test('extensions', () => { @@ -207,18 +207,18 @@ suite('LanguagesRegistry', () => { extensions: ['aExt'] }]); - assert.deepEqual(registry.getExtensions('a'), []); - assert.deepEqual(registry.getExtensions('aname'), []); - assert.deepEqual(registry.getExtensions('aName'), ['aExt']); + assert.deepStrictEqual(registry.getExtensions('a'), []); + assert.deepStrictEqual(registry.getExtensions('aname'), []); + assert.deepStrictEqual(registry.getExtensions('aName'), ['aExt']); registry._registerLanguages([{ id: 'a', extensions: ['aExt2'] }]); - assert.deepEqual(registry.getExtensions('a'), []); - assert.deepEqual(registry.getExtensions('aname'), []); - assert.deepEqual(registry.getExtensions('aName'), ['aExt', 'aExt2']); + assert.deepStrictEqual(registry.getExtensions('a'), []); + assert.deepStrictEqual(registry.getExtensions('aname'), []); + assert.deepStrictEqual(registry.getExtensions('aName'), ['aExt', 'aExt2']); }); test('extensions of primary language registration come first', () => { @@ -229,7 +229,7 @@ suite('LanguagesRegistry', () => { extensions: ['aExt3'] }]); - assert.deepEqual(registry.getExtensions('a')[0], 'aExt3'); + assert.deepStrictEqual(registry.getExtensions('a')[0], 'aExt3'); registry._registerLanguages([{ id: 'a', @@ -237,14 +237,14 @@ suite('LanguagesRegistry', () => { extensions: ['aExt'] }]); - assert.deepEqual(registry.getExtensions('a')[0], 'aExt'); + assert.deepStrictEqual(registry.getExtensions('a')[0], 'aExt'); registry._registerLanguages([{ id: 'a', extensions: ['aExt2'] }]); - assert.deepEqual(registry.getExtensions('a')[0], 'aExt'); + assert.deepStrictEqual(registry.getExtensions('a')[0], 'aExt'); }); test('filenames', () => { @@ -256,18 +256,18 @@ suite('LanguagesRegistry', () => { filenames: ['aFilename'] }]); - assert.deepEqual(registry.getFilenames('a'), []); - assert.deepEqual(registry.getFilenames('aname'), []); - assert.deepEqual(registry.getFilenames('aName'), ['aFilename']); + assert.deepStrictEqual(registry.getFilenames('a'), []); + assert.deepStrictEqual(registry.getFilenames('aname'), []); + assert.deepStrictEqual(registry.getFilenames('aName'), ['aFilename']); registry._registerLanguages([{ id: 'a', filenames: ['aFilename2'] }]); - assert.deepEqual(registry.getFilenames('a'), []); - assert.deepEqual(registry.getFilenames('aname'), []); - assert.deepEqual(registry.getFilenames('aName'), ['aFilename', 'aFilename2']); + assert.deepStrictEqual(registry.getFilenames('a'), []); + assert.deepStrictEqual(registry.getFilenames('aname'), []); + assert.deepStrictEqual(registry.getFilenames('aName'), ['aFilename', 'aFilename2']); }); test('configuration', () => { @@ -279,17 +279,17 @@ suite('LanguagesRegistry', () => { configuration: URI.file('/path/to/aFilename') }]); - assert.deepEqual(registry.getConfigurationFiles('a'), [URI.file('/path/to/aFilename')]); - assert.deepEqual(registry.getConfigurationFiles('aname'), []); - assert.deepEqual(registry.getConfigurationFiles('aName'), []); + assert.deepStrictEqual(registry.getConfigurationFiles('a'), [URI.file('/path/to/aFilename')]); + assert.deepStrictEqual(registry.getConfigurationFiles('aname'), []); + assert.deepStrictEqual(registry.getConfigurationFiles('aName'), []); registry._registerLanguages([{ id: 'a', configuration: URI.file('/path/to/aFilename2') }]); - assert.deepEqual(registry.getConfigurationFiles('a'), [URI.file('/path/to/aFilename'), URI.file('/path/to/aFilename2')]); - assert.deepEqual(registry.getConfigurationFiles('aname'), []); - assert.deepEqual(registry.getConfigurationFiles('aName'), []); + assert.deepStrictEqual(registry.getConfigurationFiles('a'), [URI.file('/path/to/aFilename'), URI.file('/path/to/aFilename2')]); + assert.deepStrictEqual(registry.getConfigurationFiles('aname'), []); + assert.deepStrictEqual(registry.getConfigurationFiles('aName'), []); }); }); diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index e6e852f6bb0..a4176c9dbf6 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -47,9 +47,9 @@ suite('ModelService', () => { const model2 = modelService.createModel('farboo', null, URI.file(platform.isWindows ? 'c:\\myroot\\myfile.txt' : '/myroot/myfile.txt')); const model3 = modelService.createModel('farboo', null, URI.file(platform.isWindows ? 'c:\\other\\myfile.txt' : '/other/myfile.txt')); - assert.equal(model1.getOptions().defaultEOL, DefaultEndOfLine.LF); - assert.equal(model2.getOptions().defaultEOL, DefaultEndOfLine.CRLF); - assert.equal(model3.getOptions().defaultEOL, DefaultEndOfLine.LF); + assert.strictEqual(model1.getOptions().defaultEOL, DefaultEndOfLine.LF); + assert.strictEqual(model2.getOptions().defaultEOL, DefaultEndOfLine.CRLF); + assert.strictEqual(model3.getOptions().defaultEOL, DefaultEndOfLine.LF); }); test('_computeEdits no change', function () { @@ -75,7 +75,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); - assert.deepEqual(actual, []); + assert.deepStrictEqual(actual, []); }); test('_computeEdits first line changed', function () { @@ -101,7 +101,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ EditOperation.replaceMove(new Range(1, 1, 2, 1), 'This is line One\n') ]); }); @@ -129,7 +129,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); - assert.deepEqual(actual, []); + assert.deepStrictEqual(actual, []); }); test('_computeEdits EOL and other change 1', function () { @@ -155,7 +155,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ EditOperation.replaceMove( new Range(1, 1, 4, 1), [ @@ -190,7 +190,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ EditOperation.replaceMove(new Range(3, 2, 3, 2), '\r\n') ]); }); @@ -317,7 +317,7 @@ suite('ModelService', () => { const model1 = modelService.createModel('text', null, resource); // make an edit model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); - assert.equal(model1.getValue(), 'text1'); + assert.strictEqual(model1.getValue(), 'text1'); // dispose it modelService.destroyModel(resource); @@ -325,7 +325,7 @@ suite('ModelService', () => { const model2 = modelService.createModel('text1', null, resource); // undo model2.undo(); - assert.equal(model2.getValue(), 'text'); + assert.strictEqual(model2.getValue(), 'text'); }); test('maintains version id and alternative version id for same resource and same content', () => { @@ -335,7 +335,7 @@ suite('ModelService', () => { const model1 = modelService.createModel('text', null, resource); // make an edit model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); - assert.equal(model1.getValue(), 'text1'); + assert.strictEqual(model1.getValue(), 'text1'); const versionId = model1.getVersionId(); const alternativeVersionId = model1.getAlternativeVersionId(); // dispose it @@ -343,8 +343,8 @@ suite('ModelService', () => { // create a new model with the same content const model2 = modelService.createModel('text1', null, resource); - assert.equal(model2.getVersionId(), versionId); - assert.equal(model2.getAlternativeVersionId(), alternativeVersionId); + assert.strictEqual(model2.getVersionId(), versionId); + assert.strictEqual(model2.getAlternativeVersionId(), alternativeVersionId); }); test('does not maintain undo for same resource and different content', () => { @@ -354,7 +354,7 @@ suite('ModelService', () => { const model1 = modelService.createModel('text', null, resource); // make an edit model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); - assert.equal(model1.getValue(), 'text1'); + assert.strictEqual(model1.getValue(), 'text1'); // dispose it modelService.destroyModel(resource); @@ -362,7 +362,7 @@ suite('ModelService', () => { const model2 = modelService.createModel('text2', null, resource); // undo model2.undo(); - assert.equal(model2.getValue(), 'text2'); + assert.strictEqual(model2.getValue(), 'text2'); }); test('setValue should clear undo stack', () => { @@ -370,11 +370,11 @@ suite('ModelService', () => { const model = modelService.createModel('text', null, resource); model.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); - assert.equal(model.getValue(), 'text1'); + assert.strictEqual(model.getValue(), 'text1'); model.setValue('text2'); model.undo(); - assert.equal(model.getValue(), 'text2'); + assert.strictEqual(model.getValue(), 'text2'); }); }); @@ -390,7 +390,7 @@ function assertComputeEdits(lines1: string[], lines2: string[]): void { // apply edits model.pushEditOperations([], edits, null); - assert.equal(model.getValue(), lines2.join('\n')); + assert.strictEqual(model.getValue(), lines2.join('\n')); } function getRandomInt(min: number, max: number): number { diff --git a/src/vs/editor/test/common/view/overviewZoneManager.test.ts b/src/vs/editor/test/common/view/overviewZoneManager.test.ts index 39c104fbb81..ee8c8ed7d84 100644 --- a/src/vs/editor/test/common/view/overviewZoneManager.test.ts +++ b/src/vs/editor/test/common/view/overviewZoneManager.test.ts @@ -26,7 +26,7 @@ suite('Editor View - OverviewZoneManager', () => { ]); // one line = 12, but cap is at 6 - assert.deepEqual(manager.resolveColorZones(), [ + assert.deepStrictEqual(manager.resolveColorZones(), [ new ColorZone(12, 24, 1), // new ColorZone(120, 132, 2), // 120 -> 132 new ColorZone(360, 384, 3), // 360 -> 372 [360 -> 384] @@ -52,7 +52,7 @@ suite('Editor View - OverviewZoneManager', () => { ]); // one line = 6, cap is at 6 - assert.deepEqual(manager.resolveColorZones(), [ + assert.deepStrictEqual(manager.resolveColorZones(), [ new ColorZone(6, 12, 1), // new ColorZone(60, 66, 2), // 60 -> 66 new ColorZone(180, 192, 3), // 180 -> 192 @@ -78,7 +78,7 @@ suite('Editor View - OverviewZoneManager', () => { ]); // one line = 6, cap is at 12 - assert.deepEqual(manager.resolveColorZones(), [ + assert.deepStrictEqual(manager.resolveColorZones(), [ new ColorZone(12, 24, 1), // new ColorZone(120, 132, 2), // 120 -> 132 new ColorZone(360, 384, 3), // 360 -> 384 diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index 910165a0ea9..a0fa69bc866 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -95,7 +95,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { maxDigitWidth: input.maxDigitWidth, pixelRatio: input.pixelRatio, }); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } test('EditorLayoutProvider 1', () => { diff --git a/src/vs/editor/test/common/viewLayout/lineDecorations.test.ts b/src/vs/editor/test/common/viewLayout/lineDecorations.test.ts index 8be7627bc72..e8939e78484 100644 --- a/src/vs/editor/test/common/viewLayout/lineDecorations.test.ts +++ b/src/vs/editor/test/common/viewLayout/lineDecorations.test.ts @@ -17,7 +17,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular) ]); - assert.deepEqual(result, [ + assert.deepStrictEqual(result, [ new DecorationSegment(0, 1, 'c1', 0), new DecorationSegment(2, 2, 'c2 c1', 0), new DecorationSegment(3, 9, 'c1', 0), @@ -31,7 +31,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new LineDecoration(20, 21, 'inline-folded', InlineDecorationType.Regular), ]); - assert.deepEqual(result, [ + assert.deepStrictEqual(result, [ new DecorationSegment(14, 18, 'mtkw', 0), new DecorationSegment(19, 19, 'mtkw inline-folded', 0) ]); @@ -43,7 +43,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new InlineDecoration(new Range(2, 12, 3, 30), 'detected-link', InlineDecorationType.Regular) ], 3, 12, 500); - assert.deepEqual(result, [ + assert.deepStrictEqual(result, [ new LineDecoration(12, 30, 'detected-link', InlineDecorationType.Regular), ]); }); @@ -54,7 +54,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new InlineDecoration(new Range(4, 0, 4, 1), 'after', InlineDecorationType.After), ], 4, 1, 500); - assert.deepEqual(result, [ + assert.deepStrictEqual(result, [ new LineDecoration(1, 2, 'before', InlineDecorationType.Before), new LineDecoration(0, 1, 'after', InlineDecorationType.After), ]); @@ -62,7 +62,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { test('ViewLineParts', () => { - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 2, 'c1', InlineDecorationType.Regular), new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular) ]), [ @@ -70,7 +70,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c2', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 3, 'c1', InlineDecorationType.Regular), new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular) ]), [ @@ -78,7 +78,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c2', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular), new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular) ]), [ @@ -86,7 +86,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c1 c2', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular), new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular) @@ -95,7 +95,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c1 c1* c2', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular), @@ -105,7 +105,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c1 c1* c1** c2', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular), @@ -116,7 +116,7 @@ suite('Editor ViewLayout - ViewLineParts', () => { new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*', 0) ]); - assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ + assert.deepStrictEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [ new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular), new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular), diff --git a/src/vs/editor/test/common/viewLayout/linesLayout.test.ts b/src/vs/editor/test/common/viewLayout/linesLayout.test.ts index 3205a10ce2b..6d619cf604f 100644 --- a/src/vs/editor/test/common/viewLayout/linesLayout.test.ts +++ b/src/vs/editor/test/common/viewLayout/linesLayout.test.ts @@ -34,105 +34,105 @@ suite('Editor ViewLayout - LinesLayout', () => { // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: - - assert.equal(linesLayout.getLinesTotalHeight(), 100); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 30); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 50); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 60); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 70); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 80); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 90); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 100); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 30); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 50); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 60); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 70); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 80); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 90); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(5), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(11), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(29), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(5), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(11), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(29), 3); // Add whitespace of height 5px after 2nd line insertWhitespace(linesLayout, 2, 0, 5, 0); // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: a(2,5) - assert.equal(linesLayout.getLinesTotalHeight(), 105); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 25); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 35); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 45); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 105); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 25); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 35); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 45); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(45), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(104), 10); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(105), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(45), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(104), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(105), 10); // Add two more whitespaces of height 5px insertWhitespace(linesLayout, 3, 0, 5, 0); insertWhitespace(linesLayout, 4, 0, 5, 0); // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: a(2,5), b(3, 5), c(4, 5) - assert.equal(linesLayout.getLinesTotalHeight(), 115); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 25); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 55); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 65); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 115); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 25); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 55); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 65); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(64), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(65), 6); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(64), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(65), 6); - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(0), 20); // 20 -> 25 - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(1), 35); // 35 -> 40 - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(2), 50); + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(0), 20); // 20 -> 25 + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(1), 35); // 35 -> 40 + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(2), 50); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(0), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(19), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(20), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(21), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(22), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(23), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(24), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(25), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(26), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(34), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(35), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(36), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(39), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(40), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(41), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(49), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(50), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(51), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(54), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(55), -1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(1000), -1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(0), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(19), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(20), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(21), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(22), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(23), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(24), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(25), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(26), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(34), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(35), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(36), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(39), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(40), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(41), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(49), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(50), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(51), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(54), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(55), -1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(1000), -1); }); @@ -144,94 +144,94 @@ suite('Editor ViewLayout - LinesLayout', () => { // 10 lines // whitespace: - a(2,5) - assert.equal(linesLayout.getLinesTotalHeight(), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 7); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 8); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 9); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 11); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 12); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 13); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 14); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 7); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 8); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 9); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 11); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 12); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 13); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 14); // Change whitespace height // 10 lines // whitespace: - a(2,10) changeOneWhitespace(linesLayout, a, 2, 10); - assert.equal(linesLayout.getLinesTotalHeight(), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 12); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 13); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 14); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 19); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 12); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 13); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 14); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 19); // Change whitespace position // 10 lines // whitespace: - a(5,10) changeOneWhitespace(linesLayout, a, 5, 10); - assert.equal(linesLayout.getLinesTotalHeight(), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 4); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 19); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 4); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 19); // Pretend that lines 5 and 6 were deleted // 8 lines // whitespace: - a(4,10) linesLayout.onLinesDeleted(5, 6); - assert.equal(linesLayout.getLinesTotalHeight(), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 14); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 14); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); // Insert two lines at the beginning // 10 lines // whitespace: - a(6,10) linesLayout.onLinesInserted(1, 2); - assert.equal(linesLayout.getLinesTotalHeight(), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 4); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 5); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 19); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 4); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 5); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 19); // Remove whitespace // 10 lines removeWhitespace(linesLayout, a); - assert.equal(linesLayout.getLinesTotalHeight(), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 4); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 5); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 6); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 7); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 8); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 9); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 4); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 5); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 6); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 7); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 8); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 9); }); test('LinesLayout Padding', () => { @@ -240,93 +240,93 @@ suite('Editor ViewLayout - LinesLayout', () => { // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: - - assert.equal(linesLayout.getLinesTotalHeight(), 135); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 35); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 45); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 55); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 65); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 75); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 85); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 95); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 105); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 135); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 25); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 35); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 45); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 55); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 65); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 75); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 85); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 95); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 105); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); // Add whitespace of height 5px after 2nd line insertWhitespace(linesLayout, 2, 0, 5, 0); // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: a(2,5) - assert.equal(linesLayout.getLinesTotalHeight(), 140); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 50); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 140); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 25); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 50); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(41), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(41), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4); // Add two more whitespaces of height 5px insertWhitespace(linesLayout, 3, 0, 5, 0); insertWhitespace(linesLayout, 4, 0, 5, 0); // lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // whitespace: a(2,5), b(3, 5), c(4, 5) - assert.equal(linesLayout.getLinesTotalHeight(), 150); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 55); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 70); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 80); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 150); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 15); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 25); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 55); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 70); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 80); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(30), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(54), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(55), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(64), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(65), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(69), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(70), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(80), 6); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(30), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(54), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(55), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(64), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(65), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(69), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(70), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(80), 6); - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(0), 35); // 35 -> 40 - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(1), 50); // 50 -> 55 - assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(2), 65); + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(0), 35); // 35 -> 40 + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(1), 50); // 50 -> 55 + assert.strictEqual(linesLayout.getVerticalOffsetForWhitespaceIndex(2), 65); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(0), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(34), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(35), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(39), 0); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(40), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(49), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(50), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(54), 1); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(55), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(64), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(65), 2); - assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(70), -1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(0), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(34), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(35), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(39), 0); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(40), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(49), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(50), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(54), 1); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(55), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(64), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(65), 2); + assert.strictEqual(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(70), -1); }); test('LinesLayout getLineNumberAtOrAfterVerticalOffset', () => { @@ -335,47 +335,47 @@ suite('Editor ViewLayout - LinesLayout', () => { // 10 lines // whitespace: - a(6,10) - assert.equal(linesLayout.getLinesTotalHeight(), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 4); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 5); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 19); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 4); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 5); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 19); // Do some hit testing // line [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // vertical: [0, 1, 2, 3, 4, 5, 16, 17, 18, 19] - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(-100), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(-1), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 2); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(2), 3); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(3), 4); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(4), 5); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(5), 6); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(6), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(7), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(8), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(11), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(12), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(13), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(14), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(16), 7); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(17), 8); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(18), 9); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 10); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 10); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 10); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(22), 10); - assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(23), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(-100), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(-1), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(1), 2); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(2), 3); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(3), 4); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(4), 5); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(5), 6); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(6), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(7), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(8), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(9), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(11), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(12), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(13), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(14), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(16), 7); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(17), 8); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(18), 9); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(19), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(20), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(21), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(22), 10); + assert.strictEqual(linesLayout.getLineNumberAtOrAfterVerticalOffset(23), 10); }); test('LinesLayout getCenteredLineInViewport', () => { @@ -384,81 +384,81 @@ suite('Editor ViewLayout - LinesLayout', () => { // 10 lines // whitespace: - a(6,10) - assert.equal(linesLayout.getLinesTotalHeight(), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 2); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 3); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 4); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 5); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 16); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 17); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 18); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 19); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 1); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 2); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 3); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 4); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 5); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 16); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 17); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 18); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 19); // Find centered line in viewport 1 // line [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // vertical: [0, 1, 2, 3, 4, 5, 16, 17, 18, 19] - assert.equal(linesLayout.getLinesViewportData(0, 1).centeredLineNumber, 1); - assert.equal(linesLayout.getLinesViewportData(0, 2).centeredLineNumber, 2); - assert.equal(linesLayout.getLinesViewportData(0, 3).centeredLineNumber, 2); - assert.equal(linesLayout.getLinesViewportData(0, 4).centeredLineNumber, 3); - assert.equal(linesLayout.getLinesViewportData(0, 5).centeredLineNumber, 3); - assert.equal(linesLayout.getLinesViewportData(0, 6).centeredLineNumber, 4); - assert.equal(linesLayout.getLinesViewportData(0, 7).centeredLineNumber, 4); - assert.equal(linesLayout.getLinesViewportData(0, 8).centeredLineNumber, 5); - assert.equal(linesLayout.getLinesViewportData(0, 9).centeredLineNumber, 5); - assert.equal(linesLayout.getLinesViewportData(0, 10).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 11).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 12).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 13).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 14).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 15).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 16).centeredLineNumber, 6); - assert.equal(linesLayout.getLinesViewportData(0, 17).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 18).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 19).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 21).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 22).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 23).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 24).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 25).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 26).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 27).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 28).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 29).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 30).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 31).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 32).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(0, 33).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 1).centeredLineNumber, 1); + assert.strictEqual(linesLayout.getLinesViewportData(0, 2).centeredLineNumber, 2); + assert.strictEqual(linesLayout.getLinesViewportData(0, 3).centeredLineNumber, 2); + assert.strictEqual(linesLayout.getLinesViewportData(0, 4).centeredLineNumber, 3); + assert.strictEqual(linesLayout.getLinesViewportData(0, 5).centeredLineNumber, 3); + assert.strictEqual(linesLayout.getLinesViewportData(0, 6).centeredLineNumber, 4); + assert.strictEqual(linesLayout.getLinesViewportData(0, 7).centeredLineNumber, 4); + assert.strictEqual(linesLayout.getLinesViewportData(0, 8).centeredLineNumber, 5); + assert.strictEqual(linesLayout.getLinesViewportData(0, 9).centeredLineNumber, 5); + assert.strictEqual(linesLayout.getLinesViewportData(0, 10).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 11).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 12).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 13).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 14).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 15).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 16).centeredLineNumber, 6); + assert.strictEqual(linesLayout.getLinesViewportData(0, 17).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 18).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 19).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 21).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 22).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 23).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 24).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 25).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 26).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 27).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 28).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 29).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 30).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 31).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 32).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(0, 33).centeredLineNumber, 7); // Find centered line in viewport 2 // line [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // vertical: [0, 1, 2, 3, 4, 5, 16, 17, 18, 19] - assert.equal(linesLayout.getLinesViewportData(0, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(1, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(2, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(3, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(4, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(5, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(6, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(7, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(8, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(9, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(10, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(11, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(12, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(13, 20).centeredLineNumber, 7); - assert.equal(linesLayout.getLinesViewportData(14, 20).centeredLineNumber, 8); - assert.equal(linesLayout.getLinesViewportData(15, 20).centeredLineNumber, 8); - assert.equal(linesLayout.getLinesViewportData(16, 20).centeredLineNumber, 9); - assert.equal(linesLayout.getLinesViewportData(17, 20).centeredLineNumber, 9); - assert.equal(linesLayout.getLinesViewportData(18, 20).centeredLineNumber, 10); - assert.equal(linesLayout.getLinesViewportData(19, 20).centeredLineNumber, 10); - assert.equal(linesLayout.getLinesViewportData(20, 23).centeredLineNumber, 10); - assert.equal(linesLayout.getLinesViewportData(21, 23).centeredLineNumber, 10); - assert.equal(linesLayout.getLinesViewportData(22, 23).centeredLineNumber, 10); + assert.strictEqual(linesLayout.getLinesViewportData(0, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(1, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(2, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(3, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(4, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(5, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(6, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(7, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(8, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(9, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(10, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(11, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(12, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(13, 20).centeredLineNumber, 7); + assert.strictEqual(linesLayout.getLinesViewportData(14, 20).centeredLineNumber, 8); + assert.strictEqual(linesLayout.getLinesViewportData(15, 20).centeredLineNumber, 8); + assert.strictEqual(linesLayout.getLinesViewportData(16, 20).centeredLineNumber, 9); + assert.strictEqual(linesLayout.getLinesViewportData(17, 20).centeredLineNumber, 9); + assert.strictEqual(linesLayout.getLinesViewportData(18, 20).centeredLineNumber, 10); + assert.strictEqual(linesLayout.getLinesViewportData(19, 20).centeredLineNumber, 10); + assert.strictEqual(linesLayout.getLinesViewportData(20, 23).centeredLineNumber, 10); + assert.strictEqual(linesLayout.getLinesViewportData(21, 23).centeredLineNumber, 10); + assert.strictEqual(linesLayout.getLinesViewportData(22, 23).centeredLineNumber, 10); }); test('LinesLayout getLinesViewportData 1', () => { @@ -467,131 +467,131 @@ suite('Editor ViewLayout - LinesLayout', () => { // 10 lines // whitespace: - a(6,100) - assert.equal(linesLayout.getLinesTotalHeight(), 200); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 30); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 50); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 160); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 170); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 180); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 190); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 200); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 30); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 50); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 160); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 170); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 180); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 190); // viewport 0->50 let viewportData = linesLayout.getLinesViewportData(0, 50); - assert.equal(viewportData.startLineNumber, 1); - assert.equal(viewportData.endLineNumber, 5); - assert.equal(viewportData.completelyVisibleStartLineNumber, 1); - assert.equal(viewportData.completelyVisibleEndLineNumber, 5); - assert.deepEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40]); + assert.strictEqual(viewportData.startLineNumber, 1); + assert.strictEqual(viewportData.endLineNumber, 5); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 1); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 5); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40]); // viewport 1->51 viewportData = linesLayout.getLinesViewportData(1, 51); - assert.equal(viewportData.startLineNumber, 1); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 2); - assert.equal(viewportData.completelyVisibleEndLineNumber, 5); - assert.deepEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40, 50]); + assert.strictEqual(viewportData.startLineNumber, 1); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 2); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 5); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40, 50]); // viewport 5->55 viewportData = linesLayout.getLinesViewportData(5, 55); - assert.equal(viewportData.startLineNumber, 1); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 2); - assert.equal(viewportData.completelyVisibleEndLineNumber, 5); - assert.deepEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40, 50]); + assert.strictEqual(viewportData.startLineNumber, 1); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 2); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 5); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [0, 10, 20, 30, 40, 50]); // viewport 10->60 viewportData = linesLayout.getLinesViewportData(10, 60); - assert.equal(viewportData.startLineNumber, 2); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 2); - assert.equal(viewportData.completelyVisibleEndLineNumber, 6); - assert.deepEqual(viewportData.relativeVerticalOffset, [10, 20, 30, 40, 50]); + assert.strictEqual(viewportData.startLineNumber, 2); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 2); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 6); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [10, 20, 30, 40, 50]); // viewport 50->100 viewportData = linesLayout.getLinesViewportData(50, 100); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 6); - assert.deepEqual(viewportData.relativeVerticalOffset, [50]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 6); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50]); // viewport 60->110 viewportData = linesLayout.getLinesViewportData(60, 110); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [160]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160]); // viewport 65->115 viewportData = linesLayout.getLinesViewportData(65, 115); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [160]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160]); // viewport 50->159 viewportData = linesLayout.getLinesViewportData(50, 159); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 6); - assert.deepEqual(viewportData.relativeVerticalOffset, [50]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 6); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50]); // viewport 50->160 viewportData = linesLayout.getLinesViewportData(50, 160); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 6); - assert.deepEqual(viewportData.relativeVerticalOffset, [50]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 6); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50]); // viewport 51->161 viewportData = linesLayout.getLinesViewportData(51, 161); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [50, 160]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50, 160]); // viewport 150->169 viewportData = linesLayout.getLinesViewportData(150, 169); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [160]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160]); // viewport 159->169 viewportData = linesLayout.getLinesViewportData(159, 169); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [160]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160]); // viewport 160->169 viewportData = linesLayout.getLinesViewportData(160, 169); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [160]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160]); // viewport 160->1000 viewportData = linesLayout.getLinesViewportData(160, 1000); - assert.equal(viewportData.startLineNumber, 7); - assert.equal(viewportData.endLineNumber, 10); - assert.equal(viewportData.completelyVisibleStartLineNumber, 7); - assert.equal(viewportData.completelyVisibleEndLineNumber, 10); - assert.deepEqual(viewportData.relativeVerticalOffset, [160, 170, 180, 190]); + assert.strictEqual(viewportData.startLineNumber, 7); + assert.strictEqual(viewportData.endLineNumber, 10); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 10); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [160, 170, 180, 190]); }); test('LinesLayout getLinesViewportData 2 & getWhitespaceViewportData', () => { @@ -601,27 +601,27 @@ suite('Editor ViewLayout - LinesLayout', () => { // 10 lines // whitespace: - a(6,100), b(7, 50) - assert.equal(linesLayout.getLinesTotalHeight(), 250); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 10); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 20); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 30); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 40); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 50); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 160); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 220); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 230); - assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 240); + assert.strictEqual(linesLayout.getLinesTotalHeight(), 250); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(1), 0); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(2), 10); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(3), 20); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(4), 30); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(5), 40); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(6), 50); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(7), 160); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(8), 220); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(9), 230); + assert.strictEqual(linesLayout.getVerticalOffsetForLineNumber(10), 240); // viewport 50->160 let viewportData = linesLayout.getLinesViewportData(50, 160); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 6); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 6); - assert.deepEqual(viewportData.relativeVerticalOffset, [50]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 6); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50]); let whitespaceData = linesLayout.getWhitespaceViewportData(50, 160); - assert.deepEqual(whitespaceData, [{ + assert.deepStrictEqual(whitespaceData, [{ id: a, afterLineNumber: 6, verticalOffset: 60, @@ -630,13 +630,13 @@ suite('Editor ViewLayout - LinesLayout', () => { // viewport 50->219 viewportData = linesLayout.getLinesViewportData(50, 219); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [50, 160]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50, 160]); whitespaceData = linesLayout.getWhitespaceViewportData(50, 219); - assert.deepEqual(whitespaceData, [{ + assert.deepStrictEqual(whitespaceData, [{ id: a, afterLineNumber: 6, verticalOffset: 60, @@ -650,19 +650,19 @@ suite('Editor ViewLayout - LinesLayout', () => { // viewport 50->220 viewportData = linesLayout.getLinesViewportData(50, 220); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 7); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 7); - assert.deepEqual(viewportData.relativeVerticalOffset, [50, 160]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 7); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 7); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50, 160]); // viewport 50->250 viewportData = linesLayout.getLinesViewportData(50, 250); - assert.equal(viewportData.startLineNumber, 6); - assert.equal(viewportData.endLineNumber, 10); - assert.equal(viewportData.completelyVisibleStartLineNumber, 6); - assert.equal(viewportData.completelyVisibleEndLineNumber, 10); - assert.deepEqual(viewportData.relativeVerticalOffset, [50, 160, 220, 230, 240]); + assert.strictEqual(viewportData.startLineNumber, 6); + assert.strictEqual(viewportData.endLineNumber, 10); + assert.strictEqual(viewportData.completelyVisibleStartLineNumber, 6); + assert.strictEqual(viewportData.completelyVisibleEndLineNumber, 10); + assert.deepStrictEqual(viewportData.relativeVerticalOffset, [50, 160, 220, 230, 240]); }); test('LinesLayout getWhitespaceAtVerticalOffset', () => { @@ -671,40 +671,40 @@ suite('Editor ViewLayout - LinesLayout', () => { let b = insertWhitespace(linesLayout, 7, 0, 50, 0); let whitespace = linesLayout.getWhitespaceAtVerticalOffset(0); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); whitespace = linesLayout.getWhitespaceAtVerticalOffset(59); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); whitespace = linesLayout.getWhitespaceAtVerticalOffset(60); - assert.equal(whitespace!.id, a); + assert.strictEqual(whitespace!.id, a); whitespace = linesLayout.getWhitespaceAtVerticalOffset(61); - assert.equal(whitespace!.id, a); + assert.strictEqual(whitespace!.id, a); whitespace = linesLayout.getWhitespaceAtVerticalOffset(159); - assert.equal(whitespace!.id, a); + assert.strictEqual(whitespace!.id, a); whitespace = linesLayout.getWhitespaceAtVerticalOffset(160); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); whitespace = linesLayout.getWhitespaceAtVerticalOffset(161); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); whitespace = linesLayout.getWhitespaceAtVerticalOffset(169); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); whitespace = linesLayout.getWhitespaceAtVerticalOffset(170); - assert.equal(whitespace!.id, b); + assert.strictEqual(whitespace!.id, b); whitespace = linesLayout.getWhitespaceAtVerticalOffset(171); - assert.equal(whitespace!.id, b); + assert.strictEqual(whitespace!.id, b); whitespace = linesLayout.getWhitespaceAtVerticalOffset(219); - assert.equal(whitespace!.id, b); + assert.strictEqual(whitespace!.id, b); whitespace = linesLayout.getWhitespaceAtVerticalOffset(220); - assert.equal(whitespace, null); + assert.strictEqual(whitespace, null); }); test('LinesLayout', () => { @@ -714,230 +714,230 @@ suite('Editor ViewLayout - LinesLayout', () => { // Insert a whitespace after line number 2, of height 10 const a = insertWhitespace(linesLayout, 2, 0, 10, 0); // whitespaces: a(2, 10) - assert.equal(linesLayout.getWhitespacesCount(), 1); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 10); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10); + assert.strictEqual(linesLayout.getWhitespacesCount(), 1); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 10); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 10); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 10); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10); // Insert a whitespace again after line number 2, of height 20 let b = insertWhitespace(linesLayout, 2, 0, 20, 0); // whitespaces: a(2, 10), b(2, 20) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 30); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 30); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 10); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 10); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 30); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 30); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); // Change last inserted whitespace height to 30 changeOneWhitespace(linesLayout, b, 2, 30); // whitespaces: a(2, 10), b(2, 30) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 30); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 40); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 40); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 40); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 40); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 10); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 30); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 10); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 40); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 40); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 40); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 40); // Remove last inserted whitespace removeWhitespace(linesLayout, b); // whitespaces: a(2, 10) - assert.equal(linesLayout.getWhitespacesCount(), 1); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 10); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10); + assert.strictEqual(linesLayout.getWhitespacesCount(), 1); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 10); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 10); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 10); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10); // Add a whitespace before the first line of height 50 b = insertWhitespace(linesLayout, 0, 0, 50, 0); // whitespaces: b(0, 50), a(2, 10) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 60); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 50); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 10); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 50); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 60); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 60); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60); // Add a whitespace after line 4 of height 20 insertWhitespace(linesLayout, 4, 0, 20, 0); // whitespaces: b(0, 50), a(2, 10), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 3); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 80); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 80); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 80); + assert.strictEqual(linesLayout.getWhitespacesCount(), 3); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 50); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 10); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(2), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 50); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 60); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(2), 80); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 80); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 80); // Add a whitespace after line 3 of height 30 insertWhitespace(linesLayout, 3, 0, 30, 0); // whitespaces: b(0, 50), a(2, 10), d(3, 30), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 4); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(3), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 90); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(3), 110); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 110); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 90); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 110); + assert.strictEqual(linesLayout.getWhitespacesCount(), 4); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 50); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 10); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(2), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(3), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 50); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 60); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(2), 90); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(3), 110); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 110); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 90); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 110); // Change whitespace after line 2 to height of 100 changeOneWhitespace(linesLayout, a, 2, 100); // whitespaces: b(0, 50), a(2, 100), d(3, 30), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 4); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 100); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(3), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 150); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 180); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(3), 200); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 200); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 150); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 180); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 200); + assert.strictEqual(linesLayout.getWhitespacesCount(), 4); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 50); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 100); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(2), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(3), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 50); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 150); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(2), 180); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(3), 200); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 200); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 150); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 180); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 200); // Remove whitespace after line 2 removeWhitespace(linesLayout, a); // whitespaces: b(0, 50), d(3, 30), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 3); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 80); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 100); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 100); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 80); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 100); + assert.strictEqual(linesLayout.getWhitespacesCount(), 3); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 50); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(2), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 50); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 80); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(2), 100); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 100); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 80); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 100); // Remove whitespace before line 1 removeWhitespace(linesLayout, b); // whitespaces: d(3, 30), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 30); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 50); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); // Delete line 1 linesLayout.onLinesDeleted(1, 1); // whitespaces: d(2, 30), c(3, 20) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 30); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 50); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); // Insert a line before line 1 linesLayout.onLinesInserted(1, 1); // whitespaces: d(3, 30), c(4, 20) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 30); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 50); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); // Delete line 4 linesLayout.onLinesDeleted(4, 4); // whitespaces: d(3, 30), c(3, 20) - assert.equal(linesLayout.getWhitespacesCount(), 2); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30); - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30); - assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50); - assert.equal(linesLayout.getWhitespacesTotalHeight(), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50); - assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); + assert.strictEqual(linesLayout.getWhitespacesCount(), 2); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(0), 30); + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getHeightForWhitespaceIndex(1), 20); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(0), 30); + assert.strictEqual(linesLayout.getWhitespacesAccumulatedHeight(1), 50); + assert.strictEqual(linesLayout.getWhitespacesTotalHeight(), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50); + assert.strictEqual(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50); }); test('LinesLayout findInsertionIndex', () => { @@ -949,114 +949,114 @@ suite('Editor ViewLayout - LinesLayout', () => { let arr: EditorWhitespace[]; arr = makeInternalWhitespace([]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 0); arr = makeInternalWhitespace([1]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); arr = makeInternalWhitespace([1, 3]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); arr = makeInternalWhitespace([1, 3, 5]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); arr = makeInternalWhitespace([1, 3, 5], 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); arr = makeInternalWhitespace([1, 3, 5, 7]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 7, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 8, 0), 4); arr = makeInternalWhitespace([1, 3, 5, 7, 9]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 7, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 8, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 9, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 10, 0), 5); arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6); - assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 7, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 8, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 9, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 10, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 11, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 12, 0), 6); arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11, 13]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6); - assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6); - assert.equal(LinesLayout.findInsertionIndex(arr, 13, 0), 7); - assert.equal(LinesLayout.findInsertionIndex(arr, 14, 0), 7); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 7, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 8, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 9, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 10, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 11, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 12, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 13, 0), 7); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 14, 0), 7); arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11, 13, 15]); - assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0); - assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1); - assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2); - assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3); - assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4); - assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5); - assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6); - assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6); - assert.equal(LinesLayout.findInsertionIndex(arr, 13, 0), 7); - assert.equal(LinesLayout.findInsertionIndex(arr, 14, 0), 7); - assert.equal(LinesLayout.findInsertionIndex(arr, 15, 0), 8); - assert.equal(LinesLayout.findInsertionIndex(arr, 16, 0), 8); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 0, 0), 0); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 1, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 2, 0), 1); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 3, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 4, 0), 2); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 5, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 6, 0), 3); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 7, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 8, 0), 4); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 9, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 10, 0), 5); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 11, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 12, 0), 6); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 13, 0), 7); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 14, 0), 7); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 15, 0), 8); + assert.strictEqual(LinesLayout.findInsertionIndex(arr, 16, 0), 8); }); test('LinesLayout changeWhitespaceAfterLineNumber & getFirstWhitespaceIndexAfterLineNumber', () => { @@ -1066,121 +1066,121 @@ suite('Editor ViewLayout - LinesLayout', () => { const b = insertWhitespace(linesLayout, 7, 0, 1, 0); const c = insertWhitespace(linesLayout, 3, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), c); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- // Do not really move a changeOneWhitespace(linesLayout, a, 1, 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 1 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 1 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 1); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), c); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- // Do not really move a changeOneWhitespace(linesLayout, a, 2, 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 2 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 2 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), c); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- // Change a to conflict with c => a gets placed after c changeOneWhitespace(linesLayout, a, 3, 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), c); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), a); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), c); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), a); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- // Make a no-op changeOneWhitespace(linesLayout, c, 3, 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), c); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), a); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), c); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), a); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- // Conflict c with b => c gets placed after b changeOneWhitespace(linesLayout, c, 7, 1); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 3 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); - assert.equal(linesLayout.getIdForWhitespaceIndex(1), b); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 7); - assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 7 - assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 3 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), b); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 7); + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), c); // 7 + assert.strictEqual(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7); - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // a - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 1); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 1); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 1); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 1); // b - assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // a + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 1); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 1); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 1); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 1); // b + assert.strictEqual(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // -- }); test('LinesLayout Bug', () => { @@ -1189,53 +1189,53 @@ suite('Editor ViewLayout - LinesLayout', () => { const a = insertWhitespace(linesLayout, 0, 0, 1, 0); const b = insertWhitespace(linesLayout, 7, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), b); // 7 const c = insertWhitespace(linesLayout, 3, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), b); // 7 const d = insertWhitespace(linesLayout, 2, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), d); // 2 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(3), b); // 7 const e = insertWhitespace(linesLayout, 8, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7 - assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), d); // 2 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(3), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(4), e); // 8 const f = insertWhitespace(linesLayout, 11, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7 - assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8 - assert.equal(linesLayout.getIdForWhitespaceIndex(5), f); // 11 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), d); // 2 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(3), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(4), e); // 8 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(5), f); // 11 const g = insertWhitespace(linesLayout, 10, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7 - assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8 - assert.equal(linesLayout.getIdForWhitespaceIndex(5), g); // 10 - assert.equal(linesLayout.getIdForWhitespaceIndex(6), f); // 11 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), d); // 2 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(3), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(4), e); // 8 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(5), g); // 10 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(6), f); // 11 const h = insertWhitespace(linesLayout, 0, 0, 1, 0); - assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(1), h); // 0 - assert.equal(linesLayout.getIdForWhitespaceIndex(2), d); // 2 - assert.equal(linesLayout.getIdForWhitespaceIndex(3), c); // 3 - assert.equal(linesLayout.getIdForWhitespaceIndex(4), b); // 7 - assert.equal(linesLayout.getIdForWhitespaceIndex(5), e); // 8 - assert.equal(linesLayout.getIdForWhitespaceIndex(6), g); // 10 - assert.equal(linesLayout.getIdForWhitespaceIndex(7), f); // 11 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(0), a); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(1), h); // 0 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(2), d); // 2 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(3), c); // 3 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(4), b); // 7 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(5), e); // 8 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(6), g); // 10 + assert.strictEqual(linesLayout.getIdForWhitespaceIndex(7), f); // 11 }); }); diff --git a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts index 46f3690130a..672a4a86f66 100644 --- a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts +++ b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts @@ -48,7 +48,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expected + ''); + assert.strictEqual(_actual.html, '' + expected + ''); assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart, expectedPartLengts); } @@ -101,7 +101,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expected + ''); + assert.strictEqual(_actual.html, '' + expected + ''); assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart, expectedPartLengts); } @@ -167,7 +167,7 @@ suite('viewLineRenderer.renderLine', () => { '' ].join(''); - assert.equal(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); assertCharacterMapping(_actual.characterMapping, [ [0], @@ -252,7 +252,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [4, 4, 6, 1, 5, 1, 4, 1, 1, 1, 3, 15, 2, 3]); }); @@ -318,7 +318,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]); }); @@ -384,7 +384,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]); }); @@ -444,7 +444,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(actual.html, '' + expectedOutput + ''); + assert.strictEqual(actual.html, '' + expectedOutput + ''); assertCharacterMapping2(actual.characterMapping, expectedCharacterMapping); }); @@ -487,8 +487,8 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expectedOutput + ''); - assert.equal(_actual.containsRTL, true); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.containsRTL, true); }); test('issue #6885: Splits large tokens', () => { @@ -520,7 +520,7 @@ suite('viewLineRenderer.renderLine', () => { false, null )); - assert.equal(actual.html, '' + expectedOutput.join('') + '', message); + assert.strictEqual(actual.html, '' + expectedOutput.join('') + '', message); } // A token with 49 chars @@ -624,7 +624,7 @@ suite('viewLineRenderer.renderLine', () => { true, null )); - assert.equal(actual.html, '' + expectedOutput.join('') + '', message); + assert.strictEqual(actual.html, '' + expectedOutput.join('') + '', message); } // A token with 101 chars @@ -669,7 +669,7 @@ suite('viewLineRenderer.renderLine', () => { let expectedOutput = [ 'a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', ]; - assert.equal(actual.html, '' + expectedOutput.join('') + ''); + assert.strictEqual(actual.html, '' + expectedOutput.join('') + ''); }); test('issue #6885: Does not split large tokens in RTL text', () => { @@ -699,8 +699,8 @@ suite('viewLineRenderer.renderLine', () => { false, null )); - assert.equal(actual.html, '' + expectedOutput.join('') + ''); - assert.equal(actual.containsRTL, true); + assert.strictEqual(actual.html, '' + expectedOutput.join('') + ''); + assert.strictEqual(actual.containsRTL, true); }); test('issue #95685: Uses unicode replacement character for Paragraph Separator', () => { @@ -730,7 +730,7 @@ suite('viewLineRenderer.renderLine', () => { false, null )); - assert.equal(actual.html, '' + expectedOutput.join('') + ''); + assert.strictEqual(actual.html, '' + expectedOutput.join('') + ''); }); test('issue #19673: Monokai Theme bad-highlighting in line wrap', () => { @@ -780,7 +780,7 @@ suite('viewLineRenderer.renderLine', () => { null )); - assert.equal(_actual.html, '' + expectedOutput + ''); + assert.strictEqual(_actual.html, '' + expectedOutput + ''); }); interface ICharMappingData { @@ -807,7 +807,7 @@ suite('viewLineRenderer.renderLine', () => { function assertCharacterMapping2(actual: CharacterMapping, expected: CharacterMapping): void { const _actual = decodeCharacterMapping(actual); const _expected = decodeCharacterMapping(expected); - assert.deepEqual(_actual, _expected); + assert.deepStrictEqual(_actual, _expected); } function assertCharacterMapping(actual: CharacterMapping, expectedCharPartOffsets: number[][], expectedPartLengths: number[]): void { @@ -830,7 +830,7 @@ suite('viewLineRenderer.renderLine', () => { for (let i = 0; i < tmp.length; i++) { actualCharOffset[i] = tmp[i]; } - assert.deepEqual(actualCharOffset, expectedCharAbsoluteOffset); + assert.deepStrictEqual(actualCharOffset, expectedCharAbsoluteOffset); } function assertCharPartOffsets(actual: CharacterMapping, expected: number[][]): void { @@ -844,7 +844,7 @@ suite('viewLineRenderer.renderLine', () => { let actualPartIndex = CharacterMapping.getPartIndex(_actualPartData); let actualCharIndex = CharacterMapping.getCharIndex(_actualPartData); - assert.deepEqual( + assert.deepStrictEqual( { partIndex: actualPartIndex, charIndex: actualCharIndex }, { partIndex: partIndex, charIndex: charIndex }, `character mapping for offset ${charOffset}` @@ -853,7 +853,7 @@ suite('viewLineRenderer.renderLine', () => { // here let actualOffset = actual.partDataToCharOffset(partIndex, part[part.length - 1] + 1, charIndex); - assert.equal( + assert.strictEqual( actualOffset, charOffset, `character mapping for part ${partIndex}, ${charIndex}` @@ -863,7 +863,7 @@ suite('viewLineRenderer.renderLine', () => { } } - assert.equal(actual.length, charOffset); + assert.strictEqual(actual.length, charOffset); } }); @@ -892,7 +892,7 @@ suite('viewLineRenderer.renderLine 2', () => { selections )); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); } test('issue #18616: Inline decorations ending at the text length are no longer rendered', () => { @@ -927,7 +927,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #19207: Link in Monokai is not rendered correctly', () => { @@ -976,7 +976,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('createLineParts simple', () => { @@ -1477,7 +1477,7 @@ suite('viewLineRenderer.renderLine 2', () => { // bb--------- // -cccccc---- - assert.deepEqual(actual.html, [ + assert.deepStrictEqual(actual.html, [ '', 'H', 'e', @@ -1522,7 +1522,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #32436: Non-monospace font + visible whitespace + After decorator causes line to "jump"', () => { @@ -1559,7 +1559,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #30133: Empty lines don\'t render inline decorations', () => { @@ -1594,7 +1594,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #37208: Collapsing bullet point containing emoji in Markdown document results in [??] character', () => { @@ -1628,7 +1628,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #37401 #40127: Allow both before and after decorations on empty line', () => { @@ -1665,7 +1665,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #38935: GitLens end-of-line blame no longer rendering', () => { @@ -1702,7 +1702,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #22832: Consider fullwidth characters when rendering tabs', () => { @@ -1735,7 +1735,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #22832: Consider fullwidth characters when rendering tabs (render whitespace)', () => { @@ -1774,7 +1774,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #22352: COMBINING ACUTE ACCENT (U+0301)', () => { @@ -1807,7 +1807,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #22352: Partially Broken Complex Script Rendering of Tamil', () => { @@ -1842,7 +1842,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #42700: Hindi characters are not being rendered properly', () => { @@ -1877,7 +1877,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #38123: editor.renderWhitespace: "boundary" renders whitespace at line wrap point when line is wrapped', () => { @@ -1909,7 +1909,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #33525: Long line with ligatures takes a long time to paint decorations', () => { @@ -1945,7 +1945,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #33525: Long line with ligatures takes a long time to paint decorations - not possible', () => { @@ -1977,7 +1977,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); test('issue #91936: Semantic token color highlighting fails on line with selected text', () => { @@ -2062,7 +2062,7 @@ suite('viewLineRenderer.renderLine 2', () => { '' ].join(''); - assert.deepEqual(actual.html, expected); + assert.deepStrictEqual(actual.html, expected); }); @@ -2092,7 +2092,7 @@ suite('viewLineRenderer.renderLine 2', () => { return (partIndex: number, partLength: number, offset: number, expected: number) => { let charOffset = renderLineOutput.characterMapping.partDataToCharOffset(partIndex, partLength, offset); let actual = charOffset + 1; - assert.equal(actual, expected, 'getColumnOfLinePartOffset for ' + partIndex + ' @ ' + offset); + assert.strictEqual(actual, expected, 'getColumnOfLinePartOffset for ' + partIndex + ' @ ' + offset); }; } diff --git a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts index 0c40449f4ce..eec0e2b2717 100644 --- a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts @@ -75,7 +75,7 @@ function assertLineBreaks(factory: ILineBreaksComputerFactory, tabSize: number, const lineBreakData = getLineBreakData(factory, tabSize, breakAfter, 2, wrappingIndent, text, null); const actualAnnotatedText = toAnnotatedText(text, lineBreakData); - assert.equal(actualAnnotatedText, annotatedText); + assert.strictEqual(actualAnnotatedText, annotatedText); return lineBreakData; } @@ -125,11 +125,11 @@ suite('Editor ViewModel - MonospaceLineBreaksComputer', () => { function assertLineBreakDataEqual(a: LineBreakData | null, b: LineBreakData | null): void { if (!a || !b) { - assert.deepEqual(a, b); + assert.deepStrictEqual(a, b); return; } - assert.deepEqual(a.breakOffsets, b.breakOffsets); - assert.deepEqual(a.wrappedTextIndentLength, b.wrappedTextIndentLength); + assert.deepStrictEqual(a.breakOffsets, b.breakOffsets); + assert.deepStrictEqual(a.wrappedTextIndentLength, b.wrappedTextIndentLength); for (let i = 0; i < a.breakOffsetsVisibleColumn.length; i++) { const diff = a.breakOffsetsVisibleColumn[i] - b.breakOffsetsVisibleColumn[i]; assert.ok(diff < 0.001); @@ -138,25 +138,25 @@ suite('Editor ViewModel - MonospaceLineBreaksComputer', () => { function assertIncrementalLineBreaks(factory: ILineBreaksComputerFactory, text: string, tabSize: number, breakAfter1: number, annotatedText1: string, breakAfter2: number, annotatedText2: string, wrappingIndent = WrappingIndent.None, columnsForFullWidthChar: number = 2): void { // sanity check the test - assert.equal(text, parseAnnotatedText(annotatedText1).text); - assert.equal(text, parseAnnotatedText(annotatedText2).text); + assert.strictEqual(text, parseAnnotatedText(annotatedText1).text); + assert.strictEqual(text, parseAnnotatedText(annotatedText2).text); // check that the direct mapping is ok for 1 const directLineBreakData1 = getLineBreakData(factory, tabSize, breakAfter1, columnsForFullWidthChar, wrappingIndent, text, null); - assert.equal(toAnnotatedText(text, directLineBreakData1), annotatedText1); + assert.strictEqual(toAnnotatedText(text, directLineBreakData1), annotatedText1); // check that the direct mapping is ok for 2 const directLineBreakData2 = getLineBreakData(factory, tabSize, breakAfter2, columnsForFullWidthChar, wrappingIndent, text, null); - assert.equal(toAnnotatedText(text, directLineBreakData2), annotatedText2); + assert.strictEqual(toAnnotatedText(text, directLineBreakData2), annotatedText2); // check that going from 1 to 2 is ok const lineBreakData2from1 = getLineBreakData(factory, tabSize, breakAfter2, columnsForFullWidthChar, wrappingIndent, text, directLineBreakData1); - assert.equal(toAnnotatedText(text, lineBreakData2from1), annotatedText2); + assert.strictEqual(toAnnotatedText(text, lineBreakData2from1), annotatedText2); assertLineBreakDataEqual(lineBreakData2from1, directLineBreakData2); // check that going from 2 to 1 is ok const lineBreakData1from2 = getLineBreakData(factory, tabSize, breakAfter1, columnsForFullWidthChar, wrappingIndent, text, directLineBreakData2); - assert.equal(toAnnotatedText(text, lineBreakData1from2), annotatedText1); + assert.strictEqual(toAnnotatedText(text, lineBreakData1from2), annotatedText1); assertLineBreakDataEqual(lineBreakData1from2, directLineBreakData1); } @@ -266,7 +266,7 @@ suite('Editor ViewModel - MonospaceLineBreaksComputer', () => { test('issue #35162: wrappingIndent not consistently working', () => { let factory = new MonospaceLineBreaksComputerFactory('', '\t '); let mapper = assertLineBreaks(factory, 4, 24, ' t h i s |i s |a l |o n |g l |i n |e', WrappingIndent.Indent); - assert.equal(mapper!.wrappedTextIndentLength, ' '.length); + assert.strictEqual(mapper!.wrappedTextIndentLength, ' '.length); }); test('issue #75494: surrogate pairs', () => { @@ -287,7 +287,7 @@ suite('Editor ViewModel - MonospaceLineBreaksComputer', () => { test('MonospaceLineBreaksComputer - WrappingIndent.DeepIndent', () => { let factory = new MonospaceLineBreaksComputerFactory('', '\t '); let mapper = assertLineBreaks(factory, 4, 26, ' W e A r e T e s t |i n g D e |e p I n d |e n t a t |i o n', WrappingIndent.DeepIndent); - assert.equal(mapper!.wrappedTextIndentLength, ' '.length); + assert.strictEqual(mapper!.wrappedTextIndentLength, ' '.length); }); test('issue #33366: Word wrap algorithm behaves differently around punctuation', () => { diff --git a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts index 65cc26efd4c..80df1a94eb2 100644 --- a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts @@ -22,158 +22,158 @@ suite('Editor ViewModel - PrefixSumComputer', () => { let indexOfResult: PrefixSumIndexOfResult; let psc = new PrefixSumComputer(toUint32Array([1, 1, 2, 1, 3])); - assert.equal(psc.getTotalValue(), 8); - assert.equal(psc.getAccumulatedValue(-1), 0); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 2); - assert.equal(psc.getAccumulatedValue(2), 4); - assert.equal(psc.getAccumulatedValue(3), 5); - assert.equal(psc.getAccumulatedValue(4), 8); + assert.strictEqual(psc.getTotalValue(), 8); + assert.strictEqual(psc.getAccumulatedValue(-1), 0); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 2); + assert.strictEqual(psc.getAccumulatedValue(2), 4); + assert.strictEqual(psc.getAccumulatedValue(3), 5); + assert.strictEqual(psc.getAccumulatedValue(4), 8); indexOfResult = psc.getIndexOf(0); - assert.equal(indexOfResult.index, 0); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 0); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(1); - assert.equal(indexOfResult.index, 1); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 1); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(2); - assert.equal(indexOfResult.index, 2); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 2); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(3); - assert.equal(indexOfResult.index, 2); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 2); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(4); - assert.equal(indexOfResult.index, 3); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 3); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(5); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(6); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(7); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 2); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 2); indexOfResult = psc.getIndexOf(8); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 3); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 3); // [1, 2, 2, 1, 3] psc.changeValue(1, 2); - assert.equal(psc.getTotalValue(), 9); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 3); - assert.equal(psc.getAccumulatedValue(2), 5); - assert.equal(psc.getAccumulatedValue(3), 6); - assert.equal(psc.getAccumulatedValue(4), 9); + assert.strictEqual(psc.getTotalValue(), 9); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 3); + assert.strictEqual(psc.getAccumulatedValue(2), 5); + assert.strictEqual(psc.getAccumulatedValue(3), 6); + assert.strictEqual(psc.getAccumulatedValue(4), 9); // [1, 0, 2, 1, 3] psc.changeValue(1, 0); - assert.equal(psc.getTotalValue(), 7); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 1); - assert.equal(psc.getAccumulatedValue(2), 3); - assert.equal(psc.getAccumulatedValue(3), 4); - assert.equal(psc.getAccumulatedValue(4), 7); + assert.strictEqual(psc.getTotalValue(), 7); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 1); + assert.strictEqual(psc.getAccumulatedValue(2), 3); + assert.strictEqual(psc.getAccumulatedValue(3), 4); + assert.strictEqual(psc.getAccumulatedValue(4), 7); indexOfResult = psc.getIndexOf(0); - assert.equal(indexOfResult.index, 0); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 0); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(1); - assert.equal(indexOfResult.index, 2); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 2); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(2); - assert.equal(indexOfResult.index, 2); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 2); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(3); - assert.equal(indexOfResult.index, 3); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 3); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(4); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(5); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(6); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 2); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 2); indexOfResult = psc.getIndexOf(7); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 3); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 3); // [1, 0, 0, 1, 3] psc.changeValue(2, 0); - assert.equal(psc.getTotalValue(), 5); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 1); - assert.equal(psc.getAccumulatedValue(2), 1); - assert.equal(psc.getAccumulatedValue(3), 2); - assert.equal(psc.getAccumulatedValue(4), 5); + assert.strictEqual(psc.getTotalValue(), 5); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 1); + assert.strictEqual(psc.getAccumulatedValue(2), 1); + assert.strictEqual(psc.getAccumulatedValue(3), 2); + assert.strictEqual(psc.getAccumulatedValue(4), 5); indexOfResult = psc.getIndexOf(0); - assert.equal(indexOfResult.index, 0); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 0); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(1); - assert.equal(indexOfResult.index, 3); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 3); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(2); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(3); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(4); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 2); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 2); indexOfResult = psc.getIndexOf(5); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 3); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 3); // [1, 0, 0, 0, 3] psc.changeValue(3, 0); - assert.equal(psc.getTotalValue(), 4); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 1); - assert.equal(psc.getAccumulatedValue(2), 1); - assert.equal(psc.getAccumulatedValue(3), 1); - assert.equal(psc.getAccumulatedValue(4), 4); + assert.strictEqual(psc.getTotalValue(), 4); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 1); + assert.strictEqual(psc.getAccumulatedValue(2), 1); + assert.strictEqual(psc.getAccumulatedValue(3), 1); + assert.strictEqual(psc.getAccumulatedValue(4), 4); indexOfResult = psc.getIndexOf(0); - assert.equal(indexOfResult.index, 0); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 0); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(1); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(2); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 1); indexOfResult = psc.getIndexOf(3); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 2); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 2); indexOfResult = psc.getIndexOf(4); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 3); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 3); // [1, 1, 0, 1, 1] psc.changeValue(1, 1); psc.changeValue(3, 1); psc.changeValue(4, 1); - assert.equal(psc.getTotalValue(), 4); - assert.equal(psc.getAccumulatedValue(0), 1); - assert.equal(psc.getAccumulatedValue(1), 2); - assert.equal(psc.getAccumulatedValue(2), 2); - assert.equal(psc.getAccumulatedValue(3), 3); - assert.equal(psc.getAccumulatedValue(4), 4); + assert.strictEqual(psc.getTotalValue(), 4); + assert.strictEqual(psc.getAccumulatedValue(0), 1); + assert.strictEqual(psc.getAccumulatedValue(1), 2); + assert.strictEqual(psc.getAccumulatedValue(2), 2); + assert.strictEqual(psc.getAccumulatedValue(3), 3); + assert.strictEqual(psc.getAccumulatedValue(4), 4); indexOfResult = psc.getIndexOf(0); - assert.equal(indexOfResult.index, 0); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 0); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(1); - assert.equal(indexOfResult.index, 1); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 1); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(2); - assert.equal(indexOfResult.index, 3); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 3); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(3); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 0); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 0); indexOfResult = psc.getIndexOf(4); - assert.equal(indexOfResult.index, 4); - assert.equal(indexOfResult.remainder, 1); + assert.strictEqual(indexOfResult.index, 4); + assert.strictEqual(indexOfResult.remainder, 1); }); }); diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index 63dcb3c3ebe..3f797895235 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -25,42 +25,42 @@ suite('Editor ViewModel - SplitLinesCollection', () => { let model1 = createModel('My First LineMy Second LineAnd another one'); let line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 0); - assert.equal(line1.getViewLineCount(), 3); - assert.equal(line1.getViewLineContent(model1, 1, 0), 'My First Line'); - assert.equal(line1.getViewLineContent(model1, 1, 1), 'My Second Line'); - assert.equal(line1.getViewLineContent(model1, 1, 2), 'And another one'); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 0), 14); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 1), 15); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 2), 16); + assert.strictEqual(line1.getViewLineCount(), 3); + assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line'); + assert.strictEqual(line1.getViewLineContent(model1, 1, 1), 'My Second Line'); + assert.strictEqual(line1.getViewLineContent(model1, 1, 2), 'And another one'); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 15); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 16); for (let col = 1; col <= 14; col++) { - assert.equal(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')'); + assert.strictEqual(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')'); } for (let col = 1; col <= 15; col++) { - assert.equal(line1.getModelColumnOfViewPosition(1, col), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')'); + assert.strictEqual(line1.getModelColumnOfViewPosition(1, col), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')'); } for (let col = 1; col <= 16; col++) { - assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')'); + assert.strictEqual(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')'); } for (let col = 1; col <= 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')'); } for (let col = 1 + 13; col <= 14 + 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, col - 13), 'getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, col - 13), 'getOutputPositionOfInputPosition(' + col + ')'); } for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')'); } model1 = createModel('My First LineMy Second LineAnd another one'); line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 4); - assert.equal(line1.getViewLineCount(), 3); - assert.equal(line1.getViewLineContent(model1, 1, 0), 'My First Line'); - assert.equal(line1.getViewLineContent(model1, 1, 1), ' My Second Line'); - assert.equal(line1.getViewLineContent(model1, 1, 2), ' And another one'); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 0), 14); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 1), 19); - assert.equal(line1.getViewLineMaxColumn(model1, 1, 2), 20); + assert.strictEqual(line1.getViewLineCount(), 3); + assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line'); + assert.strictEqual(line1.getViewLineContent(model1, 1, 1), ' My Second Line'); + assert.strictEqual(line1.getViewLineContent(model1, 1, 2), ' And another one'); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 19); + assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 20); let actualViewColumnMapping: number[][] = []; for (let lineIndex = 0; lineIndex < line1.getViewLineCount(); lineIndex++) { @@ -70,20 +70,20 @@ suite('Editor ViewModel - SplitLinesCollection', () => { } actualViewColumnMapping.push(actualLineViewColumnMapping); } - assert.deepEqual(actualViewColumnMapping, [ + assert.deepStrictEqual(actualViewColumnMapping, [ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], [14, 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28], [28, 28, 28, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43], ]); for (let col = 1; col <= 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), '6.getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), '6.getOutputPositionOfInputPosition(' + col + ')'); } for (let col = 1 + 13; col <= 14 + 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 4 + col - 13), '7.getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 4 + col - 13), '7.getOutputPositionOfInputPosition(' + col + ')'); } for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) { - assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 4 + col - 13 - 14), '8.getOutputPositionOfInputPosition(' + col + ')'); + assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 4 + col - 13 - 14), '8.getOutputPositionOfInputPosition(' + col + ')'); } }); @@ -136,65 +136,65 @@ suite('Editor ViewModel - SplitLinesCollection', () => { ].join('\n'); withSplitLinesCollection(text, (model, linesCollection) => { - assert.equal(linesCollection.getViewLineCount(), 6); + assert.strictEqual(linesCollection.getViewLineCount(), 6); // getOutputIndentGuide - assert.deepEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(0, 0), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(1, 1), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(2, 2), [1]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(3, 3), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(4, 4), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(5, 5), [1]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(6, 6), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(7, 7), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 0), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(1, 1), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(2, 2), [1]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(3, 3), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(4, 4), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(5, 5), [1]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(6, 6), [0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(7, 7), [0]); - assert.deepEqual(linesCollection.getViewLinesIndentGuides(0, 7), [0, 1, 0, 0, 1, 0]); + assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 7), [0, 1, 0, 0, 1, 0]); // getOutputLineContent - assert.equal(linesCollection.getViewLineContent(-1), 'int main() {'); - assert.equal(linesCollection.getViewLineContent(0), 'int main() {'); - assert.equal(linesCollection.getViewLineContent(1), 'int main() {'); - assert.equal(linesCollection.getViewLineContent(2), '\tprintf("Hello world!");'); - assert.equal(linesCollection.getViewLineContent(3), '}'); - assert.equal(linesCollection.getViewLineContent(4), 'int main() {'); - assert.equal(linesCollection.getViewLineContent(5), '\tprintf("Hello world!");'); - assert.equal(linesCollection.getViewLineContent(6), '}'); - assert.equal(linesCollection.getViewLineContent(7), '}'); + assert.strictEqual(linesCollection.getViewLineContent(-1), 'int main() {'); + assert.strictEqual(linesCollection.getViewLineContent(0), 'int main() {'); + assert.strictEqual(linesCollection.getViewLineContent(1), 'int main() {'); + assert.strictEqual(linesCollection.getViewLineContent(2), '\tprintf("Hello world!");'); + assert.strictEqual(linesCollection.getViewLineContent(3), '}'); + assert.strictEqual(linesCollection.getViewLineContent(4), 'int main() {'); + assert.strictEqual(linesCollection.getViewLineContent(5), '\tprintf("Hello world!");'); + assert.strictEqual(linesCollection.getViewLineContent(6), '}'); + assert.strictEqual(linesCollection.getViewLineContent(7), '}'); // getOutputLineMinColumn - assert.equal(linesCollection.getViewLineMinColumn(-1), 1); - assert.equal(linesCollection.getViewLineMinColumn(0), 1); - assert.equal(linesCollection.getViewLineMinColumn(1), 1); - assert.equal(linesCollection.getViewLineMinColumn(2), 1); - assert.equal(linesCollection.getViewLineMinColumn(3), 1); - assert.equal(linesCollection.getViewLineMinColumn(4), 1); - assert.equal(linesCollection.getViewLineMinColumn(5), 1); - assert.equal(linesCollection.getViewLineMinColumn(6), 1); - assert.equal(linesCollection.getViewLineMinColumn(7), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(-1), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(0), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(1), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(2), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(3), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(4), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(5), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(6), 1); + assert.strictEqual(linesCollection.getViewLineMinColumn(7), 1); // getOutputLineMaxColumn - assert.equal(linesCollection.getViewLineMaxColumn(-1), 13); - assert.equal(linesCollection.getViewLineMaxColumn(0), 13); - assert.equal(linesCollection.getViewLineMaxColumn(1), 13); - assert.equal(linesCollection.getViewLineMaxColumn(2), 25); - assert.equal(linesCollection.getViewLineMaxColumn(3), 2); - assert.equal(linesCollection.getViewLineMaxColumn(4), 13); - assert.equal(linesCollection.getViewLineMaxColumn(5), 25); - assert.equal(linesCollection.getViewLineMaxColumn(6), 2); - assert.equal(linesCollection.getViewLineMaxColumn(7), 2); + assert.strictEqual(linesCollection.getViewLineMaxColumn(-1), 13); + assert.strictEqual(linesCollection.getViewLineMaxColumn(0), 13); + assert.strictEqual(linesCollection.getViewLineMaxColumn(1), 13); + assert.strictEqual(linesCollection.getViewLineMaxColumn(2), 25); + assert.strictEqual(linesCollection.getViewLineMaxColumn(3), 2); + assert.strictEqual(linesCollection.getViewLineMaxColumn(4), 13); + assert.strictEqual(linesCollection.getViewLineMaxColumn(5), 25); + assert.strictEqual(linesCollection.getViewLineMaxColumn(6), 2); + assert.strictEqual(linesCollection.getViewLineMaxColumn(7), 2); // convertOutputPositionToInputPosition - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(-1, 1), new Position(1, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(0, 1), new Position(1, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(1, 1), new Position(1, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(2, 1), new Position(2, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(3, 1), new Position(3, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(4, 1), new Position(4, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(5, 1), new Position(5, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(6, 1), new Position(6, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(7, 1), new Position(6, 1)); - assert.deepEqual(linesCollection.convertViewPositionToModelPosition(8, 1), new Position(6, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(-1, 1), new Position(1, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(0, 1), new Position(1, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(1, 1), new Position(1, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(2, 1), new Position(2, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(3, 1), new Position(3, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(4, 1), new Position(4, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(5, 1), new Position(5, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(6, 1), new Position(6, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(7, 1), new Position(6, 1)); + assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(8, 1), new Position(6, 1)); }); }); @@ -216,7 +216,7 @@ suite('Editor ViewModel - SplitLinesCollection', () => { ]); let viewLineCount = linesCollection.getViewLineCount(); - assert.equal(viewLineCount, 1, 'getOutputLineCount()'); + assert.strictEqual(viewLineCount, 1, 'getOutputLineCount()'); let modelLineCount = model.getLineCount(); for (let lineNumber = 0; lineNumber <= modelLineCount + 1; lineNumber++) { @@ -244,7 +244,7 @@ suite('Editor ViewModel - SplitLinesCollection', () => { viewColumn = viewMaxColumn; } let validViewPosition = new Position(viewLineNumber, viewColumn); - assert.equal(viewPosition.toString(), validViewPosition.toString(), 'model->view for ' + lineNumber + ', ' + column); + assert.strictEqual(viewPosition.toString(), validViewPosition.toString(), 'model->view for ' + lineNumber + ', ' + column); } } @@ -254,7 +254,7 @@ suite('Editor ViewModel - SplitLinesCollection', () => { for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) { let modelPosition = linesCollection.convertViewPositionToModelPosition(lineNumber, column); let validModelPosition = model.validatePosition(modelPosition); - assert.equal(modelPosition.toString(), validModelPosition.toString(), 'view->model for ' + lineNumber + ', ' + column); + assert.strictEqual(modelPosition.toString(), validModelPosition.toString(), 'view->model for ' + lineNumber + ', ' + column); } } }); @@ -374,7 +374,7 @@ suite('SplitLinesCollection', () => { value: _actual.getForeground(i) }; } - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } interface ITestMinimapLineRenderingData { @@ -392,14 +392,14 @@ suite('SplitLinesCollection', () => { if (expected === null) { assert.ok(false); } - assert.equal(actual.content, expected.content); - assert.equal(actual.minColumn, expected.minColumn); - assert.equal(actual.maxColumn, expected.maxColumn); + assert.strictEqual(actual.content, expected.content); + assert.strictEqual(actual.minColumn, expected.minColumn); + assert.strictEqual(actual.maxColumn, expected.maxColumn); assertViewLineTokens(actual.tokens, expected.tokens); } function assertMinimapLinesRenderingData(actual: ViewLineData[], expected: Array): void { - assert.equal(actual.length, expected.length); + assert.strictEqual(actual.length, expected.length); for (let i = 0; i < expected.length; i++) { assertMinimapLineRenderingData(actual[i], expected[i]); } @@ -428,15 +428,15 @@ suite('SplitLinesCollection', () => { test('getViewLinesData - no wrapping', () => { withSplitLinesCollection(model!, 'off', 0, (splitLinesCollection) => { - assert.equal(splitLinesCollection.getViewLineCount(), 8); - assert.equal(splitLinesCollection.modelPositionIsVisible(1, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(2, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(3, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(4, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(5, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(6, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(7, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(8, 1), true); + assert.strictEqual(splitLinesCollection.getViewLineCount(), 8); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true); let _expected: ITestMinimapLineRenderingData[] = [ { @@ -540,15 +540,15 @@ suite('SplitLinesCollection', () => { ]); splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]); - assert.equal(splitLinesCollection.getViewLineCount(), 5); - assert.equal(splitLinesCollection.modelPositionIsVisible(1, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(2, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(3, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(4, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(5, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(6, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(7, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(8, 1), true); + assert.strictEqual(splitLinesCollection.getViewLineCount(), 5); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true); assertAllMinimapLinesRenderingData(splitLinesCollection, [ _expected[0], @@ -562,15 +562,15 @@ suite('SplitLinesCollection', () => { test('getViewLinesData - with wrapping', () => { withSplitLinesCollection(model!, 'wordWrapColumn', 30, (splitLinesCollection) => { - assert.equal(splitLinesCollection.getViewLineCount(), 12); - assert.equal(splitLinesCollection.modelPositionIsVisible(1, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(2, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(3, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(4, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(5, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(6, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(7, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(8, 1), true); + assert.strictEqual(splitLinesCollection.getViewLineCount(), 12); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true); let _expected: ITestMinimapLineRenderingData[] = [ { @@ -710,15 +710,15 @@ suite('SplitLinesCollection', () => { ]); splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]); - assert.equal(splitLinesCollection.getViewLineCount(), 8); - assert.equal(splitLinesCollection.modelPositionIsVisible(1, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(2, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(3, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(4, 1), false); - assert.equal(splitLinesCollection.modelPositionIsVisible(5, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(6, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(7, 1), true); - assert.equal(splitLinesCollection.modelPositionIsVisible(8, 1), true); + assert.strictEqual(splitLinesCollection.getViewLineCount(), 8); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true); + assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true); assertAllMinimapLinesRenderingData(splitLinesCollection, [ _expected[0], diff --git a/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts b/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts index cd9906811b8..9b286277343 100644 --- a/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts +++ b/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { Range } from 'vs/editor/common/core/range'; -import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; +import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; import { testViewModel } from 'vs/editor/test/common/viewModel/testViewModel'; suite('ViewModelDecorations', () => { @@ -19,11 +19,11 @@ suite('ViewModelDecorations', () => { wordWrapColumn: 13 }; testViewModel(text, opts, (viewModel, model) => { - assert.equal(viewModel.getLineContent(1), 'hello world, '); - assert.equal(viewModel.getLineContent(2), 'this is a '); - assert.equal(viewModel.getLineContent(3), 'buffer that '); - assert.equal(viewModel.getLineContent(4), 'will be '); - assert.equal(viewModel.getLineContent(5), 'wrapped'); + assert.strictEqual(viewModel.getLineContent(1), 'hello world, '); + assert.strictEqual(viewModel.getLineContent(2), 'this is a '); + assert.strictEqual(viewModel.getLineContent(3), 'buffer that '); + assert.strictEqual(viewModel.getLineContent(4), 'will be '); + assert.strictEqual(viewModel.getLineContent(5), 'wrapped'); model.changeDecorations((accessor) => { let createOpts = (id: string) => { @@ -79,7 +79,7 @@ suite('ViewModelDecorations', () => { return dec.options.className; }).filter(Boolean); - assert.deepEqual(actualDecorations, [ + assert.deepStrictEqual(actualDecorations, [ 'dec1', 'dec2', 'dec3', @@ -102,112 +102,28 @@ suite('ViewModelDecorations', () => { ).inlineDecorations; // view line 2: (1,14 -> 1,24) - assert.deepEqual(inlineDecorations1, [ - { - range: new Range(1, 2, 2, 2), - inlineClassName: 'i-dec3', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 2, 2, 2), - inlineClassName: 'a-dec3', - type: InlineDecorationType.After - }, - { - range: new Range(1, 2, 3, 13), - inlineClassName: 'i-dec4', - type: InlineDecorationType.Regular - }, - { - range: new Range(1, 2, 5, 8), - inlineClassName: 'i-dec5', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'i-dec6', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'b-dec6', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'a-dec6', - type: InlineDecorationType.After - }, - { - range: new Range(2, 1, 2, 3), - inlineClassName: 'i-dec7', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'b-dec7', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 3, 2, 3), - inlineClassName: 'a-dec7', - type: InlineDecorationType.After - }, - { - range: new Range(2, 1, 3, 13), - inlineClassName: 'i-dec8', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'b-dec8', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 1, 5, 8), - inlineClassName: 'i-dec9', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 2, 1), - inlineClassName: 'b-dec9', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 3, 2, 5), - inlineClassName: 'i-dec10', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 3, 2, 3), - inlineClassName: 'b-dec10', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 5, 2, 5), - inlineClassName: 'a-dec10', - type: InlineDecorationType.After - }, - { - range: new Range(2, 3, 3, 13), - inlineClassName: 'i-dec11', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 3, 2, 3), - inlineClassName: 'b-dec11', - type: InlineDecorationType.Before - }, - { - range: new Range(2, 3, 5, 8), - inlineClassName: 'i-dec12', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 3, 2, 3), - inlineClassName: 'b-dec12', - type: InlineDecorationType.Before - }, + assert.deepStrictEqual(inlineDecorations1, [ + new InlineDecoration(new Range(1, 2, 2, 2), 'i-dec3', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 2, 2, 2), 'a-dec3', InlineDecorationType.After), + new InlineDecoration(new Range(1, 2, 3, 13), 'i-dec4', InlineDecorationType.Regular), + new InlineDecoration(new Range(1, 2, 5, 8), 'i-dec5', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 2, 1), 'i-dec6', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 2, 1), 'b-dec6', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 1, 2, 1), 'a-dec6', InlineDecorationType.After), + new InlineDecoration(new Range(2, 1, 2, 3), 'i-dec7', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 2, 1), 'b-dec7', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 3, 2, 3), 'a-dec7', InlineDecorationType.After), + new InlineDecoration(new Range(2, 1, 3, 13), 'i-dec8', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 2, 1), 'b-dec8', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 1, 5, 8), 'i-dec9', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 2, 1), 'b-dec9', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 3, 2, 5), 'i-dec10', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 3, 2, 3), 'b-dec10', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 5, 2, 5), 'a-dec10', InlineDecorationType.After), + new InlineDecoration(new Range(2, 3, 3, 13), 'i-dec11', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 3, 2, 3), 'b-dec11', InlineDecorationType.Before), + new InlineDecoration(new Range(2, 3, 5, 8), 'i-dec12', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 3, 2, 3), 'b-dec12', InlineDecorationType.Before), ]); let inlineDecorations2 = viewModel.getViewLineRenderingData( @@ -216,52 +132,16 @@ suite('ViewModelDecorations', () => { ).inlineDecorations; // view line 3 (24 -> 36) - assert.deepEqual(inlineDecorations2, [ - { - range: new Range(1, 2, 3, 13), - inlineClassName: 'i-dec4', - type: InlineDecorationType.Regular - }, - { - range: new Range(3, 13, 3, 13), - inlineClassName: 'a-dec4', - type: InlineDecorationType.After - }, - { - range: new Range(1, 2, 5, 8), - inlineClassName: 'i-dec5', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 1, 3, 13), - inlineClassName: 'i-dec8', - type: InlineDecorationType.Regular - }, - { - range: new Range(3, 13, 3, 13), - inlineClassName: 'a-dec8', - type: InlineDecorationType.After - }, - { - range: new Range(2, 1, 5, 8), - inlineClassName: 'i-dec9', - type: InlineDecorationType.Regular - }, - { - range: new Range(2, 3, 3, 13), - inlineClassName: 'i-dec11', - type: InlineDecorationType.Regular - }, - { - range: new Range(3, 13, 3, 13), - inlineClassName: 'a-dec11', - type: InlineDecorationType.After - }, - { - range: new Range(2, 3, 5, 8), - inlineClassName: 'i-dec12', - type: InlineDecorationType.Regular - }, + assert.deepStrictEqual(inlineDecorations2, [ + new InlineDecoration(new Range(1, 2, 3, 13), 'i-dec4', InlineDecorationType.Regular), + new InlineDecoration(new Range(3, 13, 3, 13), 'a-dec4', InlineDecorationType.After), + new InlineDecoration(new Range(1, 2, 5, 8), 'i-dec5', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 1, 3, 13), 'i-dec8', InlineDecorationType.Regular), + new InlineDecoration(new Range(3, 13, 3, 13), 'a-dec8', InlineDecorationType.After), + new InlineDecoration(new Range(2, 1, 5, 8), 'i-dec9', InlineDecorationType.Regular), + new InlineDecoration(new Range(2, 3, 3, 13), 'i-dec11', InlineDecorationType.Regular), + new InlineDecoration(new Range(3, 13, 3, 13), 'a-dec11', InlineDecorationType.After), + new InlineDecoration(new Range(2, 3, 5, 8), 'i-dec12', InlineDecorationType.Regular), ]); }); }); @@ -275,11 +155,11 @@ suite('ViewModelDecorations', () => { wordWrapColumn: 13 }; testViewModel(text, opts, (viewModel, model) => { - assert.equal(viewModel.getLineContent(1), 'hello world, '); - assert.equal(viewModel.getLineContent(2), 'this is a '); - assert.equal(viewModel.getLineContent(3), 'buffer that '); - assert.equal(viewModel.getLineContent(4), 'will be '); - assert.equal(viewModel.getLineContent(5), 'wrapped'); + assert.strictEqual(viewModel.getLineContent(1), 'hello world, '); + assert.strictEqual(viewModel.getLineContent(2), 'this is a '); + assert.strictEqual(viewModel.getLineContent(3), 'buffer that '); + assert.strictEqual(viewModel.getLineContent(4), 'will be '); + assert.strictEqual(viewModel.getLineContent(5), 'wrapped'); model.changeDecorations((accessor) => { accessor.addDecoration( @@ -293,19 +173,19 @@ suite('ViewModelDecorations', () => { let decorations = viewModel.getDecorationsInViewport( new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)) ).filter(x => Boolean(x.options.beforeContentClassName)); - assert.deepEqual(decorations, []); + assert.deepStrictEqual(decorations, []); let inlineDecorations1 = viewModel.getViewLineRenderingData( new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)), 2 ).inlineDecorations; - assert.deepEqual(inlineDecorations1, []); + assert.deepStrictEqual(inlineDecorations1, []); let inlineDecorations2 = viewModel.getViewLineRenderingData( new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)), 3 ).inlineDecorations; - assert.deepEqual(inlineDecorations2, []); + assert.deepStrictEqual(inlineDecorations2, []); }); }); @@ -329,17 +209,9 @@ suite('ViewModelDecorations', () => { new Range(1, 1, 1, 1), 1 ).inlineDecorations; - assert.deepEqual(inlineDecorations, [ - { - range: new Range(1, 1, 1, 1), - inlineClassName: 'before1', - type: InlineDecorationType.Before - }, - { - range: new Range(1, 1, 1, 1), - inlineClassName: 'after1', - type: InlineDecorationType.After - } + assert.deepStrictEqual(inlineDecorations, [ + new InlineDecoration(new Range(1, 1, 1, 1), 'before1', InlineDecorationType.Before), + new InlineDecoration(new Range(1, 1, 1, 1), 'after1', InlineDecorationType.After) ]); }); }); diff --git a/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts b/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts index 1e025ef3a9e..d556f3da7a5 100644 --- a/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts +++ b/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts @@ -18,7 +18,7 @@ suite('ViewModel', () => { lineNumbersMinChars: 1 }; testViewModel(text, opts, (viewModel, model) => { - assert.equal(viewModel.getLineCount(), 1); + assert.strictEqual(viewModel.getLineCount(), 1); viewModel.setViewport(1, 1, 1); @@ -38,14 +38,14 @@ suite('ViewModel', () => { ].join('\n') }]); - assert.equal(viewModel.getLineCount(), 10); + assert.strictEqual(viewModel.getLineCount(), 10); }); }); test('issue #44805: SplitLinesCollection: attempt to access a \'newer\' model', () => { const text = ['']; testViewModel(text, {}, (viewModel, model) => { - assert.equal(viewModel.getLineCount(), 1); + assert.strictEqual(viewModel.getLineCount(), 1); model.pushEditOperations([], [{ range: new Range(1, 1, 1, 1), @@ -74,7 +74,7 @@ suite('ViewModel', () => { model.undo(); viewLineCount.push(viewModel.getLineCount()); - assert.deepEqual(viewLineCount, [4, 1, 1, 1, 1]); + assert.deepStrictEqual(viewLineCount, [4, 1, 1, 1, 1]); }); }); @@ -85,7 +85,7 @@ suite('ViewModel', () => { 'line3' ]; testViewModel(text, {}, (viewModel, model) => { - assert.equal(viewModel.getLineCount(), 3); + assert.strictEqual(viewModel.getLineCount(), 3); viewModel.setHiddenAreas([new Range(1, 1, 3, 1)]); assert.ok(viewModel.getVisibleRanges() !== null); }); @@ -96,7 +96,7 @@ suite('ViewModel', () => { '' ]; testViewModel(text, {}, (viewModel, model) => { - assert.equal(viewModel.getLineCount(), 1); + assert.strictEqual(viewModel.getLineCount(), 1); model.pushEditOperations([], [{ range: new Range(1, 1, 1, 1), @@ -104,7 +104,7 @@ suite('ViewModel', () => { }], () => ([])); viewModel.setHiddenAreas([new Range(1, 1, 1, 1)]); - assert.equal(viewModel.getLineCount(), 2); + assert.strictEqual(viewModel.getLineCount(), 2); model.undo(); assert.ok(viewModel.getVisibleRanges() !== null); @@ -114,7 +114,7 @@ suite('ViewModel', () => { function assertGetPlainTextToCopy(text: string[], ranges: Range[], emptySelectionClipboard: boolean, expected: string | string[]): void { testViewModel(text, {}, (viewModel, model) => { let actual = viewModel.getPlainTextToCopy(ranges, emptySelectionClipboard, false); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); }); } @@ -259,7 +259,7 @@ suite('ViewModel', () => { testViewModel(USUAL_TEXT, {}, (viewModel, model) => { model.setEOL(EndOfLineSequence.LF); let actual = viewModel.getPlainTextToCopy([new Range(2, 1, 5, 1)], true, true); - assert.deepEqual(actual, 'line2\r\nline3\r\nline4\r\n'); + assert.deepStrictEqual(actual, 'line2\r\nline3\r\nline4\r\n'); }); }); diff --git a/src/vs/editor/test/node/classification/typescript.test.ts b/src/vs/editor/test/node/classification/typescript.test.ts index 5e399061a7b..19c7b901e7f 100644 --- a/src/vs/editor/test/node/classification/typescript.test.ts +++ b/src/vs/editor/test/node/classification/typescript.test.ts @@ -126,7 +126,7 @@ function executeTest(fileName: string, parseFunc: IParseFunc): void { actual[3 * actualIndex] + actual[3 * actualIndex + 1] >= assertion.startOffset + assertion.length, `Line ${assertion.testLineNumber} : length : ${actual[3 * actualIndex]} + ${actual[3 * actualIndex + 1]} >= ${assertion.startOffset} + ${assertion.length}.` ); - assert.equal( + assert.strictEqual( actual[3 * actualIndex + 2], assertion.tokenType, `Line ${assertion.testLineNumber} : tokenType`); diff --git a/src/vs/platform/contextkey/test/browser/contextkey.test.ts b/src/vs/platform/contextkey/test/browser/contextkey.test.ts index d436b6cdf12..aca26b1dd09 100644 --- a/src/vs/platform/contextkey/test/browser/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/browser/contextkey.test.ts @@ -34,10 +34,10 @@ suite('ContextKeyService', () => { assert.ok(e.affectsSome(new Set(['testC'])), 'testC changed'); assert.ok(!e.affectsSome(new Set(['testD'])), 'testD did not change'); - assert.equal(child.getContextKeyValue('testA'), 3); - assert.equal(child.getContextKeyValue('testB'), undefined); - assert.equal(child.getContextKeyValue('testC'), 4); - assert.equal(child.getContextKeyValue('testD'), 0); + assert.strictEqual(child.getContextKeyValue('testA'), 3); + assert.strictEqual(child.getContextKeyValue('testB'), undefined); + assert.strictEqual(child.getContextKeyValue('testC'), 4); + assert.strictEqual(child.getContextKeyValue('testD'), 0); } catch (err) { reject(err); return; diff --git a/src/vs/platform/contextkey/test/common/contextkey.test.ts b/src/vs/platform/contextkey/test/common/contextkey.test.ts index 91a548be66c..1abe1a07642 100644 --- a/src/vs/platform/contextkey/test/common/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/common/contextkey.test.ts @@ -67,7 +67,7 @@ suite('ContextKeyExpr', () => { function testExpression(expr: string, expected: boolean): void { // console.log(expr + ' ' + expected); let rules = ContextKeyExpr.deserialize(expr); - assert.equal(rules!.evaluate(context), expected, expr); + assert.strictEqual(rules!.evaluate(context), expected, expr); } function testBatch(expr: string, value: any): void { /* eslint-disable eqeqeq */ @@ -153,17 +153,17 @@ suite('ContextKeyExpr', () => { test('ContextKeyInExpr', () => { const ainb = ContextKeyExpr.deserialize('a in b')!; - assert.equal(ainb.evaluate(createContext({ 'a': 3, 'b': [3, 2, 1] })), true); - assert.equal(ainb.evaluate(createContext({ 'a': 3, 'b': [1, 2, 3] })), true); - assert.equal(ainb.evaluate(createContext({ 'a': 3, 'b': [1, 2] })), false); - assert.equal(ainb.evaluate(createContext({ 'a': 3 })), false); - assert.equal(ainb.evaluate(createContext({ 'a': 3, 'b': null })), false); - assert.equal(ainb.evaluate(createContext({ 'a': 'x', 'b': ['x'] })), true); - assert.equal(ainb.evaluate(createContext({ 'a': 'x', 'b': ['y'] })), false); - assert.equal(ainb.evaluate(createContext({ 'a': 'x', 'b': {} })), false); - assert.equal(ainb.evaluate(createContext({ 'a': 'x', 'b': { 'x': false } })), true); - assert.equal(ainb.evaluate(createContext({ 'a': 'x', 'b': { 'x': true } })), true); - assert.equal(ainb.evaluate(createContext({ 'a': 'prototype', 'b': {} })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 3, 'b': [3, 2, 1] })), true); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 3, 'b': [1, 2, 3] })), true); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 3, 'b': [1, 2] })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 3 })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 3, 'b': null })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'x', 'b': ['x'] })), true); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'x', 'b': ['y'] })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'x', 'b': {} })), false); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'x', 'b': { 'x': false } })), true); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'x', 'b': { 'x': true } })), true); + assert.strictEqual(ainb.evaluate(createContext({ 'a': 'prototype', 'b': {} })), false); }); test('issue #106524: distributing AND should normalize', () => { @@ -184,13 +184,13 @@ suite('ContextKeyExpr', () => { ContextKeyExpr.has('c') ) ); - assert.equal(actual!.equals(expected!), true); + assert.strictEqual(actual!.equals(expected!), true); }); test('Greater, GreaterEquals, Smaller, SmallerEquals evaluate', () => { function checkEvaluate(expr: string, ctx: any, expected: any): void { const _expr = ContextKeyExpr.deserialize(expr)!; - assert.equal(_expr.evaluate(createContext(ctx)), expected); + assert.strictEqual(_expr.evaluate(createContext(ctx)), expected); } checkEvaluate('a>1', {}, false); @@ -236,7 +236,7 @@ suite('ContextKeyExpr', () => { function checkNegate(expr: string, expected: string): void { const a = ContextKeyExpr.deserialize(expr)!; const b = a.negate(); - assert.equal(b.serialize(), expected); + assert.strictEqual(b.serialize(), expected); } checkNegate('a>1', 'a <= 1'); diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index cbbb5434457..d627e662606 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -211,13 +211,13 @@ suite('AbstractKeybindingService', () => { // send Ctrl/Cmd + K let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, []); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, [ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, [ `(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...` ]); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -225,13 +225,13 @@ suite('AbstractKeybindingService', () => { // send backspace shouldPreventDefault = kbService.testDispatch(KeyCode.Backspace); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, []); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, [ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, [ `The key combination (${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}, ${toUsLabel(KeyCode.Backspace)}) is not a command.` ]); - assert.deepEqual(statusMessageCallsDisposed, [ + assert.deepStrictEqual(statusMessageCallsDisposed, [ `(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...` ]); executeCommandCalls = []; @@ -241,14 +241,14 @@ suite('AbstractKeybindingService', () => { // send backspace shouldPreventDefault = kbService.testDispatch(KeyCode.Backspace); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'simpleCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -273,11 +273,11 @@ suite('AbstractKeybindingService', () => { function assertIsIgnored(keybinding: number): void { let shouldPreventDefault = kbService.testDispatch(keybinding); - assert.equal(shouldPreventDefault, false); - assert.deepEqual(executeCommandCalls, []); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.strictEqual(shouldPreventDefault, false); + assert.deepStrictEqual(executeCommandCalls, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -310,14 +310,14 @@ suite('AbstractKeybindingService', () => { key1: true }); let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'simpleCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -326,13 +326,13 @@ suite('AbstractKeybindingService', () => { // send Ctrl/Cmd + K currentContextValue = createContext({}); shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, []); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, [ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, [ `(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...` ]); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -341,14 +341,14 @@ suite('AbstractKeybindingService', () => { // send Ctrl/Cmd + X currentContextValue = createContext({}); shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_X); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'chordCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, [ + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, [ `(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...` ]); executeCommandCalls = []; @@ -370,14 +370,14 @@ suite('AbstractKeybindingService', () => { // send Ctrl/Cmd + K currentContextValue = createContext({}); let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'simpleCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -388,14 +388,14 @@ suite('AbstractKeybindingService', () => { key1: true }); shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, true); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, true); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'simpleCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -406,11 +406,11 @@ suite('AbstractKeybindingService', () => { key1: true }); shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_X); - assert.equal(shouldPreventDefault, false); - assert.deepEqual(executeCommandCalls, []); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.strictEqual(shouldPreventDefault, false); + assert.deepStrictEqual(executeCommandCalls, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; @@ -428,14 +428,14 @@ suite('AbstractKeybindingService', () => { // send Ctrl/Cmd + K currentContextValue = createContext({}); let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K); - assert.equal(shouldPreventDefault, false); - assert.deepEqual(executeCommandCalls, [{ + assert.strictEqual(shouldPreventDefault, false); + assert.deepStrictEqual(executeCommandCalls, [{ commandId: 'simpleCommand', args: [null] }]); - assert.deepEqual(showMessageCalls, []); - assert.deepEqual(statusMessageCalls, []); - assert.deepEqual(statusMessageCallsDisposed, []); + assert.deepStrictEqual(showMessageCalls, []); + assert.deepStrictEqual(statusMessageCalls, []); + assert.deepStrictEqual(statusMessageCallsDisposed, []); executeCommandCalls = []; showMessageCalls = []; statusMessageCalls = []; diff --git a/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts b/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts index a321d9b38bb..f1ef51b6428 100644 --- a/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts +++ b/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts @@ -11,7 +11,7 @@ suite('KeybindingLabels', () => { function assertUSLabel(OS: OperatingSystem, keybinding: number, expected: string): void { const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS); - assert.equal(usResolvedKeybinding.getLabel(), expected); + assert.strictEqual(usResolvedKeybinding.getLabel(), expected); } test('Windows US label', () => { @@ -116,7 +116,7 @@ suite('KeybindingLabels', () => { test('Aria label', () => { function assertAriaLabel(OS: OperatingSystem, keybinding: number, expected: string): void { const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS); - assert.equal(usResolvedKeybinding.getAriaLabel(), expected); + assert.strictEqual(usResolvedKeybinding.getAriaLabel(), expected); } assertAriaLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Control+Shift+Alt+Windows+A'); @@ -127,7 +127,7 @@ suite('KeybindingLabels', () => { test('Electron Accelerator label', () => { function assertElectronAcceleratorLabel(OS: OperatingSystem, keybinding: number, expected: string | null): void { const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS); - assert.equal(usResolvedKeybinding.getElectronAccelerator(), expected); + assert.strictEqual(usResolvedKeybinding.getElectronAccelerator(), expected); } assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Super+A'); @@ -154,7 +154,7 @@ suite('KeybindingLabels', () => { test('User Settings label', () => { function assertElectronAcceleratorLabel(OS: OperatingSystem, keybinding: number, expected: string): void { const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS); - assert.equal(usResolvedKeybinding.getUserSettingsLabel(), expected); + assert.strictEqual(usResolvedKeybinding.getUserSettingsLabel(), expected); } assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+alt+win+a'); diff --git a/src/vs/platform/keybinding/test/common/keybindingResolver.test.ts b/src/vs/platform/keybinding/test/common/keybindingResolver.test.ts index 2820e0ea4a6..33472df8a78 100644 --- a/src/vs/platform/keybinding/test/common/keybindingResolver.test.ts +++ b/src/vs/platform/keybinding/test/common/keybindingResolver.test.ts @@ -43,12 +43,12 @@ suite('KeybindingResolver', () => { let contextRules = ContextKeyExpr.equals('bar', 'baz'); let keybindingItem = kbItem(keybinding, 'yes', null, contextRules, true); - assert.equal(KeybindingResolver.contextMatchesRules(createContext({ bar: 'baz' }), contextRules), true); - assert.equal(KeybindingResolver.contextMatchesRules(createContext({ bar: 'bz' }), contextRules), false); + assert.strictEqual(KeybindingResolver.contextMatchesRules(createContext({ bar: 'baz' }), contextRules), true); + assert.strictEqual(KeybindingResolver.contextMatchesRules(createContext({ bar: 'bz' }), contextRules), false); let resolver = new KeybindingResolver([keybindingItem], [], () => { }); - assert.equal(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandId, 'yes'); - assert.equal(resolver.resolve(createContext({ bar: 'bz' }), null, getDispatchStr(runtimeKeybinding)), null); + assert.strictEqual(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandId, 'yes'); + assert.strictEqual(resolver.resolve(createContext({ bar: 'bz' }), null, getDispatchStr(runtimeKeybinding)), null); }); test('resolve key with arguments', function () { @@ -59,7 +59,7 @@ suite('KeybindingResolver', () => { let keybindingItem = kbItem(keybinding, 'yes', commandArgs, contextRules, true); let resolver = new KeybindingResolver([keybindingItem], [], () => { }); - assert.equal(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandArgs, commandArgs); + assert.strictEqual(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandArgs, commandArgs); }); test('KeybindingResolver.combine simple 1', function () { @@ -70,7 +70,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true), kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false), ]); @@ -85,7 +85,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_C, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true), kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true), kbItem(KeyCode.KEY_C, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false), @@ -101,7 +101,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_A, '-yes1', null, ContextKeyExpr.equals('1', 'b'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true), kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); @@ -116,7 +116,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_B, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true), kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); @@ -131,7 +131,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_A, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); }); @@ -145,7 +145,7 @@ suite('KeybindingResolver', () => { kbItem(0, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); }); @@ -159,7 +159,7 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_A, '-yes1', null, null!, false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); }); @@ -173,7 +173,7 @@ suite('KeybindingResolver', () => { kbItem(0, '-yes1', null, null!, false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); }); @@ -187,17 +187,17 @@ suite('KeybindingResolver', () => { kbItem(KeyCode.KEY_A, '-yes1', null, null!, false) ]; let actual = KeybindingResolver.combine(defaults, overrides); - assert.deepEqual(actual, [ + assert.deepStrictEqual(actual, [ kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true) ]); }); test('contextIsEntirelyIncluded', () => { const assertIsIncluded = (a: string | null, b: string | null) => { - assert.equal(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), true); + assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), true); }; const assertIsNotIncluded = (a: string | null, b: string | null) => { - assert.equal(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), false); + assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), false); }; assertIsIncluded('key1', null); @@ -314,11 +314,11 @@ suite('KeybindingResolver', () => { let testKey = (commandId: string, expectedKeys: number[]) => { // Test lookup let lookupResult = resolver.lookupKeybindings(commandId); - assert.equal(lookupResult.length, expectedKeys.length, 'Length mismatch @ commandId ' + commandId + '; GOT: ' + JSON.stringify(lookupResult, null, '\t')); + assert.strictEqual(lookupResult.length, expectedKeys.length, 'Length mismatch @ commandId ' + commandId + '; GOT: ' + JSON.stringify(lookupResult, null, '\t')); for (let i = 0, len = lookupResult.length; i < len; i++) { const expected = new USLayoutResolvedKeybinding(createKeybinding(expectedKeys[i], OS)!, OS); - assert.equal(lookupResult[i].resolvedKeybinding!.getUserSettingsLabel(), expected.getUserSettingsLabel(), 'value mismatch @ commandId ' + commandId); + assert.strictEqual(lookupResult[i].resolvedKeybinding!.getUserSettingsLabel(), expected.getUserSettingsLabel(), 'value mismatch @ commandId ' + commandId); } }; @@ -333,14 +333,14 @@ suite('KeybindingResolver', () => { // if it's the final part, then we should find a valid command, // and there should not be a chord. assert.ok(result !== null, `Enters chord for ${commandId} at part ${i}`); - assert.equal(result!.commandId, commandId, `Enters chord for ${commandId} at part ${i}`); - assert.equal(result!.enterChord, false, `Enters chord for ${commandId} at part ${i}`); + assert.strictEqual(result!.commandId, commandId, `Enters chord for ${commandId} at part ${i}`); + assert.strictEqual(result!.enterChord, false, `Enters chord for ${commandId} at part ${i}`); } else { // if it's not the final part, then we should not find a valid command, // and there should be a chord. assert.ok(result !== null, `Enters chord for ${commandId} at part ${i}`); - assert.equal(result!.commandId, null, `Enters chord for ${commandId} at part ${i}`); - assert.equal(result!.enterChord, true, `Enters chord for ${commandId} at part ${i}`); + assert.strictEqual(result!.commandId, null, `Enters chord for ${commandId} at part ${i}`); + assert.strictEqual(result!.enterChord, true, `Enters chord for ${commandId} at part ${i}`); } previousPart = part; } diff --git a/src/vs/platform/undoRedo/test/common/undoRedoService.test.ts b/src/vs/platform/undoRedo/test/common/undoRedoService.test.ts index 4c0a48e5875..49f4944544b 100644 --- a/src/vs/platform/undoRedo/test/common/undoRedoService.test.ts +++ b/src/vs/platform/undoRedo/test/common/undoRedoService.test.ts @@ -23,9 +23,9 @@ suite('UndoRedoService', () => { const resource = URI.file('test.txt'); const service = createUndoRedoService(); - assert.equal(service.canUndo(resource), false); - assert.equal(service.canRedo(resource), false); - assert.equal(service.hasElements(resource), false); + assert.strictEqual(service.canUndo(resource), false); + assert.strictEqual(service.canRedo(resource), false); + assert.strictEqual(service.hasElements(resource), false); assert.ok(service.getLastElement(resource) === null); let undoCall1 = 0; @@ -39,27 +39,27 @@ suite('UndoRedoService', () => { }; service.pushElement(element1); - assert.equal(undoCall1, 0); - assert.equal(redoCall1, 0); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), false); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 0); + assert.strictEqual(redoCall1, 0); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), false); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === element1); service.undo(resource); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 0); - assert.equal(service.canUndo(resource), false); - assert.equal(service.canRedo(resource), true); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 0); + assert.strictEqual(service.canUndo(resource), false); + assert.strictEqual(service.canRedo(resource), true); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === null); service.redo(resource); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), false); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), false); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === element1); let undoCall2 = 0; @@ -73,24 +73,24 @@ suite('UndoRedoService', () => { }; service.pushElement(element2); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(undoCall2, 0); - assert.equal(redoCall2, 0); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), false); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(undoCall2, 0); + assert.strictEqual(redoCall2, 0); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), false); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === element2); service.undo(resource); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(undoCall2, 1); - assert.equal(redoCall2, 0); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), true); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(undoCall2, 1); + assert.strictEqual(redoCall2, 0); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), true); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === null); let undoCall3 = 0; @@ -104,28 +104,28 @@ suite('UndoRedoService', () => { }; service.pushElement(element3); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(undoCall2, 1); - assert.equal(redoCall2, 0); - assert.equal(undoCall3, 0); - assert.equal(redoCall3, 0); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), false); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(undoCall2, 1); + assert.strictEqual(redoCall2, 0); + assert.strictEqual(undoCall3, 0); + assert.strictEqual(redoCall3, 0); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), false); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === element3); service.undo(resource); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(undoCall2, 1); - assert.equal(redoCall2, 0); - assert.equal(undoCall3, 1); - assert.equal(redoCall3, 0); - assert.equal(service.canUndo(resource), true); - assert.equal(service.canRedo(resource), true); - assert.equal(service.hasElements(resource), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(undoCall2, 1); + assert.strictEqual(redoCall2, 0); + assert.strictEqual(undoCall3, 1); + assert.strictEqual(redoCall3, 0); + assert.strictEqual(service.canUndo(resource), true); + assert.strictEqual(service.canRedo(resource), true); + assert.strictEqual(service.hasElements(resource), true); assert.ok(service.getLastElement(resource) === null); }); @@ -169,50 +169,50 @@ suite('UndoRedoService', () => { }; service.pushElement(element1); - assert.equal(service.canUndo(resource1), true); - assert.equal(service.canRedo(resource1), false); - assert.equal(service.hasElements(resource1), true); + assert.strictEqual(service.canUndo(resource1), true); + assert.strictEqual(service.canRedo(resource1), false); + assert.strictEqual(service.hasElements(resource1), true); assert.ok(service.getLastElement(resource1) === element1); - assert.equal(service.canUndo(resource2), true); - assert.equal(service.canRedo(resource2), false); - assert.equal(service.hasElements(resource2), true); + assert.strictEqual(service.canUndo(resource2), true); + assert.strictEqual(service.canRedo(resource2), false); + assert.strictEqual(service.hasElements(resource2), true); assert.ok(service.getLastElement(resource2) === element1); await service.undo(resource1); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 0); - assert.equal(service.canUndo(resource1), false); - assert.equal(service.canRedo(resource1), true); - assert.equal(service.hasElements(resource1), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 0); + assert.strictEqual(service.canUndo(resource1), false); + assert.strictEqual(service.canRedo(resource1), true); + assert.strictEqual(service.hasElements(resource1), true); assert.ok(service.getLastElement(resource1) === null); - assert.equal(service.canUndo(resource2), false); - assert.equal(service.canRedo(resource2), true); - assert.equal(service.hasElements(resource2), true); + assert.strictEqual(service.canUndo(resource2), false); + assert.strictEqual(service.canRedo(resource2), true); + assert.strictEqual(service.hasElements(resource2), true); assert.ok(service.getLastElement(resource2) === null); await service.redo(resource2); - assert.equal(undoCall1, 1); - assert.equal(redoCall1, 1); - assert.equal(undoCall11, 0); - assert.equal(redoCall11, 0); - assert.equal(undoCall12, 0); - assert.equal(redoCall12, 0); - assert.equal(service.canUndo(resource1), true); - assert.equal(service.canRedo(resource1), false); - assert.equal(service.hasElements(resource1), true); + assert.strictEqual(undoCall1, 1); + assert.strictEqual(redoCall1, 1); + assert.strictEqual(undoCall11, 0); + assert.strictEqual(redoCall11, 0); + assert.strictEqual(undoCall12, 0); + assert.strictEqual(redoCall12, 0); + assert.strictEqual(service.canUndo(resource1), true); + assert.strictEqual(service.canRedo(resource1), false); + assert.strictEqual(service.hasElements(resource1), true); assert.ok(service.getLastElement(resource1) === element1); - assert.equal(service.canUndo(resource2), true); - assert.equal(service.canRedo(resource2), false); - assert.equal(service.hasElements(resource2), true); + assert.strictEqual(service.canUndo(resource2), true); + assert.strictEqual(service.canRedo(resource2), false); + assert.strictEqual(service.hasElements(resource2), true); assert.ok(service.getLastElement(resource2) === element1); }); test('UndoRedoGroup.None uses id 0', () => { - assert.equal(UndoRedoGroup.None.id, 0); - assert.equal(UndoRedoGroup.None.nextOrder(), 0); - assert.equal(UndoRedoGroup.None.nextOrder(), 0); + assert.strictEqual(UndoRedoGroup.None.id, 0); + assert.strictEqual(UndoRedoGroup.None.nextOrder(), 0); + assert.strictEqual(UndoRedoGroup.None.nextOrder(), 0); }); }); 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 77a803dfa60..6d8c494380c 100644 --- a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts +++ b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts @@ -9,80 +9,80 @@ import { ExtensionRunningLocation } from 'vs/workbench/services/extensions/commo suite('BrowserExtensionService', () => { test('pickRunningLocation', () => { - assert.deepEqual(BrowserExtensionService.pickRunningLocation([], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation([], false, true), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation([], true, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation([], true, true), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, true), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, true), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false), ExtensionRunningLocation.None); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true), ExtensionRunningLocation.Remote); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); - assert.deepEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true), ExtensionRunningLocation.Remote); }); }); diff --git a/src/vs/workbench/services/extensions/test/common/extensionsUtil.test.ts b/src/vs/workbench/services/extensions/test/common/extensionsUtil.test.ts index b5c5671dd01..4ca1afc4eeb 100644 --- a/src/vs/workbench/services/extensions/test/common/extensionsUtil.test.ts +++ b/src/vs/workbench/services/extensions/test/common/extensionsUtil.test.ts @@ -10,7 +10,7 @@ import { IExtensionManifest, ExtensionKind } from 'vs/platform/extensions/common suite('ExtensionKind', () => { function check(manifest: Partial, expected: ExtensionKind[]): void { - assert.deepEqual(deduceExtensionKind(manifest), expected); + assert.deepStrictEqual(deduceExtensionKind(manifest), expected); } test('declarative with extension dependencies => workspace', () => { diff --git a/src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts b/src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts index 976d2b1cc19..5264e3d7801 100644 --- a/src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts +++ b/src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts @@ -56,7 +56,7 @@ suite('RPCProtocol', () => { test('simple call', function (done) { delegate = (a1: number, a2: number) => a1 + a2; bProxy.$m(4, 1).then((res: number) => { - assert.equal(res, 5); + assert.strictEqual(res, 5); done(null); }, done); }); @@ -64,7 +64,7 @@ suite('RPCProtocol', () => { test('simple call without result', function (done) { delegate = (a1: number, a2: number) => { }; bProxy.$m(4, 1).then((res: number) => { - assert.equal(res, undefined); + assert.strictEqual(res, undefined); done(null); }, done); }); @@ -80,7 +80,7 @@ suite('RPCProtocol', () => { b.buffer[2] = 3; b.buffer[3] = 4; bProxy.$m(b, 2).then((res: number) => { - assert.equal(res, 3); + assert.strictEqual(res, 3); done(null); }, done); }); @@ -96,10 +96,10 @@ suite('RPCProtocol', () => { }; bProxy.$m(4, 1).then((res: VSBuffer) => { assert.ok(res instanceof VSBuffer); - assert.equal(res.buffer[0], 1); - assert.equal(res.buffer[1], 2); - assert.equal(res.buffer[2], 3); - assert.equal(res.buffer[3], 4); + assert.strictEqual(res.buffer[0], 1); + assert.strictEqual(res.buffer[1], 2); + assert.strictEqual(res.buffer[2], 3); + assert.strictEqual(res.buffer[3], 4); done(null); }, done); }); @@ -121,7 +121,7 @@ suite('RPCProtocol', () => { return a1 + 1; }; bProxy.$m(4, CancellationToken.None).then((res: number) => { - assert.equal(res, 5); + assert.strictEqual(res, 5); done(null); }, done); }); @@ -138,7 +138,7 @@ suite('RPCProtocol', () => { let tokenSource = new CancellationTokenSource(); let p = bProxy.$m(4, tokenSource.token); p.then((res: number) => { - assert.equal(res, 7); + assert.strictEqual(res, 7); }, (err) => { assert.fail('should not receive error'); }).finally(done); @@ -152,7 +152,7 @@ suite('RPCProtocol', () => { bProxy.$m(4, 1).then((res) => { assert.fail('unexpected'); }, (err) => { - assert.equal(err.message, 'nope'); + assert.strictEqual(err.message, 'nope'); }).finally(done); }); @@ -163,7 +163,7 @@ suite('RPCProtocol', () => { bProxy.$m(4, 1).then((res) => { assert.fail('unexpected'); }, (err) => { - assert.equal(err, undefined); + assert.strictEqual(err, undefined); }).finally(done); }); @@ -174,7 +174,7 @@ suite('RPCProtocol', () => { return circular; }; bProxy.$m(4, 1).then((res) => { - assert.equal(res, null); + assert.strictEqual(res, null); }, (err) => { assert.fail('unexpected'); }).finally(done); @@ -188,18 +188,18 @@ suite('RPCProtocol', () => { bProxy.$m(4, 1).then((res) => { assert.fail('unexpected'); }, (err) => { - assert.equal(err.what, 'what'); + assert.strictEqual(err.what, 'what'); }).finally(done); }); test('undefined arguments arrive as null', function () { delegate = (a1: any, a2: any) => { - assert.equal(typeof a1, 'undefined'); - assert.equal(a2, null); + assert.strictEqual(typeof a1, 'undefined'); + assert.strictEqual(a2, null); return 7; }; return bProxy.$m(undefined, null).then((res) => { - assert.equal(res, 7); + assert.strictEqual(res, 7); }); }); diff --git a/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts index ec5c902be90..d6aea0fce03 100644 --- a/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/browser/browserKeyboardMapper.test.ts @@ -41,12 +41,12 @@ suite('keyboard layout loader', () => { let instance = new TestKeyboardMapperFactory(notitifcationService, storageService, commandService); test('load default US keyboard layout', () => { - assert.notEqual(instance.activeKeyboardLayout, null); + assert.notStrictEqual(instance.activeKeyboardLayout, null); }); test('isKeyMappingActive', () => { instance.setUSKeyboardLayout(); - assert.equal(instance.isKeyMappingActive({ + assert.strictEqual(instance.isKeyMappingActive({ KeyA: { value: 'a', valueIsDeadKey: false, @@ -59,7 +59,7 @@ suite('keyboard layout loader', () => { } }), true); - assert.equal(instance.isKeyMappingActive({ + assert.strictEqual(instance.isKeyMappingActive({ KeyA: { value: 'a', valueIsDeadKey: false, @@ -82,7 +82,7 @@ suite('keyboard layout loader', () => { } }), true); - assert.equal(instance.isKeyMappingActive({ + assert.strictEqual(instance.isKeyMappingActive({ KeyZ: { value: 'y', valueIsDeadKey: false, @@ -110,8 +110,8 @@ suite('keyboard layout loader', () => { withShiftAltGrIsDeadKey: false } }); - assert.equal(!!instance.activeKeyboardLayout!.isUSStandard, false); - assert.equal(instance.isKeyMappingActive({ + assert.strictEqual(!!instance.activeKeyboardLayout!.isUSStandard, false); + assert.strictEqual(instance.isKeyMappingActive({ KeyZ: { value: 'y', valueIsDeadKey: false, @@ -125,13 +125,13 @@ suite('keyboard layout loader', () => { }), true); instance.setUSKeyboardLayout(); - assert.equal(instance.activeKeyboardLayout!.isUSStandard, true); + assert.strictEqual(instance.activeKeyboardLayout!.isUSStandard, true); }); test('Switch keyboard layout info', () => { instance.setKeyboardLayout('com.apple.keylayout.German'); - assert.equal(!!instance.activeKeyboardLayout!.isUSStandard, false); - assert.equal(instance.isKeyMappingActive({ + assert.strictEqual(!!instance.activeKeyboardLayout!.isUSStandard, false); + assert.strictEqual(instance.isKeyMappingActive({ KeyZ: { value: 'y', valueIsDeadKey: false, @@ -145,6 +145,6 @@ suite('keyboard layout loader', () => { }), true); instance.setUSKeyboardLayout(); - assert.equal(instance.activeKeyboardLayout!.isUSStandard, true); + assert.strictEqual(instance.activeKeyboardLayout!.isUSStandard, true); }); }); diff --git a/src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts b/src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts index 99a2ef11a08..3a873b4e82c 100644 --- a/src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts +++ b/src/vs/workbench/services/keybinding/test/browser/keybindingIO.test.ts @@ -18,7 +18,7 @@ suite('keybindingIO', () => { function testOneSerialization(keybinding: number, expected: string, msg: string, OS: OperatingSystem): void { let usLayoutResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS); let actualSerialized = usLayoutResolvedKeybinding.getUserSettingsLabel(); - assert.equal(actualSerialized, expected, expected + ' - ' + msg); + assert.strictEqual(actualSerialized, expected, expected + ' - ' + msg); } function testSerialization(keybinding: number, expectedWin: string, expectedMac: string, expectedLinux: string): void { testOneSerialization(keybinding, expectedWin, 'win', OperatingSystem.Windows); @@ -29,7 +29,7 @@ suite('keybindingIO', () => { function testOneDeserialization(keybinding: string, _expected: number, msg: string, OS: OperatingSystem): void { let actualDeserialized = KeybindingParser.parseKeybinding(keybinding, OS); let expected = createKeybinding(_expected, OS); - assert.deepEqual(actualDeserialized, expected, keybinding + ' - ' + msg); + assert.deepStrictEqual(actualDeserialized, expected, keybinding + ' - ' + msg); } function testDeserialization(inWin: string, inMac: string, inLinux: string, expected: number): void { testOneDeserialization(inWin, expected, 'win', OperatingSystem.Windows); @@ -117,7 +117,7 @@ suite('keybindingIO', () => { }); test('deserialize scan codes', () => { - assert.deepEqual( + assert.deepStrictEqual( KeybindingParser.parseUserBinding('ctrl+shift+[comma] ctrl+/'), [new ScanCodeBinding(true, true, false, false, ScanCode.Comma), new SimpleKeybinding(true, false, false, false, KeyCode.US_SLASH)] ); @@ -127,34 +127,34 @@ suite('keybindingIO', () => { let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": ["firstcommand", "seccondcommand"] }]`; let userKeybinding = JSON.parse(strJSON)[0]; let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding); - assert.equal(keybindingItem.command, null); + assert.strictEqual(keybindingItem.command, null); }); test('issue #10452 - invalid when', () => { let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": "firstcommand", "when": [] }]`; let userKeybinding = JSON.parse(strJSON)[0]; let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding); - assert.equal(keybindingItem.when, null); + assert.strictEqual(keybindingItem.when, undefined); }); test('issue #10452 - invalid key', () => { let strJSON = `[{ "key": [], "command": "firstcommand" }]`; let userKeybinding = JSON.parse(strJSON)[0]; let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding); - assert.deepEqual(keybindingItem.parts, []); + assert.deepStrictEqual(keybindingItem.parts, []); }); test('issue #10452 - invalid key 2', () => { let strJSON = `[{ "key": "", "command": "firstcommand" }]`; let userKeybinding = JSON.parse(strJSON)[0]; let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding); - assert.deepEqual(keybindingItem.parts, []); + assert.deepStrictEqual(keybindingItem.parts, []); }); test('test commands args', () => { let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": "firstcommand", "when": [], "args": { "text": "theText" } }]`; let userKeybinding = JSON.parse(strJSON)[0]; let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding); - assert.equal(keybindingItem.commandArgs.text, 'theText'); + assert.strictEqual(keybindingItem.commandArgs.text, 'theText'); }); }); diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/macLinuxKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/macLinuxKeyboardMapper.test.ts index 7126a022e17..b16e44bc900 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/macLinuxKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/macLinuxKeyboardMapper.test.ts @@ -1465,11 +1465,11 @@ function _assertKeybindingTranslation(mapper: MacLinuxKeyboardMapper, OS: Operat const actualHardwareKeypresses = mapper.simpleKeybindingToScanCodeBinding(runtimeKeybinding); if (actualHardwareKeypresses.length === 0) { - assert.deepEqual([], expected, `simpleKeybindingToHardwareKeypress -- "${keybindingLabel}" -- actual: "[]" -- expected: "${expected}"`); + assert.deepStrictEqual([], expected, `simpleKeybindingToHardwareKeypress -- "${keybindingLabel}" -- actual: "[]" -- expected: "${expected}"`); return; } const actual = actualHardwareKeypresses .map(k => UserSettingsLabelProvider.toLabel(OS, [k], (keybinding) => ScanCodeUtils.toString(keybinding.scanCode))); - assert.deepEqual(actual, expected, `simpleKeybindingToHardwareKeypress -- "${keybindingLabel}" -- actual: "${actual}" -- expected: "${expected}"`); + assert.deepStrictEqual(actual, expected, `simpleKeybindingToHardwareKeypress -- "${keybindingLabel}" -- actual: "${actual}" -- expected: "${expected}"`); } diff --git a/src/vs/workbench/test/common/api/semanticTokensDto.test.ts b/src/vs/workbench/test/common/api/semanticTokensDto.test.ts index 091bc24e2f3..1a47041c3c4 100644 --- a/src/vs/workbench/test/common/api/semanticTokensDto.test.ts +++ b/src/vs/workbench/test/common/api/semanticTokensDto.test.ts @@ -25,7 +25,7 @@ suite('SemanticTokensDto', () => { data: toArr(dto.data) }; }; - assert.deepEqual(convert(actual), convert(expected)); + assert.deepStrictEqual(convert(actual), convert(expected)); } function assertEqualDelta(actual: IDeltaSemanticTokensDto, expected: IDeltaSemanticTokensDto): void { @@ -46,7 +46,7 @@ suite('SemanticTokensDto', () => { deltas: dto.deltas.map(convertOne) }; }; - assert.deepEqual(convert(actual), convert(expected)); + assert.deepStrictEqual(convert(actual), convert(expected)); } function testRoundTrip(value: ISemanticTokensDto): void { From e3b18fa3efb2aa0933fbe9d3a7437b88beabe310 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 11 Jan 2021 13:03:59 -0800 Subject: [PATCH 1803/1837] testing: add filter box --- .vscode/settings.json | 1 + src/vs/base/common/async.ts | 2 +- .../browser/explorerProjections/nodeHelper.ts | 5 +- .../explorerProjections/stateByLocation.ts | 18 ++- .../explorerProjections/stateByName.ts | 9 +- .../contrib/testing/browser/media/testing.css | 15 +++ .../testing/browser/testingExplorerFilter.ts | 103 ++++++++++++++++++ .../testing/browser/testingExplorerView.ts | 87 ++++++++++++--- .../contrib/testing/common/storedValue.ts | 79 ++++++++++++++ 9 files changed, 296 insertions(+), 23 deletions(-) create mode 100644 src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts create mode 100644 src/vs/workbench/contrib/testing/common/storedValue.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 0222b24c2a4..6f02065ef02 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -78,5 +78,6 @@ "editor.defaultFormatter": "vscode.typescript-language-features", "editor.formatOnSave": true, }, + "typescript.format.semicolons": "insert", "typescript.tsc.autoDetect": "off" } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index d17ec9468bc..8ac40d01a28 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -205,7 +205,7 @@ export class SequencerByKey { } /** - * A helper to delay execution of a task that is being requested often. + * A helper to delay (debounce) execution of a task that is being requested often. * * Following the throttler, now imagine the mail man wants to optimize the number of * trips proactively. The trip itself can be long, so he decides not to make the trip diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts index 402ad544208..f65ca5c71bb 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts @@ -6,8 +6,11 @@ import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; import { CompressibleObjectTree, ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { Iterable } from 'vs/base/common/iterator'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +export const isRunningState = (s: TestRunState) => s === TestRunState.Queued || s === TestRunState.Running; + /** * Removes nodes from the set whose parents don't exist in the tree. This is * useful to remove nodes that are queued to be updated or rendered, who will @@ -24,7 +27,7 @@ export const pruneNodesWithParentsNotInTree = (nodes /** * Helper to gather and bulk-apply tree updates. */ -export class NodeChangeList; parentItem: T | null }> { +export class NodeChangeList; parentItem: T | null; }> { private changedParents = new Set(); private updatedNodes = new Set(); diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts index ca855782405..9f22cbea700 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts @@ -15,7 +15,7 @@ import { Location as ModeLocation } from 'vs/editor/common/modes'; import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; -import { NodeChangeList } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; +import { isRunningState, NodeChangeList } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; import { statesInOrder } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; @@ -187,9 +187,19 @@ export class StateByLocationProjection extends AbstractIncrementalTestCollection } }, update: node => { + const isRunning = isRunningState(node.item.state.runState); if (node.item.state.runState !== node.previousState) { - this.pruneStateElements(node, node.previousState); - this.resolveNodesRecursive(node); + if (isRunning && node.treeElements.has(node.previousState)) { + node.treeElements.get(node.previousState)!.computedState = TestRunState.Running; + } else { + this.pruneStateElements(node, node.previousState); + this.resolveNodesRecursive(node); + } + } else if (!isRunning) { + const previous = node.treeElements.get(node.item.state.runState); + if (previous) { + previous.computedState = node.item.state.runState; + } } const locationChanged = !locationsEqual(node.location, node.item.location); @@ -199,7 +209,7 @@ export class StateByLocationProjection extends AbstractIncrementalTestCollection this.locations.add(node); } - const treeNode = node.treeElements.get(node.item.state.runState)!; + const treeNode = node.treeElements.get(node.previousState)!; this.changes.updated(treeNode); }, complete: () => { diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts index 7c08a73d038..e9aa93cd0de 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts @@ -178,10 +178,15 @@ export class StateByNameProjection extends AbstractIncrementalTestCollection { - if (node.item.state.runState !== node.previousState) { - this.removeNode(node); + if (node.item.state.runState !== node.previousState && node.node) { + if (node.item.state.runState === TestRunState.Running) { + node.node.computedState = node.item.state.runState; + } else { + this.removeNode(node); + } } + node.previousState = node.item.state.runState; this.resolveNodesRecursive(node); const locationChanged = !locationsEqual(node.location, node.item.location); diff --git a/src/vs/workbench/contrib/testing/browser/media/testing.css b/src/vs/workbench/contrib/testing/browser/media/testing.css index 32d89bdce01..5ff9ccc79cf 100644 --- a/src/vs/workbench/contrib/testing/browser/media/testing.css +++ b/src/vs/workbench/contrib/testing/browser/media/testing.css @@ -3,6 +3,21 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +.test-explorer { + display: flex; + flex-direction: column; +} + +.test-explorer > .monaco-inputbox { + flex-shrink: 0; + margin: 4px 12px; +} + +.test-explorer > .test-explorer-tree { + flex-grow: 1; + height: 0px; +} + .test-explorer .test-item { display: flex; align-items: center; diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts new file mode 100644 index 00000000000..e434d327b14 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.ts @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { addStandardDisposableListener, EventType } from 'vs/base/browser/dom'; +import { HistoryInputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { Widget } from 'vs/base/browser/ui/widget'; +import { Delayer } from 'vs/base/common/async'; +import { Emitter } from 'vs/base/common/event'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { localize } from 'vs/nls'; +import { ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedHistoryWidget'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue'; + +export class TestingFilterState { + private readonly changeEmitter = new Emitter(); + + public readonly onDidChange = this.changeEmitter.event; + + public get value() { + return this._value; + } + + public set value(v: string) { + if (v !== this._value) { + this._value = v; + this.changeEmitter.fire(v); + } + } + + constructor(private _value = '') { } +} + +export class TestingExplorerFilter extends Widget { + private readonly input: HistoryInputBox; + private readonly history: StoredValue = this.instantiationService.createInstance(StoredValue, { + key: 'testing.filterHistory', + scope: StorageScope.WORKSPACE, + target: StorageTarget.USER + }); + + constructor( + container: HTMLElement, + private readonly state: TestingFilterState, + @IContextViewService contextViewService: IContextViewService, + @IThemeService themeService: IThemeService, + @IInstantiationService private readonly instantiationService: IInstantiationService, + ) { + super(); + + const updateDelayer = this._register(new Delayer(400)); + + const input = this.input = this._register(instantiationService.createInstance(ContextScopedHistoryInputBox, container, contextViewService, { + placeholder: localize('testExplorerFilter', "Filter (e.g. text, !exclude)"), + history: this.history.get([]), + })); + input.value = state.value; + this._register(attachInputBoxStyler(input, themeService)); + + this._register(state.onDidChange(newValue => { + input.value = newValue; + })); + + this._register(input.onDidChange(() => updateDelayer.trigger(() => { + input.addToHistory(); + this.state.value = input.value; + }))); + + this._register(addStandardDisposableListener(input.inputElement, EventType.KEY_DOWN, e => { + if (e.equals(KeyCode.Escape)) { + input.value = ''; + e.stopPropagation(); + e.preventDefault(); + } + })); + } + + + /** + * Focuses the filter input. + */ + public focus(): void { + this.input.focus(); + } + + /** + * Persists changes to the input history. + */ + public saveState() { + const history = this.input.getHistory(); + if (history.length) { + this.history.store(history); + } else { + this.history.delete(); + } + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index 53bc0ce7776..fd51128785a 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -13,6 +13,7 @@ import { ITreeEvent, ITreeFilter, ITreeNode, ITreeSorter, TreeFilterResult, Tree import { throttle } from 'vs/base/common/decorators'; import { Event } from 'vs/base/common/event'; import { FuzzyScore } from 'vs/base/common/filters'; +import { splitGlobAware } from 'vs/base/common/glob'; import { Iterable } from 'vs/base/common/iterator'; import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import 'vs/css!./media/testing'; @@ -49,6 +50,7 @@ import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProje import { testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons'; import { cmpPriority } from 'vs/workbench/contrib/testing/browser/testExplorerTree'; import { ITestingCollectionService, TestSubscriptionListener } from 'vs/workbench/contrib/testing/browser/testingCollectionService'; +import { TestingExplorerFilter, TestingFilterState } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter'; import { TestExplorerViewGrouping, TestExplorerViewMode } from 'vs/workbench/contrib/testing/common/constants'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; @@ -57,8 +59,10 @@ import { DebugAction, RunAction } from './testExplorerActions'; export class TestingExplorerView extends ViewPane { public viewModel!: TestingExplorerViewModel; + private readonly filterState = new TestingFilterState(); + private filter!: TestingExplorerFilter; private currentSubscription?: TestSubscriptionListener; - private listContainer!: HTMLElement; + private container!: HTMLElement; private finishDiscovery?: () => void; constructor( @@ -93,8 +97,12 @@ export class TestingExplorerView extends ViewPane { protected renderBody(container: HTMLElement): void { super.renderBody(container); - this.listContainer = dom.append(container, dom.$('.test-explorer')); - this.viewModel = this.instantiationService.createInstance(TestingExplorerViewModel, this.listContainer, this.onDidChangeBodyVisibility, this.currentSubscription); + this.container = dom.append(container, dom.$('.test-explorer')); + this.filter = this.instantiationService.createInstance(TestingExplorerFilter, this.container, this.filterState); + this._register(this.filter); + + const listContainer = dom.append(this.container, dom.$('.test-explorer-tree')); + this.viewModel = this.instantiationService.createInstance(TestingExplorerViewModel, listContainer, this.onDidChangeBodyVisibility, this.currentSubscription, this.filterState); this._register(this.viewModel); this.updateProgressIndicator(); @@ -118,6 +126,14 @@ export class TestingExplorerView extends ViewPane { })); } + /** + * @override + */ + public saveState() { + super.saveState(); + this.filter.saveState(); + } + private updateProgressIndicator() { const busy = Iterable.some(this.testService.busyTestLocations, s => s.resource === ExtHostTestingResource.Workspace); if (!busy && this.finishDiscovery) { @@ -134,7 +150,7 @@ export class TestingExplorerView extends ViewPane { */ protected layoutBody(height: number, width: number): void { super.layoutBody(height, width); - this.listContainer.style.height = `${height}px`; + this.container.style.height = `${height}px`; this.viewModel.layout(height, width); } @@ -189,6 +205,7 @@ export class TestingExplorerViewModel extends Disposable { listContainer: HTMLElement, onDidChangeVisibility: Event, private listener: TestSubscriptionListener | undefined, + filterState: TestingFilterState, @IInstantiationService instantiationService: IInstantiationService, @IEditorService editorService: IEditorService, @ICodeEditorService codeEditorService: ICodeEditorService, @@ -202,7 +219,12 @@ export class TestingExplorerViewModel extends Disposable { const labels = this._register(instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: onDidChangeVisibility })); - this.filter = new TestsFilter(); + this.filter = new TestsFilter(filterState.value); + this._register(filterState.onDidChange(text => { + this.filter.setFilter(text); + this.tree.refilter(); + })); + this.tree = instantiationService.createInstance( WorkbenchCompressibleObjectTree, 'Test Explorer List', @@ -375,30 +397,65 @@ class CodeEditorTracker { } } +class TestsFilter implements ITreeFilter { + private filters: [include: boolean, value: string][] | undefined; -class TestsFilter implements ITreeFilter { - private filterText: string | undefined; - - public setFilter(filterText: string) { - this.filterText = filterText; + constructor(initialFilter: string) { + this.setFilter(initialFilter); } - public filter(element: ITestTreeElement): TreeFilterResult { + /** + * Parses and updates the tree filter. Supports lists of patterns that can be !negated. + */ + public setFilter(text: string) { + text = text.trim(); + + if (!text) { + this.filters = undefined; + return; + } + + this.filters = []; + for (const filter of splitGlobAware(text, ',').map(s => s.trim()).filter(s => !!s.length)) { + if (filter.startsWith('!')) { + this.filters.push([false, filter.slice(1).toLowerCase()]); + } else { + this.filters.push([true, filter.toLowerCase()]); + } + } + } + + public filter(element: ITestTreeElement): TreeFilterResult { if (element instanceof HierarchicalByNameElement && element.elementType !== ListElementType.TestLeaf && !element.isTestRoot) { return TreeVisibility.Hidden; } - if (!this.filterText) { + if (this.testFilterText(element.label)) { return TreeVisibility.Visible; } - if (element.label.includes(this.filterText)) { - return TreeVisibility.Visible; + return Iterable.isEmpty(element.getChildren()) ? TreeVisibility.Hidden : TreeVisibility.Recurse; + } + + private testFilterText(data: string) { + if (!this.filters) { + return true; } - return TreeVisibility.Recurse; + // start as included if the first glob is a negation + let included = this.filters[0][0] === false; + data = data.toLowerCase(); + + for (const [include, filter] of this.filters) { + if (data.includes(filter)) { + included = include; + } + } + + return included; } } + class TreeSorter implements ITreeSorter { public compare(a: ITestTreeElement, b: ITestTreeElement): number { if (a instanceof StateElement && b instanceof StateElement) { diff --git a/src/vs/workbench/contrib/testing/common/storedValue.ts b/src/vs/workbench/contrib/testing/common/storedValue.ts new file mode 100644 index 00000000000..6102358129c --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/storedValue.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; + +export interface IStoredValueSerialization { + deserialize(data: string): T; + serialize(data: T): string; +} + +const defaultSerialization: IStoredValueSerialization = { + deserialize: d => JSON.parse(d), + serialize: d => JSON.stringify(d), +}; + +interface IStoredValueOptions { + key: string; + scope: StorageScope; + target: StorageTarget; + serialization?: IStoredValueSerialization; +} + +/** + * todo@connor4312: is this worthy to be in common? + */ +export class StoredValue { + private readonly serialization: IStoredValueSerialization; + private readonly key: string; + private readonly scope: StorageScope; + private readonly target: StorageTarget; + + /** + * Emitted whenever the value is updated or deleted. + */ + public readonly onDidChange = Event.filter(this.storage.onDidChangeValue, e => e.key === this.key); + + constructor( + options: IStoredValueOptions, + @IStorageService private readonly storage: IStorageService, + ) { + this.key = options.key; + this.scope = options.scope; + this.target = options.target; + this.serialization = options.serialization ?? defaultSerialization; + } + + /** + * Reads the value, returning the undefined if it's not set. + */ + public get(): T | undefined; + + /** + * Reads the value, returning the default value if it's not set. + */ + public get(defaultValue: T): T; + + public get(defaultValue?: T): T | undefined { + const value = this.storage.get(this.key, this.scope); + return value === undefined ? defaultValue : this.serialization.deserialize(value); + } + + /** + * Persists changes to the value. + * @param value + */ + public store(value: T) { + this.storage.store(this.key, this.serialization.serialize(value), this.scope, this.target); + } + + /** + * Delete an element stored under the provided key from storage. + */ + public delete() { + this.storage.remove(this.key, this.scope); + } +} From a2efefd3713605a3f12968ebed9c2308627863b9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 21:04:27 +0100 Subject: [PATCH 1804/1837] use in-mem fsp - workspace tests --- .../configurationService.test.ts | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 755fd8d5d2c..ffda818058f 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -161,43 +161,42 @@ suite('WorkspaceContextService - Folder', () => { suite('WorkspaceContextService - Workspace', () => { - let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; + let testObject: WorkspaceService; const disposables = new DisposableStore(); - setup(() => { - return setUpWorkspace(['a', 'b']) - .then(({ parentDir, configPath }) => { + setup(async () => { + const logService = new NullLogService(); + const fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(Schemas.file, fileSystemProvider); - parentResource = parentDir; + const appSettingsHome = URI.file('user'); + const folderA = URI.file('a'); + const folderB = URI.file('b'); + const configResource = URI.file('vsctests.code-workspace'); + const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; - instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); - instantiationService.stub(IRemoteAgentService, remoteAgentService); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + await fileService.createFolder(appSettingsHome); + await fileService.createFolder(folderA); + await fileService.createFolder(folderB); + await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IEnvironmentService, environmentService); + const instantiationService = workbenchInstantiationService(); + const environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { - workspaceService.acquireInstantiationService(instantiationService); - testObject = workspaceService; - }); - }); + instantiationService.stub(IWorkspaceContextService, testObject); + instantiationService.stub(IConfigurationService, testObject); + instantiationService.stub(IEnvironmentService, environmentService); + + await testObject.initialize(getWorkspaceIdentifier(configResource)); + testObject.acquireInstantiationService(instantiationService); }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); test('workspace folders', () => { const actual = testObject.getWorkspace().folders; From 722a6664f84327dfd34a5fafb946b68aac1d6dea Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 21:36:59 +0100 Subject: [PATCH 1805/1837] use in-mem fsp - workspace editing tests --- .../configurationService.test.ts | 305 ++++++++---------- 1 file changed, 140 insertions(+), 165 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index ffda818058f..91c59aca198 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -30,7 +30,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService'; import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; -import { originalFSPath, joinPath, dirname } from 'vs/base/common/resources'; +import { originalFSPath, joinPath, dirname, basename } from 'vs/base/common/resources'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-sandbox/remoteAuthorityResolverService'; @@ -219,142 +219,125 @@ suite('WorkspaceContextService - Workspace', () => { suite('WorkspaceContextService - Workspace Editing', () => { - let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; + let testObject: WorkspaceService, fileService: IFileService; const disposables = new DisposableStore(); - setup(() => { - return setUpWorkspace(['a', 'b']) - .then(({ parentDir, configPath }) => { + setup(async () => { + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(Schemas.file, fileSystemProvider); - parentResource = parentDir; + const appSettingsHome = URI.file('user'); + const folderA = URI.file('a'); + const folderB = URI.file('b'); + const configResource = URI.file('vsctests.code-workspace'); + const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; - instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); - instantiationService.stub(IRemoteAgentService, remoteAgentService); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + await fileService.createFolder(appSettingsHome); + await fileService.createFolder(folderA); + await fileService.createFolder(folderB); + await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IEnvironmentService, environmentService); + const instantiationService = workbenchInstantiationService(); + const environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { - instantiationService.stub(IFileService, fileService); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.acquireInstantiationService(instantiationService); + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IWorkspaceContextService, testObject); + instantiationService.stub(IConfigurationService, testObject); + instantiationService.stub(IEnvironmentService, environmentService); - testObject = workspaceService; - }); - }); + await testObject.initialize(getWorkspaceIdentifier(configResource)); + instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); + testObject.acquireInstantiationService(instantiationService); }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; + teardown(() => disposables.clear()); + + test('add folders', async () => { + await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }]); + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(basename(actual[0].uri), 'a'); + assert.equal(basename(actual[1].uri), 'b'); + assert.equal(basename(actual[2].uri), 'd'); + assert.equal(basename(actual[3].uri), 'c'); }); - test('add folders', () => { - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]) - .then(() => { - const actual = testObject.getWorkspace().folders; + test('add folders (at specific index)', async () => { + await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }], 0); + const actual = testObject.getWorkspace().folders; - assert.equal(actual.length, 4); - assert.equal(path.basename(actual[0].uri.fsPath), 'a'); - assert.equal(path.basename(actual[1].uri.fsPath), 'b'); - assert.equal(path.basename(actual[2].uri.fsPath), 'd'); - assert.equal(path.basename(actual[3].uri.fsPath), 'c'); - }); + assert.equal(actual.length, 4); + assert.equal(basename(actual[0].uri), 'd'); + assert.equal(basename(actual[1].uri), 'c'); + assert.equal(basename(actual[2].uri), 'a'); + assert.equal(basename(actual[3].uri), 'b'); }); - test('add folders (at specific index)', () => { - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 0) - .then(() => { - const actual = testObject.getWorkspace().folders; + test('add folders (at specific wrong index)', async () => { + await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }], 10); + const actual = testObject.getWorkspace().folders; - assert.equal(actual.length, 4); - assert.equal(path.basename(actual[0].uri.fsPath), 'd'); - assert.equal(path.basename(actual[1].uri.fsPath), 'c'); - assert.equal(path.basename(actual[2].uri.fsPath), 'a'); - assert.equal(path.basename(actual[3].uri.fsPath), 'b'); - }); + assert.equal(actual.length, 4); + assert.equal(basename(actual[0].uri), 'a'); + assert.equal(basename(actual[1].uri), 'b'); + assert.equal(basename(actual[2].uri), 'd'); + assert.equal(basename(actual[3].uri), 'c'); }); - test('add folders (at specific wrong index)', () => { - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 10) - .then(() => { - const actual = testObject.getWorkspace().folders; + test('add folders (with name)', async () => { + await testObject.addFolders([{ uri: URI.file('d'), name: 'DDD' }, { uri: URI.file('c'), name: 'CCC' }]); + const actual = testObject.getWorkspace().folders; - assert.equal(actual.length, 4); - assert.equal(path.basename(actual[0].uri.fsPath), 'a'); - assert.equal(path.basename(actual[1].uri.fsPath), 'b'); - assert.equal(path.basename(actual[2].uri.fsPath), 'd'); - assert.equal(path.basename(actual[3].uri.fsPath), 'c'); - }); + assert.equal(actual.length, 4); + assert.equal(basename(actual[0].uri), 'a'); + assert.equal(basename(actual[1].uri), 'b'); + assert.equal(basename(actual[2].uri), 'd'); + assert.equal(basename(actual[3].uri), 'c'); + assert.equal(actual[2].name, 'DDD'); + assert.equal(actual[3].name, 'CCC'); }); - test('add folders (with name)', () => { - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')), name: 'DDD' }, { uri: URI.file(path.join(workspaceDir, 'c')), name: 'CCC' }]) - .then(() => { - const actual = testObject.getWorkspace().folders; - - assert.equal(actual.length, 4); - assert.equal(path.basename(actual[0].uri.fsPath), 'a'); - assert.equal(path.basename(actual[1].uri.fsPath), 'b'); - assert.equal(path.basename(actual[2].uri.fsPath), 'd'); - assert.equal(path.basename(actual[3].uri.fsPath), 'c'); - assert.equal(actual[2].name, 'DDD'); - assert.equal(actual[3].name, 'CCC'); - }); - }); - - test('add folders triggers change event', () => { + test('add folders triggers change event', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; - return testObject.addFolders(addedFolders) - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); - assert.deepEqual(actual.removed, []); - assert.deepEqual(actual.changed, []); - }); + + const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; + await testObject.addFolders(addedFolders); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual_1.removed, []); + assert.deepEqual(actual_1.changed, []); }); - test('remove folders', () => { - return testObject.removeFolders([testObject.getWorkspace().folders[0].uri]) - .then(() => { - const actual = testObject.getWorkspace().folders; - assert.equal(actual.length, 1); - assert.equal(path.basename(actual[0].uri.fsPath), 'b'); - }); + test('remove folders', async () => { + await testObject.removeFolders([testObject.getWorkspace().folders[0].uri]); + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 1); + assert.equal(basename(actual[0].uri), 'b'); }); - test('remove folders triggers change event', () => { + test('remove folders triggers change event', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); const removedFolder = testObject.getWorkspace().folders[0]; - return testObject.removeFolders([removedFolder.uri]) - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added, []); - assert.deepEqual(actual.removed.map(r => r.uri.toString()), [removedFolder.uri.toString()]); - assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); - }); + await testObject.removeFolders([removedFolder.uri]); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added, []); + assert.deepEqual(actual_1.removed.map(r => r.uri.toString()), [removedFolder.uri.toString()]); + assert.deepEqual(actual_1.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); }); test('remove folders and add them back by writing into the file', async () => { @@ -372,88 +355,80 @@ suite('WorkspaceContextService - Workspace Editing', () => { }); }); - const workspace = { folders: [{ path: folders[0].uri.fsPath }, { path: folders[1].uri.fsPath }] }; - await instantiationService.get(ITextFileService).write(testObject.getWorkspace().configuration!, JSON.stringify(workspace, null, '\t')); + const workspace = { folders: [{ path: folders[0].uri.path }, { path: folders[1].uri.path }] }; + await fileService.writeFile(testObject.getWorkspace().configuration!, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); await promise; }); - test('update folders (remove last and add to end)', () => { + test('update folders (remove last and add to end)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; + const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; const removedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); - return testObject.updateFolders(addedFolders, removedFolders) - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); - assert.deepEqual(actual.removed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); - assert.deepEqual(actual.changed, []); - }); + await testObject.updateFolders(addedFolders, removedFolders); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual_1.removed.map(r_1 => r_1.uri.toString()), removedFolders.map(a_1 => a_1.toString())); + assert.deepEqual(actual_1.changed, []); }); - test('update folders (rename first via add and remove)', () => { + test('update folders (rename first via add and remove)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'a')), name: 'The Folder' }]; + const addedFolders = [{ uri: URI.file('a'), name: 'The Folder' }]; const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); - return testObject.updateFolders(addedFolders, removedFolders, 0) - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added, []); - assert.deepEqual(actual.removed, []); - assert.deepEqual(actual.changed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); - }); + await testObject.updateFolders(addedFolders, removedFolders, 0); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added, []); + assert.deepEqual(actual_1.removed, []); + assert.deepEqual(actual_1.changed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); }); - test('update folders (remove first and add to end)', () => { + test('update folders (remove first and add to end)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); - const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; + const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); const changedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); - return testObject.updateFolders(addedFolders, removedFolders) - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); - assert.deepEqual(actual.removed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); - assert.deepEqual(actual.changed.map(r => r.uri.toString()), changedFolders.map(a => a.toString())); - }); + await testObject.updateFolders(addedFolders, removedFolders); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual_1.removed.map(r_1 => r_1.uri.toString()), removedFolders.map(a_1 => a_1.toString())); + assert.deepEqual(actual_1.changed.map(r_2 => r_2.uri.toString()), changedFolders.map(a_2 => a_2.toString())); }); - test('reorder folders trigger change event', () => { + test('reorder folders trigger change event', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspace = { folders: [{ path: testObject.getWorkspace().folders[1].uri.fsPath }, { path: testObject.getWorkspace().folders[0].uri.fsPath }] }; - fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t')); - return testObject.reloadConfiguration() - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added, []); - assert.deepEqual(actual.removed, []); - assert.deepEqual(actual.changed.map(c => c.uri.toString()), testObject.getWorkspace().folders.map(f => f.uri.toString()).reverse()); - }); + const workspace = { folders: [{ path: testObject.getWorkspace().folders[1].uri.path }, { path: testObject.getWorkspace().folders[0].uri.path }] }; + await fileService.writeFile(testObject.getWorkspace().configuration!, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); + await testObject.reloadConfiguration(); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added, []); + assert.deepEqual(actual_1.removed, []); + assert.deepEqual(actual_1.changed.map(c => c.uri.toString()), testObject.getWorkspace().folders.map(f => f.uri.toString()).reverse()); }); - test('rename folders trigger change event', () => { + test('rename folders trigger change event', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const workspace = { folders: [{ path: testObject.getWorkspace().folders[0].uri.fsPath, name: '1' }, { path: testObject.getWorkspace().folders[1].uri.fsPath }] }; - fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t')); - return testObject.reloadConfiguration() - .then(() => { - assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); - const actual = target.args[0][0]; - assert.deepEqual(actual.added, []); - assert.deepEqual(actual.removed, []); - assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); - }); + const workspace = { folders: [{ path: testObject.getWorkspace().folders[0].uri.path, name: '1' }, { path: testObject.getWorkspace().folders[1].uri.path }] }; + fileService.writeFile(testObject.getWorkspace().configuration!, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); + await testObject.reloadConfiguration(); + + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual_1 = (target.args[0][0]); + assert.deepEqual(actual_1.added, []); + assert.deepEqual(actual_1.removed, []); + assert.deepEqual(actual_1.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); }); }); From 84f2cf6449ab244ed6fe271a9c0dab04e7492f8f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 22:02:54 +0100 Subject: [PATCH 1806/1837] use in-mem fsp - workspace init tests --- .../configurationService.test.ts | 339 ++++++++---------- 1 file changed, 151 insertions(+), 188 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 91c59aca198..c757c09b7bd 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -56,6 +56,7 @@ import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/enviro import { Event } from 'vs/base/common/event'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; +import { flakySuite } from 'vs/base/test/node/testUtils'; class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -435,7 +436,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { suite('WorkspaceService - Initialization', () => { - let parentResource: string, workspaceConfigPath: URI, testObject: WorkspaceService, globalSettingsFile: string; + let configResource: URI, testObject: WorkspaceService, fileService: IFileService, environmentService: NativeWorkbenchEnvironmentService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); const disposables = new DisposableStore(); @@ -458,240 +459,204 @@ suite('WorkspaceService - Initialization', () => { }); }); - setup(() => { - return setUpWorkspace(['1', '2']) - .then(({ parentDir, configPath }) => { + setup(async () => { + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(Schemas.file, fileSystemProvider); - parentResource = parentDir; - workspaceConfigPath = configPath; - globalSettingsFile = path.join(parentDir, 'settings.json'); + const appSettingsHome = URI.file('user'); + const folderA = URI.file('a'); + const folderB = URI.file('b'); + configResource = URI.file('vsctests.code-workspace'); + const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; - const instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); - instantiationService.stub(IRemoteAgentService, remoteAgentService); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IEnvironmentService, environmentService); + await fileService.createFolder(appSettingsHome); + await fileService.createFolder(folderA); + await fileService.createFolder(folderB); + await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - return workspaceService.initialize({ id: '' }).then(() => { - instantiationService.stub(IFileService, fileService); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.acquireInstantiationService(instantiationService); - testObject = workspaceService; - }); - }); + const instantiationService = workbenchInstantiationService(); + environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IWorkspaceContextService, testObject); + instantiationService.stub(IConfigurationService, testObject); + instantiationService.stub(IEnvironmentService, environmentService); + + await testObject.initialize({ id: '' }); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + testObject.acquireInstantiationService(instantiationService); }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); - test('initialize a folder workspace from an empty workspace with no configuration changes', () => { + test('initialize a folder workspace from an empty workspace with no configuration changes', async () => { - fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) - .then(() => { - assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); - assert.equal(target.callCount, 3); - assert.deepEqual(target.args[0], [WorkbenchState.FOLDER]); - assert.deepEqual(target.args[1], [undefined]); - assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); - assert.deepEqual((target.args[2][0]).removed, []); - assert.deepEqual((target.args[2][0]).changed, []); - }); + const folder = URI.file('a'); + await testObject.initialize(convertToWorkspacePayload(folder)); - }); + assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); + assert.equal(target.callCount, 3); + assert.deepEqual(target.args[0], [WorkbenchState.FOLDER]); + assert.deepEqual(target.args[1], [undefined]); + assert.deepEqual((target.args[2][0]).added.map(f => f.uri.toString()), [folder.toString()]); + assert.deepEqual((target.args[2][0]).removed, []); + assert.deepEqual((target.args[2][0]).changed, []); }); - test('initialize a folder workspace from an empty workspace with configuration changes', () => { + test('initialize a folder workspace from an empty workspace with configuration changes', async () => { - fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue" }'); + const folder = URI.file('a'); + await fileService.writeFile(joinPath(folder, '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue" }')); + await testObject.initialize(convertToWorkspacePayload(folder)); - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) - .then(() => { - assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue'); - assert.equal(target.callCount, 4); - assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); - assert.deepEqual(target.args[1], [WorkbenchState.FOLDER]); - assert.deepEqual(target.args[2], [undefined]); - assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); - assert.deepEqual((target.args[3][0]).removed, []); - assert.deepEqual((target.args[3][0]).changed, []); - }); - - }); + assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue'); + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual(target.args[1], [WorkbenchState.FOLDER]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(f => f.uri.toString()), [folder.toString()]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); }); - test('initialize a multi root workspace from an empty workspace with no configuration changes', () => { + test('initialize a multi root workspace from an empty workspace with no configuration changes', async () => { - fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) - .then(() => { - assert.equal(target.callCount, 3); - assert.deepEqual(target.args[0], [WorkbenchState.WORKSPACE]); - assert.deepEqual(target.args[1], [undefined]); - assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath, URI.file(path.join(parentResource, '2')).fsPath]); - assert.deepEqual((target.args[2][0]).removed, []); - assert.deepEqual((target.args[2][0]).changed, []); - }); + await testObject.initialize(getWorkspaceIdentifier(configResource)); - }); + assert.equal(target.callCount, 3); + assert.deepEqual(target.args[0], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[1], [undefined]); + assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.toString()), [URI.file('a').toString(), URI.file('b').toString()]); + assert.deepEqual((target.args[2][0]).removed, []); + assert.deepEqual((target.args[2][0]).changed, []); }); - test('initialize a multi root workspace from an empty workspace with configuration changes', () => { + test('initialize a multi root workspace from an empty workspace with configuration changes', async () => { - fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue1" }'); - fs.writeFileSync(path.join(parentResource, '2', '.vscode', 'settings.json'), '{ "initialization.testSetting2": "workspaceValue2" }'); + await fileService.writeFile(joinPath(URI.file('a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue1" }')); + await fileService.writeFile(joinPath(URI.file('b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting2": "workspaceValue2" }')); + await testObject.initialize(getWorkspaceIdentifier(configResource)); - return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) - .then(() => { - assert.equal(target.callCount, 4); - assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1', 'initialization.testSetting2']); - assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); - assert.deepEqual(target.args[2], [undefined]); - assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath, URI.file(path.join(parentResource, '2')).fsPath]); - assert.deepEqual((target.args[3][0]).removed, []); - assert.deepEqual((target.args[3][0]).changed, []); - }); - - }); + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1', 'initialization.testSetting2']); + assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.toString()), [URI.file('a').toString(), URI.file('b').toString()]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); }); - test('initialize a folder workspace from a folder workspace with no configuration changes', () => { + test('initialize a folder workspace from a folder workspace with no configuration changes', async () => { - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) - .then(() => { - fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await testObject.initialize(convertToWorkspacePayload(URI.file('b'))); - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '2')))) - .then(() => { - assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); - assert.equal(target.callCount, 1); - assert.deepEqual((target.args[0][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); - assert.deepEqual((target.args[0][0]).removed.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); - assert.deepEqual((target.args[0][0]).changed, []); - }); - - }); - }); + assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); + assert.equal(target.callCount, 1); + assert.deepEqual((target.args[0][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); + assert.deepEqual((target.args[0][0]).removed.map(folder_2 => folder_2.uri.toString()), [URI.file('a').toString()]); + assert.deepEqual((target.args[0][0]).changed, []); }); - test('initialize a folder workspace from a folder workspace with configuration changes', () => { + test('initialize a folder workspace from a folder workspace with configuration changes', async () => { - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) - .then(() => { + await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - const target = sinon.spy(); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); + await fileService.writeFile(joinPath(URI.file('b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); + await testObject.initialize(convertToWorkspacePayload(URI.file('b'))); - fs.writeFileSync(path.join(parentResource, '2', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue2" }'); - return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '2')))) - .then(() => { - assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue2'); - assert.equal(target.callCount, 2); - assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); - assert.deepEqual((target.args[1][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); - assert.deepEqual((target.args[1][0]).removed.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); - assert.deepEqual((target.args[1][0]).changed, []); - }); - }); + assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue2'); + assert.equal(target.callCount, 2); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual((target.args[1][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); + assert.deepEqual((target.args[1][0]).removed.map(folder_2 => folder_2.uri.toString()), [URI.file('a').toString()]); + assert.deepEqual((target.args[1][0]).changed, []); }); - test('initialize a multi folder workspace from a folder workspacce triggers change events in the right order', () => { - const folderDir = path.join(parentResource, '1'); - return testObject.initialize(convertToWorkspacePayload(URI.file(folderDir))) - .then(() => { + test('initialize a multi folder workspace from a folder workspacce triggers change events in the right order', async () => { + await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); - const target = sinon.spy(); + await fileService.writeFile(joinPath(URI.file('a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); + await testObject.initialize(getWorkspaceIdentifier(configResource)); - testObject.onDidChangeWorkbenchState(target); - testObject.onDidChangeWorkspaceName(target); - testObject.onDidChangeWorkspaceFolders(target); - testObject.onDidChangeConfiguration(target); - - fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue2" }'); - return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) - .then(() => { - assert.equal(target.callCount, 4); - assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); - assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); - assert.deepEqual(target.args[2], [undefined]); - assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); - assert.deepEqual((target.args[3][0]).removed, []); - assert.deepEqual((target.args[3][0]).changed, []); - }); - }); + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); }); }); -suite('WorkspaceConfigurationService - Folder', () => { +flakySuite('WorkspaceConfigurationService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string, globalTasksFile: string, workspaceService: WorkspaceService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -1220,7 +1185,7 @@ suite('WorkspaceConfigurationService - Folder', () => { }); }); -suite('WorkspaceConfigurationService-Multiroot', () => { +flakySuite('WorkspaceConfigurationService-Multiroot', () => { let parentResource: string, workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService, globalSettingsFile: string; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -1843,7 +1808,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => { }); }); -suite('WorkspaceConfigurationService - Remote Folder', () => { +flakySuite('WorkspaceConfigurationService - Remote Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: WorkspaceService, globalSettingsFile: string, remoteSettingsFile: string, remoteSettingsResource: URI, instantiationService: TestInstantiationService, resolveRemoteEnvironment: () => void; const remoteAuthority = 'configuraiton-tests'; @@ -2091,9 +2056,7 @@ suite('ConfigurationService - Configuration Defaults', () => { }); }); - teardown(() => { - disposableStore.clear(); - }); + teardown(() => disposableStore.clear()); test('when default value is not overriden', () => { const testObject = createConfiurationService({}); From 03450bf09414f1883dd9b8cfea02df3fac8df0f4 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 11 Jan 2021 13:14:02 -0800 Subject: [PATCH 1807/1837] Update Codicons: Update '+' modifier location (fixes #114016) https://github.com/microsoft/vscode-codicons/commit/4b668019e884d0e88094796ae9653609eebcfedd --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 62556 -> 62564 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 acbaeafa87d4f4669c0b6aa5678254cf961e85ad..caaabfd09c38f67f5ea5533192b852050d3592cf 100644 GIT binary patch delta 814 zcmccfg89h{<_QiW5BSczF)+x^VPH6Hkdd00A|3EmZeoZIi~XzOqKPfaf@c^Qn79h^ zi%ZH^y^LmHcywdp4g;C};jOph`E9;3a5KMP0D?P85!x_%GYey_bo~^QYo>Chex`k9 zGG-;_73Mq4zgVPLOtWOLOtIW!Wo0$N>W4LtwUc#^^%?6IHWD^AHV153Y-ia1v&*o% zX3u3`XTQ(>nS+}{hC`X7m*X+VcTQzar<`4!H@Wb*WVp<6x#4Q#y3CEw&BLw8ZHn6! zcO`cp_ZIg<9y%Tc9@{)U>OFUOnRzvNb9j4s_jv#Caq&6g^TLUy@=hvP+49uXoV1B{8ia`iyz6JvWqau=__KZMt1=(X1`5A$h$TKQ318oM{ z541~EnYrs;`R5AQMGTvb+WQ6Ta~UKVlo<3GEErsXZV+KNHq&F~W0GSwH)Ydf zv}2NEWHmA~QBz_Q5fe8uGZ*J$R8mtnmt!;+Gc(a+1c`#3BnoyO(>o@6cHP*fzLr!I z7Tc_L_wZQ(VkN7VB>&5jQc*EcRh_PAC8i@E6csG5BW61fB<7;3y3M|}7KoUH`32nD zvus&RQd|0(Vs+W=xq@e}ZPv7#U;)xRn^V@u7;AVco00g)H?dE~en^_oZrR%4eoG}$Kbun!* z6Ee#(&of_V{>mcCqQ~N!Wt8P6D+8-Gt9RB+))v-H)`zU`+3?vI*=)1UpW;y9dmYYUgyH$lHxMM<%+9?>moNUHy5`&w+U_+ z+~wRo+#B5Yd1!d#cx>`?srTICW#m=o&EoCm-QoSk$HC`-&l6uZKMB7uzaqbR{tW&q z{!#u*0-^$10*(dp1)2qB1x^aQ5Hv05N-$S&ScpW3OURW_q0p|-ZJ}SnD#EsfGlaW^ z_k}-*;EITfXo}bpaUs$ua#EB>R9DoTsC7{XqAo?-M7KoWi4llNi+L9->kwNOyDLsA zE-h|H+`V|Fc>X_#X*U37-<(5~pmQBYQrhJ{uTz+zc`d@(c{Z%BISu#-_%i#-hrq z@{EG)it2*Kf{KD5VMTUP<6m}r_5cy%w5x3LfBWU_n2dk@Vsz!*%4EFTe)n$st+yoq zzLA$_jQDqgaqBO8``y5}U;@Pl^D3|%N(>B)K%+#Jf#w5kVF%h}&*-6O3WVZtyA;_O zw}C9N+Y=`*WF*OW^N`)6UqtP8Yh_wL+x)xR|&cqq!LnD)TYvG21bkvm2S2s420D zh>07SnTzu=DygZP1C@Y8`4~mSnBGA={jW39%Uwg0RZrK;XS2Vrp%JG&M{xbbDo<92 z5|213RaFxemFbEB)}p%dK~cf-I$}2SAcD-Rz}{ixG&1z{-|XY1tH-LT;qDdbQR2Yr pSv9dfnB#|v2}t`~DRCV|B^5;-3F)~&5k?gg6$XaQGiIKN0sxIO04M+e From f92251d8e613f77a830ea95ab881ce40eb68f937 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 22:33:01 +0100 Subject: [PATCH 1808/1837] use in-mem fsp - workspace folder config tests --- .../configurationService.test.ts | 341 ++++++++---------- 1 file changed, 154 insertions(+), 187 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index c757c09b7bd..05289b001c2 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -31,7 +31,7 @@ import { JSONEditingService } from 'vs/workbench/services/configuration/common/j import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; import { originalFSPath, joinPath, dirname, basename } from 'vs/base/common/resources'; -import { isLinux, isMacintosh } from 'vs/base/common/platform'; +import { isLinux } from 'vs/base/common/platform'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-sandbox/remoteAuthorityResolverService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -68,7 +68,7 @@ class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService } -function setUpFolderWorkspace(folderName: string): Promise<{ parentDir: string, folderDir: string }> { +function setUpFolderWorkspace(folderName: string): Promise<{ parentDir: string, folderDir: string; }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); return setUpFolder(folderName, parentDir).then(folderDir => ({ parentDir, folderDir })); @@ -87,7 +87,7 @@ function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceInitializ } as ISingleFolderWorkspaceInitializationPayload; } -function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: URI }> { +function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: URI; }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); @@ -656,11 +656,10 @@ suite('WorkspaceService - Initialization', () => { }); -flakySuite('WorkspaceConfigurationService - Folder', () => { +suite('WorkspaceConfigurationService - Folder', () => { - let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string, globalTasksFile: string, workspaceService: WorkspaceService; + let testObject: IConfigurationService, workspaceService: WorkspaceService, fileService: IFileService, environmentService: NativeWorkbenchEnvironmentService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); - let fileService: IFileService; const disposables: DisposableStore = new DisposableStore(); suiteSetup(() => { @@ -697,132 +696,111 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); }); - setup(() => { - return setUpFolderWorkspace(workspaceName) - .then(({ parentDir, folderDir }) => { + setup(async () => { + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(Schemas.file, fileSystemProvider); - parentResource = parentDir; - workspaceDir = folderDir; - globalSettingsFile = path.join(parentDir, 'settings.json'); - globalTasksFile = path.join(parentDir, 'tasks.json'); + const folder = joinPath(URI.file('a')); + const appSettingsHome = joinPath(URI.file('user')); + await fileService.createFolder(folder); + await fileService.createFolder(appSettingsHome); - const instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); - instantiationService.stub(IRemoteAgentService, remoteAgentService); - fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IEnvironmentService, environmentService); + const instantiationService = workbenchInstantiationService(); + environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); + workspaceService = testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IWorkspaceContextService, testObject); + instantiationService.stub(IConfigurationService, testObject); + instantiationService.stub(IEnvironmentService, environmentService); - // Watch workspace configuration directory - disposables.add(fileService.watch(joinPath(URI.file(workspaceDir), '.vscode'))); - - return workspaceService.initialize(convertToWorkspacePayload(URI.file(folderDir))).then(() => { - instantiationService.stub(IFileService, fileService); - instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.acquireInstantiationService(instantiationService); - testObject = workspaceService; - }); - }); + await workspaceService.initialize(convertToWorkspacePayload(folder)); + instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); test('defaults', () => { assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'applicationSetting': 'isSet', 'machineSetting': 'isSet', 'machineOverridableSetting': 'isSet', 'testSetting': 'isSet', 'languageSetting': 'isSet' } }); }); - test('globals override defaults', () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); - return testObject.reloadConfiguration() - .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue')); + test('globals override defaults', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); + await testObject.reloadConfiguration(); + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue'); }); - test('globals', () => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - return testObject.reloadConfiguration() - .then(() => assert.equal(testObject.getValue('testworkbench.editor.tabs'), true)); + test('globals', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }')); + await testObject.reloadConfiguration(); + assert.equal(testObject.getValue('testworkbench.editor.tabs'), true); }); - test('workspace settings', () => { - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - return testObject.reloadConfiguration() - .then(() => assert.equal(testObject.getValue('testworkbench.editor.icons'), true)); + test('workspace settings', async () => { + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "testworkbench.editor.icons": true }')); + await testObject.reloadConfiguration(); + assert.equal(testObject.getValue('testworkbench.editor.icons'), true); }); - test('workspace settings override user settings', () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); - return testObject.reloadConfiguration() - .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue')); + test('workspace settings override user settings', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + return assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'); }); - test('machine overridable settings override user Settings', () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineOverridableSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineOverridableSetting": "workspaceValue" }'); - return testObject.reloadConfiguration() - .then(() => assert.equal(testObject.getValue('configurationService.folder.machineOverridableSetting'), 'workspaceValue')); + test('machine overridable settings override user Settings', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineOverridableSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineOverridableSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + return assert.equal(testObject.getValue('configurationService.folder.machineOverridableSetting'), 'workspaceValue'); }); - test('workspace settings override user settings after defaults are registered ', () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.newSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.newSetting": "workspaceValue" }'); - return testObject.reloadConfiguration() - .then(() => { - - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'configurationService.folder.newSetting': { - 'type': 'string', - 'default': 'isSet' - } - } - }); - - assert.equal(testObject.getValue('configurationService.folder.newSetting'), 'workspaceValue'); - }); + test('workspace settings override user settings after defaults are registered ', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.newSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.newSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.newSetting': { + 'type': 'string', + 'default': 'isSet' + } + } + }); + assert.equal(testObject.getValue('configurationService.folder.newSetting'), 'workspaceValue'); }); - test('machine overridable settings override user settings after defaults are registered ', () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.newMachineOverridableSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.newMachineOverridableSetting": "workspaceValue" }'); - return testObject.reloadConfiguration() - .then(() => { - - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'configurationService.folder.newMachineOverridableSetting': { - 'type': 'string', - 'default': 'isSet', - scope: ConfigurationScope.MACHINE_OVERRIDABLE - } - } - }); - - assert.equal(testObject.getValue('configurationService.folder.newMachineOverridableSetting'), 'workspaceValue'); - }); + test('machine overridable settings override user settings after defaults are registered ', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.newMachineOverridableSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.newMachineOverridableSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.newMachineOverridableSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE_OVERRIDABLE + } + } + }); + assert.equal(testObject.getValue('configurationService.folder.newMachineOverridableSetting'), 'workspaceValue'); }); test('application settings are not read from workspace', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.applicationSetting": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); @@ -830,8 +808,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('application settings are not read from workspace when workspace folder uri is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.applicationSetting": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); @@ -839,8 +817,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('machine settings are not read from workspace', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); @@ -848,8 +826,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('machine settings are not read from workspace when workspace folder uri is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); @@ -857,8 +835,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('get application scope settings are not loaded after defaults are registered', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting-2": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.applicationSetting-2": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting-2": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.applicationSetting-2": "workspaceValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.folder.applicationSetting-2'), 'workspaceValue'); @@ -882,8 +860,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('get application scope settings are not loaded after defaults are registered when workspace folder uri is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting-3": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.applicationSetting-3": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting-3": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.applicationSetting-3": "workspaceValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.folder.applicationSetting-3', { resource: workspaceService.getWorkspace().folders[0].uri }), 'workspaceValue'); @@ -907,8 +885,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('get machine scope settings are not loaded after defaults are registered', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting-2": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting-2": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting-2": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineSetting-2": "workspaceValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.folder.machineSetting-2'), 'workspaceValue'); @@ -932,8 +910,8 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { }); test('get machine scope settings are not loaded after defaults are registered when workspace folder uri is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting-3": "userValue" }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting-3": "workspaceValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting-3": "userValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineSetting-3": "workspaceValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.folder.machineSetting-3', { resource: workspaceService.getWorkspace().folders[0].uri }), 'workspaceValue'); @@ -956,33 +934,33 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { assert.equal(testObject.getValue('configurationService.folder.machineSetting-3', { resource: workspaceService.getWorkspace().folders[0].uri }), 'userValue'); }); - test('reload configuration emits events after global configuraiton changes', () => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + test('reload configuration emits events after global configuraiton changes', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }')); const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + await testObject.reloadConfiguration(); + return assert.ok(target.called); }); - test('reload configuration emits events after workspace configuraiton changes', () => { - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + test('reload configuration emits events after workspace configuraiton changes', async () => { + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + await testObject.reloadConfiguration(); + assert.ok(target.called); }); - test('reload configuration should not emit event if no changes', () => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); - return testObject.reloadConfiguration() - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeConfiguration(() => { target(); }); - return testObject.reloadConfiguration() - .then(() => assert.ok(!target.called)); - }); + test('reload configuration should not emit event if no changes', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(() => { target(); }); + await testObject.reloadConfiguration(); + return assert.ok(!target.called); }); - test('inspect', () => { + test('inspect', async () => { let actual = testObject.inspect('something.missing'); assert.equal(actual.defaultValue, undefined); assert.equal(actual.userValue, undefined); @@ -997,57 +975,47 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { assert.equal(actual.workspaceFolderValue, undefined); assert.equal(actual.value, 'isSet'); - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.inspect('configurationService.folder.testSetting'); - assert.equal(actual.defaultValue, 'isSet'); - assert.equal(actual.userValue, 'userValue'); - assert.equal(actual.workspaceValue, undefined); - assert.equal(actual.workspaceFolderValue, undefined); - assert.equal(actual.value, 'userValue'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.defaultValue, 'isSet'); + assert.equal(actual.userValue, 'userValue'); + assert.equal(actual.workspaceValue, undefined); + assert.equal(actual.workspaceFolderValue, undefined); + assert.equal(actual.value, 'userValue'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); - - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.inspect('configurationService.folder.testSetting'); - assert.equal(actual.defaultValue, 'isSet'); - assert.equal(actual.userValue, 'userValue'); - assert.equal(actual.workspaceValue, 'workspaceValue'); - assert.equal(actual.workspaceFolderValue, undefined); - assert.equal(actual.value, 'workspaceValue'); - }); - }); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.defaultValue, 'isSet'); + assert.equal(actual.userValue, 'userValue'); + assert.equal(actual.workspaceValue, 'workspaceValue'); + assert.equal(actual.workspaceFolderValue, undefined); + assert.equal(actual.value, 'workspaceValue'); }); - test('keys', () => { + test('keys', async () => { let actual = testObject.keys(); assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); assert.deepEqual(actual.user, []); assert.deepEqual(actual.workspace, []); assert.deepEqual(actual.workspaceFolder, []); - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.keys(); - assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); - assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); - assert.deepEqual(actual.workspace, []); - assert.deepEqual(actual.workspaceFolder, []); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, []); + assert.deepEqual(actual.workspaceFolder, []); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); - - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.keys(); - assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); - assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); - assert.deepEqual(actual.workspace, ['configurationService.folder.testSetting']); - assert.deepEqual(actual.workspaceFolder, []); - }); - }); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspaceFolder, []); }); test('update user configuration', () => { @@ -1151,15 +1119,14 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { assert.ok(target.notCalled); }); - test('change event when there are global tasks', () => { - fs.writeFileSync(globalTasksFile, '{ "version": "1.0.0", "tasks": [{ "taskName": "myTask" }'); + test('change event when there are global tasks', async () => { + await fileService.writeFile(joinPath(environmentService.userRoamingDataHome, 'tasks.json'), VSBuffer.fromString('{ "version": "1.0.0", "tasks": [{ "taskName": "myTask" }')); return new Promise((c) => testObject.onDidChangeConfiguration(() => c())); }); test('creating workspace settings', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); await testObject.reloadConfiguration(); - const workspaceSettingsResource = URI.file(path.join(workspaceDir, '.vscode', 'settings.json')); await new Promise(async (c) => { const disposable = testObject.onDidChangeConfiguration(e => { assert.ok(e.affectsConfiguration('configurationService.folder.testSetting')); @@ -1167,13 +1134,13 @@ flakySuite('WorkspaceConfigurationService - Folder', () => { disposable.dispose(); c(); }); - await fileService.writeFile(workspaceSettingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); }); }); - (!isMacintosh ? test.skip : test)('deleting workspace settings', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); - const workspaceSettingsResource = URI.file(path.join(workspaceDir, '.vscode', 'settings.json')); + test('deleting workspace settings', async () => { + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); + const workspaceSettingsResource = joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'); await fileService.writeFile(workspaceSettingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); const e = await new Promise(async (c) => { From 041a5c3b6b933ed52681e737a1ebc635261be156 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 23:05:09 +0100 Subject: [PATCH 1809/1837] fix tests - do not use file scheme --- .../electron-browser/desktop.main.ts | 2 +- .../electron-browser/configurationCache.ts | 10 +- .../configurationEditingService.test.ts | 2 +- .../configurationService.test.ts | 132 +++++++++--------- 4 files changed, 75 insertions(+), 71 deletions(-) diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index 0acfacc1a9b..722d27eae11 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -393,7 +393,7 @@ class DesktopMain extends Disposable { } private async createWorkspaceService(payload: IWorkspaceInitializationPayload, fileService: FileService, remoteAgentService: IRemoteAgentService, uriIdentityService: IUriIdentityService, logService: ILogService): Promise { - const workspaceService = new WorkspaceService({ remoteAuthority: this.environmentService.remoteAuthority, configurationCache: new ConfigurationCache(this.environmentService, fileService) }, this.environmentService, fileService, remoteAgentService, uriIdentityService, logService); + const workspaceService = new WorkspaceService({ remoteAuthority: this.environmentService.remoteAuthority, configurationCache: new ConfigurationCache(URI.file(this.environmentService.userDataPath), fileService) }, this.environmentService, fileService, remoteAgentService, uriIdentityService, logService); try { await workspaceService.initialize(payload); diff --git a/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts b/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts index 41908807355..27d36e5fa95 100644 --- a/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts +++ b/src/vs/workbench/services/configuration/electron-browser/configurationCache.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { join } from 'vs/base/common/path'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IConfigurationCache, ConfigurationKey } from 'vs/workbench/services/configuration/common/configuration'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; @@ -16,7 +14,7 @@ export class ConfigurationCache implements IConfigurationCache { private readonly cachedConfigurations: Map = new Map(); - constructor(private readonly environmentService: INativeWorkbenchEnvironmentService, private readonly fileService: IFileService) { + constructor(private readonly cacheHome: URI, private readonly fileService: IFileService) { } needsCaching(resource: URI): boolean { @@ -40,7 +38,7 @@ export class ConfigurationCache implements IConfigurationCache { const k = `${type}:${key}`; let cachedConfiguration = this.cachedConfigurations.get(k); if (!cachedConfiguration) { - cachedConfiguration = new CachedConfiguration({ type, key }, this.environmentService, this.fileService); + cachedConfiguration = new CachedConfiguration({ type, key }, this.cacheHome, this.fileService); this.cachedConfigurations.set(k, cachedConfiguration); } return cachedConfiguration; @@ -56,10 +54,10 @@ class CachedConfiguration { constructor( { type, key }: ConfigurationKey, - environmentService: INativeWorkbenchEnvironmentService, + cacheHome: URI, private readonly fileService: IFileService ) { - this.cachedConfigurationFolderResource = URI.file(join(environmentService.userDataPath, 'CachedConfigurations', type, key)); + this.cachedConfigurationFolderResource = joinPath(cacheHome, 'CachedConfigurations', type, key); this.cachedConfigurationFileResource = joinPath(this.cachedConfigurationFolderResource, type === 'workspaces' ? 'workspace.json' : 'configuration.json'); } diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index 292b26d3aea..a863a4ede6f 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -99,7 +99,7 @@ suite('ConfigurationEditingService', () => { disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, logService)))); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(URI.file(environmentService.userDataPath), fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); await workspaceService.initialize({ folder: workspaceFolder, id: createHash('md5').update(workspaceFolder.toString()).digest('hex') }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 05289b001c2..291b2143167 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -38,8 +38,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; -import { ConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; -import { ConfigurationCache as BrowserConfigurationCache } from 'vs/workbench/services/configuration/browser/configurationCache'; +import { ConfigurationCache as NativeConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { IConfigurationCache } from 'vs/workbench/services/configuration/common/configuration'; import { SignService } from 'vs/platform/sign/browser/signService'; @@ -68,6 +67,12 @@ class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService } +class ConfigurationCache extends NativeConfigurationCache { + needsCaching(resource: URI): boolean { + return false; + } +} + function setUpFolderWorkspace(folderName: string): Promise<{ parentDir: string, folderDir: string; }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); @@ -104,6 +109,7 @@ function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configP } +const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' }); suite('WorkspaceContextService - Folder', () => { @@ -114,14 +120,14 @@ suite('WorkspaceContextService - Folder', () => { const logService = new NullLogService(); const fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - fileService.registerProvider(Schemas.file, fileSystemProvider); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - folder = joinPath(URI.file(uuid.generateUuid()), folderName); + folder = joinPath(ROOT, folderName); await fileService.createFolder(folder); const environmentService = new TestWorkbenchEnvironmentService(folder); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); - testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService())); await (testObject).initialize(convertToWorkspacePayload(folder)); }); @@ -169,12 +175,12 @@ suite('WorkspaceContextService - Workspace', () => { const logService = new NullLogService(); const fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - fileService.registerProvider(Schemas.file, fileSystemProvider); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - const appSettingsHome = URI.file('user'); - const folderA = URI.file('a'); - const folderB = URI.file('b'); - const configResource = URI.file('vsctests.code-workspace'); + const appSettingsHome = joinPath(ROOT, 'user'); + const folderA = joinPath(ROOT, 'a'); + const folderB = joinPath(ROOT, 'b'); + const configResource = joinPath(ROOT, 'vsctests.code-workspace'); const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; await fileService.createFolder(appSettingsHome); @@ -186,8 +192,8 @@ suite('WorkspaceContextService - Workspace', () => { const environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); instantiationService.stub(IRemoteAgentService, remoteAgentService); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); - testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, testObject); instantiationService.stub(IConfigurationService, testObject); @@ -227,12 +233,12 @@ suite('WorkspaceContextService - Workspace Editing', () => { const logService = new NullLogService(); fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - fileService.registerProvider(Schemas.file, fileSystemProvider); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - const appSettingsHome = URI.file('user'); - const folderA = URI.file('a'); - const folderB = URI.file('b'); - const configResource = URI.file('vsctests.code-workspace'); + const appSettingsHome = joinPath(ROOT, 'user'); + const folderA = joinPath(ROOT, 'a'); + const folderB = joinPath(ROOT, 'b'); + const configResource = joinPath(ROOT, 'vsctests.code-workspace'); const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; await fileService.createFolder(appSettingsHome); @@ -244,8 +250,8 @@ suite('WorkspaceContextService - Workspace Editing', () => { const environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); const remoteAgentService = instantiationService.createInstance(RemoteAgentService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); - testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IFileService, fileService); instantiationService.stub(IWorkspaceContextService, testObject); @@ -261,7 +267,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { teardown(() => disposables.clear()); test('add folders', async () => { - await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }]); + await testObject.addFolders([{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }]); const actual = testObject.getWorkspace().folders; assert.equal(actual.length, 4); @@ -272,7 +278,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { }); test('add folders (at specific index)', async () => { - await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }], 0); + await testObject.addFolders([{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }], 0); const actual = testObject.getWorkspace().folders; assert.equal(actual.length, 4); @@ -283,7 +289,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { }); test('add folders (at specific wrong index)', async () => { - await testObject.addFolders([{ uri: URI.file('d') }, { uri: URI.file('c') }], 10); + await testObject.addFolders([{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }], 10); const actual = testObject.getWorkspace().folders; assert.equal(actual.length, 4); @@ -294,7 +300,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { }); test('add folders (with name)', async () => { - await testObject.addFolders([{ uri: URI.file('d'), name: 'DDD' }, { uri: URI.file('c'), name: 'CCC' }]); + await testObject.addFolders([{ uri: joinPath(ROOT, 'd'), name: 'DDD' }, { uri: joinPath(ROOT, 'c'), name: 'CCC' }]); const actual = testObject.getWorkspace().folders; assert.equal(actual.length, 4); @@ -310,7 +316,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; + const addedFolders = [{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }]; await testObject.addFolders(addedFolders); assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); @@ -364,7 +370,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { test('update folders (remove last and add to end)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; + const addedFolders = [{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }]; const removedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); await testObject.updateFolders(addedFolders, removedFolders); @@ -378,7 +384,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { test('update folders (rename first via add and remove)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const addedFolders = [{ uri: URI.file('a'), name: 'The Folder' }]; + const addedFolders = [{ uri: joinPath(ROOT, 'a'), name: 'The Folder' }]; const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); await testObject.updateFolders(addedFolders, removedFolders, 0); @@ -392,7 +398,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { test('update folders (remove first and add to end)', async () => { const target = sinon.spy(); testObject.onDidChangeWorkspaceFolders(target); - const addedFolders = [{ uri: URI.file('d') }, { uri: URI.file('c') }]; + const addedFolders = [{ uri: joinPath(ROOT, 'd') }, { uri: joinPath(ROOT, 'c') }]; const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); const changedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); await testObject.updateFolders(addedFolders, removedFolders); @@ -463,12 +469,12 @@ suite('WorkspaceService - Initialization', () => { const logService = new NullLogService(); fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - fileService.registerProvider(Schemas.file, fileSystemProvider); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - const appSettingsHome = URI.file('user'); - const folderA = URI.file('a'); - const folderB = URI.file('b'); - configResource = URI.file('vsctests.code-workspace'); + const appSettingsHome = joinPath(ROOT, 'user'); + const folderA = joinPath(ROOT, 'a'); + const folderB = joinPath(ROOT, 'b'); + configResource = joinPath(ROOT, 'vsctests.code-workspace'); const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; await fileService.createFolder(appSettingsHome); @@ -480,8 +486,8 @@ suite('WorkspaceService - Initialization', () => { environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); const remoteAgentService = instantiationService.createInstance(RemoteAgentService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); - testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IFileService, fileService); instantiationService.stub(IWorkspaceContextService, testObject); instantiationService.stub(IConfigurationService, testObject); @@ -506,7 +512,7 @@ suite('WorkspaceService - Initialization', () => { testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - const folder = URI.file('a'); + const folder = joinPath(ROOT, 'a'); await testObject.initialize(convertToWorkspacePayload(folder)); assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); @@ -530,7 +536,7 @@ suite('WorkspaceService - Initialization', () => { testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - const folder = URI.file('a'); + const folder = joinPath(ROOT, 'a'); await fileService.writeFile(joinPath(folder, '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue" }')); await testObject.initialize(convertToWorkspacePayload(folder)); @@ -561,7 +567,7 @@ suite('WorkspaceService - Initialization', () => { assert.equal(target.callCount, 3); assert.deepEqual(target.args[0], [WorkbenchState.WORKSPACE]); assert.deepEqual(target.args[1], [undefined]); - assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.toString()), [URI.file('a').toString(), URI.file('b').toString()]); + assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.toString()), [joinPath(ROOT, 'a').toString(), joinPath(ROOT, 'b').toString()]); assert.deepEqual((target.args[2][0]).removed, []); assert.deepEqual((target.args[2][0]).changed, []); @@ -578,15 +584,15 @@ suite('WorkspaceService - Initialization', () => { testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - await fileService.writeFile(joinPath(URI.file('a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue1" }')); - await fileService.writeFile(joinPath(URI.file('b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting2": "workspaceValue2" }')); + await fileService.writeFile(joinPath(joinPath(ROOT, 'a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue1" }')); + await fileService.writeFile(joinPath(joinPath(ROOT, 'b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting2": "workspaceValue2" }')); await testObject.initialize(getWorkspaceIdentifier(configResource)); assert.equal(target.callCount, 4); assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1', 'initialization.testSetting2']); assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); assert.deepEqual(target.args[2], [undefined]); - assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.toString()), [URI.file('a').toString(), URI.file('b').toString()]); + assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.toString()), [joinPath(ROOT, 'a').toString(), joinPath(ROOT, 'b').toString()]); assert.deepEqual((target.args[3][0]).removed, []); assert.deepEqual((target.args[3][0]).changed, []); @@ -594,7 +600,7 @@ suite('WorkspaceService - Initialization', () => { test('initialize a folder workspace from a folder workspace with no configuration changes', async () => { - await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + await testObject.initialize(convertToWorkspacePayload(joinPath(ROOT, 'a'))); await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "initialization.testSetting1": "userValue" }')); await testObject.reloadConfiguration(); const target = sinon.spy(); @@ -603,53 +609,53 @@ suite('WorkspaceService - Initialization', () => { testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - await testObject.initialize(convertToWorkspacePayload(URI.file('b'))); + await testObject.initialize(convertToWorkspacePayload(joinPath(ROOT, 'b'))); assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); assert.equal(target.callCount, 1); - assert.deepEqual((target.args[0][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); - assert.deepEqual((target.args[0][0]).removed.map(folder_2 => folder_2.uri.toString()), [URI.file('a').toString()]); + assert.deepEqual((target.args[0][0]).added.map(folder_1 => folder_1.uri.toString()), [joinPath(ROOT, 'b').toString()]); + assert.deepEqual((target.args[0][0]).removed.map(folder_2 => folder_2.uri.toString()), [joinPath(ROOT, 'a').toString()]); assert.deepEqual((target.args[0][0]).changed, []); }); test('initialize a folder workspace from a folder workspace with configuration changes', async () => { - await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + await testObject.initialize(convertToWorkspacePayload(joinPath(ROOT, 'a'))); const target = sinon.spy(); testObject.onDidChangeWorkbenchState(target); testObject.onDidChangeWorkspaceName(target); testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - await fileService.writeFile(joinPath(URI.file('b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); - await testObject.initialize(convertToWorkspacePayload(URI.file('b'))); + await fileService.writeFile(joinPath(joinPath(ROOT, 'b'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); + await testObject.initialize(convertToWorkspacePayload(joinPath(ROOT, 'b'))); assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue2'); assert.equal(target.callCount, 2); assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); - assert.deepEqual((target.args[1][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); - assert.deepEqual((target.args[1][0]).removed.map(folder_2 => folder_2.uri.toString()), [URI.file('a').toString()]); + assert.deepEqual((target.args[1][0]).added.map(folder_1 => folder_1.uri.toString()), [joinPath(ROOT, 'b').toString()]); + assert.deepEqual((target.args[1][0]).removed.map(folder_2 => folder_2.uri.toString()), [joinPath(ROOT, 'a').toString()]); assert.deepEqual((target.args[1][0]).changed, []); }); test('initialize a multi folder workspace from a folder workspacce triggers change events in the right order', async () => { - await testObject.initialize(convertToWorkspacePayload(URI.file('a'))); + await testObject.initialize(convertToWorkspacePayload(joinPath(ROOT, 'a'))); const target = sinon.spy(); testObject.onDidChangeWorkbenchState(target); testObject.onDidChangeWorkspaceName(target); testObject.onDidChangeWorkspaceFolders(target); testObject.onDidChangeConfiguration(target); - await fileService.writeFile(joinPath(URI.file('a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); + await fileService.writeFile(joinPath(joinPath(ROOT, 'a'), '.vscode', 'settings.json'), VSBuffer.fromString('{ "initialization.testSetting1": "workspaceValue2" }')); await testObject.initialize(getWorkspaceIdentifier(configResource)); assert.equal(target.callCount, 4); assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); assert.deepEqual(target.args[2], [undefined]); - assert.deepEqual((target.args[3][0]).added.map(folder_1 => folder_1.uri.toString()), [URI.file('b').toString()]); + assert.deepEqual((target.args[3][0]).added.map(folder_1 => folder_1.uri.toString()), [joinPath(ROOT, 'b').toString()]); assert.deepEqual((target.args[3][0]).removed, []); assert.deepEqual((target.args[3][0]).changed, []); }); @@ -700,10 +706,10 @@ suite('WorkspaceConfigurationService - Folder', () => { const logService = new NullLogService(); fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - fileService.registerProvider(Schemas.file, fileSystemProvider); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - const folder = joinPath(URI.file('a')); - const appSettingsHome = joinPath(URI.file('user')); + const appSettingsHome = joinPath(joinPath(ROOT, 'user')); + const folder = joinPath(joinPath(ROOT, 'a')); await fileService.createFolder(folder); await fileService.createFolder(appSettingsHome); @@ -711,8 +717,8 @@ suite('WorkspaceConfigurationService - Folder', () => { environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); const remoteAgentService = instantiationService.createInstance(RemoteAgentService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, new NullLogService()))); - workspaceService = testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + workspaceService = testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IFileService, fileService); instantiationService.stub(IWorkspaceContextService, testObject); instantiationService.stub(IConfigurationService, testObject); @@ -1211,7 +1217,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -2026,20 +2032,20 @@ suite('ConfigurationService - Configuration Defaults', () => { teardown(() => disposableStore.clear()); test('when default value is not overriden', () => { - const testObject = createConfiurationService({}); + const testObject = createConfigurationService({}); assert.deepEqual(testObject.getValue('configurationService.defaultOverridesSetting'), 'isSet'); }); test('when default value is overriden', () => { - const testObject = createConfiurationService({ 'configurationService.defaultOverridesSetting': 'overriddenValue' }); + const testObject = createConfigurationService({ 'configurationService.defaultOverridesSetting': 'overriddenValue' }); assert.deepEqual(testObject.getValue('configurationService.defaultOverridesSetting'), 'overriddenValue'); }); - function createConfiurationService(configurationDefaults: Record): IConfigurationService { + function createConfigurationService(configurationDefaults: Record): IConfigurationService { const remoteAgentService = (workbenchInstantiationService()).createInstance(RemoteAgentService); const environmentService = new BrowserWorkbenchEnvironmentService({ logsPath: URI.file(''), workspaceId: '', configurationDefaults }, TestProductService); const fileService = new FileService(new NullLogService()); - return disposableStore.add(new WorkspaceService({ configurationCache: new BrowserConfigurationCache() }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + return disposableStore.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); } }); From 506ae4a53e778c6c525e96633c2afe4116a41207 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 23:30:43 +0100 Subject: [PATCH 1810/1837] use in-mem fsp - multi root workspace config tests --- .../configurationService.test.ts | 423 ++++++++---------- 1 file changed, 192 insertions(+), 231 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 291b2143167..7b69ef80b28 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -92,23 +92,6 @@ function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceInitializ } as ISingleFolderWorkspaceInitializationPayload; } -function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: URI; }> { - - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - - return Promise.resolve(pfs.mkdirp(parentDir, 493) - .then(() => { - const configPath = path.join(parentDir, 'vsctests.code-workspace'); - const workspace = { folders: folders.map(path => ({ path })) }; - fs.writeFileSync(configPath, JSON.stringify(workspace, null, '\t')); - - return Promise.all(folders.map(folder => setUpFolder(folder, parentDir))) - .then(() => ({ parentDir, configPath: URI.file(configPath) })); - })); - -} - const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' }); suite('WorkspaceContextService - Folder', () => { @@ -759,14 +742,14 @@ suite('WorkspaceConfigurationService - Folder', () => { await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "userValue" }')); await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); - return assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'); + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'); }); test('machine overridable settings override user Settings', async () => { await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineOverridableSetting": "userValue" }')); await fileService.writeFile(joinPath(workspaceService.getWorkspace().folders[0].uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.folder.machineOverridableSetting": "workspaceValue" }')); await testObject.reloadConfiguration(); - return assert.equal(testObject.getValue('configurationService.folder.machineOverridableSetting'), 'workspaceValue'); + assert.equal(testObject.getValue('configurationService.folder.machineOverridableSetting'), 'workspaceValue'); }); test('workspace settings override user settings after defaults are registered ', async () => { @@ -945,7 +928,7 @@ suite('WorkspaceConfigurationService - Folder', () => { const target = sinon.spy(); testObject.onDidChangeConfiguration(target); await testObject.reloadConfiguration(); - return assert.ok(target.called); + assert.ok(target.called); }); test('reload configuration emits events after workspace configuraiton changes', async () => { @@ -963,7 +946,7 @@ suite('WorkspaceConfigurationService - Folder', () => { const target = sinon.spy(); testObject.onDidChangeConfiguration(() => { target(); }); await testObject.reloadConfiguration(); - return assert.ok(!target.called); + assert.ok(!target.called); }); test('inspect', async () => { @@ -1158,9 +1141,9 @@ suite('WorkspaceConfigurationService - Folder', () => { }); }); -flakySuite('WorkspaceConfigurationService-Multiroot', () => { +suite('WorkspaceConfigurationService-Multiroot', () => { - let parentResource: string, workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService, globalSettingsFile: string; + let workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService, fileService: IFileService, environmentService: NativeWorkbenchEnvironmentService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); const disposables = new DisposableStore(); @@ -1202,52 +1185,51 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); }); - setup(() => { - return setUpWorkspace(['1', '2']) - .then(({ parentDir, configPath }) => { + setup(async () => { + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - parentResource = parentDir; - globalSettingsFile = path.join(parentDir, 'settings.json'); + const appSettingsHome = joinPath(ROOT, 'user'); + const folderA = joinPath(ROOT, 'a'); + const folderB = joinPath(ROOT, 'b'); + const configResource = joinPath(ROOT, 'vsctests.code-workspace'); + const workspace = { folders: [{ path: folderA.path }, { path: folderB.path }] }; - const instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteAgentService = instantiationService.createInstance(RemoteAgentService); - instantiationService.stub(IRemoteAgentService, remoteAgentService); - const fileService = disposables.add(new FileService(new NullLogService())); - const diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + await fileService.createFolder(appSettingsHome); + await fileService.createFolder(folderA); + await fileService.createFolder(folderB); + await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IWorkbenchEnvironmentService, environmentService); - instantiationService.stub(INativeWorkbenchEnvironmentService, environmentService); + const instantiationService = workbenchInstantiationService(); + environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + const workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { - instantiationService.stub(IFileService, fileService); - instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.acquireInstantiationService(instantiationService); + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IWorkbenchEnvironmentService, environmentService); + instantiationService.stub(INativeWorkbenchEnvironmentService, environmentService); - workspaceContextService = workspaceService; - jsonEditingServce = instantiationService.createInstance(JSONEditingService); - testObject = workspaceService; - }); - }); + await workspaceService.initialize(getWorkspaceIdentifier(configResource)); + instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); + + workspaceContextService = workspaceService; + jsonEditingServce = instantiationService.createInstance(JSONEditingService); + testObject = workspaceService; }); - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); test('application settings are not read from workspace', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.applicationSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1256,7 +1238,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('application settings are not read from workspace when folder is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.applicationSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.applicationSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1265,7 +1247,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('machine settings are not read from workspace', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.machineSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1274,7 +1256,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('machine settings are not read from workspace when folder is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.folder.machineSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.machineSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1283,7 +1265,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('get application scope settings are not loaded after defaults are registered', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.newSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.newSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.newSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1308,7 +1290,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('get application scope settings are not loaded after defaults are registered when workspace folder is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.newSetting-2": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.newSetting-2": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.newSetting-2': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1333,7 +1315,7 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('workspace settings override user settings after defaults are registered for machine overridable settings ', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.newMachineOverridableSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.newMachineOverridableSetting": "userValue" }')); await jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.newMachineOverridableSetting': 'workspaceValue' } }], true); await testObject.reloadConfiguration(); @@ -1359,8 +1341,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('application settings are not read from workspace folder', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.applicationSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.applicationSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.applicationSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.applicationSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); @@ -1368,8 +1350,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('application settings are not read from workspace folder when workspace folder is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.applicationSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.applicationSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.applicationSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.applicationSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); @@ -1377,8 +1359,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('machine settings are not read from workspace folder', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.machineSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.machineSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); @@ -1386,8 +1368,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('machine settings are not read from workspace folder when workspace folder is passed', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.machineSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.machineSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); @@ -1395,8 +1377,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('application settings are not read from workspace folder after defaults are registered', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testNewApplicationSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewApplicationSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.testNewApplicationSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testNewApplicationSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.workspace.testNewApplicationSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); @@ -1420,8 +1402,8 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { }); test('application settings are not read from workspace folder after defaults are registered', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testNewMachineSetting": "userValue" }'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewMachineSetting": "workspaceFolderValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.testNewMachineSetting": "userValue" }')); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testNewMachineSetting": "workspaceFolderValue" }')); await testObject.reloadConfiguration(); assert.equal(testObject.getValue('configurationService.workspace.testNewMachineSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); @@ -1444,67 +1426,61 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { assert.equal(testObject.getValue('configurationService.workspace.testNewMachineSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'userValue'); }); - test('resource setting in folder is read after it is registered later', () => { - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewResourceSetting2": "workspaceFolderValue" }'); - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'configurationService.workspace.testNewResourceSetting2': { - 'type': 'string', - 'default': 'isSet', - scope: ConfigurationScope.RESOURCE - } - } - }); - assert.equal(testObject.getValue('configurationService.workspace.testNewResourceSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); - }); + test('resource setting in folder is read after it is registered later', async () => { + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testNewResourceSetting2": "workspaceFolderValue" }')); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['settings'], value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }], true); + await testObject.reloadConfiguration(); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewResourceSetting2': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewResourceSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); }); - test('resource language setting in folder is read after it is registered later', () => { - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewResourceLanguageSetting2": "workspaceFolderValue" }'); - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.testNewResourceLanguageSetting2': 'workspaceValue' } }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'configurationService.workspace.testNewResourceLanguageSetting2': { - 'type': 'string', - 'default': 'isSet', - scope: ConfigurationScope.LANGUAGE_OVERRIDABLE - } - } - }); - assert.equal(testObject.getValue('configurationService.workspace.testNewResourceLanguageSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); - }); + test('resource language setting in folder is read after it is registered later', async () => { + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testNewResourceLanguageSetting2": "workspaceFolderValue" }')); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['settings'], value: { 'configurationService.workspace.testNewResourceLanguageSetting2': 'workspaceValue' } }], true); + await testObject.reloadConfiguration(); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewResourceLanguageSetting2': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.LANGUAGE_OVERRIDABLE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewResourceLanguageSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); }); - test('machine overridable setting in folder is read after it is registered later', () => { - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewMachineOverridableSetting2": "workspaceFolderValue" }'); - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.testNewMachineOverridableSetting2': 'workspaceValue' } }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'configurationService.workspace.testNewMachineOverridableSetting2': { - 'type': 'string', - 'default': 'isSet', - scope: ConfigurationScope.MACHINE_OVERRIDABLE - } - } - }); - assert.equal(testObject.getValue('configurationService.workspace.testNewMachineOverridableSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); - }); + test('machine overridable setting in folder is read after it is registered later', async () => { + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testNewMachineOverridableSetting2": "workspaceFolderValue" }')); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['settings'], value: { 'configurationService.workspace.testNewMachineOverridableSetting2': 'workspaceValue' } }], true); + await testObject.reloadConfiguration(); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewMachineOverridableSetting2': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE_OVERRIDABLE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewMachineOverridableSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); }); - test('inspect', () => { + test('inspect', async () => { let actual = testObject.inspect('something.missing'); assert.equal(actual.defaultValue, undefined); assert.equal(actual.userValue, undefined); @@ -1519,42 +1495,35 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { assert.equal(actual.workspaceFolderValue, undefined); assert.equal(actual.value, 'isSet'); - fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testResourceSetting": "userValue" }'); - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.inspect('configurationService.workspace.testResourceSetting'); - assert.equal(actual.defaultValue, 'isSet'); - assert.equal(actual.userValue, 'userValue'); - assert.equal(actual.workspaceValue, undefined); - assert.equal(actual.workspaceFolderValue, undefined); - assert.equal(actual.value, 'userValue'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.workspace.testResourceSetting": "userValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.inspect('configurationService.workspace.testResourceSetting'); + assert.equal(actual.defaultValue, 'isSet'); + assert.equal(actual.userValue, 'userValue'); + assert.equal(actual.workspaceValue, undefined); + assert.equal(actual.workspaceFolderValue, undefined); + assert.equal(actual.value, 'userValue'); - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['settings'], value: { 'configurationService.workspace.testResourceSetting': 'workspaceValue' } }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - actual = testObject.inspect('configurationService.workspace.testResourceSetting'); - assert.equal(actual.defaultValue, 'isSet'); - assert.equal(actual.userValue, 'userValue'); - assert.equal(actual.workspaceValue, 'workspaceValue'); - assert.equal(actual.workspaceFolderValue, undefined); - assert.equal(actual.value, 'workspaceValue'); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['settings'], value: { 'configurationService.workspace.testResourceSetting': 'workspaceValue' } }], true); + await testObject.reloadConfiguration(); + actual = testObject.inspect('configurationService.workspace.testResourceSetting'); + assert.equal(actual.defaultValue, 'isSet'); + assert.equal(actual.userValue, 'userValue'); + assert.equal(actual.workspaceValue, 'workspaceValue'); + assert.equal(actual.workspaceFolderValue, undefined); + assert.equal(actual.value, 'workspaceValue'); - fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }'); - - return testObject.reloadConfiguration() - .then(() => { - actual = testObject.inspect('configurationService.workspace.testResourceSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }); - assert.equal(actual.defaultValue, 'isSet'); - assert.equal(actual.userValue, 'userValue'); - assert.equal(actual.workspaceValue, 'workspaceValue'); - assert.equal(actual.workspaceFolderValue, 'workspaceFolderValue'); - assert.equal(actual.value, 'workspaceFolderValue'); - }); - }); - }); + await fileService.writeFile(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }')); + await testObject.reloadConfiguration(); + actual = testObject.inspect('configurationService.workspace.testResourceSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }); + assert.equal(actual.defaultValue, 'isSet'); + assert.equal(actual.userValue, 'userValue'); + assert.equal(actual.workspaceValue, 'workspaceValue'); + assert.equal(actual.workspaceFolderValue, 'workspaceFolderValue'); + assert.equal(actual.value, 'workspaceFolderValue'); }); - test('get launch configuration', () => { + test('get launch configuration', async () => { const expectedLaunchConfiguration = { 'version': '0.1.0', 'configurations': [ @@ -1571,15 +1540,13 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { } ] }; - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['launch'], value: expectedLaunchConfiguration }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.getValue('launch'); - assert.deepEqual(actual, expectedLaunchConfiguration); - }); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['launch'], value: expectedLaunchConfiguration }], true); + await testObject.reloadConfiguration(); + const actual = testObject.getValue('launch'); + assert.deepEqual(actual, expectedLaunchConfiguration); }); - test('inspect launch configuration', () => { + test('inspect launch configuration', async () => { const expectedLaunchConfiguration = { 'version': '0.1.0', 'configurations': [ @@ -1596,16 +1563,14 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { } ] }; - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['launch'], value: expectedLaunchConfiguration }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.inspect('launch').workspaceValue; - assert.deepEqual(actual, expectedLaunchConfiguration); - }); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['launch'], value: expectedLaunchConfiguration }], true); + await testObject.reloadConfiguration(); + const actual = testObject.inspect('launch').workspaceValue; + assert.deepEqual(actual, expectedLaunchConfiguration); }); - test('get tasks configuration', () => { + test('get tasks configuration', async () => { const expectedTasksConfiguration = { 'version': '2.0.0', 'tasks': [ @@ -1620,12 +1585,10 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { } ] }; - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ path: ['tasks'], value: expectedTasksConfiguration }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.getValue('tasks'); - assert.deepEqual(actual, expectedTasksConfiguration); - }); + await jsonEditingServce.write((workspaceContextService.getWorkspace().configuration!), [{ path: ['tasks'], value: expectedTasksConfiguration }], true); + await testObject.reloadConfiguration(); + const actual = testObject.getValue('tasks'); + assert.deepEqual(actual, expectedTasksConfiguration); }); test('inspect tasks configuration', async () => { @@ -1649,28 +1612,28 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { assert.deepEqual(actual, expectedTasksConfiguration); }); - test('update user configuration', () => { - return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) - .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); + test('update user configuration', async () => { + await testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER); + assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue'); }); - test('update user configuration should trigger change event before promise is resolve', () => { + test('update user configuration should trigger change event before promise is resolve', async () => { const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) - .then(() => assert.ok(target.called)); + await testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER); + assert.ok(target.called); }); - test('update workspace configuration', () => { - return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) - .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'workspaceValue')); + test('update workspace configuration', async () => { + await testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE); + assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'workspaceValue'); }); - test('update workspace configuration should trigger change event before promise is resolve', () => { + test('update workspace configuration should trigger change event before promise is resolve', async () => { const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) - .then(() => assert.ok(target.called)); + await testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE); + assert.ok(target.called); }); test('update application setting into workspace configuration in a workspace is not supported', () => { @@ -1689,41 +1652,39 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue')); }); - test('update resource language configuration in workspace folder', () => { + test('update resource language configuration in workspace folder', async () => { const workspace = workspaceContextService.getWorkspace(); - return testObject.updateValue('configurationService.workspace.testLanguageSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) - .then(() => assert.equal(testObject.getValue('configurationService.workspace.testLanguageSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue')); + await testObject.updateValue('configurationService.workspace.testLanguageSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); + assert.equal(testObject.getValue('configurationService.workspace.testLanguageSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue'); }); - test('update workspace folder configuration should trigger change event before promise is resolve', () => { + test('update workspace folder configuration should trigger change event before promise is resolve', async () => { const workspace = workspaceContextService.getWorkspace(); const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) - .then(() => assert.ok(target.called)); + await testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); + assert.ok(target.called); }); - test('update workspace folder configuration second time should trigger change event before promise is resolve', () => { + test('update workspace folder configuration second time should trigger change event before promise is resolve', async () => { const workspace = workspaceContextService.getWorkspace(); - return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) - .then(() => { - const target = sinon.spy(); - testObject.onDidChangeConfiguration(target); - return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue2', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) - .then(() => assert.ok(target.called)); - }); - }); - - test('update memory configuration', () => { - return testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) - .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'memoryValue')); - }); - - test('update memory configuration should trigger change event before promise is resolve', () => { + await testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); const target = sinon.spy(); testObject.onDidChangeConfiguration(target); - return testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) - .then(() => assert.ok(target.called)); + await testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue2', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); + assert.ok(target.called); + }); + + test('update memory configuration', async () => { + await testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY); + assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'memoryValue'); + }); + + test('update memory configuration should trigger change event before promise is resolve', async () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + await testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY); + assert.ok(target.called); }); test('remove setting from all targets', async () => { @@ -1742,30 +1703,30 @@ flakySuite('WorkspaceConfigurationService-Multiroot', () => { assert.equal(actual.workspaceFolderValue, undefined); }); - test('update tasks configuration in a folder', () => { + test('update tasks configuration in a folder', async () => { const workspace = workspaceContextService.getWorkspace(); - return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) - .then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); + await testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER); + assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }); }); - test('update launch configuration in a workspace', () => { + test('update launch configuration in a workspace', async () => { const workspace = workspaceContextService.getWorkspace(); - return testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) - .then(() => assert.deepEqual(testObject.getValue('launch'), { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] })); + await testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true); + assert.deepEqual(testObject.getValue('launch'), { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }); }); - test('update tasks configuration in a workspace', () => { + test('update tasks configuration in a workspace', async () => { const workspace = workspaceContextService.getWorkspace(); const tasks = { 'version': '2.0.0', tasks: [{ 'label': 'myTask' }] }; - return testObject.updateValue('tasks', tasks, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) - .then(() => assert.deepEqual(testObject.getValue('tasks'), tasks)); + await testObject.updateValue('tasks', tasks, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true); + assert.deepEqual(testObject.getValue('tasks'), tasks); }); test('configuration of newly added folder is available on configuration change event', async () => { const workspaceService = testObject; const uri = workspaceService.getWorkspace().folders[1].uri; await workspaceService.removeFolders([uri]); - fs.writeFileSync(path.join(uri.fsPath, '.vscode', 'settings.json'), '{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }'); + await fileService.writeFile(joinPath(uri, '.vscode', 'settings.json'), VSBuffer.fromString('{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }')); return new Promise((c, e) => { testObject.onDidChangeConfiguration(() => { From c88ab9e0b63c380a238aa2beb5ba44525404430b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 23:50:00 +0100 Subject: [PATCH 1811/1837] use in-mem fsp - remote folder config tests --- .../configurationService.test.ts | 109 +++++++----------- 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 7b69ef80b28..def734cffba 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -5,14 +5,9 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import * as fs from 'fs'; -import * as path from 'vs/base/common/path'; -import * as os from 'os'; import { URI } from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import * as pfs from 'vs/base/node/pfs'; -import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService'; import { ISingleFolderWorkspaceInitializationPayload, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; @@ -30,14 +25,13 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService'; import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; -import { originalFSPath, joinPath, dirname, basename } from 'vs/base/common/resources'; +import { joinPath, dirname, basename } from 'vs/base/common/resources'; import { isLinux } from 'vs/base/common/platform'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-sandbox/remoteAuthorityResolverService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; -import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { ConfigurationCache as NativeConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { IConfigurationCache } from 'vs/workbench/services/configuration/common/configuration'; @@ -55,7 +49,6 @@ import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/enviro import { Event } from 'vs/base/common/event'; import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; -import { flakySuite } from 'vs/base/test/node/testUtils'; class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -73,18 +66,6 @@ class ConfigurationCache extends NativeConfigurationCache { } } -function setUpFolderWorkspace(folderName: string): Promise<{ parentDir: string, folderDir: string; }> { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - return setUpFolder(folderName, parentDir).then(folderDir => ({ parentDir, folderDir })); -} - -function setUpFolder(folderName: string, parentDir: string): Promise { - const folderDir = path.join(parentDir, folderName); - const workspaceSettingsDir = path.join(folderDir, '.vscode'); - return Promise.resolve(pfs.mkdirp(workspaceSettingsDir, 493).then(() => folderDir)); -} - function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceInitializationPayload { return { id: createHash('md5').update(folder.fsPath).digest('hex'), @@ -192,8 +173,8 @@ suite('WorkspaceContextService - Workspace', () => { const actual = testObject.getWorkspace().folders; assert.equal(actual.length, 2); - assert.equal(path.basename(actual[0].uri.fsPath), 'a'); - assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(basename(actual[0].uri), 'a'); + assert.equal(basename(actual[1].uri), 'b'); }); test('getWorkbenchState()', () => { @@ -1742,13 +1723,14 @@ suite('WorkspaceConfigurationService-Multiroot', () => { }); }); -flakySuite('WorkspaceConfigurationService - Remote Folder', () => { +suite('WorkspaceConfigurationService - Remote Folder', () => { - let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: WorkspaceService, globalSettingsFile: string, remoteSettingsFile: string, remoteSettingsResource: URI, instantiationService: TestInstantiationService, resolveRemoteEnvironment: () => void; + let testObject: WorkspaceService, folder: URI, + machineSettingsResource: URI, remoteSettingsResource: URI, fileSystemProvider: InMemoryFileSystemProvider, resolveRemoteEnvironment: () => void, + instantiationService: TestInstantiationService, fileService: IFileService, environmentService: NativeWorkbenchEnvironmentService; const remoteAuthority = 'configuraiton-tests'; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); const disposables = new DisposableStore(); - let diskFileSystemProvider: DiskFileSystemProvider; suiteSetup(() => { configurationRegistry.registerConfiguration({ @@ -1779,42 +1761,41 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); }); - setup(() => { - return setUpFolderWorkspace(workspaceName) - .then(({ parentDir, folderDir }) => { + setup(async () => { + const logService = new NullLogService(); + fileService = disposables.add(new FileService(logService)); + fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); + fileService.registerProvider(ROOT.scheme, fileSystemProvider); - parentResource = parentDir; - workspaceDir = folderDir; - globalSettingsFile = path.join(parentDir, 'settings.json'); - remoteSettingsFile = path.join(parentDir, 'remote-settings.json'); - remoteSettingsResource = URI.file(remoteSettingsFile).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority }); + const appSettingsHome = joinPath(joinPath(ROOT, 'user')); + folder = joinPath(joinPath(ROOT, 'a')); + await fileService.createFolder(folder); + await fileService.createFolder(appSettingsHome); + machineSettingsResource = joinPath(ROOT, 'machine-settings.json'); + remoteSettingsResource = machineSettingsResource.with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority }); - instantiationService = workbenchInstantiationService(); - const environmentService = new TestWorkbenchEnvironmentService(URI.file(parentDir)); - const remoteEnvironmentPromise = new Promise>(c => resolveRemoteEnvironment = () => c({ settingsPath: remoteSettingsResource })); - const remoteAgentService = instantiationService.stub(IRemoteAgentService, >{ getEnvironment: () => remoteEnvironmentPromise }); - const fileService = disposables.add(new FileService(new NullLogService())); - diskFileSystemProvider = disposables.add(new DiskFileSystemProvider(new NullLogService())); - fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()))); - const configurationCache: IConfigurationCache = { read: () => Promise.resolve(''), write: () => Promise.resolve(), remove: () => Promise.resolve(), needsCaching: () => false }; - testObject = disposables.add(new WorkspaceService({ configurationCache, remoteAuthority }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); - instantiationService.stub(IWorkspaceContextService, testObject); - instantiationService.stub(IConfigurationService, testObject); - instantiationService.stub(IEnvironmentService, environmentService); - instantiationService.stub(IFileService, fileService); - }); + instantiationService = workbenchInstantiationService(); + environmentService = new TestWorkbenchEnvironmentService(appSettingsHome); + const remoteEnvironmentPromise = new Promise>(c => resolveRemoteEnvironment = () => c({ settingsPath: remoteSettingsResource })); + const remoteAgentService = instantiationService.stub(IRemoteAgentService, >{ getEnvironment: () => remoteEnvironmentPromise }); + fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService()))); + const configurationCache: IConfigurationCache = { read: () => Promise.resolve(''), write: () => Promise.resolve(), remove: () => Promise.resolve(), needsCaching: () => false }; + testObject = disposables.add(new WorkspaceService({ configurationCache, remoteAuthority }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + instantiationService.stub(IWorkspaceContextService, testObject); + instantiationService.stub(IConfigurationService, testObject); + instantiationService.stub(IEnvironmentService, environmentService); + instantiationService.stub(IFileService, fileService); }); async function initialize(): Promise { - await testObject.initialize(convertToWorkspacePayload(URI.file(workspaceDir))); + await testObject.initialize(convertToWorkspacePayload(folder)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); testObject.acquireInstantiationService(instantiationService); } function registerRemoteFileSystemProvider(): void { - instantiationService.get(IFileService).registerProvider(Schemas.vscodeRemote, new RemoteFileSystemProvider(diskFileSystemProvider, remoteAuthority)); + instantiationService.get(IFileService).registerProvider(Schemas.vscodeRemote, new RemoteFileSystemProvider(fileSystemProvider, remoteAuthority)); } function registerRemoteFileSystemProviderOnActivation(): void { @@ -1826,16 +1807,10 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); } - teardown(() => { - disposables.clear(); - if (parentResource) { - return pfs.rimraf(parentResource); - } - return undefined; - }); + teardown(() => disposables.clear()); test('remote settings override globals', async () => { - fs.writeFileSync(remoteSettingsFile, '{ "configurationService.remote.machineSetting": "remoteValue" }'); + await fileService.writeFile(machineSettingsResource, VSBuffer.fromString('{ "configurationService.remote.machineSetting": "remoteValue" }')); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); await initialize(); @@ -1843,7 +1818,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('remote settings override globals after remote provider is registered on activation', async () => { - fs.writeFileSync(remoteSettingsFile, '{ "configurationService.remote.machineSetting": "remoteValue" }'); + await fileService.writeFile(machineSettingsResource, VSBuffer.fromString('{ "configurationService.remote.machineSetting": "remoteValue" }')); resolveRemoteEnvironment(); registerRemoteFileSystemProviderOnActivation(); await initialize(); @@ -1851,7 +1826,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('remote settings override globals after remote environment is resolved', async () => { - fs.writeFileSync(remoteSettingsFile, '{ "configurationService.remote.machineSetting": "remoteValue" }'); + await fileService.writeFile(machineSettingsResource, VSBuffer.fromString('{ "configurationService.remote.machineSetting": "remoteValue" }')); registerRemoteFileSystemProvider(); await initialize(); const promise = new Promise((c, e) => { @@ -1871,7 +1846,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('remote settings override globals after remote provider is registered on activation and remote environment is resolved', async () => { - fs.writeFileSync(remoteSettingsFile, '{ "configurationService.remote.machineSetting": "remoteValue" }'); + await fileService.writeFile(machineSettingsResource, VSBuffer.fromString('{ "configurationService.remote.machineSetting": "remoteValue" }')); registerRemoteFileSystemProviderOnActivation(); await initialize(); const promise = new Promise((c, e) => { @@ -1891,7 +1866,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('machine settings in local user settings does not override defaults', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.machineSetting": "globalValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.remote.machineSetting": "globalValue" }')); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); await initialize(); @@ -1899,7 +1874,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('machine overridable settings in local user settings does not override defaults', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.machineOverridableSetting": "globalValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.remote.machineOverridableSetting": "globalValue" }')); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); await initialize(); @@ -1934,7 +1909,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('machine settings in local user settings does not override defaults after defalts are registered ', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.newMachineSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.remote.newMachineSetting": "userValue" }')); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); await initialize(); @@ -1953,7 +1928,7 @@ flakySuite('WorkspaceConfigurationService - Remote Folder', () => { }); test('machine overridable settings in local user settings does not override defaults after defaults are registered ', async () => { - fs.writeFileSync(globalSettingsFile, '{ "configurationService.remote.newMachineOverridableSetting": "userValue" }'); + await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString('{ "configurationService.remote.newMachineOverridableSetting": "userValue" }')); registerRemoteFileSystemProvider(); resolveRemoteEnvironment(); await initialize(); @@ -2004,7 +1979,7 @@ suite('ConfigurationService - Configuration Defaults', () => { function createConfigurationService(configurationDefaults: Record): IConfigurationService { const remoteAgentService = (workbenchInstantiationService()).createInstance(RemoteAgentService); - const environmentService = new BrowserWorkbenchEnvironmentService({ logsPath: URI.file(''), workspaceId: '', configurationDefaults }, TestProductService); + const environmentService = new BrowserWorkbenchEnvironmentService({ logsPath: joinPath(ROOT, 'logs'), workspaceId: '', configurationDefaults }, TestProductService); const fileService = new FileService(new NullLogService()); return disposableStore.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); } @@ -2012,7 +1987,7 @@ suite('ConfigurationService - Configuration Defaults', () => { }); function getWorkspaceId(configPath: URI): string { - let workspaceConfigPath = configPath.scheme === Schemas.file ? originalFSPath(configPath) : configPath.toString(); + let workspaceConfigPath = configPath.toString(); if (!isLinux) { workspaceConfigPath = workspaceConfigPath.toLowerCase(); // sanitize for platform file system } From 74038b7e0d83f3a7fc2afa082a9d183db6e8abb5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 11 Jan 2021 23:53:09 +0100 Subject: [PATCH 1812/1837] do not use file scheme --- .../configurationEditingService.test.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index a863a4ede6f..81326a9be1a 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -37,7 +37,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; -import { ConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; +import { ConfigurationCache as NativeConfigurationCache } from 'vs/workbench/services/configuration/electron-browser/configurationCache'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { joinPath } from 'vs/base/common/resources'; import { VSBuffer } from 'vs/base/common/buffer'; @@ -51,6 +51,14 @@ class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService get appSettingsHome() { return this._appSettingsHome; } } +class ConfigurationCache extends NativeConfigurationCache { + needsCaching(resource: URI): boolean { + return false; + } +} + +const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' }); + suite('ConfigurationEditingService', () => { let instantiationService: TestInstantiationService; @@ -87,19 +95,19 @@ suite('ConfigurationEditingService', () => { const logService = new NullLogService(); fileService = disposables.add(new FileService(logService)); const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); - disposables.add(fileService.registerProvider(Schemas.file, fileSystemProvider)); + disposables.add(fileService.registerProvider(ROOT.scheme, fileSystemProvider)); - const workspaceFolder = URI.file(uuid.generateUuid()); + const workspaceFolder = joinPath(ROOT, uuid.generateUuid()); await fileService.createFolder(workspaceFolder); instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = new TestWorkbenchEnvironmentService(workspaceFolder); instantiationService.stub(IEnvironmentService, environmentService); const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); - disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(Schemas.file, fileSystemProvider, Schemas.userData, logService)))); + disposables.add(fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, logService)))); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); - workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(URI.file(environmentService.userDataPath), fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); + workspaceService = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache(ROOT, fileService) }, environmentService, fileService, remoteAgentService, new UriIdentityService(fileService), new NullLogService())); instantiationService.stub(IWorkspaceContextService, workspaceService); await workspaceService.initialize({ folder: workspaceFolder, id: createHash('md5').update(workspaceFolder.toString()).digest('hex') }); From 732d4ff89e8ed9fa872d61ac31cdd7f84a7663a1 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Mon, 11 Jan 2021 15:38:03 -0800 Subject: [PATCH 1813/1837] Make PowerShell 7 default if available and show in choose shell menu (#112768) * make PowerShell 7 default if available and show in choose shell menu * misc feedback * better handle ARM and use pfs everywhere also update pfs to handle AppExecLinks * fix test * move to async * add logging * powershell global tool is in the image apparently * have path test be the same * try/catch the readlink * await exists * fix test * check what arch node is * fix indexes * address daniel's feedback * have getProgramFilesPath return null instead --- src/vs/base/node/pfs.ts | 24 +- src/vs/base/node/powershell.ts | 316 ++++++++++++++++++ src/vs/base/node/shell.ts | 45 ++- src/vs/base/test/node/powershell.test.ts | 67 ++++ src/vs/code/node/shellEnv.ts | 4 +- .../api/node/extHostTerminalService.ts | 12 +- .../browser/terminal.web.contribution.ts | 4 +- .../terminal/common/terminalConfiguration.ts | 31 +- .../electron-browser/terminal.contribution.ts | 3 +- .../terminalInstanceService.ts | 4 +- .../contrib/terminal/node/terminal.ts | 39 ++- 11 files changed, 500 insertions(+), 49 deletions(-) create mode 100644 src/vs/base/node/powershell.ts create mode 100644 src/vs/base/test/node/powershell.test.ts diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index fa07dcb9b7e..ddf8a804965 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -247,6 +247,10 @@ export function renameIgnoreError(oldPath: string, newPath: string): Promise fs.rename(oldPath, newPath, () => resolve())); } +export function readlink(path: string): Promise { + return promisify(fs.readlink)(path); +} + export function unlink(path: string): Promise { return promisify(fs.unlink)(path); } @@ -422,7 +426,15 @@ export async function dirExists(path: string): Promise { return fileStat.isDirectory(); } catch (error) { - return false; + // This catch will be called on some symbolic links on Windows (AppExecLink for example). + // So we try our best to see if it's a Directory. + try { + const fileStat = await stat(await readlink(path)); + + return fileStat.isDirectory(); + } catch { + return false; + } } } @@ -432,7 +444,15 @@ export async function fileExists(path: string): Promise { return fileStat.isFile(); } catch (error) { - return false; + // This catch will be called on some symbolic links on Windows (AppExecLink for example). + // So we try our best to see if it's a File. + try { + const fileStat = await stat(await readlink(path)); + + return fileStat.isFile(); + } catch { + return false; + } } } diff --git a/src/vs/base/node/powershell.ts b/src/vs/base/node/powershell.ts new file mode 100644 index 00000000000..3f50271ecf3 --- /dev/null +++ b/src/vs/base/node/powershell.ts @@ -0,0 +1,316 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as pfs from 'vs/base/node/pfs'; +import * as os from 'os'; +import * as path from 'vs/base/common/path'; +import { env } from 'vs/base/common/process'; + +const WindowsPowerShell64BitLabel = 'Windows PowerShell'; +const WindowsPowerShell32BitLabel = 'Windows PowerShell (x86)'; + +// This is required, since parseInt("7-preview") will return 7. +const IntRegex: RegExp = /^\d+$/; + +const PwshMsixRegex: RegExp = /^Microsoft.PowerShell_.*/; +const PwshPreviewMsixRegex: RegExp = /^Microsoft.PowerShellPreview_.*/; + +// The platform details descriptor for the platform we're on +const isProcess64Bit: boolean = process.arch === 'x64'; +const isOS64Bit: boolean = isProcess64Bit || env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + +export interface IPowerShellExeDetails { + readonly displayName: string; + readonly exePath: string; +} + +export interface IPossiblePowerShellExe extends IPowerShellExeDetails { + exists(): Promise; +} + +class PossiblePowerShellExe implements IPossiblePowerShellExe { + constructor( + public readonly exePath: string, + public readonly displayName: string, + private knownToExist?: boolean) { } + + public async exists(): Promise { + if (this.knownToExist === undefined) { + this.knownToExist = await pfs.fileExists(this.exePath); + } + return this.knownToExist; + } +} + +function getProgramFilesPath( + { useAlternateBitness = false }: { useAlternateBitness?: boolean } = {}): string | null { + + if (!useAlternateBitness) { + // Just use the native system bitness + return env.ProgramFiles || null; + } + + // We might be a 64-bit process looking for 32-bit program files + if (isProcess64Bit) { + return env['ProgramFiles(x86)'] || null; + } + + // We might be a 32-bit process looking for 64-bit program files + if (isOS64Bit) { + return env.ProgramW6432 || null; + } + + // We're a 32-bit process on 32-bit Windows, there is no other Program Files dir + return null; +} + +function getSystem32Path({ useAlternateBitness = false }: { useAlternateBitness?: boolean } = {}): string { + const windir: string = env.windir!; + + if (!useAlternateBitness) { + // Just use the native system bitness + return path.join(windir, 'System32'); + } + + // We might be a 64-bit process looking for 32-bit system32 + if (isProcess64Bit) { + return path.join(windir, 'SysWOW64'); + } + + // We might be a 32-bit process looking for 64-bit system32 + if (isOS64Bit) { + return path.join(windir, 'Sysnative'); + } + + // We're on a 32-bit Windows, so no alternate bitness + return path.join(windir, 'System32'); +} + +async function findPSCoreWindowsInstallation( + { useAlternateBitness = false, findPreview = false }: + { useAlternateBitness?: boolean; findPreview?: boolean } = {}): Promise { + + const programFilesPath = getProgramFilesPath({ useAlternateBitness }); + if (!programFilesPath) { + return null; + } + + const powerShellInstallBaseDir = path.join(programFilesPath, 'PowerShell'); + + // Ensure the base directory exists + if (!await pfs.dirExists(powerShellInstallBaseDir)) { + return null; + } + + let highestSeenVersion: number = -1; + let pwshExePath: string | null = null; + for (const item of await pfs.readdir(powerShellInstallBaseDir)) { + + let currentVersion: number = -1; + if (findPreview) { + // We are looking for something like "7-preview" + + // Preview dirs all have dashes in them + const dashIndex = item.indexOf('-'); + if (dashIndex < 0) { + continue; + } + + // Verify that the part before the dash is an integer + // and that the part after the dash is "preview" + const intPart: string = item.substring(0, dashIndex); + if (!IntRegex.test(intPart) || item.substring(dashIndex + 1) !== 'preview') { + continue; + } + + currentVersion = parseInt(intPart, 10); + } else { + // Search for a directory like "6" or "7" + if (!IntRegex.test(item)) { + continue; + } + + currentVersion = parseInt(item, 10); + } + + // Ensure we haven't already seen a higher version + if (currentVersion <= highestSeenVersion) { + continue; + } + + // Now look for the file + const exePath = path.join(powerShellInstallBaseDir, item, 'pwsh.exe'); + if (!await pfs.fileExists(exePath)) { + continue; + } + + pwshExePath = exePath; + highestSeenVersion = currentVersion; + } + + if (!pwshExePath) { + return null; + } + + const bitness: string = programFilesPath.includes('x86') ? ' (x86)' : ''; + const preview: string = findPreview ? ' Preview' : ''; + + return new PossiblePowerShellExe(pwshExePath, `PowerShell${preview}${bitness}`, true); +} + +async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}): Promise { + // We can't proceed if there's no LOCALAPPDATA path + if (!env.LOCALAPPDATA) { + return null; + } + + // Find the base directory for MSIX application exe shortcuts + const msixAppDir = path.join(env.LOCALAPPDATA, 'Microsoft', 'WindowsApps'); + + if (!await pfs.dirExists(msixAppDir)) { + return null; + } + + // Define whether we're looking for the preview or the stable + const { pwshMsixDirRegex, pwshMsixName } = findPreview + ? { pwshMsixDirRegex: PwshPreviewMsixRegex, pwshMsixName: 'PowerShell Preview (Store)' } + : { pwshMsixDirRegex: PwshMsixRegex, pwshMsixName: 'PowerShell (Store)' }; + + // We should find only one such application, so return on the first one + for (const subdir of await pfs.readdir(msixAppDir)) { + if (pwshMsixDirRegex.test(subdir)) { + const pwshMsixPath = path.join(msixAppDir, subdir, 'pwsh.exe'); + return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName); + } + } + + // If we find nothing, return null + return null; +} + +function findPSCoreDotnetGlobalTool(): IPossiblePowerShellExe { + const dotnetGlobalToolExePath: string = path.join(os.homedir(), '.dotnet', 'tools', 'pwsh.exe'); + + return new PossiblePowerShellExe(dotnetGlobalToolExePath, '.NET Core PowerShell Global Tool'); +} + +function findWinPS({ useAlternateBitness = false }: { useAlternateBitness?: boolean } = {}): IPossiblePowerShellExe | null { + + // x86 and ARM only have one WinPS on them + if (!isOS64Bit && useAlternateBitness) { + return null; + } + + const systemFolderPath = getSystem32Path({ useAlternateBitness }); + + const winPSPath = path.join(systemFolderPath, 'WindowsPowerShell', 'v1.0', 'powershell.exe'); + + let displayName: string; + if (isProcess64Bit) { + displayName = useAlternateBitness + ? WindowsPowerShell32BitLabel + : WindowsPowerShell64BitLabel; + } else if (isOS64Bit) { + displayName = useAlternateBitness + ? WindowsPowerShell64BitLabel + : WindowsPowerShell32BitLabel; + } else { + // NOTE: ARM Windows devices also have Windows PowerShell x86 on them. There is no + // "ARM Windows PowerShell". + displayName = WindowsPowerShell32BitLabel; + } + + return new PossiblePowerShellExe(winPSPath, displayName, true); +} + +/** + * Iterates through all the possible well-known PowerShell installations on a machine. + * Returned values may not exist, but come with an .exists property + * which will check whether the executable exists. + */ +async function* enumerateDefaultPowerShellInstallations(): AsyncIterable { + // Find PSCore stable first + let pwshExe = await findPSCoreWindowsInstallation(); + if (pwshExe) { + yield pwshExe; + } + + // Windows may have a 32-bit pwsh.exe + pwshExe = await findPSCoreWindowsInstallation({ useAlternateBitness: true }); + if (pwshExe) { + yield pwshExe; + } + + // Also look for the MSIX/UWP installation + pwshExe = await findPSCoreMsix(); + if (pwshExe) { + yield pwshExe; + } + + // Look for the .NET global tool + // Some older versions of PowerShell have a bug in this where startup will fail, + // but this is fixed in newer versions + pwshExe = findPSCoreDotnetGlobalTool(); + if (pwshExe) { + yield pwshExe; + } + + // Look for PSCore preview + pwshExe = await findPSCoreWindowsInstallation({ findPreview: true }); + if (pwshExe) { + yield pwshExe; + } + + // Find a preview MSIX + pwshExe = await findPSCoreMsix({ findPreview: true }); + if (pwshExe) { + yield pwshExe; + } + + // Look for pwsh-preview with the opposite bitness + pwshExe = await findPSCoreWindowsInstallation({ useAlternateBitness: true, findPreview: true }); + if (pwshExe) { + yield pwshExe; + } + + // Finally, get Windows PowerShell + + // Get the natural Windows PowerShell for the process bitness + pwshExe = findWinPS(); + if (pwshExe) { + yield pwshExe; + } + + // Get the alternate bitness Windows PowerShell + pwshExe = findWinPS({ useAlternateBitness: true }); + if (pwshExe) { + yield pwshExe; + } +} + +/** + * Iterates through PowerShell installations on the machine according + * to configuration passed in through the constructor. + * PowerShell items returned by this object are verified + * to exist on the filesystem. + */ +export async function* enumeratePowerShellInstallations(): AsyncIterable { + // Get the default PowerShell installations first + for await (const defaultPwsh of enumerateDefaultPowerShellInstallations()) { + if (await defaultPwsh.exists()) { + yield defaultPwsh; + } + } +} + +/** +* Returns the first available PowerShell executable found in the search order. +*/ +export async function getFirstAvailablePowerShellInstallation(): Promise { + for await (const pwsh of enumeratePowerShellInstallations()) { + return pwsh; + } + return null; +} diff --git a/src/vs/base/node/shell.ts b/src/vs/base/node/shell.ts index 91ed33a10c3..cacc2da4db2 100644 --- a/src/vs/base/node/shell.ts +++ b/src/vs/base/node/shell.ts @@ -5,6 +5,7 @@ import * as os from 'os'; import * as platform from 'vs/base/common/platform'; +import { getFirstAvailablePowerShellInstallation } from 'vs/base/node/powershell'; import * as processes from 'vs/base/node/processes'; /** @@ -12,23 +13,37 @@ import * as processes from 'vs/base/node/processes'; * shell that the terminal uses by default. * @param p The platform to detect the shell of. */ -export function getSystemShell(p: platform.Platform, env = process.env as platform.IProcessEnvironment): string { +export async function getSystemShell(p: platform.Platform, env = process.env as platform.IProcessEnvironment): Promise { if (p === platform.Platform.Windows) { if (platform.isWindows) { - return getSystemShellWindows(env); + return getSystemShellWindows(); } // Don't detect Windows shell when not on Windows return processes.getWindowsShell(env); } + + return getSystemShellUnixLike(p, env); +} + +export function getSystemShellSync(p: platform.Platform, env = process.env as platform.IProcessEnvironment): string { + if (p === platform.Platform.Windows) { + if (platform.isWindows) { + return getSystemShellWindowsSync(env); + } + // Don't detect Windows shell when not on Windows + return processes.getWindowsShell(env); + } + + return getSystemShellUnixLike(p, env); +} + +let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null; +function getSystemShellUnixLike(p: platform.Platform, env: platform.IProcessEnvironment): string { // Only use $SHELL for the current OS if (platform.isLinux && p === platform.Platform.Mac || platform.isMacintosh && p === platform.Platform.Linux) { return '/bin/bash'; } - return getSystemShellUnixLike(env); -} -let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null; -function getSystemShellUnixLike(env: platform.IProcessEnvironment): string { if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) { let unixLikeTerminal: string; if (platform.isWindows) { @@ -59,12 +74,20 @@ function getSystemShellUnixLike(env: platform.IProcessEnvironment): string { } let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null; -function getSystemShellWindows(env: platform.IProcessEnvironment): string { +async function getSystemShellWindows(): Promise { if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) { - const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10; - const is32ProcessOn64Windows = env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); - const powerShellPath = `${env['windir']}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; - _TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(env); + _TERMINAL_DEFAULT_SHELL_WINDOWS = (await getFirstAvailablePowerShellInstallation())!.exePath; } return _TERMINAL_DEFAULT_SHELL_WINDOWS; } + +function getSystemShellWindowsSync(env: platform.IProcessEnvironment): string { + if (_TERMINAL_DEFAULT_SHELL_WINDOWS) { + return _TERMINAL_DEFAULT_SHELL_WINDOWS; + } + + const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10; + const is32ProcessOn64Windows = env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + const powerShellPath = `${env['windir']}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; + return isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(env); +} diff --git a/src/vs/base/test/node/powershell.test.ts b/src/vs/base/test/node/powershell.test.ts new file mode 100644 index 00000000000..fa490742401 --- /dev/null +++ b/src/vs/base/test/node/powershell.test.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as platform from 'vs/base/common/platform'; +import * as fs from 'fs'; +import { enumeratePowerShellInstallations, getFirstAvailablePowerShellInstallation, IPowerShellExeDetails } from 'vs/base/node/powershell'; + +function checkPath(exePath: string) { + // Check to see if the path exists + let pathCheckResult = false; + try { + const stat = fs.statSync(exePath); + pathCheckResult = stat.isFile(); + } catch { + // fs.exists throws on Windows with SymbolicLinks so we + // also use lstat to try and see if the file exists. + try { + pathCheckResult = fs.statSync(fs.readlinkSync(exePath)).isFile(); + } catch { + + } + } + + assert.strictEqual(pathCheckResult, true); +} + +if (platform.isWindows) { + suite('PowerShell finder', () => { + + test('Can find first available PowerShell', async () => { + const pwshExe = await getFirstAvailablePowerShellInstallation(); + const exePath = pwshExe?.exePath; + assert.notStrictEqual(exePath, null); + assert.notStrictEqual(pwshExe?.displayName, null); + + checkPath(exePath!); + }); + + test('Can enumerate PowerShells', async () => { + const pwshs = new Array(); + for await (const p of enumeratePowerShellInstallations()) { + pwshs.push(p); + } + + // In Azure DevOps and GitHub Actions there should be an extra PowerShell since PowerShell 7 comes pre-installed + const minNumberOfPowerShells = process.env.TF_BUILD || process.env.CI ? 3 : 2; + + assert.strictEqual(pwshs.length >= minNumberOfPowerShells, true, 'Found these PowerShells:\n' + pwshs.map(p => `${p.displayName}: ${p.exePath}`).join('\n')); + + for (const pwsh of pwshs) { + checkPath(pwsh.exePath); + } + + const lastIndex = pwshs.length - 1; + checkPath(pwshs[lastIndex].exePath); + assert.strictEqual(pwshs[lastIndex].displayName, 'Windows PowerShell (x86)'); + + if (process.arch === 'x64') { + const secondToLastIndex = pwshs.length - 2; + checkPath(pwshs[secondToLastIndex].exePath); + assert.strictEqual(pwshs[secondToLastIndex].displayName, 'Windows PowerShell'); + } + }); + }); +} diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 2ea93f9c5af..9454f1d4730 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -59,7 +59,7 @@ export async function resolveShellEnv(logService: ILogService, args: NativeParse let unixShellEnvPromise: Promise | undefined = undefined; async function doResolveUnixShellEnv(logService: ILogService): Promise { - const promise = new Promise((resolve, reject) => { + const promise = new Promise(async (resolve, reject) => { const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; logService.trace('getUnixShellEnvironment#runAsNode', runAsNode); @@ -79,7 +79,7 @@ async function doResolveUnixShellEnv(logService: ILogService): Promise this._defaultShell = s); + this._updateLastActiveWorkspace(); this._updateVariableResolver(); this._registerListeners(); @@ -78,10 +85,11 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { .inspect(key.substr(key.lastIndexOf('.') + 1)); return this._apiInspectConfigToPlain(setting); }; + return terminalEnvironment.getDefaultShell( fetchSetting, this._isWorkspaceShellAllowed, - getSystemShell(platform.platform), + this._defaultShell ?? getSystemShellSync(platform.platform), process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), process.env.windir, terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, this._variableResolver), diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts index e2c091ae9cd..6773ae9e4aa 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts @@ -8,12 +8,12 @@ import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/co import { Registry } from 'vs/platform/registry/common/platform'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { getTerminalShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; +import { getNoDefaultTerminalShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; // Desktop shell configuration are registered in electron-browser as their default values rely // on process.env const configurationRegistry = Registry.as(Extensions.Configuration); -configurationRegistry.registerConfiguration(getTerminalShellConfiguration()); +configurationRegistry.registerConfiguration(getNoDefaultTerminalShellConfiguration()); // Register standard external terminal keybinding as integrated terminal when in web as the // external terminal is not available diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 759e7c2eb96..d2fe5d11fec 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -401,7 +401,7 @@ export const terminalConfiguration: IConfigurationNode = { } }; -export function getTerminalShellConfiguration(getSystemShell?: (p: Platform) => string): IConfigurationNode { +function getTerminalShellConfigurationStub(linux: string, osx: string, windows: string): IConfigurationNode { return { id: 'terminal', order: 100, @@ -409,29 +409,34 @@ export function getTerminalShellConfiguration(getSystemShell?: (p: Platform) => type: 'object', properties: { 'terminal.integrated.shell.linux': { - markdownDescription: - getSystemShell - ? localize('terminal.integrated.shell.linux', "The path of the shell that the terminal uses on Linux (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", getSystemShell(Platform.Linux)) - : localize('terminal.integrated.shell.linux.noDefault', "The path of the shell that the terminal uses on Linux. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + markdownDescription: linux, type: ['string', 'null'], default: null }, 'terminal.integrated.shell.osx': { - markdownDescription: - getSystemShell - ? localize('terminal.integrated.shell.osx', "The path of the shell that the terminal uses on macOS (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", getSystemShell(Platform.Mac)) - : localize('terminal.integrated.shell.osx.noDefault', "The path of the shell that the terminal uses on macOS. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + markdownDescription: osx, type: ['string', 'null'], default: null }, 'terminal.integrated.shell.windows': { - markdownDescription: - getSystemShell - ? localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", getSystemShell(Platform.Windows)) - : localize('terminal.integrated.shell.windows.noDefault', "The path of the shell that the terminal uses on Windows. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + markdownDescription: windows, type: ['string', 'null'], default: null } } }; } + +export function getNoDefaultTerminalShellConfiguration(): IConfigurationNode { + return getTerminalShellConfigurationStub( + localize('terminal.integrated.shell.linux.noDefault', "The path of the shell that the terminal uses on Linux. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + localize('terminal.integrated.shell.osx.noDefault', "The path of the shell that the terminal uses on macOS. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + localize('terminal.integrated.shell.windows.noDefault', "The path of the shell that the terminal uses on Windows. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).")); +} + +export async function getTerminalShellConfiguration(getSystemShell: (p: Platform) => Promise): Promise { + return getTerminalShellConfigurationStub( + localize('terminal.integrated.shell.linux', "The path of the shell that the terminal uses on Linux (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(Platform.Linux)), + localize('terminal.integrated.shell.osx', "The path of the shell that the terminal uses on macOS (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(Platform.Mac)), + localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(Platform.Windows))); +} diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index 0ea7c35c273..0c11faaf0b3 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -24,4 +24,5 @@ workbenchRegistry.registerWorkbenchContribution(TerminalNativeContribution, Life // Register configurations const configurationRegistry = Registry.as(Extensions.Configuration); -configurationRegistry.registerConfiguration(getTerminalShellConfiguration(getSystemShell)); + +getTerminalShellConfiguration(getSystemShell).then(config => configurationRegistry.registerConfiguration(config)); diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts index 03012b1ca05..2692cf9e171 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -82,7 +82,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { return this._storageService.getBoolean(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, StorageScope.WORKSPACE, false); } - public getDefaultShellAndArgs(useAutomationShell: boolean, platformOverride: Platform = platform): Promise<{ shell: string, args: string | string[] }> { + public async getDefaultShellAndArgs(useAutomationShell: boolean, platformOverride: Platform = platform): Promise<{ shell: string, args: string | string[] }> { const isWorkspaceShellAllowed = this._isWorkspaceShellAllowed(); const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(); let lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : undefined; @@ -90,7 +90,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { const shell = getDefaultShell( (key) => this._configurationService.inspect(key), isWorkspaceShellAllowed, - getSystemShell(platformOverride), + await getSystemShell(platformOverride), process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), process.env.windir, createVariableResolver(lastActiveWorkspace, this._configurationResolverService), diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index f8281c244da..ff36c4e6331 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -5,10 +5,11 @@ import * as os from 'os'; import * as platform from 'vs/base/common/platform'; -import { readFile, fileExists, stat } from 'vs/base/node/pfs'; +import { readFile, fileExists, stat, lstat } from 'vs/base/node/pfs'; import { LinuxDistro, IShellDefinition } from 'vs/workbench/contrib/terminal/common/terminal'; import { coalesce } from 'vs/base/common/arrays'; import { normalize, basename } from 'vs/base/common/path'; +import { enumeratePowerShellInstallations } from 'vs/base/node/powershell'; let detectedDistro = LinuxDistro.Unknown; if (platform.isLinux) { @@ -58,8 +59,6 @@ async function detectAvailableWindowsShells(): Promise { const expectedLocations: { [key: string]: string[] } = { 'Command Prompt': [`${system32Path}\\cmd.exe`], - 'Windows PowerShell': [`${system32Path}\\WindowsPowerShell\\v1.0\\powershell.exe`], - 'PowerShell': [await getShellPathFromRegistry('pwsh')], 'WSL Bash': [`${system32Path}\\${useWSLexe ? 'wsl.exe' : 'bash.exe'}`], 'Git Bash': [ `${process.env['ProgramW6432']}\\Git\\bin\\bash.exe`, @@ -74,6 +73,12 @@ async function detectAvailableWindowsShells(): Promise { // `${process.env['HOMEDRIVE']}\\cygwin\\bin\\bash.exe` // ] }; + + // Add all of the different kinds of PowerShells + for await (const pwshExe of enumeratePowerShellInstallations()) { + expectedLocations[pwshExe.displayName] = [pwshExe.exePath]; + } + const promises: Promise[] = []; Object.keys(expectedLocations).forEach(key => promises.push(validateShellPaths(key, expectedLocations[key]))); const shells = await Promise.all(promises); @@ -107,16 +112,22 @@ async function validateShellPaths(label: string, potentialPaths: string[]): Prom path: current }; } - } catch { /* noop */ } + } catch (e) { + // Also try using lstat as some symbolic links on Windows + // throw 'permission denied' using 'stat' but don't throw + // using 'lstat' + try { + const result = await lstat(normalize(current)); + if (result.isFile() || result.isSymbolicLink()) { + return { + label, + path: current + }; + } + } + catch (e) { + // noop + } + } return validateShellPaths(label, potentialPaths); } - -async function getShellPathFromRegistry(shellName: string): Promise { - const Registry = await import('vscode-windows-registry'); - try { - const shellPath = Registry.GetStringRegKey('HKEY_LOCAL_MACHINE', `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\${shellName}.exe`, ''); - return shellPath ? shellPath : ''; - } catch (error) { - return ''; - } -} From 09d99f7d71b91b7faa88480b88db184bbd78bea0 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 11 Jan 2021 17:23:01 -0800 Subject: [PATCH 1814/1837] resolve kernel providers and kernels. --- .../notebook/browser/contrib/coreActions.ts | 52 +++++++++++++++++-- .../notebook/browser/notebookServiceImpl.ts | 19 +++++-- .../notebook/common/notebookService.ts | 5 +- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index acf32d1a96a..0b55cb204ca 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -23,11 +23,12 @@ import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/ import { CATEGORIES } from 'vs/workbench/common/actions'; import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, IActiveNotebookEditor, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, ICellEditOperation, ICellRange, INotebookDocumentFilter, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; // Notebook Commands const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute'; @@ -580,7 +581,7 @@ registerAction2(class extends NotebookCellAction { export function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor | undefined { // TODO@roblourens can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? - const activeEditorPane = editorService.activeEditorPane as unknown as { isNotebookEditor?: boolean } | undefined; + const activeEditorPane = editorService.activeEditorPane as unknown as { isNotebookEditor?: boolean; } | undefined; return activeEditorPane?.isNotebookEditor ? (editorService.activeEditorPane?.getControl() as INotebookEditor) : undefined; } @@ -1891,8 +1892,8 @@ CommandsRegistry.registerCommand('notebook.trust', (accessor, args) => { CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor, args): { viewType: string; displayName: string; - options: { transientOutputs: boolean; transientMetadata: TransientMetadata }; - filenamePattern: (string | glob.IRelativePattern | { include: string | glob.IRelativePattern, exclude: string | glob.IRelativePattern })[] + options: { transientOutputs: boolean; transientMetadata: TransientMetadata; }; + filenamePattern: (string | glob.IRelativePattern | { include: string | glob.IRelativePattern, exclude: string | glob.IRelativePattern; })[]; }[] => { const notebookService = accessor.get(INotebookService); const contentProviders = notebookService.getContributedNotebookProviders(); @@ -1914,7 +1915,7 @@ CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor, a } return null; - }).filter(pattern => pattern !== null) as (string | glob.IRelativePattern | { include: string | glob.IRelativePattern, exclude: string | glob.IRelativePattern })[]; + }).filter(pattern => pattern !== null) as (string | glob.IRelativePattern | { include: string | glob.IRelativePattern, exclude: string | glob.IRelativePattern; })[]; return { viewType: provider.id, @@ -1924,3 +1925,44 @@ CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor, a }; }); }); + +CommandsRegistry.registerCommand('_resolveNotebookKernelProviders', async (accessor, args): Promise<{ + extensionId: string; + description?: string; + selector: INotebookDocumentFilter; +}[]> => { + const notebookService = accessor.get(INotebookService); + const providers = await notebookService.getContributedNotebookKernelProviders(); + return providers.map(provider => ({ + extensionId: provider.providerExtensionId, + description: provider.providerDescription, + selector: provider.selector + })); +}); + +CommandsRegistry.registerCommand('_resolveNotebookKernels', async (accessor, args: { + viewType: string; + uri: UriComponents; +}): Promise<{ + id?: string; + label: string; + description?: string; + detail?: string; + isPreferred?: boolean; + preloads?: URI[]; +}[]> => { + const notebookService = accessor.get(INotebookService); + const uri = URI.revive(args.uri as UriComponents); + const source = new CancellationTokenSource(); + const kernels = await notebookService.getContributedNotebookKernels(args.viewType, uri, source.token); + source.dispose(); + + return kernels.map(provider => ({ + id: provider.id, + label: provider.label, + description: provider.description, + detail: provider.detail, + isPreferred: provider.isPreferred, + preloads: provider.preloads?.map(preload => URI.revive(preload)) || [] + })); +}); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index df96eaf4654..8c7b5415234 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -65,6 +65,10 @@ export class NotebookKernelProviderInfoStore extends Disposable { return this._notebookKernelProviders.filter(provider => notebookDocumentFilterMatch(provider.selector, viewType, resource)); } + getContributedKernelProviders() { + return [...this._notebookKernelProviders.values()]; + } + private _updateProviderExtensionsInfo() { NotebookKernelProviderAssociationRegistry.extensionIds.length = 0; NotebookKernelProviderAssociationRegistry.extensionDescriptions.length = 0; @@ -237,7 +241,7 @@ class ModelData implements IDisposable { } export class NotebookService extends Disposable implements INotebookService, ICustomEditorViewTypesHandler { declare readonly _serviceBrand: undefined; - private readonly _notebookProviders = new Map(); + private readonly _notebookProviders = new Map(); notebookProviderInfoStore: NotebookProviderInfoStore; notebookRenderersInfoStore: NotebookOutputRendererInfoStore = new NotebookOutputRendererInfoStore(); notebookKernelProviderInfoStore: NotebookKernelProviderInfoStore = new NotebookKernelProviderInfoStore(); @@ -266,12 +270,12 @@ export class NotebookService extends Disposable implements INotebookService, ICu private readonly _onDidChangeKernels = new Emitter(); onDidChangeKernels: Event = this._onDidChangeKernels.event; - private readonly _onDidChangeNotebookActiveKernel = new Emitter<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>(); - onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }> = this._onDidChangeNotebookActiveKernel.event; + private readonly _onDidChangeNotebookActiveKernel = new Emitter<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }>(); + onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }> = this._onDidChangeNotebookActiveKernel.event; private cutItems: NotebookCellTextModel[] | undefined; private _lastClipboardIsCopy: boolean = true; - private _displayOrder: { userOrder: string[], defaultOrder: string[] } = Object.create(null); + private _displayOrder: { userOrder: string[], defaultOrder: string[]; } = Object.create(null); private readonly _decorationOptionProviders = new Map(); constructor( @@ -718,6 +722,11 @@ export class NotebookService extends Disposable implements INotebookService, ICu return flatten(result); } + async getContributedNotebookKernelProviders(): Promise { + const kernelProviders = this.notebookKernelProviderInfoStore.getContributedKernelProviders(); + return kernelProviders; + } + getRendererInfo(id: string): INotebookRendererInfo | undefined { return this.notebookRenderersInfoStore.get(id); } @@ -890,7 +899,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu listVisibleNotebookEditors(): INotebookEditor[] { return this._editorService.visibleEditorPanes - .filter(pane => (pane as unknown as { isNotebookEditor?: boolean }).isNotebookEditor) + .filter(pane => (pane as unknown as { isNotebookEditor?: boolean; }).isNotebookEditor) .map(pane => pane.getControl() as INotebookEditor) .filter(editor => !!editor) .filter(editor => this._notebookEditors.has(editor.getId())); diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 06f77081750..a97fc85eb65 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -26,7 +26,7 @@ export interface IMainNotebookController { supportBackup: boolean; viewOptions?: { displayName: string; filenamePattern: (string | IRelativePattern | INotebookExclusiveDocumentFilter)[]; exclusive: boolean; }; options: { transientOutputs: boolean; transientMetadata: TransientMetadata; }; - resolveNotebookDocument(viewType: string, uri: URI, backupId?: string): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions }>; + resolveNotebookDocument(viewType: string, uri: URI, backupId?: string): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions; }>; reloadNotebook(mainthreadTextModel: NotebookTextModel): Promise; resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise; onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: any): void; @@ -46,13 +46,14 @@ export interface INotebookService { onDidAddNotebookDocument: Event; onNotebookDocumentSaved: Event; onDidChangeKernels: Event; - onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>; + onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }>; registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable; getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[]; registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable; getContributedNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise; + getContributedNotebookKernelProviders(): Promise; getContributedNotebookOutputRenderers(id: string): NotebookOutputRendererInfo | undefined; getRendererInfo(id: string): INotebookRendererInfo | undefined; From f5665378fd2a8d6c620c55305f13412ab1910584 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 11 Jan 2021 17:27:07 -0800 Subject: [PATCH 1815/1837] testing: start of diff peek view --- src/vs/editor/browser/editorBrowser.ts | 10 +- .../browser/outline/documentSymbolsOutline.ts | 2 +- .../testing/browser/testing.contribution.ts | 31 +++- .../testing/browser/testingOutputPeek.ts | 169 ++++++++++++++++++ .../contrib/testing/common/constants.ts | 1 + 5 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index bf15f7f7dcb..bfa07b8dcf9 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -1052,7 +1052,7 @@ export interface IDiffEditor extends editorCommon.IEditor { /** *@internal */ -export function isCodeEditor(thing: any): thing is ICodeEditor { +export function isCodeEditor(thing: unknown): thing is ICodeEditor { if (thing && typeof (thing).getEditorType === 'function') { return (thing).getEditorType() === editorCommon.EditorType.ICodeEditor; } else { @@ -1063,7 +1063,7 @@ export function isCodeEditor(thing: any): thing is ICodeEditor { /** *@internal */ -export function isDiffEditor(thing: any): thing is IDiffEditor { +export function isDiffEditor(thing: unknown): thing is IDiffEditor { if (thing && typeof (thing).getEditorType === 'function') { return (thing).getEditorType() === editorCommon.EditorType.IDiffEditor; } else { @@ -1074,8 +1074,8 @@ export function isDiffEditor(thing: any): thing is IDiffEditor { /** *@internal */ -export function isCompositeEditor(thing: any): thing is editorCommon.ICompositeCodeEditor { - return thing +export function isCompositeEditor(thing: unknown): thing is editorCommon.ICompositeCodeEditor { + return !!thing && typeof thing === 'object' && typeof (thing).onDidChangeActiveEditor === 'function'; @@ -1084,7 +1084,7 @@ export function isCompositeEditor(thing: any): thing is editorCommon.ICompositeC /** *@internal */ -export function getCodeEditor(thing: any): ICodeEditor | null { +export function getCodeEditor(thing: unknown): ICodeEditor | null { if (isCodeEditor(thing)) { return thing; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts index f057b0090af..2f4ec893d5f 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts @@ -430,7 +430,7 @@ class DocumentSymbolsOutlineCreator implements IOutlineCreator { @@ -92,3 +99,25 @@ CommandsRegistry.registerCommand({ testService.runTests({ debug: true, tests: tests.filter(t => t.providerId && t.testId) }); } }); + +CommandsRegistry.registerCommand({ + id: 'vscode.revealTestMessage', + handler: async (accessor: ServicesAccessor, message: ITestMessage) => { + if (!message.location) { + console.warn('Cannot reveal a test message without an associated location'); + return; + } + + const pane = await accessor.get(IEditorService).openEditor({ + resource: URI.revive(message.location.uri), + options: { selection: message.location.range } + }); + + const control = pane?.getControl(); + if (!isCodeEditor(control)) { + return; + } + + TestingOutputPeekController.get(control).show(message); + } +}); diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts new file mode 100644 index 00000000000..21de43168dd --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -0,0 +1,169 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as dom from 'vs/base/browser/dom'; +import { Color } from 'vs/base/common/color'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; +import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorContribution } from 'vs/editor/common/editorCommon'; +import { TextModel } from 'vs/editor/common/model/textModel'; +import { IPeekViewService, peekViewBorder, peekViewTitleBackground, peekViewTitleForeground, peekViewTitleInfoForeground, PeekViewWidget } from 'vs/editor/contrib/peekView/peekView'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +import { EditorModel } from 'vs/workbench/common/editor'; +import { Testing } from 'vs/workbench/contrib/testing/common/constants'; +import { ITestMessage } from 'vs/workbench/contrib/testing/common/testCollection'; + +export class TestingOutputPeekController implements IEditorContribution { + /** + * Gets the controller associated with the given code editor. + */ + public static get(editor: ICodeEditor): TestingOutputPeekController { + return editor.getContribution(Testing.OutputPeekContributionId); + } + + /** + * Currently-shown peek view. + */ + private peek?: TestingOutputPeek; + + constructor(private readonly editor: ICodeEditor, @IInstantiationService private readonly instantiationService: IInstantiationService) { } + + public dispose(): void { + // no-op + } + + /** + * Shows a peek for the message in th editor. + */ + public show(output: ITestMessage) { + this.removePeek(); + if (!output.location) { + return; + } + + this.peek = this.instantiationService.createInstance(TestingOutputPeek, this.editor, output); + this.peek.show(output.location.range, 18); + } + + private removePeek() { + if (this.peek) { + this.peek.dispose(); + this.peek = undefined; + } + } +} + +export class TestingOutputPeek extends PeekViewWidget { + private readonly disposable = new DisposableStore(); + private diff?: EmbeddedDiffEditorWidget; + private dimension?: dom.Dimension; + + constructor( + editor: ICodeEditor, + private readonly message: ITestMessage, + @IThemeService themeService: IThemeService, + @IPeekViewService peekViewService: IPeekViewService, + @IInstantiationService protected readonly instantiationService: IInstantiationService, + @IUndoRedoService private readonly undoRedo: IUndoRedoService, + ) { + super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true }, instantiationService); + + this._disposables.add(themeService.onDidColorThemeChange(this.applyTheme, this)); + this.applyTheme(themeService.getColorTheme()); + + peekViewService.addExclusiveWidget(editor, this); + + this.create(); + this.setTitle(message.message.toString()); + } + + private applyTheme(theme: IColorTheme) { + const borderColor = theme.getColor(peekViewBorder) || Color.transparent; + this.style({ + arrowColor: borderColor, + frameColor: borderColor, + headerBackgroundColor: theme.getColor(peekViewTitleBackground) || Color.transparent, + primaryHeadingColor: theme.getColor(peekViewTitleForeground), + secondaryHeadingColor: theme.getColor(peekViewTitleInfoForeground) + }); + } + + /** + * @override + */ + public dispose() { + super.dispose(); + this.disposable.dispose(); + } + + /** + * @override + */ + protected _fillBody(containerElement: HTMLElement): void { + const diffContainer = dom.append(containerElement, dom.$('div.preview.inline')); + let options: IDiffEditorOptions = { + scrollBeyondLastLine: false, + scrollbar: { + verticalScrollbarSize: 14, + horizontal: 'auto', + useShadows: true, + verticalHasArrows: false, + horizontalHasArrows: false, + alwaysConsumeMouseWheel: false + }, + overviewRulerLanes: 2, + fixedOverflowWidgets: true, + readOnly: true, + minimap: { + enabled: false + }, + enableSplitViewResizing: true, + isInEmbeddedEditor: true, + renderOverviewRuler: false, + ignoreTrimWhitespace: false, + renderSideBySide: true, + }; + + const preview = this.diff = this.instantiationService.createInstance(EmbeddedDiffEditorWidget, diffContainer, options, this.editor); + this.disposable.add(preview); + + // todo: we probably want to have uri schemes for these guys since this + // does not work very well right now + preview.setModel(new SimpleDiffEditorModel( + new TextModel(this.message.expectedOutput!, TextModel.DEFAULT_CREATION_OPTIONS, null, null, this.undoRedo), + new TextModel(this.message.actualOutput!, TextModel.DEFAULT_CREATION_OPTIONS, null, null, this.undoRedo) + )); + + if (this.dimension) { + preview.layout(this.dimension); + } + } + + /** + * @override + */ + protected _doLayoutBody(height: number, width: number) { + super._doLayoutBody(height, width); + this.dimension = new dom.Dimension(width, height); + this.diff?.layout(this.dimension); + } +} + +class SimpleDiffEditorModel extends EditorModel { + constructor( + readonly original: TextModel, + readonly modified: TextModel, + ) { + super(); + } + + async load(): Promise { + return this; + } +} diff --git a/src/vs/workbench/contrib/testing/common/constants.ts b/src/vs/workbench/contrib/testing/common/constants.ts index 95c9c661c57..1d896c6b3de 100644 --- a/src/vs/workbench/contrib/testing/common/constants.ts +++ b/src/vs/workbench/contrib/testing/common/constants.ts @@ -9,6 +9,7 @@ import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; export const enum Testing { ViewletId = 'workbench.view.testing', ExplorerViewId = 'workbench.view.testing', + OutputPeekContributionId = 'editor.contrib.testingOutputPeek', } export const enum TestExplorerViewMode { From 913fff96a3c1717cac5948b267221b85b9fcd9ae Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 11 Jan 2021 17:27:44 -0800 Subject: [PATCH 1816/1837] testing: fix error when test view is hidden after showing --- .../contrib/testing/browser/testingExplorerView.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index fd51128785a..414492fcd2f 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -287,6 +287,10 @@ export class TestingExplorerViewModel extends Disposable { * Reveals and moves focus to the item. */ public async revealItem(item: ITestTreeElement, reveal = true): Promise { + if (!this.tree.hasElement(item)) { + return; + } + const chain: ITestTreeElement[] = []; for (let parent = item.parentItem; parent; parent = parent.parentItem) { chain.push(parent); @@ -364,6 +368,8 @@ class CodeEditorTracker { const register = (editor: ICodeEditor) => { const store = new DisposableStore(); + editorStores.add(store); + store.add(editor.onDidChangeCursorPosition(evt => { const uri = editor.getModel()?.uri; if (!uri) { From 6dc779565e1e4a26104002fde340b68c157c3bc5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 07:23:35 +0100 Subject: [PATCH 1817/1837] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 51af24174dc..2c16d19324a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.53.0", - "distro": "8fc3bcb85e651a881b66975f5a877982f6e1aaec", + "distro": "c4fb7b0acc2f3aa3c062521563684cf40565d004", "author": { "name": "Microsoft Corporation" }, From d61eb64745cd29e2ceaeac11de2560ca09f97057 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 08:14:00 +0100 Subject: [PATCH 1818/1837] activity bar - change visibility of entries to checkboxes (#113757) --- .../browser/actions/layoutActions.ts | 23 ++------- src/vs/workbench/browser/layout.ts | 30 +++++++++-- .../parts/activitybar/activitybarPart.ts | 51 +++++++++++-------- .../services/layout/browser/layoutService.ts | 9 +++- .../test/browser/workbenchTestServices.ts | 19 +++---- 5 files changed, 74 insertions(+), 58 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 391d3ae3062..6a18d2e8a57 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -12,7 +12,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; -import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { isWindows, isLinux, isWeb } from 'vs/base/common/platform'; import { IsMacNativeContext } from 'vs/platform/contextkey/common/contextkeys'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -441,32 +440,16 @@ export class ToggleMenuBarAction extends Action { static readonly ID = 'workbench.action.toggleMenuBar'; static readonly LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar"); - private static readonly menuBarVisibilityKey = 'window.menuBarVisibility'; - constructor( id: string, label: string, - @IConfigurationService private readonly configurationService: IConfigurationService + @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService ) { super(id, label); } - run(): Promise { - let currentVisibilityValue = getMenuBarVisibility(this.configurationService); - if (typeof currentVisibilityValue !== 'string') { - currentVisibilityValue = 'default'; - } - - let newVisibilityValue: string; - if (currentVisibilityValue === 'visible' || currentVisibilityValue === 'default') { - newVisibilityValue = 'toggle'; - } else if (currentVisibilityValue === 'compact') { - newVisibilityValue = 'hidden'; - } else { - newVisibilityValue = (isWeb && currentVisibilityValue === 'hidden') ? 'compact' : 'default'; - } - - return this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue); + async run(): Promise { + this.layoutService.toggleMenuBar(); } } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 3f834c579c3..363ea859ddf 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -78,7 +78,9 @@ enum Storage { GRID_LAYOUT = 'workbench.grid.layout', GRID_WIDTH = 'workbench.grid.width', - GRID_HEIGHT = 'workbench.grid.height' + GRID_HEIGHT = 'workbench.grid.height', + + MENU_VISIBILITY = 'window.menuBarVisibility' } enum Classes { @@ -622,7 +624,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi return this._openedDefaultEditors; } - private getInitialFilesToOpen(): { filesToOpenOrCreate?: IPath[], filesToDiff?: IPath[] } | undefined { + private getInitialFilesToOpen(): { filesToOpenOrCreate?: IPath[], filesToDiff?: IPath[]; } | undefined { const defaultLayout = this.environmentService.options?.defaultLayout; if (defaultLayout?.editors?.length && this.storageService.isNew(StorageScope.WORKSPACE)) { this._openedDefaultEditors = true; @@ -677,9 +679,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi if (this.state.views.defaults?.length) { mark('code/willOpenDefaultViews'); - let locationsRestored: { id: string; order: number }[] = []; + let locationsRestored: { id: string; order: number; }[] = []; - const tryOpenView = (view: { id: string; order: number }): boolean => { + const tryOpenView = (view: { id: string; order: number; }): boolean => { const location = this.viewDescriptorService.getViewLocationById(view.id); if (location !== null) { const container = this.viewDescriptorService.getViewContainerByViewId(view.id); @@ -1128,7 +1130,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi [Parts.STATUSBAR_PART]: this.statusBarPartView }; - const fromJSON = ({ type }: { type: Parts }) => viewMap[type]; + const fromJSON = ({ type }: { type: Parts; }) => viewMap[type]; const workbenchGrid = SerializableGrid.deserialize( this.createGridDescriptor(), { fromJSON }, @@ -1551,6 +1553,24 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi return this.state.menuBar.visibility; } + toggleMenuBar(): void { + let currentVisibilityValue = getMenuBarVisibility(this.configurationService); + if (typeof currentVisibilityValue !== 'string') { + currentVisibilityValue = 'default'; + } + + let newVisibilityValue: string; + if (currentVisibilityValue === 'visible' || currentVisibilityValue === 'default') { + newVisibilityValue = 'toggle'; + } else if (currentVisibilityValue === 'compact') { + newVisibilityValue = 'hidden'; + } else { + newVisibilityValue = (isWeb && currentVisibilityValue === 'hidden') ? 'compact' : 'default'; + } + + this.configurationService.updateValue(Storage.MENU_VISIBILITY, newVisibilityValue); + } + getPanelPosition(): Position { return this.state.panel.position; } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 38033874552..679abe1fbf7 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -13,7 +13,7 @@ import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; -import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions'; +import { ToggleActivityBarVisibilityAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions'; import { IThemeService, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -49,7 +49,7 @@ interface IPlaceholderViewContainer { readonly name?: string; readonly iconUrl?: UriComponents; readonly themeIcon?: ThemeIcon; - readonly views?: { when?: string }[]; + readonly views?: { when?: string; }[]; } interface IPinnedViewContainer { @@ -66,7 +66,7 @@ interface ICachedViewContainer { readonly pinned: boolean; readonly order?: number; visible: boolean; - views?: { when?: string }[]; + views?: { when?: string; }[]; } const settingsViewBarIcon = registerIcon('settings-view-bar-icon', Codicon.settingsGear, nls.localize('settingsViewBarIcon', 'Settings icon in the view bar.')); @@ -110,7 +110,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private readonly accountsActivity: ICompositeActivity[] = []; - private readonly compositeActions = new Map(); + private readonly compositeActions = new Map(); private readonly viewContainerDisposables = new Map(); private readonly keyboardNavigationDisposables = this._register(new DisposableStore()); @@ -170,29 +170,36 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Home if (this.homeBarContainer) { - actions.push(new Action( - 'toggleHomeBarAction', - this.homeBarVisibilityPreference ? nls.localize('hideHomeBar', "Hide Home Button") : nls.localize('showHomeBar', "Show Home Button"), - undefined, - true, - async () => { this.homeBarVisibilityPreference = !this.homeBarVisibilityPreference; } - )); + actions.push({ + id: 'toggleHomeBarAction', + label: nls.localize('homeButton', "Home Button"), + checked: this.homeBarVisibilityPreference, + enabled: true, + run: () => this.homeBarVisibilityPreference = !this.homeBarVisibilityPreference + }); } // Menu const menuBarVisibility = getMenuBarVisibility(this.configurationService); if (menuBarVisibility === 'compact' || (menuBarVisibility === 'hidden' && isWeb)) { - actions.push(this.instantiationService.createInstance(ToggleMenuBarAction, ToggleMenuBarAction.ID, menuBarVisibility === 'compact' ? nls.localize('hideMenu', "Hide Menu") : nls.localize('showMenu', "Show Menu"))); + actions.push({ + id: 'toggleMenuVisibility', + label: nls.localize('menu', "Menu"), + checked: menuBarVisibility === 'compact', + enabled: true, + run: () => this.layoutService.toggleMenuBar() + }); } // Accounts - actions.push(new Action( - 'toggleAccountsVisibility', - this.accountsVisibilityPreference ? nls.localize('hideAccounts', "Hide Accounts") : nls.localize('showAccounts', "Show Accounts"), - undefined, - true, - async () => { this.accountsVisibilityPreference = !this.accountsVisibilityPreference; } - )); + actions.push({ + id: 'toggleAccountsVisibility', + label: nls.localize('accounts', "Accounts"), + checked: this.accountsVisibilityPreference, + enabled: true, + run: () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference + }); + actions.push(new Separator()); // Toggle Sidebar @@ -278,7 +285,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { })); } - private onDidChangeViewContainers(added: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>, removed: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>) { + private onDidChangeViewContainers(added: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation; }>, removed: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation; }>) { removed.filter(({ location }) => location === ViewContainerLocation.Sidebar).forEach(({ container }) => this.onDidDeregisterViewContainer(container)); this.onDidRegisterViewContainers(added.filter(({ location }) => location === ViewContainerLocation.Sidebar).map(({ container }) => container)); } @@ -640,7 +647,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.updateGlobalActivity(ACCOUNTS_ACTIVITY_ID); } - private getCompositeActions(compositeId: string): { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction } { + private getCompositeActions(compositeId: string): { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction; } { let compositeActions = this.compositeActions.get(compositeId); if (!compositeActions) { const viewContainer = this.getViewContainer(compositeId); @@ -921,7 +928,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { const viewContainer = this.getViewContainer(compositeItem.id); if (viewContainer) { const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer); - const views: { when: string | undefined }[] = []; + const views: { when: string | undefined; }[] = []; for (const { when } of viewContainerModel.allViewDescriptors) { views.push({ when: when ? when.serialize() : undefined }); } diff --git a/src/vs/workbench/services/layout/browser/layoutService.ts b/src/vs/workbench/services/layout/browser/layoutService.ts index a405e8973c6..34d74f2b490 100644 --- a/src/vs/workbench/services/layout/browser/layoutService.ts +++ b/src/vs/workbench/services/layout/browser/layoutService.ts @@ -43,7 +43,7 @@ export function positionToString(position: Position): string { } } -const positionsByString: { [key: string]: Position } = { +const positionsByString: { [key: string]: Position; } = { [positionToString(Position.LEFT)]: Position.LEFT, [positionToString(Position.RIGHT)]: Position.RIGHT, [positionToString(Position.BOTTOM)]: Position.BOTTOM @@ -62,7 +62,7 @@ export function panelOpensMaximizedSettingToString(setting: PanelOpensMaximizedO } } -const panelOpensMaximizedByString: { [key: string]: PanelOpensMaximizedOptions } = { +const panelOpensMaximizedByString: { [key: string]: PanelOpensMaximizedOptions; } = { [panelOpensMaximizedSettingToString(PanelOpensMaximizedOptions.ALWAYS)]: PanelOpensMaximizedOptions.ALWAYS, [panelOpensMaximizedSettingToString(PanelOpensMaximizedOptions.NEVER)]: PanelOpensMaximizedOptions.NEVER, [panelOpensMaximizedSettingToString(PanelOpensMaximizedOptions.REMEMBER_LAST)]: PanelOpensMaximizedOptions.REMEMBER_LAST @@ -194,6 +194,11 @@ export interface IWorkbenchLayoutService extends ILayoutService { */ getMenubarVisibility(): MenuBarVisibility; + /** + * Toggles the menu bar visibility. + */ + toggleMenuBar(): void; + /** * Gets the current panel position. Note that the panel can be hidden too. */ diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index e8424d3318c..0a87eb616cf 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -125,7 +125,7 @@ export interface ITestInstantiationService extends IInstantiationService { export function workbenchInstantiationService( overrides?: { - textFileService?: (instantiationService: IInstantiationService) => ITextFileService + textFileService?: (instantiationService: IInstantiationService) => ITextFileService; pathService?: (instantiationService: IInstantiationService) => IPathService, editorService?: (instantiationService: IInstantiationService) => IEditorService, contextKeyService?: (instantiationService: IInstantiationService) => IContextKeyService, @@ -456,6 +456,7 @@ export class TestLayoutService implements IWorkbenchLayoutService { toggleMaximizedPanel(): void { } isPanelMaximized(): boolean { return false; } getMenubarVisibility(): MenuBarVisibility { throw new Error('not implemented'); } + toggleMenuBar(): void { } getSideBarPosition() { return 0; } getPanelPosition() { return 0; } async setPanelPosition(_position: PartPosition): Promise { } @@ -504,7 +505,7 @@ export class TestViewletService implements IViewletService { export class TestPanelService implements IPanelService { declare readonly _serviceBrand: undefined; - onDidPanelOpen = new Emitter<{ panel: IPanel, focus: boolean }>().event; + onDidPanelOpen = new Emitter<{ panel: IPanel, focus: boolean; }>().event; onDidPanelClose = new Emitter().event; async openPanel(id?: string, focus?: boolean): Promise { return undefined; } @@ -524,7 +525,7 @@ export class TestViewsService implements IViewsService { declare readonly _serviceBrand: undefined; - onDidChangeViewContainerVisibility = new Emitter<{ id: string; visible: boolean; location: ViewContainerLocation }>().event; + onDidChangeViewContainerVisibility = new Emitter<{ id: string; visible: boolean; location: ViewContainerLocation; }>().event; isViewContainerVisible(id: string): boolean { return true; } getVisibleViewContainer(): ViewContainer | null { return null; } openViewContainer(id: string, focus?: boolean): Promise { return Promise.resolve(null); } @@ -570,8 +571,8 @@ export class TestEditorGroupsService implements IEditorGroupsService { findGroup(_scope: IFindGroupScope, _source?: number | IEditorGroup, _wrap?: boolean): IEditorGroup { throw new Error('not implemented'); } activateGroup(_group: number | IEditorGroup): IEditorGroup { throw new Error('not implemented'); } restoreGroup(_group: number | IEditorGroup): IEditorGroup { throw new Error('not implemented'); } - getSize(_group: number | IEditorGroup): { width: number, height: number } { return { width: 100, height: 100 }; } - setSize(_group: number | IEditorGroup, _size: { width: number, height: number }): void { } + getSize(_group: number | IEditorGroup): { width: number, height: number; } { return { width: 100, height: 100 }; } + setSize(_group: number | IEditorGroup, _size: { width: number, height: number; }): void { } arrangeGroups(_arrangement: GroupsArrangement): void { } applyLayout(_layout: EditorGroupLayout): void { } setGroupOrientation(_orientation: GroupOrientation): void { } @@ -729,7 +730,7 @@ export class TestEditorService implements EditorServiceImpl { saveAll(options?: ISaveEditorsOptions): Promise { throw new Error('Method not implemented.'); } revert(editors: IEditorIdentifier[], options?: IRevertOptions): Promise { throw new Error('Method not implemented.'); } revertAll(options?: IRevertAllEditorsOptions): Promise { throw new Error('Method not implemented.'); } - whenClosed(editors: IResourceEditorInput[], options?: { waitForSaved: boolean }): Promise { throw new Error('Method not implemented.'); } + whenClosed(editors: IResourceEditorInput[], options?: { waitForSaved: boolean; }): Promise { throw new Error('Method not implemented.'); } } export class TestFileService implements IFileService { @@ -769,7 +770,7 @@ export class TestFileService implements IFileService { }); } - async resolveAll(toResolve: { resource: URI, options?: IResolveFileOptions }[]): Promise { + async resolveAll(toResolve: { resource: URI, options?: IResolveFileOptions; }[]): Promise { const stats = await Promise.all(toResolve.map(resourceAndOption => this.resolve(resourceAndOption.resource, resourceAndOption.options))); return stats.map(stat => ({ stat, success: true })); @@ -873,7 +874,7 @@ export class TestFileService implements IFileService { return false; } - async del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean }): Promise { } + async del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean; }): Promise { } readonly watches: URI[] = []; watch(_resource: URI): IDisposable { @@ -1056,7 +1057,7 @@ export class TestHostService implements IHostService { async reload(): Promise { } async close(): Promise { } - async focus(options?: { force: boolean }): Promise { } + async focus(options?: { force: boolean; }): Promise { } async openWindow(arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: IOpenWindowOptions): Promise { } From b33b28dd078bdd14a2d832e95bbdc015c4eff062 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 12 Jan 2021 08:16:00 +0100 Subject: [PATCH 1819/1837] Activate onStartupFinished (#110031) --- extensions/merge-conflict/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index 708166d4508..ab645a38f22 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -14,7 +14,7 @@ "Other" ], "activationEvents": [ - "*" + "onStartupFinished" ], "main": "./out/mergeConflictMain", "browser": "./dist/browser/mergeConflictMain", From 2b0132d09f1053746a42828fba3f8aca6e1a0592 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 08:33:54 +0100 Subject: [PATCH 1820/1837] activity bar - update order of entries to reflect visual order (#113757) --- src/vs/base/common/actions.ts | 10 ++--- .../parts/activitybar/activitybarPart.ts | 40 ++++++++++++------- .../workbench/browser/parts/compositeBar.ts | 16 ++++---- .../browser/parts/panel/panelPart.ts | 31 +++++++------- 4 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 1f24e8e86a2..b8089466ce1 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -14,8 +14,8 @@ export interface ITelemetryData { } export type WorkbenchActionExecutedClassification = { - id: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - from: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + id: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; }; + from: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; }; }; export type WorkbenchActionExecutedEvent = { @@ -63,7 +63,7 @@ export interface IActionChangeEvent { export class Action extends Disposable implements IAction { protected _onDidChange = this._register(new Emitter()); - readonly onDidChange: Event = this._onDidChange.event; + readonly onDidChange = this._onDidChange.event; protected readonly _id: string; protected _label: string; @@ -179,10 +179,10 @@ export interface IRunEvent { export class ActionRunner extends Disposable implements IActionRunner { private _onBeforeRun = this._register(new Emitter()); - readonly onBeforeRun: Event = this._onBeforeRun.event; + readonly onBeforeRun = this._onBeforeRun.event; private _onDidRun = this._register(new Emitter()); - readonly onDidRun: Event = this._onDidRun.event; + readonly onDidRun = this._onDidRun.event; async run(action: IAction, context?: any): Promise { if (!action.enabled) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 679abe1fbf7..b7db3590da4 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -35,7 +35,7 @@ import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { isNative, isWeb } from 'vs/base/common/platform'; import { Before2D } from 'vs/workbench/browser/dnd'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; -import { Action, Separator } from 'vs/base/common/actions'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -161,43 +161,57 @@ export class ActivitybarPart extends Part implements IActivityBarService { icon: true, orientation: ActionsOrientation.VERTICAL, preventLoopNavigation: true, - openComposite: (compositeId: string) => this.viewsService.openViewContainer(compositeId, true), - getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction, - getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction, - getOnCompositeClickAction: (compositeId: string) => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)), - getContextMenuActions: () => { - const actions = []; + openComposite: compositeId => this.viewsService.openViewContainer(compositeId, true), + getActivityAction: compositeId => this.getCompositeActions(compositeId).activityAction, + getCompositePinnedAction: compositeId => this.getCompositeActions(compositeId).pinnedAction, + getOnCompositeClickAction: compositeId => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)), + fillExtraContextMenuActions: actions => { // Home + const topActions: IAction[] = []; if (this.homeBarContainer) { - actions.push({ + topActions.push({ id: 'toggleHomeBarAction', label: nls.localize('homeButton', "Home Button"), + class: undefined, + tooltip: nls.localize('homeButton', "Home Button"), checked: this.homeBarVisibilityPreference, enabled: true, - run: () => this.homeBarVisibilityPreference = !this.homeBarVisibilityPreference + run: async () => this.homeBarVisibilityPreference = !this.homeBarVisibilityPreference, + dispose: () => { } }); } // Menu const menuBarVisibility = getMenuBarVisibility(this.configurationService); if (menuBarVisibility === 'compact' || (menuBarVisibility === 'hidden' && isWeb)) { - actions.push({ + topActions.push({ id: 'toggleMenuVisibility', label: nls.localize('menu', "Menu"), + class: undefined, + tooltip: nls.localize('menu', "Menu"), checked: menuBarVisibility === 'compact', enabled: true, - run: () => this.layoutService.toggleMenuBar() + run: async () => this.layoutService.toggleMenuBar(), + dispose: () => { } }); } + if (topActions.length) { + actions.unshift(...topActions, new Separator()); + } + // Accounts + actions.push(new Separator()); actions.push({ id: 'toggleAccountsVisibility', label: nls.localize('accounts', "Accounts"), + class: undefined, + tooltip: nls.localize('accounts', "Accounts"), checked: this.accountsVisibilityPreference, enabled: true, - run: () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference + run: async () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference, + dispose: () => { } }); actions.push(new Separator()); @@ -213,8 +227,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { true, async () => { this.instantiationService.invokeFunction(accessor => new ToggleActivityBarVisibilityAction().run(accessor)); } )); - - return actions; }, getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId), getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id, diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 06a031a5632..3d84ff76cfc 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { Action, IAction } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; import * as arrays from 'vs/base/common/arrays'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -151,7 +151,7 @@ export interface ICompositeBarOptions { getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOnCompositeClickAction: (compositeId: string) => Action; - getContextMenuActions: () => Action[]; + fillExtraContextMenuActions: (actions: IAction[]) => void; getContextMenuActionsForComposite: (compositeId: string) => Action[]; openComposite: (compositeId: string) => Promise; getDefaultCompositeId: () => string; @@ -319,7 +319,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this.updateCompositeSwitcher(); } - addComposite({ id, name, order, requestedIndex }: { id: string; name: string, order?: number, requestedIndex?: number }): void { + addComposite({ id, name, order, requestedIndex }: { id: string; name: string, order?: number, requestedIndex?: number; }): void { // Add to the model if (this.model.add(id, name, order, requestedIndex)) { this.computeSizes([this.model.findItem(id)]); @@ -610,7 +610,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this._onDidChange.fire(); } - private getOverflowingComposites(): { id: string, name?: string }[] { + private getOverflowingComposites(): { id: string, name?: string; }[] { let overflowingIds = this.model.visibleItems.filter(item => item.pinned).map(item => item.id); // Show the active composite even if it is not pinned @@ -646,11 +646,9 @@ export class CompositeBar extends Widget implements ICompositeBar { } } })); - const otherActions = this.options.getContextMenuActions(); - if (otherActions.length) { - actions.push(new Separator()); - actions.push(...otherActions); - } + + this.options.fillExtraContextMenuActions(actions); + return actions; } } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index abe4c095397..11c565b543c 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/panelpart'; -import { IAction, Action } from 'vs/base/common/actions'; +import { IAction, Action, Separator } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -46,7 +46,7 @@ interface ICachedPanel { pinned: boolean; order?: number; visible: boolean; - views?: { when?: string }[]; + views?: { when?: string; }[]; } interface IPlaceholderViewContainer { @@ -149,18 +149,21 @@ export class PanelPart extends CompositePart implements IPanelService { this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), { icon: false, orientation: ActionsOrientation.HORIZONTAL, - openComposite: (compositeId: string) => this.openPanel(compositeId, true).then(panel => panel || null), - getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction, - getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction, - getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))), - getContextMenuActions: () => [ - ...PositionPanelActionConfigs - // show the contextual menu item if it is not in that position - .filter(({ when }) => contextKeyService.contextMatchesRules(when)) - .map(({ id, label }) => this.instantiationService.createInstance(SetPanelPositionAction, id, label)), - this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel")) - ] as Action[], - getContextMenuActionsForComposite: (compositeId: string) => this.getContextMenuActionsForComposite(compositeId) as Action[], + openComposite: compositeId => this.openPanel(compositeId, true).then(panel => panel || null), + getActivityAction: compositeId => this.getCompositeActions(compositeId).activityAction, + getCompositePinnedAction: compositeId => this.getCompositeActions(compositeId).pinnedAction, + getOnCompositeClickAction: compositeId => this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))), + fillExtraContextMenuActions: actions => { + actions.push(...[ + new Separator(), + ...PositionPanelActionConfigs + // show the contextual menu item if it is not in that position + .filter(({ when }) => contextKeyService.contextMatchesRules(when)) + .map(({ id, label }) => this.instantiationService.createInstance(SetPanelPositionAction, id, label)), + this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel")) + ]); + }, + getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId) as Action[], getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(), hidePart: () => this.layoutService.setPanelHidden(true), dndHandler: this.dndHandler, From b9aaba047c651ec84d87236be5839989b4cbb254 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 08:37:52 +0100 Subject: [PATCH 1821/1837] activity bar - remove "Hide" from left click menus (#113757) --- .../parts/activitybar/activitybarActions.ts | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index d28964ecb2f..3bc98ea640a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -29,7 +29,6 @@ import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; import { AuthenticationSession } from 'vs/editor/common/modes'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IProductService } from 'vs/platform/product/common/productService'; import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview'; @@ -97,10 +96,10 @@ export class ViewContainerActivityAction extends ActivityAction { private logAction(action: string) { type ActivityBarActionClassification = { - viewletId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - action: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + viewletId: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; }; + action: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; }; }; - this.telemetryService.publicLog2<{ viewletId: String, action: String }, ActivityBarActionClassification>('activityBarAction', { viewletId: this.activity.id, action }); + this.telemetryService.publicLog2<{ viewletId: String, action: String; }, ActivityBarActionClassification>('activityBarAction', { viewletId: this.activity.id, action }); } } @@ -185,8 +184,7 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { @IContextMenuService contextMenuService: IContextMenuService, @IContextKeyService contextKeyService: IContextKeyService, @IConfigurationService configurationService: IConfigurationService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, - @IStorageService private readonly storageService: IStorageService + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService ) { super(MenuId.MenubarHomeMenu, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } @@ -196,19 +194,13 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { // Go Home actions.push(disposables.add(new Action('goHome', nls.localize('goHome', "Go Home"), undefined, true, async () => window.location.href = this.goHomeHref))); - actions.push(disposables.add(new Separator())); // Contributed const contributedActions = await super.resolveActions(homeMenu, disposables); - actions.push(...contributedActions); - - // Hide - if (contributedActions.length > 0) { + if (contributedActions.length) { actions.push(disposables.add(new Separator())); + actions.push(...contributedActions); } - actions.push(disposables.add(new Action('hide', nls.localize('hide', "Hide Home Button"), undefined, true, async () => { - this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, false, StorageScope.GLOBAL, StorageTarget.USER); - }))); return actions; } @@ -227,7 +219,6 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { @IContextKeyService contextKeyService: IContextKeyService, @IAuthenticationService private readonly authenticationService: IAuthenticationService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, - @IStorageService private readonly storageService: IStorageService, @IProductService private readonly productService: IProductService, @IConfigurationService configurationService: IConfigurationService, ) { @@ -243,7 +234,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { try { const sessions = await this.authenticationService.getSessions(providerId); - const groupedSessions: { [label: string]: AuthenticationSession[] } = {}; + const groupedSessions: { [label: string]: AuthenticationSession[]; } = {}; sessions.forEach(session => { if (groupedSessions[session.account.label]) { groupedSessions[session.account.label].push(session); @@ -302,14 +293,6 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { } }); - if (menus.length) { - menus.push(disposables.add(new Separator())); - } - - menus.push(disposables.add(new Action('hide', nls.localize('hideAccounts', "Hide Accounts"), undefined, true, async () => { - this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); - }))); - return menus; } } From e17aea136d32fdb06d9b32184b04ccd36bb51e9c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Jan 2021 09:08:20 +0100 Subject: [PATCH 1822/1837] Fix #114189 - disable caching --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index b7db3590da4..935517cceed 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -133,7 +133,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { for (const cachedViewContainer of this.cachedViewContainers) { if ( - (environmentService.remoteAuthority && isNative) || // In desktop with remote connection, hide activity bar entries until registered. + environmentService.remoteAuthority || // In remote window, hide activity bar entries until registered. this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer) ) { cachedViewContainer.visible = false; From f675564c5dc06e80d4ddc10df347f08b98730ced Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 09:15:40 +0100 Subject: [PATCH 1823/1837] fix #114028 --- src/vs/base/test/common/async.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index ac12abf371b..43a0d0c4f46 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -711,7 +711,11 @@ suite('Async', () => { assert.equal(counter.increment(), 2); assert.equal(counter.increment(), 3); + const now = Date.now(); await async.timeout(20); + if (Date.now() - now < 11) { + return; // Firefox in Playwright seems to have a flaky timeout implementation (https://github.com/microsoft/vscode/issues/114028) + } assert.equal(counter.increment(), 1); assert.equal(counter.increment(), 2); From 7ab5c2a90ae6b0cf0bd97f175d901251fb206648 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 09:40:54 +0100 Subject: [PATCH 1824/1837] activity bar - consistently show right click menu everywhere (#113757) --- .../parts/activitybar/activitybarActions.ts | 35 +++++++++++++------ .../parts/activitybar/activitybarPart.ts | 6 ++-- .../workbench/browser/parts/compositeBar.ts | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 3bc98ea640a..5bc5582a43b 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -108,6 +108,7 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { constructor( private readonly menuId: MenuId, action: ActivityAction, + private contextMenuActionsProvider: () => IAction[], colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, @IMenuService protected readonly menuService: IMenuService, @@ -144,11 +145,16 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { })); } - protected async showContextMenu(e?: MouseEvent): Promise { + private async showContextMenu(e?: MouseEvent): Promise { const disposables = new DisposableStore(); - const menu = disposables.add(this.menuService.createMenu(this.menuId, this.contextKeyService)); - const actions = await this.resolveActions(menu, disposables); + let actions: IAction[]; + if (e?.button !== 2) { + const menu = disposables.add(this.menuService.createMenu(this.menuId, this.contextKeyService)); + actions = await this.resolveMainMenuActions(menu, disposables); + } else { + actions = await this.resolveContextMenuActions(); + } const isUsingCustomMenu = isWeb || (getTitleBarStyle(this.configurationService) !== 'native' && !isMacintosh); // see #40262 const position = this.configurationService.getValue('workbench.sideBar.location'); @@ -162,13 +168,17 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { }); } - protected async resolveActions(menu: IMenu, disposables: DisposableStore): Promise { + protected async resolveMainMenuActions(menu: IMenu, disposables: DisposableStore): Promise { const actions: IAction[] = []; disposables.add(createAndFillInActionBarActions(menu, undefined, { primary: [], secondary: actions })); return actions; } + + private async resolveContextMenuActions(): Promise { + return this.contextMenuActionsProvider(); + } } export class HomeActivityActionViewItem extends MenuActivityActionViewItem { @@ -178,6 +188,7 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { constructor( private readonly goHomeHref: string, action: ActivityAction, + contextMenuActionsProvider: () => IAction[], colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, @IMenuService menuService: IMenuService, @@ -186,17 +197,17 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { @IConfigurationService configurationService: IConfigurationService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService ) { - super(MenuId.MenubarHomeMenu, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); + super(MenuId.MenubarHomeMenu, action, contextMenuActionsProvider, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } - protected async resolveActions(homeMenu: IMenu, disposables: DisposableStore): Promise { + protected async resolveMainMenuActions(homeMenu: IMenu, disposables: DisposableStore): Promise { const actions = []; // Go Home actions.push(disposables.add(new Action('goHome', nls.localize('goHome', "Go Home"), undefined, true, async () => window.location.href = this.goHomeHref))); // Contributed - const contributedActions = await super.resolveActions(homeMenu, disposables); + const contributedActions = await super.resolveMainMenuActions(homeMenu, disposables); if (contributedActions.length) { actions.push(disposables.add(new Separator())); actions.push(...contributedActions); @@ -212,6 +223,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { constructor( action: ActivityAction, + contextMenuActionsProvider: () => IAction[], colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, @IContextMenuService contextMenuService: IContextMenuService, @@ -222,11 +234,11 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { @IProductService private readonly productService: IProductService, @IConfigurationService configurationService: IConfigurationService, ) { - super(MenuId.AccountsContext, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); + super(MenuId.AccountsContext, action, contextMenuActionsProvider, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } - protected async resolveActions(accountsMenu: IMenu, disposables: DisposableStore): Promise { - await super.resolveActions(accountsMenu, disposables); + protected async resolveMainMenuActions(accountsMenu: IMenu, disposables: DisposableStore): Promise { + await super.resolveMainMenuActions(accountsMenu, disposables); const otherCommands = accountsMenu.getActions(); const providers = this.authenticationService.getProviderIds(); @@ -301,6 +313,7 @@ export class GlobalActivityActionViewItem extends MenuActivityActionViewItem { constructor( action: ActivityAction, + contextMenuActionsProvider: () => IAction[], colors: (theme: IColorTheme) => ICompositeBarColors, @IThemeService themeService: IThemeService, @IMenuService menuService: IMenuService, @@ -309,7 +322,7 @@ export class GlobalActivityActionViewItem extends MenuActivityActionViewItem { @IConfigurationService configurationService: IConfigurationService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService ) { - super(MenuId.GlobalActivity, action, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); + super(MenuId.GlobalActivity, action, contextMenuActionsProvider, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 935517cceed..b8b887528cf 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -580,7 +580,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.homeBarContainer.classList.add('home-bar'); this.homeBar = this._register(new ActionBar(this.homeBarContainer, { - actionViewItemProvider: action => this.instantiationService.createInstance(HomeActivityActionViewItem, href, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)), + actionViewItemProvider: action => this.instantiationService.createInstance(HomeActivityActionViewItem, href, action as ActivityAction, () => this.compositeBar.getContextMenuActions(), (theme: IColorTheme) => this.getActivitybarItemColors(theme)), orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('home', "Home"), animated: false, @@ -606,11 +606,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.globalActivityActionBar = this._register(new ActionBar(container, { actionViewItemProvider: action => { if (action.id === 'workbench.actions.manage') { - return this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); + return this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, () => this.compositeBar.getContextMenuActions(), (theme: IColorTheme) => this.getActivitybarItemColors(theme)); } if (action.id === 'workbench.actions.accounts') { - return this.instantiationService.createInstance(AccountsActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); + return this.instantiationService.createInstance(AccountsActivityActionViewItem, action as ActivityAction, () => this.compositeBar.getContextMenuActions(), (theme: IColorTheme) => this.getActivitybarItemColors(theme)); } throw new Error(`No view item for action '${action.id}'`); diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 3d84ff76cfc..97e2e8cf348 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -631,7 +631,7 @@ export class CompositeBar extends Widget implements ICompositeBar { }); } - private getContextMenuActions(): IAction[] { + getContextMenuActions(): IAction[] { const actions: IAction[] = this.model.visibleItems .map(({ id, name, activityAction }) => ({ id, From b5b160e015e881cb336e65b028d709823f9c6ea8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 09:52:34 +0100 Subject: [PATCH 1825/1837] activity bar - show a "Hide" entry for accounts and home indicator (fix #113757) --- .../parts/activitybar/activitybarActions.ts | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 5bc5582a43b..77b9109953a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -34,6 +34,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { getTitleBarStyle } from 'vs/platform/windows/common/windows'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; export class ViewContainerActivityAction extends ActivityAction { @@ -153,7 +154,7 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { const menu = disposables.add(this.menuService.createMenu(this.menuId, this.contextKeyService)); actions = await this.resolveMainMenuActions(menu, disposables); } else { - actions = await this.resolveContextMenuActions(); + actions = await this.resolveContextMenuActions(disposables); } const isUsingCustomMenu = isWeb || (getTitleBarStyle(this.configurationService) !== 'native' && !isMacintosh); // see #40262 @@ -176,7 +177,7 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { return actions; } - private async resolveContextMenuActions(): Promise { + protected async resolveContextMenuActions(disposables: DisposableStore): Promise { return this.contextMenuActionsProvider(); } } @@ -195,7 +196,8 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { @IContextMenuService contextMenuService: IContextMenuService, @IContextKeyService contextKeyService: IContextKeyService, @IConfigurationService configurationService: IConfigurationService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IStorageService private readonly storageService: IStorageService ) { super(MenuId.MenubarHomeMenu, action, contextMenuActionsProvider, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } @@ -215,6 +217,19 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { return actions; } + + protected async resolveContextMenuActions(disposables: DisposableStore): Promise { + const actions = await super.resolveContextMenuActions(disposables); + + actions.unshift(...[ + new Action('hideHomeButton', nls.localize('hideHomeButton', "Hide Home Button"), undefined, true, async () => { + this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, false, StorageScope.GLOBAL, StorageTarget.USER); + }), + new Separator() + ]); + + return actions; + } } export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { @@ -233,6 +248,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IProductService private readonly productService: IProductService, @IConfigurationService configurationService: IConfigurationService, + @IStorageService private readonly storageService: IStorageService ) { super(MenuId.AccountsContext, action, contextMenuActionsProvider, colors, themeService, menuService, contextMenuService, contextKeyService, configurationService, environmentService); } @@ -307,6 +323,19 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { return menus; } + + protected async resolveContextMenuActions(disposables: DisposableStore): Promise { + const actions = await super.resolveContextMenuActions(disposables); + + actions.unshift(...[ + new Action('hideAccounts', nls.localize('hideAccounts', "Hide Accounts"), undefined, true, async () => { + this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + }), + new Separator() + ]); + + return actions; + } } export class GlobalActivityActionViewItem extends MenuActivityActionViewItem { From 7a8c7f5731262df445c8270dc4f5a992aca32add Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 11:07:31 +0100 Subject: [PATCH 1826/1837] activity bar - use IAction in more places --- src/vs/base/browser/ui/button/button.ts | 2 +- .../ui/dropdown/dropdownActionViewItem.ts | 2 +- src/vs/base/common/actions.ts | 13 ++++ .../parts/activitybar/activitybarActions.ts | 38 +++++------ .../parts/activitybar/activitybarPart.ts | 64 ++++++++----------- .../workbench/browser/parts/compositeBar.ts | 22 +++---- .../browser/parts/compositeBarActions.ts | 16 ++--- .../browser/parts/statusbar/statusbarPart.ts | 2 +- .../files/browser/editors/textFileEditor.ts | 26 ++++---- .../files/electron-sandbox/textFileEditor.ts | 28 ++++---- 10 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index ccd30d2f57c..ebfe8d59f17 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -256,7 +256,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.button = this._register(new Button(this.element, options)); this._register(this.button.onDidClick(e => this._onDidClick.fire(e))); - this.action = new Action('primaryAction', this.button.label, undefined, true, async () => this._onDidClick.fire(undefined)); + this.action = this._register(new Action('primaryAction', this.button.label, undefined, true, async () => this._onDidClick.fire(undefined))); this.dropdownButton = this._register(new Button(this.element, { ...options, title: false, supportIcons: true })); this.dropdownButton.element.classList.add('monaco-dropdown-button'); diff --git a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts index 91b7db34dcc..2a712e089f9 100644 --- a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts +++ b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts @@ -176,7 +176,7 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem { return [this._action, ...(Array.isArray(actionsProvider) ? actionsProvider : actionsProvider.getActions())]; } }; - this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(new Action('dropdownAction', undefined), menuActionsProvider, this.contextMenuProvider, { classNames: ['dropdown', ...Codicon.dropDownButton.classNamesArray, ...(this.options).menuActionClassNames || []] }); + this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(this._register(new Action('dropdownAction', undefined)), menuActionsProvider, this.contextMenuProvider, { classNames: ['dropdown', ...Codicon.dropDownButton.classNamesArray, ...(this.options).menuActionClassNames || []] }); this.dropdownMenuActionViewItem.render(this.element); } } diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index b8089466ce1..41b0fd8241a 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -283,3 +283,16 @@ export class EmptySubmenuAction extends Action { super(EmptySubmenuAction.ID, nls.localize('submenu.empty', '(empty)'), undefined, false); } } + +export function toAction(props: { id: string, label: string, enabled?: boolean, checked?: boolean, run: Function; }): IAction { + return { + id: props.id, + label: props.label, + class: undefined, + enabled: props.enabled ?? true, + checked: props.checked ?? false, + run: async () => props.run(), + tooltip: props.label, + dispose: () => { } + }; +} diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 77b9109953a..485e48516c6 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/activityaction'; -import * as nls from 'vs/nls'; -import * as DOM from 'vs/base/browser/dom'; +import { localize } from 'vs/nls'; +import { EventType, addDisposableListener, EventHelper } from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; -import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions'; +import { Action, IAction, Separator, SubmenuAction, toAction } from 'vs/base/common/actions'; import { KeyCode } from 'vs/base/common/keyCodes'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IMenuService, MenuId, IMenu, registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions'; @@ -127,21 +127,21 @@ class MenuActivityActionViewItem extends ActivityActionViewItem { // Context menus are triggered on mouse down so that an item can be picked // and executed with releasing the mouse over it - this._register(DOM.addDisposableListener(this.container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { - DOM.EventHelper.stop(e, true); + this._register(addDisposableListener(this.container, EventType.MOUSE_DOWN, (e: MouseEvent) => { + EventHelper.stop(e, true); this.showContextMenu(e); })); - this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { + this._register(addDisposableListener(this.container, EventType.KEY_UP, (e: KeyboardEvent) => { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { - DOM.EventHelper.stop(e, true); + EventHelper.stop(e, true); this.showContextMenu(); } })); - this._register(DOM.addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => { - DOM.EventHelper.stop(e, true); + this._register(addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => { + EventHelper.stop(e, true); this.showContextMenu(); })); } @@ -206,7 +206,7 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { const actions = []; // Go Home - actions.push(disposables.add(new Action('goHome', nls.localize('goHome', "Go Home"), undefined, true, async () => window.location.href = this.goHomeHref))); + actions.push(toAction({ id: 'goHome', label: localize('goHome', "Go Home"), run: () => window.location.href = this.goHomeHref })); // Contributed const contributedActions = await super.resolveMainMenuActions(homeMenu, disposables); @@ -222,9 +222,7 @@ export class HomeActivityActionViewItem extends MenuActivityActionViewItem { const actions = await super.resolveContextMenuActions(disposables); actions.unshift(...[ - new Action('hideHomeButton', nls.localize('hideHomeButton', "Hide Home Button"), undefined, true, async () => { - this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, false, StorageScope.GLOBAL, StorageTarget.USER); - }), + toAction({ id: 'hideHomeButton', label: localize('hideHomeButton', "Hide Home Button"), run: () => this.storageService.store(HomeActivityActionViewItem.HOME_BAR_VISIBILITY_PREFERENCE, false, StorageScope.GLOBAL, StorageTarget.USER) }), new Separator() ]); @@ -285,11 +283,11 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { if (sessionInfo.sessions) { Object.keys(sessionInfo.sessions).forEach(accountName => { - const manageExtensionsAction = disposables.add(new Action(`configureSessions${accountName}`, nls.localize('manageTrustedExtensions', "Manage Trusted Extensions"), '', true, () => { + const manageExtensionsAction = disposables.add(new Action(`configureSessions${accountName}`, localize('manageTrustedExtensions', "Manage Trusted Extensions"), '', true, () => { return this.authenticationService.manageTrustedExtensionsForAccount(sessionInfo.providerId, accountName); })); - const signOutAction = disposables.add(new Action('signOut', nls.localize('signOut', "Sign Out"), '', true, () => { + const signOutAction = disposables.add(new Action('signOut', localize('signOut', "Sign Out"), '', true, () => { return this.authenticationService.signOutOfAccount(sessionInfo.providerId, accountName); })); @@ -304,7 +302,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { menus.push(providerSubMenu); }); } else { - const providerUnavailableAction = disposables.add(new Action('providerUnavailable', nls.localize('authProviderUnavailable', '{0} is currently unavailable', providerDisplayName))); + const providerUnavailableAction = disposables.add(new Action('providerUnavailable', localize('authProviderUnavailable', '{0} is currently unavailable', providerDisplayName))); menus.push(providerUnavailableAction); } }); @@ -328,9 +326,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { const actions = await super.resolveContextMenuActions(disposables); actions.unshift(...[ - new Action('hideAccounts', nls.localize('hideAccounts', "Hide Accounts"), undefined, true, async () => { - this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); - }), + toAction({ id: 'hideAccounts', label: localize('hideAccounts', "Hide Accounts"), run: () => this.storageService.store(AccountsActivityActionViewItem.ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER) }), new Separator() ]); @@ -404,7 +400,7 @@ registerAction2( constructor() { super({ id: 'workbench.action.previousSideBarView', - title: { value: nls.localize('previousSideBarView', "Previous Side Bar View"), original: 'Previous Side Bar View' }, + title: { value: localize('previousSideBarView', "Previous Side Bar View"), original: 'Previous Side Bar View' }, category: CATEGORIES.View, f1: true }, -1); @@ -417,7 +413,7 @@ registerAction2( constructor() { super({ id: 'workbench.action.nextSideBarView', - title: { value: nls.localize('nextSideBarView', "Next Side Bar View"), original: 'Next Side Bar View' }, + title: { value: localize('nextSideBarView', "Next Side Bar View"), original: 'Next Side Bar View' }, category: CATEGORIES.View, f1: true }, 1); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index b8b887528cf..6cf24bcb318 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/activitybarpart'; -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { GLOBAL_ACTIVITY_ID, IActivity, ACCOUNTS_ACTIVITY_ID } from 'vs/workbench/common/activity'; import { Part } from 'vs/workbench/browser/part'; @@ -35,7 +35,7 @@ import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { isNative, isWeb } from 'vs/base/common/platform'; import { Before2D } from 'vs/workbench/browser/dnd'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; -import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { IAction, Separator, toAction } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -69,9 +69,6 @@ interface ICachedViewContainer { views?: { when?: string; }[]; } -const settingsViewBarIcon = registerIcon('settings-view-bar-icon', Codicon.settingsGear, nls.localize('settingsViewBarIcon', 'Settings icon in the view bar.')); -const accountsViewBarIcon = registerIcon('accounts-view-bar-icon', Codicon.account, nls.localize('accountsViewBarIcon', 'Accounts icon in the view bar.')); - export class ActivitybarPart extends Part implements IActivityBarService { declare readonly _serviceBrand: undefined; @@ -81,6 +78,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { private static readonly ACTION_HEIGHT = 48; private static readonly ACCOUNTS_ACTION_INDEX = 0; + private static readonly GEAR_ICON = registerIcon('settings-view-bar-icon', Codicon.settingsGear, localize('settingsViewBarIcon', "Settings icon in the view bar.")); + private static readonly ACCOUNTS_ICON = registerIcon('accounts-view-bar-icon', Codicon.account, localize('accountsViewBarIcon', "Accounts icon in the view bar.")); + //#region IView readonly minimumWidth: number = 48; @@ -164,7 +164,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { openComposite: compositeId => this.viewsService.openViewContainer(compositeId, true), getActivityAction: compositeId => this.getCompositeActions(compositeId).activityAction, getCompositePinnedAction: compositeId => this.getCompositeActions(compositeId).pinnedAction, - getOnCompositeClickAction: compositeId => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)), + getOnCompositeClickAction: compositeId => toAction({ id: compositeId, label: '', run: async () => this.viewsService.isViewContainerVisible(compositeId) ? this.viewsService.closeViewContainer(compositeId) : this.viewsService.openViewContainer(compositeId) }), fillExtraContextMenuActions: actions => { // Home @@ -172,9 +172,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (this.homeBarContainer) { topActions.push({ id: 'toggleHomeBarAction', - label: nls.localize('homeButton', "Home Button"), + label: localize('homeButton', "Home Button"), class: undefined, - tooltip: nls.localize('homeButton', "Home Button"), + tooltip: localize('homeButton', "Home Button"), checked: this.homeBarVisibilityPreference, enabled: true, run: async () => this.homeBarVisibilityPreference = !this.homeBarVisibilityPreference, @@ -187,9 +187,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (menuBarVisibility === 'compact' || (menuBarVisibility === 'hidden' && isWeb)) { topActions.push({ id: 'toggleMenuVisibility', - label: nls.localize('menu', "Menu"), + label: localize('menu', "Menu"), class: undefined, - tooltip: nls.localize('menu', "Menu"), + tooltip: localize('menu', "Menu"), checked: menuBarVisibility === 'compact', enabled: true, run: async () => this.layoutService.toggleMenuBar(), @@ -205,9 +205,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { actions.push(new Separator()); actions.push({ id: 'toggleAccountsVisibility', - label: nls.localize('accounts', "Accounts"), + label: localize('accounts', "Accounts"), class: undefined, - tooltip: nls.localize('accounts', "Accounts"), + tooltip: localize('accounts', "Accounts"), checked: this.accountsVisibilityPreference, enabled: true, run: async () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference, @@ -220,13 +220,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { actions.push(this.instantiationService.createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService))); // Toggle Activity Bar - actions.push(new Action( - ToggleActivityBarVisibilityAction.ID, - nls.localize('hideActivitBar', "Hide Activity Bar"), - undefined, - true, - async () => { this.instantiationService.invokeFunction(accessor => new ToggleActivityBarVisibilityAction().run(accessor)); } - )); + actions.push(toAction({ id: ToggleActivityBarVisibilityAction.ID, label: localize('hideActivitBar', "Hide Activity Bar"), run: async () => this.instantiationService.invokeFunction(accessor => new ToggleActivityBarVisibilityAction().run(accessor)) })); }, getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId), getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id, @@ -242,24 +236,20 @@ export class ActivitybarPart extends Part implements IActivityBarService { })); } - private getContextMenuActionsForComposite(compositeId: string): Action[] { - const actions = []; + private getContextMenuActionsForComposite(compositeId: string): IAction[] { + const actions: IAction[] = []; const viewContainer = this.viewDescriptorService.getViewContainerById(compositeId)!; const defaultLocation = this.viewDescriptorService.getDefaultViewContainerLocation(viewContainer)!; if (defaultLocation !== this.viewDescriptorService.getViewContainerLocation(viewContainer)) { - actions.push(new Action('resetLocationAction', nls.localize('resetLocation', "Reset Location"), undefined, true, async () => { - this.viewDescriptorService.moveViewContainerToLocation(viewContainer, defaultLocation); - })); + actions.push(toAction({ id: 'resetLocationAction', label: localize('resetLocation', "Reset Location"), run: () => this.viewDescriptorService.moveViewContainerToLocation(viewContainer, defaultLocation) })); } else { const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer); if (viewContainerModel.allViewDescriptors.length === 1) { const viewToReset = viewContainerModel.allViewDescriptors[0]; const defaultContainer = this.viewDescriptorService.getDefaultContainerById(viewToReset.id)!; if (defaultContainer !== viewContainer) { - actions.push(new Action('resetLocationAction', nls.localize('resetLocation', "Reset Location"), undefined, true, async () => { - this.viewDescriptorService.moveViewsToContainer([viewToReset], defaultContainer); - })); + actions.push(toAction({ id: 'resetLocationAction', label: localize('resetLocation', "Reset Location"), run: () => this.viewDescriptorService.moveViewsToContainer([viewToReset], defaultContainer) })); } } } @@ -575,14 +565,14 @@ export class ActivitybarPart extends Part implements IActivityBarService { private createHomeBar(href: string, icon: Codicon): void { this.homeBarContainer = document.createElement('div'); - this.homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home")); + this.homeBarContainer.setAttribute('aria-label', localize('homeIndicator', "Home")); this.homeBarContainer.setAttribute('role', 'toolbar'); this.homeBarContainer.classList.add('home-bar'); this.homeBar = this._register(new ActionBar(this.homeBarContainer, { actionViewItemProvider: action => this.instantiationService.createInstance(HomeActivityActionViewItem, href, action as ActivityAction, () => this.compositeBar.getContextMenuActions(), (theme: IColorTheme) => this.getActivitybarItemColors(theme)), orientation: ActionsOrientation.VERTICAL, - ariaLabel: nls.localize('home', "Home"), + ariaLabel: localize('home', "Home"), animated: false, preventLoopNavigation: true, ignoreOrientationForPreviousAndNextKey: true @@ -594,7 +584,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.homeBar.push(this._register(new ActivityAction({ id: 'workbench.actions.home', - name: nls.localize('home', "Home"), + name: localize('home', "Home"), cssClass: icon.classNames }))); @@ -616,7 +606,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { throw new Error(`No view item for action '${action.id}'`); }, orientation: ActionsOrientation.VERTICAL, - ariaLabel: nls.localize('manage', "Manage"), + ariaLabel: localize('manage', "Manage"), animated: false, preventLoopNavigation: true, ignoreOrientationForPreviousAndNextKey: true @@ -624,15 +614,15 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.globalActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.manage', - name: nls.localize('manage', "Manage"), - cssClass: ThemeIcon.asClassName(settingsViewBarIcon) + name: localize('manage', "Manage"), + cssClass: ThemeIcon.asClassName(ActivitybarPart.GEAR_ICON) })); if (this.accountsVisibilityPreference) { this.accountsActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.accounts', - name: nls.localize('accounts', "Accounts"), - cssClass: ThemeIcon.asClassName(accountsViewBarIcon) + name: localize('accounts', "Accounts"), + cssClass: ThemeIcon.asClassName(ActivitybarPart.ACCOUNTS_ICON) })); this.globalActivityActionBar.push(this.accountsActivityAction, { index: ActivitybarPart.ACCOUNTS_ACTION_INDEX }); @@ -649,7 +639,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } else { this.accountsActivityAction = this._register(new ActivityAction({ id: 'workbench.actions.accounts', - name: nls.localize('accounts', "Accounts"), + name: localize('accounts', "Accounts"), cssClass: Codicon.account.classNames })); this.globalActivityActionBar.push(this.accountsActivityAction, { index: ActivitybarPart.ACCOUNTS_ACTION_INDEX }); @@ -1088,7 +1078,7 @@ class FocusActivityBarAction extends Action2 { constructor() { super({ id: 'workbench.action.focusActivityBar', - title: { value: nls.localize('focusActivityBar', "Focus Activity Bar"), original: 'Focus Activity Bar' }, + title: { value: localize('focusActivityBar', "Focus Activity Bar"), original: 'Focus Activity Bar' }, category: CATEGORIES.View, f1: true }); diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 97e2e8cf348..70d629fb2c0 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { Action, IAction } from 'vs/base/common/actions'; +import { IAction, toAction } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; import * as arrays from 'vs/base/common/arrays'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -149,10 +149,10 @@ export interface ICompositeBarOptions { readonly preventLoopNavigation?: boolean; getActivityAction: (compositeId: string) => ActivityAction; - getCompositePinnedAction: (compositeId: string) => Action; - getOnCompositeClickAction: (compositeId: string) => Action; + getCompositePinnedAction: (compositeId: string) => IAction; + getOnCompositeClickAction: (compositeId: string) => IAction; fillExtraContextMenuActions: (actions: IAction[]) => void; - getContextMenuActionsForComposite: (compositeId: string) => Action[]; + getContextMenuActionsForComposite: (compositeId: string) => IAction[]; openComposite: (compositeId: string) => Promise; getDefaultCompositeId: () => string; hidePart: () => void; @@ -208,15 +208,15 @@ export class CompositeBar extends Widget implements ICompositeBar { create(parent: HTMLElement): HTMLElement { const actionBarDiv = parent.appendChild($('.composite-bar')); this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, { - actionViewItemProvider: (action: IAction) => { + actionViewItemProvider: action => { if (action instanceof CompositeOverflowActivityAction) { return this.compositeOverflowActionViewItem; } const item = this.model.findItem(action.id); return item && this.instantiationService.createInstance( CompositeActionViewItem, action as ActivityAction, item.pinnedAction, - (compositeId: string) => this.options.getContextMenuActionsForComposite(compositeId), - () => this.getContextMenuActions() as Action[], + compositeId => this.options.getContextMenuActionsForComposite(compositeId), + () => this.getContextMenuActions(), this.options.colors, this.options.icon, this.options.dndHandler, @@ -596,7 +596,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this.compositeOverflowAction, () => this.getOverflowingComposites(), () => this.model.activeItem ? this.model.activeItem.id : undefined, - (compositeId: string) => { + compositeId => { const item = this.model.findItem(compositeId); return item?.activity[0]?.badge; }, @@ -633,7 +633,7 @@ export class CompositeBar extends Widget implements ICompositeBar { getContextMenuActions(): IAction[] { const actions: IAction[] = this.model.visibleItems - .map(({ id, name, activityAction }) => ({ + .map(({ id, name, activityAction }) => (toAction({ id, label: this.getAction(id).label || name || id, checked: this.isPinned(id), @@ -645,7 +645,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this.pin(id, true); } } - })); + }))); this.options.fillExtraContextMenuActions(actions); @@ -655,7 +655,7 @@ export class CompositeBar extends Widget implements ICompositeBar { interface ICompositeBarModelItem extends ICompositeBarItem { activityAction: ActivityAction; - pinnedAction: Action; + pinnedAction: IAction; activity: ICompositeActivity[]; } diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 3b37351b043..779b309c588 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { Action, Separator } from 'vs/base/common/actions'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; import * as dom from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { dispose, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; @@ -374,14 +374,14 @@ export class CompositeOverflowActivityAction extends ActivityAction { } export class CompositeOverflowActivityActionViewItem extends ActivityActionViewItem { - private actions: Action[] = []; + private actions: IAction[] = []; constructor( action: ActivityAction, private getOverflowingComposites: () => { id: string, name?: string }[], private getActiveCompositeId: () => string | undefined, private getBadge: (compositeId: string) => IBadge, - private getCompositeOpenAction: (compositeId: string) => Action, + private getCompositeOpenAction: (compositeId: string) => IAction, colors: (theme: IColorTheme) => ICompositeBarColors, @IContextMenuService private readonly contextMenuService: IContextMenuService, @IThemeService themeService: IThemeService @@ -404,7 +404,7 @@ export class CompositeOverflowActivityActionViewItem extends ActivityActionViewI }); } - private getActions(): Action[] { + private getActions(): IAction[] { return this.getOverflowingComposites().map(composite => { const action = this.getCompositeOpenAction(composite.id); action.checked = this.getActiveCompositeId() === action.id; @@ -457,9 +457,9 @@ export class CompositeActionViewItem extends ActivityActionViewItem { constructor( private compositeActivityAction: ActivityAction, - private toggleCompositePinnedAction: Action, - private compositeContextMenuActionsProvider: (compositeId: string) => ReadonlyArray, - private contextMenuActionsProvider: () => ReadonlyArray, + private toggleCompositePinnedAction: IAction, + private compositeContextMenuActionsProvider: (compositeId: string) => IAction[], + private contextMenuActionsProvider: () => IAction[], colors: (theme: IColorTheme) => ICompositeBarColors, icon: boolean, private dndHandler: ICompositeDragAndDrop, @@ -606,7 +606,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { } private showContextMenu(container: HTMLElement): void { - const actions: Action[] = [this.toggleCompositePinnedAction]; + const actions: IAction[] = [this.toggleCompositePinnedAction]; const compositeContextMenuActions = this.compositeContextMenuActionsProvider(this.activity.id); if (compositeContextMenuActions.length) { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 0da9015445f..1f2e0cb6e1f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -611,7 +611,7 @@ export class StatusbarPart extends Part implements IStatusbarService { } private getContextMenuActions(event: StandardMouseEvent): IAction[] { - const actions: Action[] = []; + const actions: IAction[] = []; // Provide an action to hide the status bar at last actions.push(this.instantiationService.createInstance(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, nls.localize('hideStatusBar', "Hide Status Bar"))); diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index ec837dc487e..0750bea24dc 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { isFunction, assertIsDefined } from 'vs/base/common/types'; import { isValidBasename } from 'vs/base/common/extpath'; import { basename } from 'vs/base/common/resources'; -import { Action } from 'vs/base/common/actions'; +import { toAction } from 'vs/base/common/actions'; import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -97,7 +97,7 @@ export class TextFileEditor extends BaseTextEditor { } getTitle(): string { - return this.input ? this.input.getName() : nls.localize('textFileEditor', "Text File Editor"); + return this.input ? this.input.getName() : localize('textFileEditor', "Text File Editor"); } get input(): FileEditorInput | undefined { @@ -169,22 +169,24 @@ export class TextFileEditor extends BaseTextEditor { if ((error).fileOperationResult === FileOperationResult.FILE_IS_DIRECTORY) { this.openAsFolder(input); - throw new Error(nls.localize('openFolderError', "File is a directory")); + throw new Error(localize('openFolderError', "File is a directory")); } // Offer to create a file from the error if we have a file not found and the name is valid if ((error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && isValidBasename(basename(input.preferredResource))) { throw createErrorWithActions(toErrorMessage(error), { actions: [ - new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), undefined, true, async () => { - await this.textFileService.create(input.preferredResource); + toAction({ + id: 'workbench.files.action.createMissingFile', label: localize('createFile', "Create File"), run: async () => { + await this.textFileService.create(input.preferredResource); - return this.editorService.openEditor({ - resource: input.preferredResource, - options: { - pinned: true // new file gets pinned by default - } - }); + return this.editorService.openEditor({ + resource: input.preferredResource, + options: { + pinned: true // new file gets pinned by default + } + }); + } }) ] }); diff --git a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index d310e987250..145efa74298 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { EditorOptions } from 'vs/workbench/common/editor'; import { FileOperationError, FileOperationResult, IFileService, MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files'; import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; -import { Action } from 'vs/base/common/actions'; +import { toAction } from 'vs/base/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -56,18 +56,22 @@ export class NativeTextFileEditor extends TextFileEditor { if ((error).fileOperationResult === FileOperationResult.FILE_EXCEEDS_MEMORY_LIMIT) { const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.textResourceConfigurationService.getValue(undefined, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB); - throw createErrorWithActions(nls.localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart and allow it to use more memory"), { + throw createErrorWithActions(localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart and allow it to use more memory"), { actions: [ - new Action('workbench.window.action.relaunchWithIncreasedMemoryLimit', nls.localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), undefined, true, () => { - return this.nativeHostService.relaunch({ - addArgs: [ - `--max-memory=${memoryLimit}` - ] - }); + toAction({ + id: 'workbench.window.action.relaunchWithIncreasedMemoryLimit', label: localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), run: () => { + return this.nativeHostService.relaunch({ + addArgs: [ + `--max-memory=${memoryLimit}` + ] + }); + } + }), + toAction({ + id: 'workbench.window.action.configureMemoryLimit', label: localize('configureMemoryLimit', 'Configure Memory Limit'), run: () => { + return this.preferencesService.openGlobalSettings(undefined, { query: 'files.maxMemoryForLargeFilesMB' }); + } }), - new Action('workbench.window.action.configureMemoryLimit', nls.localize('configureMemoryLimit', 'Configure Memory Limit'), undefined, true, () => { - return this.preferencesService.openGlobalSettings(undefined, { query: 'files.maxMemoryForLargeFilesMB' }); - }) ] }); } From b90166177bf32161122720a389b6f7e54dafb71b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 12 Jan 2021 11:18:17 +0100 Subject: [PATCH 1827/1837] reuse stats collector for EchoRunner, fix missing titlePath-property, fixes https://github.com/microsoft/vscode/issues/114190 --- test/unit/browser/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit/browser/index.js b/test/unit/browser/index.js index 1b888a2ec41..47605017941 100644 --- a/test/unit/browser/index.js +++ b/test/unit/browser/index.js @@ -7,9 +7,9 @@ const path = require('path'); const glob = require('glob'); -const fs = require('fs'); const events = require('events'); const mocha = require('mocha'); +const createStatsCollector = require('../../../node_modules/mocha/lib/stats-collector'); const MochaJUnitReporter = require('mocha-junit-reporter'); const url = require('url'); const minimatch = require('minimatch'); @@ -186,6 +186,7 @@ class EchoRunner extends events.EventEmitter { constructor(event, title = '') { super(); + createStatsCollector(this); event.on('start', () => this.emit('start')); event.on('end', () => this.emit('end')); event.on('suite', (suite) => this.emit('suite', EchoRunner.deserializeSuite(suite, title))); @@ -218,6 +219,7 @@ class EchoRunner extends events.EventEmitter { return { title: runnable.title, fullTitle: () => titleExtra && runnable.fullTitle ? `${runnable.fullTitle} - /${titleExtra}/` : runnable.fullTitle, + titlePath: () => runnable.titlePath, async: runnable.async, slow: () => runnable.slow, speed: runnable.speed, From 4b3ab7048fc57854e4955161058152e9c89ed43e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 11:26:12 +0100 Subject: [PATCH 1828/1837] :lipstick: --- src/vs/workbench/browser/parts/panel/panelPart.ts | 8 ++++---- src/vs/workbench/browser/parts/sidebar/sidebarPart.ts | 3 +-- src/vs/workbench/browser/parts/titlebar/titlebarPart.ts | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 11c565b543c..0ebf3f2bf86 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/panelpart'; -import { IAction, Action, Separator } from 'vs/base/common/actions'; +import { localize } from 'vs/nls'; +import { IAction, Separator } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -27,7 +28,6 @@ import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/composit import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Dimension, trackFocus, EventHelper } from 'vs/base/browser/dom'; -import { localize } from 'vs/nls'; import { IDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; @@ -163,7 +163,7 @@ export class PanelPart extends CompositePart implements IPanelService { this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel")) ]); }, - getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId) as Action[], + getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId), getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(), hidePart: () => this.layoutService.setPanelHidden(true), dndHandler: this.dndHandler, @@ -189,7 +189,7 @@ export class PanelPart extends CompositePart implements IPanelService { } private readonly panelContextMenuActionsDisposable = this._register(new MutableDisposable()); - private getContextMenuActionsForComposite(compositeId: string): readonly IAction[] { + private getContextMenuActionsForComposite(compositeId: string): IAction[] { const result: IAction[] = []; const scopedContextKeyService = this.contextKeyService.createScoped(); scopedContextKeyService.createKey('viewContainer', compositeId); diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index f42d5779d17..671a05822eb 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -6,7 +6,6 @@ import 'vs/css!./media/sidebarpart'; import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Action } from 'vs/base/common/actions'; import { CompositePart } from 'vs/workbench/browser/parts/compositePart'; import { Viewlet, ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; @@ -289,7 +288,7 @@ export class SidebarPart extends CompositePart implements IViewletServi this.contextMenuService.showContextMenu({ getAnchor: () => anchor, getActions: () => contextMenuActions.slice(), - getActionViewItem: action => this.actionViewItemProvider(action as Action), + getActionViewItem: action => this.actionViewItemProvider(action), actionRunner: activeViewlet.getActionRunner() }); } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 6138e52930a..d443d4895ea 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/titlebarpart'; +import { localize } from 'vs/nls'; import { dirname, basename } from 'vs/base/common/resources'; import { Part } from 'vs/workbench/browser/part'; import { ITitleService, ITitleProperties } from 'vs/workbench/services/title/common/titleService'; @@ -15,7 +16,6 @@ import { IAction } from 'vs/base/common/actions'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; -import * as nls from 'vs/nls'; import { EditorResourceAccessor, Verbosity, SideBySideEditor } from 'vs/workbench/common/editor'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -44,9 +44,9 @@ import { withNullAsUndefined } from 'vs/base/common/types'; export class TitlebarPart extends Part implements ITitleService { - private static readonly NLS_UNSUPPORTED = nls.localize('patchedWindowTitle', "[Unsupported]"); - private static readonly NLS_USER_IS_ADMIN = isWindows ? nls.localize('userIsAdmin', "[Administrator]") : nls.localize('userIsSudo', "[Superuser]"); - private static readonly NLS_EXTENSION_HOST = nls.localize('devExtensionWindowTitlePrefix', "[Extension Development Host]"); + private static readonly NLS_UNSUPPORTED = localize('patchedWindowTitle', "[Unsupported]"); + private static readonly NLS_USER_IS_ADMIN = isWindows ? localize('userIsAdmin', "[Administrator]") : localize('userIsSudo', "[Superuser]"); + private static readonly NLS_EXTENSION_HOST = localize('devExtensionWindowTitlePrefix', "[Extension Development Host]"); private static readonly TITLE_DIRTY = '\u25cf '; //#region IView From 22bd999e86b0b976f58303b93ee8f757a651fbf3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 11:37:25 +0100 Subject: [PATCH 1829/1837] debt - use provider extUri in file service //cc @aeschli --- src/vs/platform/files/common/fileService.ts | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index b500e925155..70117342fe6 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -3,12 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; +import { mark } from 'vs/base/common/performance'; import { Disposable, IDisposable, toDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { IFileService, IResolveFileOptions, FileChangesEvent, FileOperationEvent, IFileSystemProviderRegistrationEvent, IFileSystemProvider, IFileStat, IResolveFileResult, ICreateFileOptions, IFileSystemProviderActivationEvent, FileOperationError, FileOperationResult, FileOperation, FileSystemProviderCapabilities, FileType, toFileSystemProviderErrorCode, FileSystemProviderErrorCode, IStat, IFileStatWithMetadata, IResolveMetadataFileOptions, etag, hasReadWriteCapability, hasFileFolderCopyCapability, hasOpenReadWriteCloseCapability, toFileOperationResult, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadWriteCapability, IResolveFileResultWithMetadata, IWatchOptions, IWriteFileOptions, IReadFileOptions, IFileStreamContent, IFileContent, ETAG_DISABLED, hasFileReadStreamCapability, IFileSystemProviderWithFileReadStreamCapability, ensureFileSystemProviderError, IFileSystemProviderCapabilitiesChangeEvent } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; -import { isAbsolutePath, dirname, basename, joinPath, IExtUri, extUri, extUriIgnorePathCase } from 'vs/base/common/resources'; -import { localize } from 'vs/nls'; +import { IExtUri, extUri, extUriIgnorePathCase, isAbsolutePath } from 'vs/base/common/resources'; import { TernarySearchTree } from 'vs/base/common/map'; import { isNonEmptyArray, coalesce } from 'vs/base/common/arrays'; import { ILogService } from 'vs/platform/log/common/log'; @@ -19,7 +20,6 @@ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cance import { Schemas } from 'vs/base/common/network'; import { readFileIntoStream } from 'vs/platform/files/common/io'; import { Iterable } from 'vs/base/common/iterator'; -import * as perf from 'vs/base/common/performance'; export class FileService extends Disposable implements IFileService { @@ -49,7 +49,7 @@ export class FileService extends Disposable implements IFileService { throw new Error(`A filesystem provider for the scheme '${scheme}' is already registered.`); } - perf.mark(`code/registerFilesystem/${scheme}`); + mark(`code/registerFilesystem/${scheme}`); // Add provider with event this.provider.set(scheme, provider); @@ -104,7 +104,7 @@ export class FileService extends Disposable implements IFileService { return !!(provider && (provider.capabilities & capability)); } - listCapabilities(): Iterable<{ scheme: string, capabilities: FileSystemProviderCapabilities }> { + listCapabilities(): Iterable<{ scheme: string, capabilities: FileSystemProviderCapabilities; }> { return Iterable.map(this.provider, ([scheme, provider]) => ({ scheme, capabilities: provider.capabilities })); } @@ -217,14 +217,15 @@ export class FileService extends Disposable implements IFileService { }); } - private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat | { type: FileType } & Partial, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise; + private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat | { type: FileType; } & Partial, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise; private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat, siblings: number | undefined, resolveMetadata: true, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise; - private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat | { type: FileType } & Partial, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise { + private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat | { type: FileType; } & Partial, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise { + const { providerExtUri } = this.getExtUri(provider); // convert to file stat const fileStat: IFileStat = { resource, - name: basename(resource), + name: providerExtUri.basename(resource), isFile: (stat.type & FileType.File) !== 0, isDirectory: (stat.type & FileType.Directory) !== 0, isSymbolicLink: (stat.type & FileType.SymbolicLink) !== 0, @@ -240,7 +241,7 @@ export class FileService extends Disposable implements IFileService { const entries = await provider.readdir(resource); const resolvedEntries = await Promise.all(entries.map(async ([name, type]) => { try { - const childResource = joinPath(resource, name); + const childResource = providerExtUri.joinPath(resource, name); const childStat = resolveMetadata ? await provider.stat(childResource) : { type }; return await this.toFileStat(provider, childResource, childStat, entries.length, resolveMetadata, recurse); @@ -265,8 +266,8 @@ export class FileService extends Disposable implements IFileService { return fileStat; } - async resolveAll(toResolve: { resource: URI, options?: IResolveFileOptions }[]): Promise; - async resolveAll(toResolve: { resource: URI, options: IResolveMetadataFileOptions }[]): Promise; + async resolveAll(toResolve: { resource: URI, options?: IResolveFileOptions; }[]): Promise; + async resolveAll(toResolve: { resource: URI, options: IResolveMetadataFileOptions; }[]): Promise; async resolveAll(toResolve: { resource: URI; options?: IResolveFileOptions; }[]): Promise { return Promise.all(toResolve.map(async entry => { try { @@ -329,6 +330,7 @@ export class FileService extends Disposable implements IFileService { async writeFile(resource: URI, bufferOrReadableOrStream: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: IWriteFileOptions): Promise { const provider = this.throwIfFileSystemIsReadonly(await this.withWriteProvider(resource), resource); + const { providerExtUri } = this.getExtUri(provider); try { @@ -337,7 +339,7 @@ export class FileService extends Disposable implements IFileService { // mkdir recursively as needed if (!stat) { - await this.mkdirp(provider, dirname(resource)); + await this.mkdirp(provider, providerExtUri.dirname(resource)); } // optimization: if the provider has unbuffered write capability and the data @@ -437,7 +439,7 @@ export class FileService extends Disposable implements IFileService { return this.doReadAsFileStream(provider, resource, options); } - private async doReadAsFileStream(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions & { preferUnbuffered?: boolean }): Promise { + private async doReadAsFileStream(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions & { preferUnbuffered?: boolean; }): Promise { // install a cancellation token that gets cancelled // when any error occurs. this allows us to resolve @@ -636,7 +638,7 @@ export class FileService extends Disposable implements IFileService { } // create parent folders - await this.mkdirp(targetProvider, dirname(target)); + await this.mkdirp(targetProvider, this.getExtUri(targetProvider).providerExtUri.dirname(target)); // copy source => target if (mode === 'copy') { @@ -712,7 +714,7 @@ export class FileService extends Disposable implements IFileService { // create children in target if (Array.isArray(sourceFolder.children)) { await Promise.all(sourceFolder.children.map(async sourceChild => { - const targetChild = joinPath(targetFolder, sourceChild.name); + const targetChild = this.getExtUri(targetProvider).providerExtUri.joinPath(targetFolder, sourceChild.name); if (sourceChild.isDirectory) { return this.doCopyFolder(sourceProvider, await this.resolve(sourceChild.resource), targetProvider, targetChild); } else { @@ -722,7 +724,7 @@ export class FileService extends Disposable implements IFileService { } } - private async doValidateMoveCopy(sourceProvider: IFileSystemProvider, source: URI, targetProvider: IFileSystemProvider, target: URI, mode: 'move' | 'copy', overwrite?: boolean): Promise<{ exists: boolean, isSameResourceWithDifferentPathCase: boolean }> { + private async doValidateMoveCopy(sourceProvider: IFileSystemProvider, source: URI, targetProvider: IFileSystemProvider, target: URI, mode: 'move' | 'copy', overwrite?: boolean): Promise<{ exists: boolean, isSameResourceWithDifferentPathCase: boolean; }> { let isSameResourceWithDifferentPathCase = false; // Check if source is equal or parent to target (requires providers to be the same) @@ -763,7 +765,7 @@ export class FileService extends Disposable implements IFileService { return { exists, isSameResourceWithDifferentPathCase }; } - private getExtUri(provider: IFileSystemProvider): { providerExtUri: IExtUri, isPathCaseSensitive: boolean } { + private getExtUri(provider: IFileSystemProvider): { providerExtUri: IExtUri, isPathCaseSensitive: boolean; } { const isPathCaseSensitive = this.isPathCaseSensitive(provider); return { @@ -794,7 +796,7 @@ export class FileService extends Disposable implements IFileService { // mkdir until we reach root const { providerExtUri } = this.getExtUri(provider); - while (!providerExtUri.isEqual(directory, dirname(directory))) { + while (!providerExtUri.isEqual(directory, providerExtUri.dirname(directory))) { try { const stat = await provider.stat(directory); if ((stat.type & FileType.Directory) === 0) { @@ -810,16 +812,16 @@ export class FileService extends Disposable implements IFileService { } // Upon error, remember directories that need to be created - directoriesToCreate.push(basename(directory)); + directoriesToCreate.push(providerExtUri.basename(directory)); // Continue up - directory = dirname(directory); + directory = providerExtUri.dirname(directory); } } // Create directories as needed for (let i = directoriesToCreate.length - 1; i >= 0; i--) { - directory = joinPath(directory, directoriesToCreate[i]); + directory = providerExtUri.joinPath(directory, directoriesToCreate[i]); try { await provider.mkdir(directory); @@ -896,7 +898,7 @@ export class FileService extends Disposable implements IFileService { private readonly _onDidFilesChange = this._register(new Emitter()); readonly onDidFilesChange = this._onDidFilesChange.event; - private readonly activeWatchers = new Map(); + private readonly activeWatchers = new Map(); watch(resource: URI, options: IWatchOptions = { recursive: false, excludes: [] }): IDisposable { let watchDisposed = false; From e500f76d9cc3ee3da1b3e24e7aec98b3eeb20ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 12 Jan 2021 11:49:52 +0100 Subject: [PATCH 1830/1837] remove test dependency on theme extensions --- .../test/electron-browser/color-theme.json | 50 +++++++ .../tokenStyleResolving.test.ts | 128 ++---------------- 2 files changed, 62 insertions(+), 116 deletions(-) create mode 100644 src/vs/workbench/services/themes/test/electron-browser/color-theme.json diff --git a/src/vs/workbench/services/themes/test/electron-browser/color-theme.json b/src/vs/workbench/services/themes/test/electron-browser/color-theme.json new file mode 100644 index 00000000000..fc9f7098c44 --- /dev/null +++ b/src/vs/workbench/services/themes/test/electron-browser/color-theme.json @@ -0,0 +1,50 @@ +{ + "type": "dark", + "tokenColors": [ + { + "scope": "comment", + "settings": { + "foreground": "#000000" + } + }, + { + "scope": "string", + "settings": { + "foreground": "#444444" + } + }, + { + "scope": "constant.numeric", + "settings": { + "foreground": "#555555" + } + }, + { + "scope": "variable", + "settings": { + "fontStyle": "", + "foreground": "#111111" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#666666" + } + }, + { + "scope": "entity.name.type, entity.name.class, entity.name.namespace, entity.name.scope-resolution", + "settings": { + "fontStyle": "underline", + "foreground": "#333333" + } + }, + { + "scope": "entity.name.function", + "settings": { + "fontStyle": "", + "foreground": "#333333" + } + } + ] +} diff --git a/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts b/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts index 07d9b97cbb6..581739b7e4c 100644 --- a/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts +++ b/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts @@ -12,16 +12,14 @@ import { isString } from 'vs/base/common/types'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; -import { Schemas } from 'vs/base/common/network'; -import { URI } from 'vs/base/common/uri'; -import { getPathFromAmdModule } from 'vs/base/common/amd'; +import { FileAccess, Schemas } from 'vs/base/common/network'; import { ExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/electron-sandbox/extensionResourceLoaderService'; import { ITokenStyle } from 'vs/platform/theme/common/themeService'; const undefinedStyle = { bold: undefined, underline: undefined, italic: undefined }; const unsetStyle = { bold: false, underline: false, italic: false }; -function ts(foreground: string | undefined, styleFlags: { bold?: boolean; underline?: boolean; italic?: boolean } | undefined): TokenStyle { +function ts(foreground: string | undefined, styleFlags: { bold?: boolean; underline?: boolean; italic?: boolean; } | undefined): TokenStyle { const foregroundColor = isString(foreground) ? Color.fromHex(foreground) : undefined; return new TokenStyle(foregroundColor, styleFlags && styleFlags.bold, styleFlags && styleFlags.underline, styleFlags && styleFlags.italic); } @@ -65,7 +63,7 @@ function assertTokenStyleMetaData(colorIndex: string[], actual: ITokenStyle | un } -function assertTokenStyles(themeData: ColorThemeData, expected: { [qualifiedClassifier: string]: TokenStyle }, language = 'typescript') { +function assertTokenStyles(themeData: ColorThemeData, expected: { [qualifiedClassifier: string]: TokenStyle; }, language = 'typescript') { const colorIndex = themeData.tokenColorMap; for (let qualifiedClassifier in expected) { @@ -88,124 +86,22 @@ suite('Themes - TokenStyleResolving', () => { fileService.registerProvider(Schemas.file, diskFileSystemProvider); - test('color defaults - monokai', async () => { + test('color defaults', async () => { const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-monokai/themes/monokai-color-theme.json'); - themeData.location = URI.file(themeLocation); + themeData.location = FileAccess.asFileUri('./color-theme.json', require); await themeData.ensureLoaded(extensionResourceLoaderService); assert.equal(themeData.isLoaded, true); assertTokenStyles(themeData, { - 'comment': ts('#88846f', undefinedStyle), - 'variable': ts('#F8F8F2', unsetStyle), - 'type': ts('#A6E22E', { bold: false, underline: true, italic: false }), - 'function': ts('#A6E22E', unsetStyle), - 'string': ts('#E6DB74', undefinedStyle), - 'number': ts('#AE81FF', undefinedStyle), - 'keyword': ts('#F92672', undefinedStyle) + 'comment': ts('#000000', undefinedStyle), + 'variable': ts('#111111', unsetStyle), + 'type': ts('#333333', { bold: false, underline: true, italic: false }), + 'function': ts('#333333', unsetStyle), + 'string': ts('#444444', undefinedStyle), + 'number': ts('#555555', undefinedStyle), + 'keyword': ts('#666666', undefinedStyle) }); - - }); - - test('color defaults - dark+', async () => { - const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-defaults/themes/dark_plus.json'); - themeData.location = URI.file(themeLocation); - await themeData.ensureLoaded(extensionResourceLoaderService); - - assert.equal(themeData.isLoaded, true); - - assertTokenStyles(themeData, { - 'comment': ts('#6A9955', undefinedStyle), - 'variable': ts('#9CDCFE', undefinedStyle), - 'type': ts('#4EC9B0', undefinedStyle), - 'function': ts('#DCDCAA', undefinedStyle), - 'string': ts('#CE9178', undefinedStyle), - 'number': ts('#B5CEA8', undefinedStyle), - 'keyword': ts('#C586C0', undefinedStyle) - }); - - }); - - test('color defaults - light vs', async () => { - const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-defaults/themes/light_vs.json'); - themeData.location = URI.file(themeLocation); - await themeData.ensureLoaded(extensionResourceLoaderService); - - assert.equal(themeData.isLoaded, true); - - assertTokenStyles(themeData, { - 'comment': ts('#008000', undefinedStyle), - 'variable': ts(undefined, undefinedStyle), - 'type': ts(undefined, undefinedStyle), - 'function': ts(undefined, undefinedStyle), - 'string': ts('#a31515', undefinedStyle), - 'number': ts('#098658', undefinedStyle), - 'keyword': ts('#0000ff', undefinedStyle) - }); - - }); - - test('color defaults - hc', async () => { - const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-defaults/themes/hc_black.json'); - themeData.location = URI.file(themeLocation); - await themeData.ensureLoaded(extensionResourceLoaderService); - - assert.equal(themeData.isLoaded, true); - - assertTokenStyles(themeData, { - 'comment': ts('#7ca668', undefinedStyle), - 'variable': ts('#9CDCFE', undefinedStyle), - 'type': ts('#4EC9B0', undefinedStyle), - 'function': ts('#DCDCAA', undefinedStyle), - 'string': ts('#ce9178', undefinedStyle), - 'number': ts('#b5cea8', undefinedStyle), - 'keyword': ts('#C586C0', undefinedStyle) - }); - - }); - - test('color defaults - kimbie dark', async () => { - const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json'); - themeData.location = URI.file(themeLocation); - await themeData.ensureLoaded(extensionResourceLoaderService); - - assert.equal(themeData.isLoaded, true); - - assertTokenStyles(themeData, { - 'comment': ts('#a57a4c', undefinedStyle), - 'variable': ts('#dc3958', undefinedStyle), - 'type': ts('#f06431', undefinedStyle), - 'function': ts('#8ab1b0', undefinedStyle), - 'string': ts('#889b4a', undefinedStyle), - 'number': ts('#f79a32', undefinedStyle), - 'keyword': ts('#98676a', undefinedStyle) - }); - - }); - - test('color defaults - abyss', async () => { - const themeData = ColorThemeData.createUnloadedTheme('foo'); - const themeLocation = getPathFromAmdModule(require, '../../../../../../../extensions/theme-abyss/themes/abyss-color-theme.json'); - themeData.location = URI.file(themeLocation); - await themeData.ensureLoaded(extensionResourceLoaderService); - - assert.equal(themeData.isLoaded, true); - - assertTokenStyles(themeData, { - 'comment': ts('#384887', undefinedStyle), - 'variable': ts(undefined, unsetStyle), - 'type': ts('#ffeebb', { underline: true, bold: false, italic: false }), - 'function': ts('#ddbb88', unsetStyle), - 'string': ts('#22aa44', undefinedStyle), - 'number': ts('#f280d0', undefinedStyle), - 'keyword': ts('#225588', undefinedStyle) - }); - }); test('resolveScopes', async () => { From 05c4659e0967106a397a1f1538008aa5179c599f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 12 Jan 2021 11:58:57 +0100 Subject: [PATCH 1831/1837] use PerformanceObserver in node's perf-util --- src/vs/base/common/performance.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index ac8c2cdb714..842d3da1be0 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -72,11 +72,32 @@ function _define() { } } else if (typeof process === 'object') { - // node.js: use the normal polyfill but add the timeOrigin - // from the node perf_hooks API as very first mark - const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin); - return _definePolyfillMarks(timeOrigin); + // node.js: use "node-native" performance for mark() + // and setup a PerformanceObserver for getMarks() + const { performance, PerformanceObserver } = (require.nodeRequire || require)('perf_hooks'); + const marks = []; + const obs = new PerformanceObserver(list => { marks.push(list.getEntries()); }); + obs.observe({ entryTypes: ['mark'], buffered: true }); + + return { + mark(name) { + performance.mark(name); + }, + getMarks() { + const timeOrigin = performance.timeOrigin; + const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; + for (const array of marks) { + for (const entry of array) { + result.push({ + name: entry.name, + startTime: Math.round(timeOrigin + entry.startTime) + }); + } + } + return result; + } + }; } else { // unknown environment console.trace('perf-util loaded in UNKNOWN environment'); From 4816a253eaac7306ca2ec18e80a23dfdc31fb0a1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 12 Jan 2021 12:03:27 +0100 Subject: [PATCH 1832/1837] Revert "use PerformanceObserver in node's perf-util" This reverts commit 05c4659e0967106a397a1f1538008aa5179c599f. --- src/vs/base/common/performance.js | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 842d3da1be0..ac8c2cdb714 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -72,32 +72,11 @@ function _define() { } } else if (typeof process === 'object') { - // node.js: use "node-native" performance for mark() - // and setup a PerformanceObserver for getMarks() - const { performance, PerformanceObserver } = (require.nodeRequire || require)('perf_hooks'); + // node.js: use the normal polyfill but add the timeOrigin + // from the node perf_hooks API as very first mark + const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin); + return _definePolyfillMarks(timeOrigin); - const marks = []; - const obs = new PerformanceObserver(list => { marks.push(list.getEntries()); }); - obs.observe({ entryTypes: ['mark'], buffered: true }); - - return { - mark(name) { - performance.mark(name); - }, - getMarks() { - const timeOrigin = performance.timeOrigin; - const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; - for (const array of marks) { - for (const entry of array) { - result.push({ - name: entry.name, - startTime: Math.round(timeOrigin + entry.startTime) - }); - } - } - return result; - } - }; } else { // unknown environment console.trace('perf-util loaded in UNKNOWN environment'); From 675638196d27275f1daf688a2a4a71e70f68cd78 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Jan 2021 12:26:35 +0100 Subject: [PATCH 1833/1837] debt - remove duplicate drive letter implementations //cc @aeschli --- src/vs/base/common/extpath.ts | 17 +++++++++-- src/vs/base/common/labels.ts | 29 +++++------------- src/vs/base/test/common/extpath.test.ts | 30 ++++++++++++++++++- .../workbench/contrib/debug/node/terminals.ts | 6 ++-- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/vs/base/common/extpath.ts b/src/vs/base/common/extpath.ts index ad10163e752..40fd732e974 100644 --- a/src/vs/base/common/extpath.ts +++ b/src/vs/base/common/extpath.ts @@ -277,14 +277,25 @@ export function isRootOrDriveLetter(path: string): boolean { return false; } - return isWindowsDriveLetter(pathNormalized.charCodeAt(0)) - && pathNormalized.charCodeAt(1) === CharCode.Colon - && (path.length === 2 || pathNormalized.charCodeAt(2) === CharCode.Backslash); + return hasDriveLetter(pathNormalized) && + (path.length === 2 || pathNormalized.charCodeAt(2) === CharCode.Backslash); } return pathNormalized === posix.sep; } +export function hasDriveLetter(path: string): boolean { + if (isWindows) { + return isWindowsDriveLetter(path.charCodeAt(0)) && path.charCodeAt(1) === CharCode.Colon; + } + + return false; +} + +export function getDriveLetter(path: string): string | undefined { + return hasDriveLetter(path) ? path[0] : undefined; +} + export function indexOfPath(path: string, candidate: string, ignoreCase?: boolean): number { if (candidate.length > path.length) { return -1; diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 3d96a0cec19..a7645ba7ebc 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -9,11 +9,12 @@ import { startsWithIgnoreCase, rtrim } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform'; import { isEqual, basename, relativePath } from 'vs/base/common/resources'; +import { hasDriveLetter, isRootOrDriveLetter } from 'vs/base/common/extpath'; export interface IWorkspaceFolderProvider { - getWorkspaceFolder(resource: URI): { uri: URI, name?: string } | null; + getWorkspaceFolder(resource: URI): { uri: URI, name?: string; } | null; getWorkspace(): { - folders: { uri: URI, name?: string }[]; + folders: { uri: URI, name?: string; }[]; }; } @@ -84,27 +85,13 @@ export function getBaseLabel(resource: URI | string | undefined): string | undef const base = basename(resource) || (resource.scheme === Schemas.file ? resource.fsPath : resource.path) /* can be empty string if '/' is passed in */; // convert c: => C: - if (isDriveLetter(base)) { + if (isWindows && isRootOrDriveLetter(base)) { return normalizeDriveLetter(base); } return base; } -const WINDOWS_DRIVE_LETTER_SEP = ':'; - -function hasDriveLetter(path: string): boolean { - return !!(isWindows && path && path[1] === WINDOWS_DRIVE_LETTER_SEP); -} - -function isDriveLetter(path: string): boolean { - return hasDriveLetter(path) && path.endsWith(WINDOWS_DRIVE_LETTER_SEP); -} - -export function extractDriveLetter(path: string): string | undefined { - return hasDriveLetter(path) ? path[0] : undefined; -} - export function normalizeDriveLetter(path: string): string { if (hasDriveLetter(path)) { return path.charAt(0).toUpperCase() + path.slice(1); @@ -113,7 +100,7 @@ export function normalizeDriveLetter(path: string): string { return path; } -let normalizedUserHomeCached: { original: string; normalized: string } = Object.create(null); +let normalizedUserHomeCached: { original: string; normalized: string; } = Object.create(null); export function tildify(path: string, userHome: string): string { if (isWindows || !path || !userHome) { return path; // unsupported @@ -231,7 +218,7 @@ export function shorten(paths: string[], pathSeparator: string = sep): string[] let result = ''; // preserve disk drive or root prefix - if (segments[0].endsWith(WINDOWS_DRIVE_LETTER_SEP) || prefix !== '') { + if (segments[0].endsWith(':') || prefix !== '') { if (start === 1) { // extend subpath to include disk drive prefix start = 0; @@ -292,7 +279,7 @@ interface ISegment { * @param value string to which templating is applied * @param values the values of the templates to use */ -export function template(template: string, values: { [key: string]: string | ISeparator | undefined | null } = Object.create(null)): string { +export function template(template: string, values: { [key: string]: string | ISeparator | undefined | null; } = Object.create(null)): string { const segments: ISegment[] = []; let inVariable = false; @@ -396,7 +383,7 @@ export function unmnemonicLabel(label: string): string { /** * Splits a path in name and parent path, supporting both '/' and '\' */ -export function splitName(fullPath: string): { name: string, parentPath: string } { +export function splitName(fullPath: string): { name: string, parentPath: string; } { const p = fullPath.indexOf('/') !== -1 ? posix : win32; const name = p.basename(fullPath); const parentPath = p.dirname(fullPath); diff --git a/src/vs/base/test/common/extpath.test.ts b/src/vs/base/test/common/extpath.test.ts index e90c5d7e78c..26e5f98f588 100644 --- a/src/vs/base/test/common/extpath.test.ts +++ b/src/vs/base/test/common/extpath.test.ts @@ -107,7 +107,7 @@ suite('Paths', () => { } }); - test('isRoot', () => { + test('isRootOrDriveLetter', () => { if (platform.isWindows) { assert.ok(extpath.isRootOrDriveLetter('c:')); assert.ok(extpath.isRootOrDriveLetter('D:')); @@ -121,6 +121,34 @@ suite('Paths', () => { } }); + test('hasDriveLetter', () => { + if (platform.isWindows) { + assert.ok(extpath.hasDriveLetter('c:')); + assert.ok(extpath.hasDriveLetter('D:')); + assert.ok(extpath.hasDriveLetter('D:/')); + assert.ok(extpath.hasDriveLetter('D:\\')); + assert.ok(extpath.hasDriveLetter('D:\\path')); + assert.ok(extpath.hasDriveLetter('D:/path')); + } else { + assert.ok(!extpath.hasDriveLetter('/')); + assert.ok(!extpath.hasDriveLetter('/path')); + } + }); + + test('getDriveLetter', () => { + if (platform.isWindows) { + assert.equal(extpath.getDriveLetter('c:'), 'c'); + assert.equal(extpath.getDriveLetter('D:'), 'D'); + assert.equal(extpath.getDriveLetter('D:/'), 'D'); + assert.equal(extpath.getDriveLetter('D:\\'), 'D'); + assert.equal(extpath.getDriveLetter('D:\\path'), 'D'); + assert.equal(extpath.getDriveLetter('D:/path'), 'D'); + } else { + assert.ok(!extpath.getDriveLetter('/')); + assert.ok(!extpath.getDriveLetter('/path')); + } + }); + test('isWindowsDriveLetter', () => { assert.ok(!extpath.isWindowsDriveLetter(0)); assert.ok(!extpath.isWindowsDriveLetter(-1)); diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index 45a8fc65452..03c4fc8f6c5 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -9,7 +9,7 @@ import { WindowsExternalTerminalService, MacExternalTerminalService, LinuxExtern import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IExternalTerminalService } from 'vs/workbench/contrib/externalTerminal/common/externalTerminal'; import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration'; -import { extractDriveLetter } from 'vs/base/common/labels'; +import { getDriveLetter } from 'vs/base/common/extpath'; let externalTerminalService: IExternalTerminalService | undefined = undefined; @@ -112,7 +112,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? }; if (cwd) { - const driveLetter = extractDriveLetter(cwd); + const driveLetter = getDriveLetter(cwd); if (driveLetter) { command += `${driveLetter}:; `; } @@ -145,7 +145,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env? }; if (cwd) { - const driveLetter = extractDriveLetter(cwd); + const driveLetter = getDriveLetter(cwd); if (driveLetter) { command += `${driveLetter}: && `; } From 868271067e6a83d6d7355396ab6d07c59a2c73ae Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 12 Jan 2021 12:43:49 +0100 Subject: [PATCH 1834/1837] filter perf marks that don't start with 'code/' --- .../services/timer/browser/timerService.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/timer/browser/timerService.ts b/src/vs/workbench/services/timer/browser/timerService.ts index 961e0b7218c..f4bc25a6066 100644 --- a/src/vs/workbench/services/timer/browser/timerService.ts +++ b/src/vs/workbench/services/timer/browser/timerService.ts @@ -439,7 +439,9 @@ export abstract class AbstractTimerService implements ITimerService { } setPerformanceMarks(source: string, marks: perf.PerformanceMark[]): void { - this._marks.setMarks(source, marks); + // Perf marks are a shared resource because anyone can generate them + // and because of that we only accept marks that start with 'code/' + this._marks.setMarks(source, marks.filter(mark => mark.name.startsWith('code/'))); } getPerformanceMarks(): [source: string, marks: readonly perf.PerformanceMark[]][] { @@ -462,12 +464,12 @@ export abstract class AbstractTimerService implements ITimerService { // event and it is "normalized" to a relative timestamp where the first mark // defines the start for (const [source, marks] of this.getPerformanceMarks()) { - type Mark = { source: string; name: string; relativeStartTime: number; startTime: number }; + type Mark = { source: string; name: string; relativeStartTime: number; startTime: number; }; type MarkClassification = { - source: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }, - name: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }, - relativeStartTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }, - startTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }, + source: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth'; }, + name: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth'; }, + relativeStartTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true; }, + startTime: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true; }, }; let lastMark: perf.PerformanceMark = marks[0]; From 3653f34dbabf3e551eb5e9aef3a73fea489a9585 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 12 Jan 2021 14:23:21 +0100 Subject: [PATCH 1835/1837] Do not instantiate hover widgets in the `onModelDecorationsChanged` event --- .../contrib/colorPicker/colorContributions.ts | 2 +- src/vs/editor/contrib/hover/hover.ts | 73 +++++++++---------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/vs/editor/contrib/colorPicker/colorContributions.ts b/src/vs/editor/contrib/colorPicker/colorContributions.ts index 4a997061b43..90f91a846c1 100644 --- a/src/vs/editor/contrib/colorPicker/colorContributions.ts +++ b/src/vs/editor/contrib/colorPicker/colorContributions.ts @@ -47,7 +47,7 @@ export class ColorContribution extends Disposable implements IEditorContribution } const hoverController = this._editor.getContribution(ModesHoverController.ID); - if (!hoverController.contentWidget.isColorPickerVisible()) { + if (!hoverController.isColorPickerVisible()) { const range = new Range(mouseEvent.target.range.startLineNumber, mouseEvent.target.range.startColumn + 1, mouseEvent.target.range.endLineNumber, mouseEvent.target.range.endColumn + 1); hoverController.showContentHover(range, HoverStartMode.Delayed, false); } diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index 6bee7da5f9c..c84a2bbde87 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; @@ -34,22 +34,8 @@ export class ModesHoverController implements IEditorContribution { private readonly _toUnhook = new DisposableStore(); private readonly _didChangeConfigurationHandler: IDisposable; - private readonly _contentWidget = new MutableDisposable(); - private readonly _glyphWidget = new MutableDisposable(); - - get contentWidget(): ModesContentHoverWidget { - if (!this._contentWidget.value) { - this._createHoverWidgets(); - } - return this._contentWidget.value!; - } - - get glyphWidget(): ModesGlyphHoverWidget { - if (!this._glyphWidget.value) { - this._createHoverWidgets(); - } - return this._glyphWidget.value!; - } + private _contentWidget: ModesContentHoverWidget | null; + private _glyphWidget: ModesGlyphHoverWidget | null; private _isMouseDown: boolean; private _hoverClicked: boolean; @@ -71,6 +57,8 @@ export class ModesHoverController implements IEditorContribution { ) { this._isMouseDown = false; this._hoverClicked = false; + this._contentWidget = null; + this._glyphWidget = null; this._hookEvents(); @@ -111,8 +99,8 @@ export class ModesHoverController implements IEditorContribution { } private _onModelDecorationsChanged(): void { - this.contentWidget.onModelDecorationsChanged(); - this.glyphWidget.onModelDecorationsChanged(); + this._contentWidget?.onModelDecorationsChanged(); + this._glyphWidget?.onModelDecorationsChanged(); } private _onEditorScrollChanged(e: IScrollEvent): void { @@ -151,7 +139,7 @@ export class ModesHoverController implements IEditorContribution { private _onEditorMouseMove(mouseEvent: IEditorMouseEvent): void { let targetType = mouseEvent.target.type; - if (this._isMouseDown && this._hoverClicked && this.contentWidget.isColorPickerVisible()) { + if (this._isMouseDown && this._hoverClicked && this._contentWidget?.isColorPickerVisible()) { return; } @@ -167,7 +155,7 @@ export class ModesHoverController implements IEditorContribution { if ( !this._isHoverSticky && targetType === MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === ModesContentHoverWidget.ID - && this._contentWidget.value?.isColorPickerVisible() + && this._contentWidget?.isColorPickerVisible() ) { // though the hover is not sticky, the color picker needs to. return; @@ -188,26 +176,31 @@ export class ModesHoverController implements IEditorContribution { } if (targetType === MouseTargetType.CONTENT_TEXT) { - this.glyphWidget.hide(); + this._glyphWidget?.hide(); if (this._isHoverEnabled && mouseEvent.target.range) { // TODO@rebornix. This should be removed if we move Color Picker out of Hover component. // Check if mouse is hovering on color decorator const hoverOnColorDecorator = [...mouseEvent.target.element?.classList.values() || []].find(className => className.startsWith('ced-colorBox')) && mouseEvent.target.range.endColumn - mouseEvent.target.range.startColumn === 1; - if (hoverOnColorDecorator) { - // shift the mouse focus by one as color decorator is a `before` decoration of next character. - this.contentWidget.startShowingAt(new Range(mouseEvent.target.range.startLineNumber, mouseEvent.target.range.startColumn + 1, mouseEvent.target.range.endLineNumber, mouseEvent.target.range.endColumn + 1), HoverStartMode.Delayed, false); - } else { - this.contentWidget.startShowingAt(mouseEvent.target.range, HoverStartMode.Delayed, false); + const showAtRange = ( + hoverOnColorDecorator // shift the mouse focus by one as color decorator is a `before` decoration of next character. + ? new Range(mouseEvent.target.range.startLineNumber, mouseEvent.target.range.startColumn + 1, mouseEvent.target.range.endLineNumber, mouseEvent.target.range.endColumn + 1) + : mouseEvent.target.range + ); + if (!this._contentWidget) { + this._contentWidget = new ModesContentHoverWidget(this._editor, this._hoverVisibleKey, this._instantiationService, this._themeService); } - + this._contentWidget.startShowingAt(showAtRange, HoverStartMode.Delayed, false); } } else if (targetType === MouseTargetType.GUTTER_GLYPH_MARGIN) { - this.contentWidget.hide(); + this._contentWidget?.hide(); if (this._isHoverEnabled && mouseEvent.target.position) { - this.glyphWidget.startShowingAt(mouseEvent.target.position.lineNumber); + if (!this._glyphWidget) { + this._glyphWidget = new ModesGlyphHoverWidget(this._editor, this._modeService, this._openerService); + } + this._glyphWidget.startShowingAt(mouseEvent.target.position.lineNumber); } } else { this._hideWidgets(); @@ -222,29 +215,31 @@ export class ModesHoverController implements IEditorContribution { } private _hideWidgets(): void { - if (!this._glyphWidget.value || !this._contentWidget.value || (this._isMouseDown && this._hoverClicked && this._contentWidget.value.isColorPickerVisible())) { + if ((this._isMouseDown && this._hoverClicked && this._contentWidget?.isColorPickerVisible())) { return; } - this._glyphWidget.value.hide(); - this._contentWidget.value.hide(); + this._glyphWidget?.hide(); + this._contentWidget?.hide(); } - private _createHoverWidgets() { - this._contentWidget.value = new ModesContentHoverWidget(this._editor, this._hoverVisibleKey, this._instantiationService, this._themeService); - this._glyphWidget.value = new ModesGlyphHoverWidget(this._editor, this._modeService, this._openerService); + public isColorPickerVisible(): boolean { + return this._contentWidget?.isColorPickerVisible() || false; } public showContentHover(range: Range, mode: HoverStartMode, focus: boolean): void { - this.contentWidget.startShowingAt(range, mode, focus); + if (!this._contentWidget) { + this._contentWidget = new ModesContentHoverWidget(this._editor, this._hoverVisibleKey, this._instantiationService, this._themeService); + } + this._contentWidget.startShowingAt(range, mode, focus); } public dispose(): void { this._unhookEvents(); this._toUnhook.dispose(); this._didChangeConfigurationHandler.dispose(); - this._glyphWidget.dispose(); - this._contentWidget.dispose(); + this._glyphWidget?.dispose(); + this._contentWidget?.dispose(); } } From 53be807cb4d13560f2dd2c86fb80202f40b20e83 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 12 Jan 2021 14:23:46 +0100 Subject: [PATCH 1836/1837] throw nice error (and prevent stackoverflow) when instantiating services recrusively --- .../common/instantiationService.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts index 0fd23fd508c..00f0cb9d95e 100644 --- a/src/vs/platform/instantiation/common/instantiationService.ts +++ b/src/vs/platform/instantiation/common/instantiationService.ts @@ -132,15 +132,31 @@ export class InstantiationService implements IInstantiationService { private _getOrCreateServiceInstance(id: ServiceIdentifier, _trace: Trace): T { let thing = this._getServiceInstanceOrDescriptor(id); if (thing instanceof SyncDescriptor) { - return this._createAndCacheServiceInstance(id, thing, _trace.branch(id, true)); + return this._safeCreateAndCacheServiceInstance(id, thing, _trace.branch(id, true)); } else { _trace.branch(id, false); return thing; } } + private readonly _activeInstantiations = new Set>(); + + + private _safeCreateAndCacheServiceInstance(id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace): T { + if (this._activeInstantiations.has(id)) { + throw new Error(`illegal state - RECURSIVELY instantiating service '${id}'`); + } + this._activeInstantiations.add(id); + try { + return this._createAndCacheServiceInstance(id, desc, _trace); + } finally { + this._activeInstantiations.delete(id); + } + } + private _createAndCacheServiceInstance(id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace): T { - type Triple = { id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace }; + + type Triple = { id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace; }; const graph = new Graph(data => data.id.toString()); let cycleCount = 0; @@ -195,7 +211,6 @@ export class InstantiationService implements IInstantiationService { graph.removeNode(data); } } - return this._getServiceInstanceOrDescriptor(id); } From 67f9988bdc476e99eedd50ae083ec3d90eb38604 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 12 Jan 2021 14:40:13 +0100 Subject: [PATCH 1837/1837] Support to define additional attributes for ports Part of microsoft/vscode-remote-release#4046 --- .../contrib/remote/browser/remoteExplorer.ts | 47 +++++--- .../remote/common/remote.contribution.ts | 37 ++++++ .../remote/common/remoteExplorerService.ts | 111 +++++++++++++++++- 3 files changed, 179 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 275926c7c5e..da783c19e57 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Extensions, IViewContainersRegistry, IViewDescriptorService, IViewsRegistry, IViewsService, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views'; -import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, makeAddress, mapHasAddressLocalhostOrAllInterfaces, OnPortForward, PortsAttributes, TUNNEL_VIEW_ID } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { PORT_AUTO_FORWARD_SETTING, forwardedPortsViewEnabled, ForwardPortAction, OpenPortInBrowserAction, TunnelPanel, TunnelPanelDescriptor, TunnelViewModel } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -221,26 +221,35 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon } } -class ForwardedPortNotifier extends Disposable { +class OnAutoForwardedAction extends Disposable { private lastNotifyTime: Date; - private static COOL_DOWN = 5000; // milliseconds + private static NOTIFY_COOL_DOWN = 5000; // milliseconds private lastNotification: INotificationHandle | undefined; private lastShownPort: number | undefined; constructor(private readonly notificationService: INotificationService, private readonly remoteExplorerService: IRemoteExplorerService, private readonly openerService: IOpenerService, - private readonly tunnelService: ITunnelService) { + private readonly tunnelService: ITunnelService, + private readonly portsAttributes: PortsAttributes) { super(); this.lastNotifyTime = new Date(); this.lastNotifyTime.setFullYear(this.lastNotifyTime.getFullYear() - 1); } - public async notify(tunnels: RemoteTunnel[]) { + public async doAction(tunnels: RemoteTunnel[]): Promise { const tunnel = await this.portNumberHeuristicDelay(tunnels); if (tunnel) { - if (Date.now() - this.lastNotifyTime.getTime() > ForwardedPortNotifier.COOL_DOWN) { - this.showNotification(tunnel); + switch (this.portsAttributes.getAttributes(tunnel.tunnelRemotePort)?.onAutoForward) { + case OnPortForward.Open: { + await OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, this.openerService, tunnel.localAddress); + break; + } + case OnPortForward.Silent: break; + default: + if (Date.now() - this.lastNotifyTime.getTime() > OnAutoForwardedAction.NOTIFY_COOL_DOWN) { + this.showNotification(tunnel); + } } } } @@ -296,7 +305,7 @@ class ForwardedPortNotifier extends Disposable { let message = this.basicMessage(tunnel); const choices = [this.openChoice(tunnel)]; - if (tunnel.tunnelLocalPort !== undefined && this.tunnelService.canElevate && isPortPrivileged(tunnel.tunnelRemotePort)) { + if ((tunnel.tunnelLocalPort !== tunnel.tunnelRemotePort) && this.tunnelService.canElevate && isPortPrivileged(tunnel.tunnelRemotePort)) { // Privileged ports are not on Windows, so it's safe to use "superuser" message += nls.localize('remote.tunnelsView.elevationMessage', "You'll need to run as superuser to use port {0} locally. ", tunnel.tunnelRemotePort); choices.unshift(this.elevateChoice(tunnel)); @@ -348,7 +357,8 @@ class ForwardedPortNotifier extends Disposable { class WindowsAutomaticPortForwarding extends Disposable { private portsFeatures?: IDisposable; private urlFinder?: UrlFinder; - private notifier: ForwardedPortNotifier; + private notifier: OnAutoForwardedAction; + private portsAttributes: PortsAttributes; constructor( private readonly terminalService: ITerminalService, @@ -360,7 +370,8 @@ class WindowsAutomaticPortForwarding extends Disposable { readonly tunnelService: ITunnelService ) { super(); - this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService, tunnelService); + this.portsAttributes = new PortsAttributes(configurationService); + this.notifier = new OnAutoForwardedAction(notificationService, remoteExplorerService, openerService, tunnelService, this.portsAttributes); this._register(configurationService.onDidChangeConfiguration((e) => { if (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING)) { this.tryStartStopUrlFinder(); @@ -393,9 +404,12 @@ class WindowsAutomaticPortForwarding extends Disposable { if (mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, localUrl.host, localUrl.port)) { return; } + if (this.portsAttributes.getAttributes(localUrl.port)?.onAutoForward === OnPortForward.Ignore) { + return; + } const forwarded = await this.remoteExplorerService.forward(localUrl); if (forwarded) { - this.notifier.notify([forwarded]); + this.notifier.doAction([forwarded]); } })); } @@ -411,9 +425,10 @@ class WindowsAutomaticPortForwarding extends Disposable { class LinuxAutomaticPortForwarding extends Disposable { private candidateListener: IDisposable | undefined; private autoForwarded: Set = new Set(); - private notifier: ForwardedPortNotifier; + private notifier: OnAutoForwardedAction; private initialCandidates: Set = new Set(); private portsFeatures: IDisposable | undefined; + private portsAttributes: PortsAttributes; constructor( private readonly configurationService: IConfigurationService, @@ -423,7 +438,8 @@ class LinuxAutomaticPortForwarding extends Disposable { readonly tunnelService: ITunnelService ) { super(); - this.notifier = new ForwardedPortNotifier(notificationService, remoteExplorerService, openerService, tunnelService); + this.portsAttributes = new PortsAttributes(configurationService); + this.notifier = new OnAutoForwardedAction(notificationService, remoteExplorerService, openerService, tunnelService, this.portsAttributes); this._register(configurationService.onDidChangeConfiguration(async (e) => { if (e.affectsConfiguration(PORT_AUTO_FORWARD_SETTING)) { await this.startStopCandidateListener(); @@ -494,6 +510,9 @@ class LinuxAutomaticPortForwarding extends Disposable { if (mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, value.host, value.port)) { return undefined; } + if (this.portsAttributes.getAttributes(value.port)?.onAutoForward === OnPortForward.Ignore) { + return undefined; + } const forwarded = await this.remoteExplorerService.forward(value); if (forwarded) { this.autoForwarded.add(address); @@ -524,7 +543,7 @@ class LinuxAutomaticPortForwarding extends Disposable { const tunnels = await this.forwardCandidates(); if (tunnels) { - await this.notifier.notify(tunnels); + await this.notifier.doAction(tunnels); } } } diff --git a/src/vs/workbench/contrib/remote/common/remote.contribution.ts b/src/vs/workbench/contrib/remote/common/remote.contribution.ts index 45c211ce354..8ecdf7fcad4 100644 --- a/src/vs/workbench/contrib/remote/common/remote.contribution.ts +++ b/src/vs/workbench/contrib/remote/common/remote.contribution.ts @@ -133,6 +133,43 @@ Registry.as(ConfigurationExtensions.Configuration) type: 'boolean', markdownDescription: localize('remote.autoForwardPorts', "When enabled, new running processes are detected and ports that they listen on are automatically forwarded."), default: true + }, + 'remote.portsAttributes': { + type: 'array', + description: localize('remote.portsAttributes', "Allows setting of default properties that are set when a specific port number is forwarded."), + items: { + type: 'object', + properties: { + 'port': { + type: 'string', + pattern: '^\\d+(\\-\\d+)?$', + description: localize('remote.portsAttributes.port', "The port, or range of ports, that these attributes should apply to."), + default: '0-65535' + }, + 'onAutoForward': { + type: 'string', + enum: ['notify', 'open', 'silent', 'ignore'], + enumDescriptions: [ + localize('remote.portsAttributes.notify', "Shows a notification when a port is automatically forwarded."), + localize('remote.portsAttributes.open', "Opens the browser when the port is automatically forwarded. Depending on your settings, this could open an embedded browser."), + localize('remote.portsAttributes.silent', "Shows no notification and takes no action when this port is automatically forwarded."), + localize('remote.portsAttributes.ignore', "This port will not be automatically forwarded.") + ], + description: localize('remote.portsAttributes.onForward', "Defines the action that occurs when the port is discovered for automatic forwarding"), + default: 'notify' + }, + 'elevateIfNeeded': { + type: 'boolean', + description: localize('remote.portsAttributes.elevateIfNeeded', "Automatically prompt for elevation (if needed) when this port is forwarded. Elevate is required if the local port is a privileged port."), + default: false + } + } + }, + default: [{ + 'port': '3000', + 'onAutoForward': 'notify', + 'elevateIfNeeded': false + }] } } }); diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 99283b3c86b..63a0c592487 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -15,6 +15,7 @@ import { TunnelInformation, TunnelDescription, IRemoteAuthorityResolverService } import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { isNumber, isString } from 'vs/base/common/types'; export const IRemoteExplorerService = createDecorator('remoteExplorerService'); export const REMOTE_EXPLORER_TYPE_KEY: string = 'remote.explorerType'; @@ -105,6 +106,108 @@ export function mapHasAddressLocalhostOrAllInterfaces(map: Map, ho return undefined; } +export enum OnPortForward { + Notify = 'notify', + Open = 'open', + Silent = 'silent', + Ignore = 'ignore' +} + +interface Attributes { + label: string | undefined; + onAutoForward: OnPortForward | undefined, + elevateIfNeeded: boolean | undefined; +} + +interface PortAttributes extends Attributes { + port: number | { start: number, end: number }; +} + +export class PortsAttributes extends Disposable { + private static SETTING = 'remote.portsAttributes'; + private static RANGE = /^\d+\-\d+$/; + private portsAttributes: PortAttributes[]; + constructor(private readonly configurationService: IConfigurationService) { + super(); + this._register(configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(PortsAttributes.SETTING)) { + this.portsAttributes = this.readSetting(); + } + })); + this.portsAttributes = this.readSetting(); + } + + getAttributes(port: number): Attributes | undefined { + let index = this.findNextIndex(port, this.portsAttributes, 0); + const attributes: Attributes = { + label: undefined, + onAutoForward: undefined, + elevateIfNeeded: undefined + }; + while (index >= 0) { + const found = this.portsAttributes[index]; + if (found.port === port) { + attributes.onAutoForward = found.onAutoForward ?? attributes.onAutoForward; + attributes.elevateIfNeeded = (found.elevateIfNeeded !== undefined) ? found.elevateIfNeeded : attributes.elevateIfNeeded; + attributes.label = found.label ?? attributes.label; + } else { + // It's a range, which means that if the attribute is already set, we keep it + attributes.onAutoForward = attributes.onAutoForward ?? found.onAutoForward; + attributes.elevateIfNeeded = (attributes.elevateIfNeeded !== undefined) ? attributes.elevateIfNeeded : found.elevateIfNeeded; + attributes.label = attributes.label ?? found.label; + } + index = this.findNextIndex(port, this.portsAttributes, index + 1); + } + if (attributes.onAutoForward !== undefined || attributes.elevateIfNeeded !== undefined) { + return attributes; + } + return undefined; + } + + private findNextIndex(port: number, attributes: PortAttributes[], fromIndex: number): number { + if (fromIndex >= attributes.length) { + return -1; + } + const sliced = attributes.slice(fromIndex); + return sliced.findIndex((value) => { + return isNumber(value.port) ? (value.port === port) : (port >= value.port.start && port <= value.port.end); + }); + } + + private readSetting(): PortAttributes[] { + const settingValue = this.configurationService.getValue(PortsAttributes.SETTING); + if (!settingValue || !Array.isArray(settingValue)) { + return []; + } + + const attributes: PortAttributes[] = []; + for (let setting of settingValue) { + let port: number | { start: number, end: number } | undefined = undefined; + if (setting.port !== undefined) { + if (Number(setting.port)) { + port = Number(setting.port); + } else if (isString(setting.port) && PortsAttributes.RANGE.test(setting.port)) { + const match = (setting.port).match(PortsAttributes.RANGE); + port = { start: Number(match![1]), end: Number(match![2]) }; + } + } + if (!port) { + continue; + } + attributes.push({ + port, + elevateIfNeeded: setting.elevateIfPrivileged, + onAutoForward: setting.onAutoForward, + label: setting.label + }); + } + attributes.sort((a, b) => { + return (isNumber(a.port) ? a.port : a.port.start) - (isNumber(b.port) ? b.port : b.port.start); + }); + return attributes; + } +} + export class TunnelModel extends Disposable { readonly forwarded: Map; readonly detected: Map; @@ -124,6 +227,7 @@ export class TunnelModel extends Disposable { private _onEnvironmentTunnelsSet: Emitter = new Emitter(); public onEnvironmentTunnelsSet: Event = this._onEnvironmentTunnelsSet.event; private _environmentTunnelsSet: boolean = false; + private portsAttributes: PortsAttributes; constructor( @ITunnelService private readonly tunnelService: ITunnelService, @@ -133,6 +237,7 @@ export class TunnelModel extends Disposable { @IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, ) { super(); + this.portsAttributes = new PortsAttributes(configurationService); this.tunnelRestoreValue = this.storageService.get(TUNNELS_TO_RESTORE, StorageScope.WORKSPACE); this.forwarded = new Map(); this.remoteTunnels = new Map(); @@ -209,14 +314,16 @@ export class TunnelModel extends Disposable { getAddress: async () => { return (await this.remoteAuthorityResolverService.resolveAuthority(authority)).authority; } } : undefined; - const tunnel = await this.tunnelService.openTunnel(addressProvider, remote.host, remote.port, local, elevateIfNeeded); + const attributes = this.portsAttributes.getAttributes(local !== undefined ? local : remote.port); + + const tunnel = await this.tunnelService.openTunnel(addressProvider, remote.host, remote.port, local, (!elevateIfNeeded) ? attributes?.elevateIfNeeded : elevateIfNeeded); if (tunnel && tunnel.localAddress) { const matchingCandidate = mapHasAddressLocalhostOrAllInterfaces(this._candidates ?? new Map(), remote.host, remote.port); const newForward: Tunnel = { remoteHost: tunnel.tunnelRemoteHost, remotePort: tunnel.tunnelRemotePort, localPort: tunnel.tunnelLocalPort, - name: name, + name: name ?? attributes?.label, closeable: true, localAddress: tunnel.localAddress, runningProcess: matchingCandidate?.detail,